ちょっとお遊びで、WebRTCの音声通話で、音声の途中で都合の悪い言葉を隠すのに「ピー」という音を入れることができるようになる方法を試してみます(笑)。
Chrome for Androidでは残念ながら動作しないようです。
(参考: http://caniuse.com/#search=web%20audio )
まずはマイクの音声をキャプチャ
お約束のnavigator.getUserMedia()
です。
var mic;
navigator.getUserMedia =
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
navigator.getUserMedia(
{ audio: true },
function(s) { mic = s; },
function(e) { console.log(e); }
);
「ピー」を作る
「ピー」という音を、今回はWeb Audio APIを使って作ってみます。正弦波のオシレータを使えば、十分それっぽい雰囲気が出るのではと思います。
var context = window.AudioContext || window.webkitAudioContext;
var ctx = new context();
var osc = context.createOscillator();
osc.frequency.value = 880 * Math.pow(2,2/12); // シの音階(ラの音階より全音上)
マイクと「ピー」をミキシング
まず、WebRTC Advent Calendar 9日目のgetUserMedia使ってJSで動くチューナー作った。の記事と同様に、マイクの入力ノードをcreateMediaStreamSource()
で取り出します。
その後、マイクと「ピー」のそれぞれの音量をコントロールするゲインノードを作って接続し、それらをcreateMediaStreamDestination()
で生成した出力ノードに接続してミキシング、という順序になります。
var micNode = context.createMediaStreamSource(mic);
var micGain, oscGain;
if(context.createGain) {
micGain = context.createGain();
oscGain = context.createGain();
}
else {
// 多分不要だと思われますが、念のため古いWeb Audio APIへの対処
micGain = context.createGainNode();
oscGain = context.createGainNode();
}
micNode.connect(micGain);
osc.connect(oscGain);
// まずはマイクを鳴らして「ピー」をミュート
micGain.gain.value = 1;
oscGain.gain.value = 0;
// ミキシング
var output = context.createMediaStreamDestination();
micGain.connect(output);
oscGain.connect(output);
if(osc.start)
osc.start(0);
else
// 多分不要だと思われますが、念のため古いWeb Audio APIへの対処
osc.noteOn(0);
いよいよWebRTC
さて、いよいよWebRTCの初期化です。ここでは詳細は省かせていただいて、要点に絞って説明します。
RTCPeerConnection
の初期化やoffer/answerのやりとり等は通常の手順と同様で、RTCPeerConnection.addStream()
で渡すストリームだけ変えればよい、ということになります。
ひとまず、通常と同じようにRTCPeerConnectionインスタンスを生成し、必要な初期化を行います。
そして、addStream()
で、先ほど生成したミキシングの出力ノードのストリームをここに渡せばよい、ということになります。output
自体ではなく、output.stream
を渡す点に注意が必要です。
var PC =
window.RTCPeerConnection ||
window.webkitRTCPeerConnection ||
window.mozRTCPeerConnection;
var peer = new PC({ iceServers: [ { ... } ] });
peer.onicecandidate = function(ice) { ... };
// ミキシングの出力ノードのストリームをRTCPeerConnectionに追加
peer.addStream(output.stream);
あとは、引き続きoffer/answerを経てセッションを確立させれば、いつもどおりWebRTCで通話ができるようになるわけですが、ここでもう少々細工をして、好きなタイミングでマイクの音声の代わりに「ピー」が相手に聞こえるようにしてみます。ここでは「P」キーを押している間はマイクがミュートされて「ピー」が相手に聞こえる、というようにしています。
function startCensor(evt) {
if(evt.keyCode == 'P'.charCodeAt(0)) {
micGain.gain.value = 0;
oscGain.gain.value = 1;
}
}
function stopCensor(evt) {
if(evt.keyCode == 'P'.charCodeAt(0)) {
micGain.gain.value = 1;
oscGain.gain.value = 0;
}
}
document.addEventListener('keydown', startCensor, false);
document.addEventListener('keyup', stopCensor, false);
...というわけで、WebRTC音声チャットで「ピー」、という非常にくだらない使い道を例として(笑)、WebRTCにWeb Audio APIを組み合わせる方法、でした。
この他にも、Web Audio APIをWebRTCに組み合わせて、例えば、音楽ファイルがあれば保留音を相手に聞こえるようにする、等の使い方ができます。色々とお試しあれ。