40
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WebRTCAdvent Calendar 2014

Day 10

WebRTCで「ピー」をやってみる

Last updated at Posted at 2014-12-09

ちょっとお遊びで、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を渡す点に注意が必要です。

RTCPeerConnection初期化
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に組み合わせて、例えば、音楽ファイルがあれば保留音を相手に聞こえるようにする、等の使い方ができます。色々とお試しあれ。

40
39
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?