WebRTC + Web Audio API = スーパーサイヤ人

8,342 views
8,210 views

Published on

なれる!スーパーサイヤ人!
あなたもこれでスーパーサイヤ人になれる!

コンテンツはこちら
http://girigiribauer.com/dragonball-super-saiyan/

内部で、WebRTC (getUserMedia), Web Audio API, Canvasなどの紹介をしてます

Published in: Technology

WebRTC + Web Audio API = スーパーサイヤ人

  1. 1. WebRTC + Web Audio API = スーパーサイヤ人 2013/02/23 #daiNagoyaJS vol.513年2月23日土曜日
  2. 2. いつもぎりぎり、 @girigiribauerです13年2月23日土曜日
  3. 3. 本日のネタは、 大なごやJS Vol.3で 話したネタの 完全版です13年2月23日土曜日
  4. 4. 今日話す内容13年2月23日土曜日
  5. 5. 今日話す内容 1. 作ってきたコンテンツの概要 2. デモ 3. WebRTC, Web Audio API などの話 4. まとめ13年2月23日土曜日
  6. 6. 13年2月23日土曜日
  7. 7. 今日話す内容 1. 作ってきたコンテンツの概要 2. デモ 3. WebRTC, Web Audio API などの話 4. まとめ13年2月23日土曜日
  8. 8. WebRTC +13年2月23日土曜日
  9. 9. WebRTC + Web Audio API =13年2月23日土曜日
  10. 10. WebRTC + Web Audio API = スーパーサイヤ人13年2月23日土曜日
  11. 11. ドラゴンボールとは • みんな大好きドラゴンボール • サイヤ人は、金色の髪のスーパーサイ ヤ人に変身する • 変身すると 強くなるのは 男のロマン 映画あるよ! http://www.dragonball2013.com/13年2月23日土曜日
  12. 12. スーパーサイヤ人に なってみたかった13年2月23日土曜日
  13. 13. 元ネタ13年2月23日土曜日
  14. 14. • im a super saiyan http://www.youtube.com/watch?v=lIv88cC86r013年2月23日土曜日
  15. 15. • im a super saiyan http://www.youtube.com/watch?v=lIv88cC86r013年2月23日土曜日
  16. 16. • im a super saiyan http://www.youtube.com/watch?v=lIv88cC86r013年2月23日土曜日
  17. 17. • im a super saiyan http://www.youtube.com/watch?v=lIv88cC86r013年2月23日土曜日
  18. 18. • im a super saiyan http://www.youtube.com/watch?v=lIv88cC86r013年2月23日土曜日
  19. 19. • im a super saiyan http://www.youtube.com/watch?v=lIv88cC86r013年2月23日土曜日
  20. 20. • im a super saiyan http://www.youtube.com/watch?v=lIv88cC86r013年2月23日土曜日
  21. 21. • im a super saiyan http://www.youtube.com/watch?v=lIv88cC86r013年2月23日土曜日
  22. 22. respect! • im a super saiyan http://www.youtube.com/watch?v=lIv88cC86r013年2月23日土曜日
  23. 23. 全力投球の 中二病は coolだと思う13年2月23日土曜日
  24. 24. そして前回・・・13年2月23日土曜日
  25. 25. リベンジネタ • 実は大なごやJS Vol.3 でやったネタ (2012/07/21) • 前回は、ホントに軽く作ってみた13年2月23日土曜日
  26. 26. リベンジネタ • あれ、音声がとれない → まだ未実装 • (本番当日) 「ク、クリックで・・・ 代用しました・・・」13年2月23日土曜日
  27. 27. 13年2月23日土曜日
  28. 28. 13年2月23日土曜日
  29. 29. まさかのクリック13年2月23日土曜日
  30. 30. ユーザー体験と しては 0点13年2月23日土曜日
  31. 31. それも 今や昔の話・・・13年2月23日土曜日
  32. 32. 君もなれる! スーパーサイヤ人に!13年2月23日土曜日
  33. 33. 13年2月23日土曜日
  34. 34. 今日話す内容 1. 作ってきたコンテンツの概要 2. デモ 3. WebRTC, Web Audio API などの話 4. まとめ13年2月23日土曜日
  35. 35. デモ • なれる!スーパーサイヤ人! http://girigiribauer.com/dragonball-super-saiyan/13年2月23日土曜日
  36. 36. 満 足13年2月23日土曜日
  37. 37. 13年2月23日土曜日
  38. 38. 今日話す内容 1. 作ってきたコンテンツの概要 2. デモ 3. WebRTC, Web Audio API などの話 4. まとめ13年2月23日土曜日
  39. 39. 使用した主なAPIなど •WebRTC (getUserMedia) • Web Audio API • Canvas13年2月23日土曜日
  40. 40. このあたりの話を ピンポイントで 抜粋して紹介13年2月23日土曜日
  41. 41. 使用した主なAPIなど •WebRTC (getUserMedia) • Web Audio API • Canvas13年2月23日土曜日
  42. 42. WebRTC (getUserMedia) • RTCは、Real Time Communication の略 • その中の getUserMedia は、 ローカルにあるカメラ、マイクに アクセスできる13年2月23日土曜日
  43. 43. 対応状況 (※2013/02/23時点) • http://caniuse.com/stream13年2月23日土曜日
  44. 44. 対応状況 (※2013/02/23時点) • Chrome, Operaに続いて Firefoxも getUserMedia が使える! • Firefoxはabout:configのフラグ付き • IEは、そもそもCU-RTC-Webという 別仕様を推進してる (CU: Customizable, Ubiquitous)13年2月23日土曜日
  45. 45. getUserMedia の 基本的な使い方 • navigatorオブジェクトにある getUserMedia メソッド • 引数を3つ取る • 1つ目は、デバイスの種別指定のオブ ジェクト(テキストではない)13年2月23日土曜日
  46. 46. getUserMedia の 基本的な使い方 • 2つ目は、ローカルデバイスに アクセスが出来たときに生成される、 mediaStream オブジェクトを 引数にもつ、コールバック関数 • 3つ目は、上記失敗したときの コールバック関数13年2月23日土曜日
  47. 47. getUserMedia の 基本的な使い方 • そこまで複雑じゃない、数行レベル • クロスブラウザな書き方は、 navigator.getUserMediaに対して 上書きできないので、 ちょっと工夫する13年2月23日土曜日
  48. 48. getUserMedia の 基本的な使い方 var getUserMedia = function(t, onsuccess, onerror) { if (navigator.getUserMedia) { return navigator.getUserMedia(t, onsuccess, onerror); } else if (navigator.webkitGetUserMedia) { return navigator.webkitGetUserMedia(t, onsuccess, onerror); } else if (navigator.mozGetUserMedia) { return navigator.mozGetUserMedia(t, onsuccess, onerror); } else if (navigator.msGetUserMedia) { return navigator.msGetUserMedia(t, onsuccess, onerror); } else { throw new Error(No getUserMedia implementation found.); } }; • navigator.getUserMediaごと返す • あとはfunctionでラッピングするなり13年2月23日土曜日
  49. 49. getUserMedia の 基本的な使い方 • デバイスへの接続がうまくいった後、 とりあえず表示させるまでの話 (前回の資料をさらっと再紹介)13年2月23日土曜日
  50. 50. 取得した LocalMediaStream オブジ ェクトをきちんと表示するところまで (1) • canvas要素を作る、もしくは予め作っ た要素を参照する • var canvas = document.getElementById(canvas); var context = canvas.getContext(2d);13年2月23日土曜日
  51. 51. 取得した LocalMediaStream オブジ ェクトをきちんと表示するところまで (2) • createObjectURL にさっきの LocalMediaStream オブジェクトを ぶちこんで、BlobURL(リソースを参 照してる)を取得する • var videoUrl = createObjectURL(stream);13年2月23日土曜日
  52. 52. 取得した LocalMediaStream オブジ ェクトをきちんと表示するところまで (2) • デバイスをBlobURLとして受け取るこ とで、同様のインターフェースで扱え る(URL参照 ≒ デバイス参照) • Blobは Binary Large OBject の略、 FileAPI 周りでよく使われてる13年2月23日土曜日
  53. 53. 取得した LocalMediaStream オブジ ェクトをきちんと表示するところまで (3) • video タグの src 属性に、 さっきの BlobURL をつっこむ • var video = document.getElementById(video); video.src = videoUrl; video.autoplay = true; • ※autoplay 属性がないと最初の1コマ だけで止まっちゃうのでつける • 単に表示のみなら、ここまででOK13年2月23日土曜日
  54. 54. 取得した LocalMediaStream オブジ ェクトをきちんと表示するところまで (4) • あとは連続して canvas に video 要 素を反映してやるだけ • var render = function() { context.drawImage(video, 0, 0, w, h); requestAnimationFrame(render); }; requestAnimationFrame(render);13年2月23日土曜日
  55. 55. video は分かった では audio は?13年2月23日土曜日
  56. 56. その前に、 Web Audio API を考える必要がある13年2月23日土曜日
  57. 57. 使用した主なAPIなど •WebRTC (getUserMedia) • Web Audio API • Canvas13年2月23日土曜日
  58. 58. Web Audio API • 文字通り、Web の Audio の API • ノードというオブジェクト同士を つなぎ合わせることで制御する • 中にはAnalyserノード、数値として 解析できちゃうものもある • 仕様が幅広くて、まだまだ全容把握で きてない13年2月23日土曜日
  59. 59. 対応状況 (※2013/02/23時点) • http://caniuse.com/audio-api13年2月23日土曜日
  60. 60. 対応状況 (※2013/02/23時点) • Chrome, Safari, iOS Safari が使える • つい数日前に、Firefox Nightly にて Web Audio API がフラグ付きで導入 • Firefox21 か 22 あたりで Web Audio API が正式実装される?13年2月23日土曜日
  61. 61. 対応状況 (※2013/02/23時点) • Firefox では、about:config から media.webaudio.enabled を true に • ただし、Firefoxはまだ完全じゃないと ころもある(詳しくは後述)13年2月23日土曜日
  62. 62. Web Audio API で 今回やりたいこと • 今回やりたいのは、 入力から数値として取れるところまで • 出力側は必ずしも必要ではない • ライブ入力の音声を、リアルタイムに 周波数として取れれば良いので、 AnalyserNode を使えばOK13年2月23日土曜日
  63. 63. 少し戻って・・・13年2月23日土曜日
  64. 64. 前回の資料より13年2月23日土曜日
  65. 65. ここでようやく 今回のキモ13年2月23日土曜日
  66. 66. WebRTC +13年2月23日土曜日
  67. 67. WebRTC + Web Audio API =13年2月23日土曜日
  68. 68. WebRTC + Web Audio API = スーパーサイヤ人13年2月23日土曜日
  69. 69. WebRTC + Web Audio API = スーパーサイヤ人 (=ライブ音声入力)13年2月23日土曜日
  70. 70. ドコとドコが 繋がっているの? • 先ほどの getUserMedia で出てきた mediaStream オブジェクトを対象の メソッドに渡して連携させる • video側は、 createObjectURL(stream) を使って BlobURLを取得し、video.src として 利用していた13年2月23日土曜日
  71. 71. ドコとドコが 繋がっているの? • audio側は、AudioContext オブジェ クトを用いる • audio周りの処理が、AudioContext オブジェクトのメソッドを介して行わ れる • なので、まず AudioContext を作る • var context = getAudioContext();13年2月23日土曜日
  72. 72. ドコとドコが 繋がっているの? • video側の createObjectURL(stream) の、audio側に相当しているものは、 context.createMediaStreamSource(s tream) • 意味はそのまんま、mediaStream を 入力として作ります、と書いてある • 2つの仕様が連携することで、逆に videoよりもシンプルで分かりやすい13年2月23日土曜日
  73. 73. ライブ音声入力の 周波数ごとの値を 取得できる ところまでの流れ13年2月23日土曜日
  74. 74. 取得した LocalMediaStream オブジェクトを、値として処理 できるところまで (1) var context = getAudioContext(); var source = context.createMediaStreamSource(stream); var audioAnalyser = context.createAnalyser(); var audioAnalyzedData = new Uint8Array(audioAnalyser.frequencyBinCount); source.connect(audioAnalyser); audioAnalyser.getByteFrequencyData(audioAnalyzedData); • AudioContext を作る13年2月23日土曜日
  75. 75. 取得した LocalMediaStream オブジェクトを、値として処理 できるところまで (2) var context = getAudioContext(); var source = context.createMediaStreamSource(stream); var audioAnalyser = context.createAnalyser(); var audioAnalyzedData = new Uint8Array(audioAnalyser.frequencyBinCount); source.connect(audioAnalyser); audioAnalyser.getByteFrequencyData(audioAnalyzedData); • AudioContext に対して、 createMediaStreamSource メソッド を呼ぶと、 MediaStreamAudioSourceNode とい う 出力用のノードが取得できる13年2月23日土曜日
  76. 76. 取得した LocalMediaStream オブジェクトを、値として処理 できるところまで (3) var context = getAudioContext(); var source = context.createMediaStreamSource(stream); var audioAnalyser = context.createAnalyser(); var audioAnalyzedData = new Uint8Array(audioAnalyser.frequencyBinCount); source.connect(audioAnalyser); audioAnalyser.getByteFrequencyData(audioAnalyzedData); • 先ほどとは別に、 AudioContext に対して createAnalyser メソッドを呼ぶと、 AnalyserNode という、音データの解 析ができるノードが取得できる13年2月23日土曜日
  77. 77. 取得した LocalMediaStream オブジェクトを、値として処理 できるところまで (4) var context = getAudioContext(); var source = context.createMediaStreamSource(stream); var audioAnalyser = context.createAnalyser(); var audioAnalyzedData = new Uint8Array(audioAnalyser.frequencyBinCount); source.connect(audioAnalyser); audioAnalyser.getByteFrequencyData(audioAnalyzedData); • (今すぐ必要ではないけど、) あらかじめ周波数分のUint8Array型の 型付き配列(Typed Array)を 作っておく • ただの配列でも良いけど、速度の問題13年2月23日土曜日
  78. 78. 取得した LocalMediaStream オブジェクトを、値として処理 できるところまで (5) var context = getAudioContext(); var source = context.createMediaStreamSource(stream); var audioAnalyser = context.createAnalyser(); var audioAnalyzedData = new Uint8Array(audioAnalyser.frequencyBinCount); source.connect(audioAnalyser); audioAnalyser.getByteFrequencyData(audioAnalyzedData); • source は出力オンリーなので、 audioAnalyserノードの入力につなぐ • mediaStream オブジェクトから、 audioAnalyserノードの入力までが つながった13年2月23日土曜日
  79. 79. 取得した LocalMediaStream オブジェクトを、値として処理 できるところまで (6) var context = getAudioContext(); var source = context.createMediaStreamSource(stream); var audioAnalyser = context.createAnalyser(); var audioAnalyzedData = new Uint8Array(audioAnalyser.frequencyBinCount); source.connect(audioAnalyser); audioAnalyser.getByteFrequencyData(audioAnalyzedData); • audioAnalyserノードの getByteFrequencyData メソッドを 任意のタイミングで呼ぶことで、 型付き配列 audioAnalyzedData に 毎回データが入る13年2月23日土曜日
  80. 80. 取得した LocalMediaStream オブジェクトを、値として処理 できるところまで (7) • 後はただの配列に対する処理 • 今回のコンテンツでは、簡素化するた めに周波数ごとの平均値を取り、それ を時間軸に対しても平均化 (一瞬だけ音がでかくなることがある のを反応しないようにならす) • 平均化された数値をしきい値と比較13年2月23日土曜日
  81. 81. Web Audio API • まだまだ機能は豊富にあるけど、 きりがないので一旦この辺で・・・ • AnalyserNode だけでも、 色々応用考えられそう • 例:音声入力だけで操作するゲーム • 例:絶対音感を再現するとか13年2月23日土曜日
  82. 82. おまけ • Q. Firefoxではライブ音声入力できな いの? • A. まだAudioContext のメソッドが 足りないっぽいです13年2月23日土曜日
  83. 83. おまけ • context.create MediaStreamS ource がないで すね・・・ • これがないと、 ライブ音声入力 をつなぐことが 出来ません13年2月23日土曜日
  84. 84. 使用した主なAPIなど •WebRTC (getUserMedia) • Web Audio API • Canvas13年2月23日土曜日
  85. 85. Canvas • 前回もちょっと使ったけど、今回は よりCanvasに向いている表現にトライ • 気が溜まっていく表現は、下から上に 放射線上に変化していってほしい • (ここから先はおまけです)13年2月23日土曜日
  86. 86. Canvas • 先行して検証用コンテンツを 作ってみた • radical arrow http://jsdo.it/pypupypa/radical-arrow13年2月23日土曜日
  87. 87. Canvas13年2月23日土曜日
  88. 88. Canvas における save(), restore() • 自分も最初に Canvas を触ったころ、 勘違いして理解できなかったところ • context.save() は、Canvasのピクセ ル情報を保持するのではなく、 contextを保持する • ここでいうcontextの保持とは、 Canvasの回転、変形具合や色など13年2月23日土曜日
  89. 89. Canvas における save(), restore() • 実はこの矢印の座標計算、x軸を プラスにすることだけやっている • 回転角度から、sin, cosを使って x, yがいくつで、次の移動が・・・ みたいなことはやってない13年2月23日土曜日
  90. 90. Canvas における save(), restore() context.save(); ... context.translate(canvasWidth / 2, canvasHeight / 2); context.rotate(rad); context.translate(-canvasWidth / 2, -canvasHeight / 2); context.drawImage(image, x, y); ... context.restore(); • まず context.save() で 今のcontext を保存しておく(あとで戻すため)13年2月23日土曜日
  91. 91. Canvas における save(), restore()13年2月23日土曜日
  92. 92. Canvas における save(), restore() context.save(); ... context.translate(canvasWidth / 2, canvasHeight / 2); context.rotate(rad); context.translate(-canvasWidth / 2, -canvasHeight / 2); context.drawImage(image, x, y); ... context.restore(); • context に対して様々な処理をして drawImage で矢印を描画する13年2月23日土曜日
  93. 93. Canvas における save(), restore()13年2月23日土曜日
  94. 94. Canvas における save(), restore() context.save(); ... context.translate(canvasWidth / 2, canvasHeight / 2); context.rotate(rad); context.translate(-canvasWidth / 2, -canvasHeight / 2); context.drawImage(image, x, y); ... context.restore(); • context.restore() を呼ぶと、context に対して回転や移動などの処理をする前 の状態に戻る • 元通りの座標に戻るので、オブジェクト ごとに処理が固定化できる13年2月23日土曜日
  95. 95. Canvas における save(), restore()13年2月23日土曜日
  96. 96. Canvas その他 • 一定フレームごとの描画処理で、 前に描いたものに対して、半透明の背 景色で塗りつぶすと、残像っぽくなる • これだけたくさんのオブジェクトを DOM要素でやったらたぶんつらい (つらそうなのでやってない)13年2月23日土曜日
  97. 97. エフェクトも それなりに13年2月23日土曜日
  98. 98. 13年2月23日土曜日
  99. 99. 13年2月23日土曜日
  100. 100. 13年2月23日土曜日
  101. 101. すげーそれっぽい!13年2月23日土曜日
  102. 102. エンジニアでも これくらいまでなら 誰でもできるはず13年2月23日土曜日
  103. 103. 今日話す内容 1. 作ってきたコンテンツの概要 2. デモ 3. WebRTC, Web Audio API などの話 4. まとめ13年2月23日土曜日
  104. 104. リアルタイムWeb! • リアルタイムに色々できるように なってきた、素敵な時代 • ブラウザの進化すごい13年2月23日土曜日
  105. 105. ライブ音声入力 • 声というユーザーインターフェース • Web Audio API は、 いじりがいがありそう13年2月23日土曜日
  106. 106. くだらないことに 全力投球するの楽しい • 元ネタは、茶化すわけではなくて 本当にリスペクトしてる • あそこまで熱くなれるものを、 なんとかして他の人にも体験させられ ないだろうか? • 体験の共有13年2月23日土曜日
  107. 107. これからも くだらないことに 全力投球でいきます!13年2月23日土曜日
  108. 108. ありがとう ございました!13年2月23日土曜日

×