[Q&A]誰が話しているかわかるようにボリュームメーターを実装したい

2,135 views
Skip to first unread message

kazu N

unread,
Mar 2, 2016, 3:18:52 AM3/2/16
to SkyWay Technical Forum

はじめまして。ご相談させてください。

・誰が話しているかを表示させたい
Multipartyにて不特定多数でボイスチャットをするツールを作成しているのですが、
人数が増えると誰が話しているかわかりづらくなってしまいます。

なので、話した人がわかるようにボリュームメーター、
もしくは話した時に目印になるようなもの表示したいと思っています。

ですが、相手の音声の大きさの取得の仕方がわからず、困っています。
もしそのような事ができるのであれば教えていただけますでしょうか。

よろしくお願いいたします。

Yusuke NAKA

unread,
Mar 3, 2016, 5:18:19 AM3/3/16
to SkyWay Technical Forum
Kazu N様

SkyWay開発チームの仲です。

ボリュームメーターの実装は、Web Audio APIを利用すれば可能ではないでしょうか。

ちょうどいいサンプルがなく申し訳ありません。

上記サイトの「ボリュームを変更する」という箇所を参考に、
getUserMediaで取得したAudioStreamをWeb Audio APIの入力として、AudioGainNode経由でDestinationに接続します。
そうすると、ボリューム情報が取れるはずなので、
それをDataChannelなどで相手に送ってあげれば、相手側で話しているかどうか判定できるのではないでしょうか。
また、Chrome M49から相手側でも、送られてきたAudioStreamをWeb Audio APIで処理できるようになったため、
相手側で同様の処理を実装することも可能だと思います。

詳しい方がいれば、フォロー頂けますと幸いです。

2016年3月2日水曜日 17時18分52秒 UTC+9 kazu N:

You Kinjoh

unread,
Mar 3, 2016, 8:33:41 AM3/3/16
to skyw...@googlegroups.com
金城です。

WebRTCとWeb Audio APIを連携させて
ボイスチェンジャーを実装したことがあります。
下記スライドの198ページ以降に載せています。

http://www.slideshare.net/nttwestcon/20140805-technical-description-of-webrtc-second-edition-public-edition-full-version/198

onAudioProcess内のinputに
PCMという形式の音声データが
Float32Arrayという型で入ります。
(Float32Arrayというのは型付の値の配列で
TypedArrayというものです。)
ここからデシベル等の算出が可能です。
"誰が喋っているのか"を判断するぐらいなら
この配列内の値の平均値でも十分かもしれませんね。

音声の周波数だけの音量を取得したいのであればさらに手間が必要で、
高速フーリエ変換(FFT)を行って周波数別の値を取得したり、
ちょっと簡易的なものでよければ
Web Audio APIのAnalyserNodeのgetByteFrequencyDataを使えば良いかと思います。
getByteFrequencyDataは内部でフーリエ変換を行っているのですが、
どうもビジュアライザーとか周波数別のレベルメーターのようなものに
使うために値を弄っているのか、正確な値を取得できないようです。
が、今回の用途であれば十分に使えるのではないかと思います。

音声データの世界は奥が深く
追えば追うほど泥沼にはまるので
適当なところで引き返してくるのが吉ですね。
(デシベルは音声向けのものに限っても数種類あるとか等々...。)


2016年3月3日 19:18 Yusuke NAKA <com.y...@gmail.com>:
> --
> このメールは Google グループのグループ「SkyWay Technical Forum」に登録しているユーザーに送られています。
> このグループから退会し、グループからのメールの配信を停止するには skywayjs+u...@googlegroups.com
> にメールを送信してください。
> このディスカッションをウェブ上で閲覧するには
> https://groups.google.com/d/msgid/skywayjs/0b340bc0-25a8-4773-9794-ba2edb9dbb70%40googlegroups.com
> にアクセスしてください。
> その他のオプションについては https://groups.google.com/d/optout にアクセスしてください。

Information Kanasansoft

unread,
Mar 3, 2016, 9:09:19 AM3/3/16
to skyw...@googlegroups.com
金城です。

すいません。
Web Audio APIのScriptProcessorは廃止予定なのをすっかり忘れていました。
実装するのであればAudioWorkerを使ってください。

http://g200kg.github.io/web-audio-api-ja/#AudioWorker


2016年3月3日 22:33 You Kinjoh <you.k...@gmail.com>:
> このメールは Google グループのグループ「SkyWay Technical Forum」の登録者に送られています。
> このグループから退会し、グループからのメールの配信を停止するには skywayjs+u...@googlegroups.com にメールを送信してください。
> このディスカッションをウェブ上で閲覧するには、https://groups.google.com/d/msgid/skywayjs/CABGp01x1Knab2kRW-HfA5QxseUtAfOZVzSs%2BP1VpBpk%3D8TOnvw%40mail.gmail.com にアクセスしてください。
> その他のオプションについては、https://groups.google.com/d/optout にアクセスしてください。

