Web の利点は複数の技術をまとめて、新しいものを作れる点です。ネィティブの音声や動画をブラウザ上で利用できるということは、これらのデータストリームを <canvas>
、WebGL、Web Audio API を利用して操作することで、音声や動画を直接変更できることを意味します。例えば音声にリバーブやコンプレッションをかけたり、動画にグレイスケールやセピアのフィルタをかけたりできます。
動画の操作
動画中の各フレームに含まれる各ピクセルの情報を読み取ることが可能です。
Video 要素と Canvas 要素
<canvas>
は Web ページ上で描画を行うための有用な方法です。これは強力で、動画の処理にも有用です。
一般的なテクニックは次のようになります:
<video>
要素から取得される動画の各フレームを、<canvas>
要素に即座に描画します。- <canvas> からデータを取得し、それを操作します。
- 操作したデータを <canvas> を通じて描画し、表示します。
- これを繰り返します。
動画プレーヤーと、<canvas> 要素は次のように記述します。
<video id="my-video" controls="true" width="480" height="270"> <source src="https://jplayer.org/video/webm/Big_Buck_Bunny_Trailer.webm" type="video/webm"> <source src="https://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v" type="video/mp4"> </video> ... <canvas id="my-canvas" width="480" height="270"></canvas>
操作は以下のように行います。この例では動画を白黒に変換しています:
var processor = { timerCallback: function() { if (this.video.paused || this.video.ended) { return; } this.computeFrame(); var self = this; setTimeout(function () { self.timerCallback(); }, 16); // roughly 60 frames per second }, doLoad: function() { this.video = document.getElementById("my-video"); this.c1 = document.getElementById("my-canvas"); this.ctx1 = this.c1.getContext("2d"); var self = this; this.video.addEventListener("play", function() { self.width = self.video.width; self.height = self.video.height; self.timerCallback(); }, false); }, computeFrame: function() { this.ctx1.drawImage(this.video, 0, 0, this.width, this.height); var frame = this.ctx1.getImageData(0, 0, this.width, this.height); var l = frame.data.length / 4; for (var i = 0; i < l; i++) { var grey = (frame.data[i * 4 + 0] + frame.data[i * 4 + 1] + frame.data[i * 4 + 2]) / 3; frame.data[i * 4 + 0] = grey; frame.data[i * 4 + 1] = grey; frame.data[i * 4 + 2] = grey; } this.ctx1.putImageData(frame, 0, 0); return; } };
ページロード後に、次の関数を呼び出します。
processor.doLoad()
注意:潜在的なセキュリティ上の問題により、動画がコードと異なるドメインより配信されている場合、動画を配信しているサーバで CORS (Cross Origin Resource Sharing) を有効にする必要があります。
付記:上記の例は、動画を canvas で操作するためだけのものです。対応しているブラウザであれば setTimeout の代わりに requestAnimationFrame を利用することを効率のために検討したほうがよいでしょう。
動画と WebGL
WebGL は canvas に三次元画像を描画できる強力な API です。<video>
要素と組み合わせることで、動画をテクチャとして利用できます。つまり三次元空間上に動画を配置し、再生できます。
再生レート
音声や動画の再生レートは <audio>
もしくは <video>
要素の playbackRate
属性で指定できます(HTMLMediaElement
を参照のこと)。playbackRate
には再生スピードの倍率を指定します。例えば 0.5 を指定すると半分のスピードで、2 を指定すると倍速で再生されます。
HTML:
<video id="my-video" controls src="https://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v"></video>
JavaScript:
var myVideo = document.getElementById('my-video'); myVideo.playbackRate = 2;
注意 : playbackRate
は <audio> 要素と <video> 要素で利用できます。ただし再生スピードを変更できますが、ピッチは変更できません。音声のピッチを変更は、Web Audio API を利用すると可能です。詳しくは AudioBufferSourceNode.playbackRate
属性をご覧ください。
音声の操作
音声を操作するためには、Web Audio API を利用することが一般的です。
音源の選択
<audio>
要素、もしくは <video>
要素の音声トラックを Web Audio API で操作する音源として利用できます。またオーディオバッファ、サインウェーブのようなオシレータからの出力、WebRTC や getUserMedia からの音声ストリームも音源とできます。具体的な方法については以下のページを参照してください。
音声フィルタ
Web Audio API では BiquadFilterNode
を利用することで様々なフィルタやイフェクタを利用できます。
HTML:
<video id="my-video" controls src="myvideo.mp4" type="video/mp4"></video>
JavaScript:
var audioSource = context.createMediaElementSource(document.getElementById("my-video")); var filter = context.createBiquadFilter(); audioSource.connect(filter); filter.connect(context.destination);
注意: CORS が有効になっていない環境では、動画はコードと同じドメイン上になければなりません。これはセキュリティ上の問題を避けるためです。
このノードでよく利用されるフィルタは以下の通りです:
- ローパスフィルタ:閾値に指定された周波数より低い音は通過させ、高いものは減衰させます
- ハイパスフィルタ:閾値に指定された周波数より高い音は通過させ、低いものは減衰させます
- バンドパスフィルタ:指定された周波数帯の音は通過させ、それ以外は減衰させます
- ローシェルフフィルタ:周波数に関わらず全ての音を通過させますが、閾値より低いものは増幅(もしくは減衰)されます
- ハイシェルフフィルタ:周波数に関わらず全ての音を通過させますが、閾値より高いものは増幅(もしくは減衰)されます
- ピーキングフィルタ:周波数に関わらず全ての音を通過させますが、指定された周波数帯のものは増幅(もしくは減衰)されます
- ノッチフィルタ:指定された周波数帯を除き、全ての音を通過させます
- オールパスフィルタ:周波数に関わらず全ての音を通過させますが、幾つかの周波数間の相関係を変更します
例:
var filter = context.createBiquadFilter(); filter.type = "lowshelf"; filter.frequency.value = 1000; filter.gain.value = 25;
付記:詳しくは BiquadFilterNode
を参照してください。
たたみ込みとインパルス
ConvolverNode
を利用することで、音声にインパルス応答を適用できます。インパルス応答とはハンドクラッフのような短い音のインパルスから作成された音のことです。インパルス応答はインパルスが作られた環境、例えばトンネル内で手を叩くことでエコーが起きる、を示します。
例:
var convolver = context.createConvolver(); convolver.buffer = this.impulseResponseBuffer; // Connect the graph. source.connect(convolver); convolver.connect(context.destination);
付記:詳しくは ConvolverNode
を参照してください。
空間的な音
Panner ノードを利用することで、音源の位置を操作できます。ソースコーンの位置だけでなく、その方向も指定できます。位置や方向は三次元空間上で指定します。
例:
var panner = context.createPanner(); panner.coneOuterGain = 0.2; panner.coneOuterAngle = 120; panner.coneInnerAngle = 0; panner.connect(context.destination); source.connect(panner); source.start(0); // Position the listener at the origin. context.listener.setPosition(0, 0, 0);
付記: 詳細は ConvolverNode
を参照してください。
JavaScript によるコーデックの実装
JavasCript でより低レベルでの音声操作が可能です。これを利用することで、オーディオコーデックを自作できます。
以下にフォーマットとそのコーデックのリストを示します:
利用例
- Various Web Audio API (and other) examples
- THREE.js Video Cube example
- Convolution Effects in Real-Time
チュートリアル
- Manipulating Video Using Canvas
- HTML5 playbackRate explained
- Using the Web Audio API
- Web audio spatialisation basics
- Using Video frames as a WebGL Texture (You can also the THREE.js WebGL library (and others) to achieve this effect)
- Animating Textures in WebGL
- Developing Game Audio with the Web Audio API (Room effects and filters)
レファレンス
- The
<audio>
and<video>
elements - The
HTMLMediaElement
API - The
<canvas>
element - Web Audio API
- AudioContext
- More info on Spatial Audio