« 2012年10月 | メイン | 2013年12月 »

2013年04月 アーカイブ

2013年04月21日

getUserMediaで取得したMediaStreamをWeb Audio APIで処理してWebRTCに戻す方法を探る

Web Audio APIで処理した信号をWebRTCで扱える形式に出力する機能が、最新のChromeに実装されていたので試してみました。
使用したブラウザはGoogle Chrome Canaryです。
stableのChromeでもchrome:flagsで「getUserMedia() と Web Audio API の使用によるライブ音声入力を有効にします。」を有効にすれば試せますが、Canaryよりも不安定なようなのでCanaryで試す事をお勧めします。

まだ、Working DraftにもなっていないEditor's Draftが前提です。
CanaryはEditor's Draftの仕様を既に取り込んでいるようです。
WebRTCとWeb Audio APIの概要がわからないとこのエントリーに何が書いてあるのかさっぱりだと思うので、ほんの少しだけ説明。
WebRTCを使ったビデオチャットの大まかな流れ
navigator.getUserMediaを使ってMediaStreamを取得。
MediaStreamをvideo要素に設定(ローカルの映像と音声)。
別途取得した、RTCPeerConnectionにMediaStreamを設定(送信用)。
ICEやSDPを使って相手の接続情報を取得しリモートに接続(ここ、超適当な説明)。
リモートのMediaStreamを取得し、video要素に設定(リモートの映像と音声)。
Web Audio APIの概念
Web Audio APIは音声処理を担当するAudioNodeというものを数珠つなぎに接続し一連の処理を行います。
数珠つなぎの処理は、分岐や合流も可能になっています。
米Yahoo!のPipesやMac OSX標準のQuartz Composerを思い浮かべると良いかもしれません。
音声処理の世界では一般的な考えらしいです。
AudioNodeにはローパスフィルタやダイナミックコンプレッサー等の一般的なものが最初から準備されています。
また、波形データをJavaScriptで弄る事ができるプログラマブルなAudioNodeもあります。
getUserMediaで取得したMediaStreamをWeb Audio APIで処理してWebRTCに戻すには
上記の事から、Web Audio APIがMediaStreamを入出力できればWebRTCに処理を挟めそうですね。
以下の2つがそれに該当します。

MediaStreamAudioSourceNode
MediaStreamを入力先にできるAudioNode。
AudioContext#createMediaStreamSource()で取得。
(Working Draftに載っています。)

MediaStreamAudioDestinationNode
MediaStreamを出力先にできるAudioNode。
AudioContext#createMediaStreamDestination()で取得。
MediaStreamAudioDestinationNode#streamからMediaStreamを取得可能。
(まだ、Editor's Draftにしか載っていません。)

今回は、ノイズ除去を行うためにローパスフィルタを使ってみました。

BiquadFilterNode
双2次フィルタを扱うためのAudioNode。
AudioContext#createBiquadFilter()で取得。
今回はノイズ除去用のローパスフィルタとして使用。
getUserMediaから取得したMediaStreamをWeb Audio APIに渡す
まず、MediaStreamをWebAudio APIで処理してみます。
スピーカーに直接音を渡すAudioContext.destinationに接続すると、正常に音がWeb Audio APIに渡っているのが確認できます。
var audioContext = new webkitAudioContext();
var mediastreamsource;

var lowpassfilter = audioContext.createBiquadFilter();
lowpassfilter.type = 0;
lowpassfilter.frequency.value = 440;

function initialize() {
    navigator.webkitGetUserMedia(
        {audio : true},
        function(stream) {
            mediastreamsource = audioContext.createMediaStreamSource(stream);
            mediastreamsource.connect(lowpassfilter);
            lowpassfilter.connect(audioContext.destination);
        },
        function(e) {
            console.log(e);
        }
    );
}

window.addEventListener("load", initialize, false);
Web Audio APIからMediaStreamを取り出しaudio要素に設定
実は上手く動作しません。
大音量のノイズが再生されることがあるので注意が必要です。
再読込やCanaryの再起動等を何度か繰り返していると、たまにマイクの音がスピーカーから出力されることがあります。
出力されるのは正常な音ではなくブチブチ途切れるような音ですが、それでもWeb Audio APIからMediaStreamを取り出す事ができました。
正常に動作しないのは、まだ実装途中で不安定だからなのでしょう。
var audioContext = new webkitAudioContext();
var mediastreamsource;
var mediastreamdestination = audioContext.createMediaStreamDestination();

var lowpassfilter = audioContext.createBiquadFilter();
lowpassfilter.type = 0;
lowpassfilter.frequency.value = 440;

var audioElement;

function initialize() {

    audioElement = document.getElementById("audio");

    navigator.webkitGetUserMedia(
        {audio : true},
        function(stream) {
            mediastreamsource = audioContext.createMediaStreamSource(stream);
            mediastreamsource.connect(lowpassfilter);
            lowpassfilter.connect(mediastreamdestination);
            audioElement.src = webkitURL.createObjectURL(mediastreamdestination.stream);
            audioElement.play();
        },
        function(e) {
            console.log(e);
        }
    );

}

window.addEventListener("load", initialize, false);
まとめと所感
MediaStreamをWeb Audio APIで扱えることは確認できましたが、Web Audio APIからMediaStreamへ出力する部分はまだ正常に動作しませんでした。
Working DraftにもなっていないEditor's Draftなので致し方ありませんが、まともに使えるようになるにはまだ時間がかかりそうです。

音声チャット時に音声処理ができるようになると、ノイズリダクションやノイズキャンセラの可能性が出てきます。
また、音声送信前にボイスチェンジャーのようなことができるようにもなるため、匿名性を保った状態でボイスチャットを行えるようになる等の応用が考えられます。
映像に関しての同じような仕様がないか調べると、MediaStream Processing APIというDraftの中にHTMLCanvasElement#canvasというものが見つかりました。
実環境上で、canvas要素にstream属性がないか調べてみましたが、見当たりませんでした。
MediaStream Processing APIについては、以下の記事で触れられていますが、使えるようになるにはまだまだ時間がかかりそうです。

WebRTCとWeb Audio APIを使って「声が遅れて聞こえてくるよ」を実装しました。

表題の通り。
説明いらないよね?

2013年04月22日

WebRTCのgetUserMediaから取得した音声をWeb Audio APIのAnalyserにかけてみた

マイクから入力された音声の波形がブラウザ上でリアルタイムで表示されるの楽しいです。
仕様策定中のAPIを使っています。
現時点ではChromeのみ対応。
こんな感じで表示されます。

2013年04月30日

FirefoxOS端末がなかなか販売再開しないので、販売再開した気分に浸れるグリモン書いた

Google

タグ クラウド