ボリュームコントロールをAgoraWebSDK in ReactJSAppで実現する方法

## はじめに
Agora SDKは映像音声の送受信においてクライアントサイドのSDKとインフラを提供するPaaSです。

この記事はAgora社公式の[ブログ](https://www.agora.io/en/blog/volume-controls-using-agora-rtc-in-a-react-js-app/)の内容を翻訳したものです。

ビデオ通話アプリケーションに、任意の人の音量を操作したり、ユーザーがマイクをミュートしているのに話そうとしているときにプロンプトを表示したり、その他のオーディオ効果などの音量機能を組み込むのは、非常に面倒で時間がかかる場合があります。このブログでは、これらの機能をすべて紹介します。

## 前提条件

 - Agora開発者アカウント
 - Reactの基本
 - Agora SDK
 
## サンプルの構成

アプリケーションには、以下のような様々なコンポーネントが含まれています。

 - グローバルコンテナ：以下のすべてのコンポーネントが含まれます
 - メインビデオコンポーネント：各ユーザーのビデオフィードを保持します
 - ビデオコンポーネント：特定のユーザーの動画フィードを保持します
 - コントロールコンポーネント：オーディオ/ビデオのミュート、ユーザーの音量を変更するための入力、通話終了ボタンなどのオプションが含まれます

## ミュート中に発言した際のプロンプト表示
user.audioの状態の変化に基づいて、コントロールコンポーネントでuseEffectを使用します。関数を呼び出して別のマイク入力を作成し、それを分析して、setInterval 内に音量スコアを生成します。このスコアが一定値以上であれば、発話したとみなされます。ユーザーがミュートを解除すると、Intervalがクリアされ、それに応じてUIを更新することができます。ここでは、「speaking」という状態が使用されています。

```javascript:App.js
useEffect(() => {
   const startAudioCheck = async () => {
     const mediaStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true })
     const audioContext = new AudioContext();
     const mediaStreamAudioSourceNode = audioContext.createMediaStreamSource(mediaStream);
     const analyserNode = audioContext.createAnalyser();
     mediaStreamAudioSourceNode.connect(analyserNode);
     const pcmData = new Float32Array(analyserNode.fftSize);
 
     const checkAudio = () => {
       analyserNode.getFloatTimeDomainData(pcmData);
       let sumSquares = 0.0;
       for (const amplitude of pcmData) { sumSquares += amplitude * amplitude; }
       let vol = Math.sqrt(sumSquares / pcmData.length)
       if (vol > 0.05 && !speaking) {
         setSpeaking(true)
         setTimeout(() => { setSpeaking(false) }, 2000)
       }
     };
 
     if (user.audio === false) {
       rtc.current.checkSpeakingInterval = setInterval(checkAudio, 100)
     }
     else {
       clearInterval(rtc.current.checkSpeakingInterval)
     }
   }
   if (user.client) {
     startAudioCheck()
   }
   return () => {
     // eslint-disable-next-line
     clearInterval(rtc.current.checkSpeakingInterval)
   }
   // eslint-disable-next-line
 }, [user.audio])
```

音声ミュートしているデフォルトの状態が以下になります。
![スクリーンショット 0004-03-17 11.06.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/46081265-b798-fc96-e1be-cd83b8f7a88b.png)

この状態で発話すると以下のようにプロンプトが表示されます。
![スクリーンショット 0004-03-17 11.15.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/801cd7e6-0279-5ff7-280c-f89037868cd0.png)

## 通話中の各ユーザーの音量調整
ユーザーのstateとリモートオーディオトラックとローカルオーディオトラックをaudioTrackキーに格納する。


リモートまたはローカルのオーディオトラックに対してAgoraRTCSDKが提供するAPIに.setVolume()があります。コントロールコンポーネントで、必要に応じてトラックのボリュームを設定します。

```javascript:App.js
return (
 <div className='controls'>
   {/* Button to Mute/Unmute Mic */}
   {/* Button to Mute/Unmute Video */}
   {<input type="number" placeholder="Volume" onChange={(e) => { let vol = parseInt(e.target.value); !isNaN(vol) && vol >= 0 && vol <= 1000 && (user.audioTrack.setVolume(parseInt(e.target.value))) }} />}
   {/* Button to quit call if client */}
 </div>
)

```

## オーディオ設定のカスタマイズ
AgoraRTCSDKはオーディオ設定のAPIを提供しています。
```javascript:App.js
rtc.current.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack({
 encoderConfig: {
   sampleRate: 48000,
   stereo: true,
   bitrate: 128,
 },
})
```
また、独自のオーディオソースを使用し、それをSDKに渡すことも可能です。そのオーディオソースを好きなように操作することができます。
```javascript:App.js
const media = await navigator.mediaDevices.getUserMedia({ video: false, audio: true })
let audioTrack = media.getAudioTracks()[0]
rtc.current.localAudioTrack = AgoraRTC.createCustomAudioTrack({ mediaStreamTrack: audioTrack });
//You can manipulate the audioTrack here
```

## まとめ
Reactアプリケーションで様々な音量調節をしながら、ビデオ通話ができます。GitHubのリポジトリからコンポーネントを抽出し、アプリケーションに直接実装することができます。
その他の機能については、公式のドキュメントを参照してみてください。
このチュートリアルのコードは、[GitHub](https://github.com/prakhar0912/AgoraRTC-VolumeControls)で公開されています。

## 最後に
[**agora.ioに関するお問い合わせはこちらから**](https://jp.vcube.com/lp/agora?utm_campaign=Agora&utm_source=Qiita&arc_id=3879b0fcce4d619bd109)
[<img width="912" alt="Agoraの詳細はこちら" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/5865441c-9d31-c702-3698-3aeb84927f28.png">](https://jp.vcube.com/lp/agora?utm_campaign=Agora&utm_source=Qiita&arc_id=3879b0fcce4d619bd109)