Yusuke NAKA

unread,
Mar 3, 2016, 9:44:31 PM3/3/16
to SkyWay Technical Forum
kazu N様
金城様

仲です。

金城様、フォローありがとうございます。

すみません、私のAudioGainNodeの件は、ボリューム取得という点では適さないように思えてきました。
その後、チーム内で確認したところ2つ方法ができてましたので、共有させてもらいます。

ひとつ目はこちら。
サンプルコードもありますが、Web Audio APIのaudioContextクラスを利用するパターンです。

var processor = audioContext.createScriptProcessor(512);
processor
.onaudioprocess = volumeAudioProcess;
<略>
function volumeAudioProcess( event ) {
   
var buf = event.inputBuffer.getChannelData(0);
   
for (var i=0; i<bufLength; i++) {
        x
= buf[i];
       
if (Math.abs(x)>=this.clipLevel) {
           
this.clipping = true;
           
this.lastClip = window.performance.now();
       
}
        sum
+= x * x;
   
}
<略>

※出展:https://github.com/cwilso/volume-meter


もう一つはgetStatsというWebRTCの統計情報を収集するAPIを利用する方法です。

audioOutputLevel、audioInputLevelというプロパティを参照することで、出力レベルと入力レベルが取れます。

良いサンプルコードがありませんが、opentok.jsにOutputLevelを取得するfunctionが実装されてました。


https://static.opentok.com/v2/js/opentok.js

20719行目付近


参考になれば幸いです。



2016年3月3日木曜日 23時09分19秒 UTC+9 Information Kanasansoft:
>> このグループから退会し、グループからのメールの配信を停止するには skywayjs+unsubscribe@googlegroups.com
>> にメールを送信してください。
>> このディスカッションをウェブ上で閲覧するには
>> https://groups.google.com/d/msgid/skywayjs/0b340bc0-25a8-4773-9794-ba2edb9dbb70%40googlegroups.com
>> にアクセスしてください。
>> その他のオプションについては https://groups.google.com/d/optout にアクセスしてください。
>
> --
> このメールは Google グループのグループ「SkyWay Technical Forum」の登録者に送られています。
> このグループから退会し、グループからのメールの配信を停止するには skywayjs+unsubscribe@googlegroups.com にメールを送信してください。

Hiroki Kato

unread,
Mar 3, 2016, 10:03:51 PM3/3/16
to SkyWay Technical Forum
kazu N様

SkyWay開発チーム 加藤です。

getStatsを使ったaudioLevelの取得を行ったことがありますので、サンプルコードにて補足させていただきます。
それぞれのMediaConnectionに対して取得することで誰が話しているかが判別出来るかと思います。

call.peerConnection.getStats(function(report) {
        var rtcStatsReports = report.result();
        for (var i=0; i<rtcStatsReports.length; i++) {
            var statNames = rtcStatsReports[i].names();

                for (var j=0; j<statNames.length; j++) {
                    var statName = statNames[j];
                    var statValue = rtcStatsReports[i].stat(statName);

                    if(statName == "audioOutputLevel"){
                      console.log("音声の出力レベル:"+statValue);
                    }
                    if(statName == "audioInputLevel"){
                      console.log("音声の入力レベル:"+statValue);
                    }
                  }
        }
    });


よろしくお願いします。

2016年3月4日金曜日 11時44分31秒 UTC+9 Yusuke NAKA:
>> このグループから退会し、グループからのメールの配信を停止するには skywayjs+u...@googlegroups.com
>> にメールを送信してください。
>> このディスカッションをウェブ上で閲覧するには
>> https://groups.google.com/d/msgid/skywayjs/0b340bc0-25a8-4773-9794-ba2edb9dbb70%40googlegroups.com
>> にアクセスしてください。
>> その他のオプションについては https://groups.google.com/d/optout にアクセスしてください。
>
> --
> このメールは Google グループのグループ「SkyWay Technical Forum」の登録者に送られています。
> このグループから退会し、グループからのメールの配信を停止するには skywayjs+u...@googlegroups.com にメールを送信してください。

kazu N

unread,
Mar 4, 2016, 4:01:23 AM3/4/16
to SkyWay Technical Forum
ご回答有り難うございます。

https://github.com/cwilso/volume-meter

こちらのvolume-meterを使い、
clipした時にDataChannelで相手にその情報を送ることで思っていた動作が実現できました。

困っていたところ、有益な情報をいただき助かりました。
ありがとうございました。
Reply all
Reply to author
Forward
0 new messages