MPVolumeViewで強制的にミュートにする

はじめに

youtube_ios_player_helperでインライン再生を行う時に音が出てしまいなんとかならないか調べている過程で、MPVolumeViewというものがありこれで強制的にミュートにさせることができそうだったので試してみました。

XCDYouTubeKitを使えばそんなこと考えなくて良いんですがYoutubeが認めてくれないので使えず…

Appleのガイドラインをみると音量に関して以下の記載があったので使い方によってはリジェクトされるかもしれません。

2.5.9 音量を上げる/下げる、サウンドオン/オフといった標準スイッチの機能、および他のネイティブユーザーインターフェイスの要素やその挙動を変更または無効にするAppは却下されます。たとえば、ユーザーがその動作を想定できる別のAppや機能に対するリンクをブロックすることはできません。リンクの適切な取り扱いについて詳しくは、こちらをご確認ください。

https://developer.apple.com/jp/app-store/review/guidelines/

コード

MPVolumeViewを使うにはMediaPlayerをimportする必要があります。

追加自体は他のViewと同じくこんな感じに追加することができます。

let volumeView = MPVolumeView(frame: CGRect.zero)
volumeView.layer.position = CGPoint(x: 0, y: view.frame.height/2)
volumeView.frame.size = CGSize(width: self.view.frame.width, height: 100)
self.view.addSubview(volumeView)

強制的にミュートにする

MPVolumeViewの保持しているUISliderを取得してvalueを0に設定してあげることで強制的にミュートになります。

guard let slider = volumeView.subviews.compactMap({ $0 as? UISlider }).first else {
     return
 }
slider.value = 0

コード一覧

検証ように作ったタップ開始で音量を0にして音を再生し、タップ終了で音量を元の状態に戻すサンプルコード

import UIKit
import MediaPlayer
import AVFoundation

class ViewController: UIViewController {
    var audioPlayer: AVAudioPlayer!
    let volumeView = MPVolumeView(frame: CGRect.zero)
    
    var prevBolume:Float = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .orange
        
        //音の初期化
        let path = Bundle.main.path(forResource: "sample", ofType: "mp3")
        let url = URL(fileURLWithPath: path!)
        try! audioPlayer = AVAudioPlayer(contentsOf: url)
        audioPlayer.prepareToPlay()
        
        //画面に表示させないようにする
        volumeView.isUserInteractionEnabled = false
        volumeView.alpha = 0.0001
        self.view.addSubview(volumeView)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        guard let slider = volumeView.subviews.compactMap({ $0 as? UISlider }).first else {
             return
         }
        prevBolume = slider.value
        slider.value = 0
        
        if audioPlayer.isPlaying {
            audioPlayer.stop()
            audioPlayer.currentTime = 0
        }
        audioPlayer.play()
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        
        guard let slider = volumeView.subviews.compactMap({ $0 as? UISlider }).first else {
            return
        }
        slider.value = prevBolume
    }

}

参考文献

【iOS】マナーモードでも音量固定で音を再生する

MPVolumeView