.. API ドキュメントへのリンク定義をここに定義する .. _Sora.setAudioMode メソッド: https://sora-ios-sdk.shiguredo.jp/_static/api/docs/Classes/Sora#/s:4SoraAAC12setAudioMode_7optionss6ResultOyyts5Error_pGAA0cD0O_So29AVAudioSessionCategoryOptionsVtF .. _AudioMode: _static/api/docs/Enums/AudioMode.html .. _AudioOutput: _static/api/docs/Enums/AudioOutput.html .. _MediaStream: _static/api/docs/Protocols/MediaStream.html .. _MediaChannelHandlers: _static/api/docs/Classes/MediaChannelHandlers.html .. _Audio: ######################## 音声の操作 ######################## 用語 ===== RTCAudioTrack (音声トラック) ----------------------------- AudioTrack は 1 接続に存在する音声のストリーミングデータを表現するオブジェクトです。 配信する音声トラックは Sora のルールにより 1 本です。受信する音声トラックは接続数分あります。 例えば 3 人で通話している場合、配信する音声トラックは 1 本、受信する音声トラックは 2 本存在します。 RTCAudioTrackSink ------------------ RTCAudioTrackSink は送信または受信した音声トラックごとに、音声データのコールバックを受け取るプロトコルです。 音声トラックから音声データを取得するには、この RTCAudioTrackSink を利用します。 音声をミュートする ================================= 音声をミュートするには :ref:`devguide-MediaStream` (`MediaStream`_) の ``audioEnabled`` プロパティに ``false`` をセットします。 ただし送信音声についてミュートした場合、マイクは停止しませんので注意してください。 .. code-block:: swift // 指定の ConnectionID を持つ受信 Stream の音声のミュート状態を切り替える private func handleMuteReceiveStream(connectionId: String) { // 受信したストリームのリストを取得する // Sora 接続成功時に取得する MediaChannel を mediaChannel に保持しているものとする let downstreams = mediaChannel?.receiverStreams ?? [] // downstreams が空の場合は何もしない guard downstreams.count > 0 else { return } for stream in downstreams { // 指定のコネクションIDを持つ Stream の audioEnabled を切り替える if stream.streamId == connectionId { stream.audioEnabled = !stream.audioEnabled } } } 受信した音声の音量を変更する ============================= :ref:`role` が ``Role.recvonly`` または ``Role.sendrecv`` のとき、 :ref:`devguide-MediaStream` (`MediaStream`_) の ``remoteAudioVolume`` プロパティで受信ストリームの音量が変更できます。 このプロパティは 0 から 10 の値をとります。 0 をセットすると音声は出力されません。 送信ストリームで送信する音声の音量は変更できません。 .. code-block:: swift let config = Configuration(url: url, channelId: channelId, role: .sendrecv) // 送信または受信のストリームが追加されたときのイベントハンドラ config.mediaChannelHandlers.onAddStream = { [weak self] stream in // クロージャーの実行時、 self が存在する場合のみ処理を続けます。 guard let self = self else { return } // 受信ストリームのときのみ音量変更を行う if stream.streamId != config.publisherStreamId { stream.remoteAudioVolume = 3.0 } } .. _audio_track_sink: 受信した音声データを取得する ============================= 音声トラックごとに音声データを取得するには ``RTCAudioTrackSink`` プロトコルを利用します。 このプロトコルを実装したクラスを `MediaStream`_ の ``addAudioTrackSink(_:)`` で音声トラックに関連付けることで音声データを受信できるようになり、 ``removeAudioTrackSink(_:)`` を呼ぶか、自分もしくはリモートの配信クライアントがチャネルを離脱することで音声トラックとの関連付けが解除されます。 以下に音声データ受信の実装例を示します。 .. literalinclude:: swift/RTCAudioTrackSinkExample.swift :language: swift 音声データについて ------------------- コールバックに入ってくる音声データは非圧縮の 16 bit PCM (Pulse Code Modulation) 形式です。 onData コールバックについて ---------------------------- RTCAudioTrackSink の onData コールバックには音声データ以外の情報も含まれています。 .. code-block:: swift /// 音声データ受信コールバック。 /// /// - Parameters: /// - audioData: PCM 形式音声データ。 /// - bitsPerSample: 1 サンプルあたりのビット数。 /// libwebrtc では PCM 形式の音声データは 16 bit 固定のため、常に 16 が渡されます。 /// - sampleRate: サンプルレート (単位: Hz)。 /// - numberOfChannels: 音声データのチャンネル数。 /// モノラルなら 1、ステレオなら 2 が渡されます。 /// - numberOfFrames: audioData に含まれるフレーム数。 func onData(_ audioData: Data, bitsPerSample: Int, sampleRate: Int, numberOfChannels: Int, numberOfFrames: Int) .. caution:: onData コールバック実装の注意点 onData は 10 ms ごとに libwebrtc の音声処理スレッド上で呼び出されるコールバックであるため、 onData 内部で時間のかかる処理を行う場合、libwebrtc の音声処理がブロックされてしまいます。そのため onData 内部で時間のかかる処理を行わず、別スレッドで処理を行うようにしてください。 RTCAudioTrackSink と RTCAudioTrack の関連付けについて ------------------------------------------------------------- RTCAudioTrackSink と RTCAudioTrack の関連付けは 1:1 を前提に実装されています。1 つの RTCAudioTrackSink を複数の RTCAudioTrack に同時に関連付ける 1:N の利用は想定していません。 一方で、1 本の RTCAudioTrack に対して複数の RTCAudioTrackSink を関連付けることは可能であり、同一の RTCAudioTrack から各 RTCAudioTrackSink はそれぞれ独立して音声データを受け取ります。 RTCAudioTrackSink と RTCAudioTrack の関連付け解除について ---------------------------------------------------------- 通常、自分もしくはリモートの配信クライアントがチャネルを離脱した際に、RTCAudioTrack と RTCAudioTrackSink の関連付けは自動で解除されます。 明示的に関連付けを解除したい場合は、 `MediaStream`_ の ``removeAudioTrackSink(_:)`` を呼び出してください。 任意の音声を送信する ==================== WebRTC ライブラリの制約により、 Sora iOS SDK ではマイク入力以外の音声を送信できません。ご了承ください。 .. _audio_change_mode: AVAudioSession のプロパティを変更する =============================================== .. important:: iOS 14.0 で、音声モードをデフォルト以外からデフォルトに戻したときに音声が出力されない事象を確認しています。その場合は端末を iOS 14.1 以降にアップデートしてください。 Sora iOS SDK では、AVAudioSession のプロパティを変更する簡易的な API として、 `Sora.setAudioMode メソッド`_ を用意しています。 この API は ``AVAudioSession`` の次のプロパティを変更します - 音声モード (``AVAudioSession.Mode``) - 音声カテゴリ (``AVAudioSession.Category``) - 音声カテゴリオプション (``AVAudioSession.CategoryOptions``) - 音声経路 (``AVAudioSession.PortOverride``) ピア接続の設定や端末の状況によっては設定が反映されない場合があるので注意してください。 `Sora.setAudioMode メソッド`_ の型と引数は以下の通りです。 - mode: `AudioMode`_ - `AudioMode`_ は Sora iOS SDK で利用可能な 3 種類の音声モードです。 - default - default の音声モードを利用します。音声カテゴリ、音声出力先の指定ができます。 - videoChat - videoChat の音声モードを利用します。音声カテゴリは ``playAndRecord``、音声出力先はスピーカーを使用します - voiceChat - voiceChat の音声モードを利用します。音声カテゴリは ``playAndRecord``、音声出力先の指定ができます。 - options: ``AVAudioSession.CategoryOptions`` - 指定は任意です。デフォルトで ``allowBluetooth`` 、 ``allowBluetoothA2DP`` 、 ``allowAirPlay`` が設定されています。 - 指定した場合はデフォルトの音声カテゴリオプションは設定されず、指定した音声カテゴリオプションのみが設定されます。 AudioMode の指定方法および AVAudioSession のプロパティ設定内容 ---------------------------------------------------------------------- `AudioMode`_ はモード毎にそれぞれ異なる引数を取ります。 指定する引数の内容と、指定された引数によって設定される AVAudioSession のプロパティの値は以下のとおりです。 - ``default(category: AVAudioSession.Category, output: AudioOutput)`` - 音声モードに ``default`` を設定します - 音声カテゴリに引数で指定された category を設定します - output には `AudioOutput`_ の ``default`` または ``speaker`` を指定します - output に ``speaker`` が指定されていた時、音声カテゴリオプションに ``defaultToSpeaker`` が追加で設定されます - ``videoChat`` - 音声モードに ``videoChat`` が設定されます - 音声カテゴリに ``playAndRecord`` が設定されます - ``voiceChat(output: AudioOutput)`` - 音声モードに ``voiceChat`` を設定します - 音声カテゴリに ``playAndRecord`` を設定します - output には `AudioOutput`_ の ``default`` または ``speaker`` を指定します - output に ``speaker`` が指定されていた時、音声カテゴリオプションに ``defaultToSpeaker`` が追加で設定されます - output に ``speaker`` が指定されていた時、音声経路に ``speaker`` が設定されます 設定例 ------ 以下に `Sora.setAudioMode メソッド`_ を利用した AVAudioSession のプロパティ変更の例を示します。 .. code-block:: swift import Sora // 接続時のコールバック onConnect で音声モードを変更する config.mediaChannelHandlers.onConnect = { [weak self] _ in // setAudioMode を利用して、AVAudioSession のプロパティを変更する // AudioSession は以下のように設定される // - Category : playAndRecord // - Mode : default // - CategoryOptions : defaultToSpeaker, allowBluetooth, allowBluetoothA2DP, allowAirPlay // - output に speaker を設定することで defaultToSpeaker が設定される // - options は未指定のときと同様の設定。ここでは設定方法の例として記載している。 let result = Sora.shared.setAudioMode(.default(category: .playAndRecord, output: .speaker), options: [.allowBluetooth, .allowBluetoothA2DP, .allowAirPlay]) // 必要に応じてエラーハンドリングを行う switch result { case .success(): // 成功 case .failure(let error): // 失敗 } } さらに細かい設定を行う場合は ``AVAudioSession`` の継承クラスである libwebrtc の ``RTCAudioSession`` を使用して設定が可能です。 設定を行った結果、libwebrtc の動作に影響が出て、正常に動作しなくなる可能性があるため、libwebrtc の挙動を理解した上で設定をしてください。 音声モードを変更するタイミング ------------------------------- 音声モードの変更は **接続完了後** に行ってください。 Sora iOS SDK は接続完了時に接続設定に従って音声カテゴリを変更するので、接続完了前にセットした音声モードは接続完了時に上書きされます。 その他の操作 ============ 音声の出力は ``AVAudioSession`` により管理されているため、その他の操作は ``AVAudioSession`` を利用してください。 マイクのパーミッションについて ============================== マイクのパーミッションは配信時にのみ要求されます。 マイクを使う場合は、 :ref:`必ず Info.plist にマイクの用途を記述してください。`