aboutsummaryrefslogtreecommitdiff
path: root/files/ja/web/guide/audio_and_video_manipulation/index.html
blob: 6518a4dcd78bf4e9dedb1a7b07055bbf59ee8d20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
---
title: 音声と動画の加工
slug: Web/Guide/Audio_and_video_manipulation
tags:
  - Audio
  - Canvas
  - Examples
  - Guide
  - HTML5
  - Media
  - Video
  - Web Audio API
  - WebGL
  - developer recommendation
translation_of: Web/Guide/Audio_and_video_manipulation
---
<div class="summary">
<p>ウェブのよいところは、複数の技術をまとめて新しいものを作ることができる点です。ネイティブの音声や動画をブラウザー上で利用できるということは、これらのデータストリームを {{htmlelement("canvas")}}<a href="/ja/docs/Web/WebGL">WebGL</a><a href="/ja/docs/Web/API/Web_Audio_API">Web Audio API</a> を利用して操作することで、音声や動画に直接変更を加えることができることを意味します。例えば音声にリバーブやコンプレッション効果をかけたり、動画にグレイスケールやセピアのフィルターをかけたりすることができます。この記事では、必要なことを説明するためのリファレンスを提供します。</p>
</div>

<h2 id="Video_manipulation" name="Video_manipulation">動画の加工</h2>

<p>動画の各フレームからピクセルの値を読むことができることは、とても有用です。</p>

<h3 id="Video_and_canvas" name="Video_and_canvas">動画とキャンバス</h3>

<p>{{htmlelement("canvas")}} 要素はウェブページ上でグラフィックを描画するための平面を提供します。これは強力で、動画の処理にも有用です。</p>

<p>一般的なテクニックは次のようになります。</p>

<ol>
 <li>{{htmlelement("video")}} 要素からのフレームを中間の {{htmlelement("canvas")}} 要素に描画します。</li>
 <li>中間の <code>&lt;canvas&gt;</code> 要素からデータを取得し、それを加工します。</li>
 <li>加工したデータを「画面」の <code>&lt;canvas&gt;</code> を通じて描画します。</li>
 <li>一時停止し、繰り返します。</li>
</ol>

<p>例えば、動画を処理してグレースケールで表示する場合を考えてみましょう。この場合、ソース動画と出力のグレースケールのフレームの両方を表示します。通常、「動画をグレースケールで再生」機能を実装する場合、 <code>display: none</code><code>&lt;video&gt;</code> 要素のスタイルに追加して、ソース動画が画面に描画されず、変更されたフレームのみが表示されるキャンバスが表示されるようにします。</p>

<h4 id="HTML">HTML</h4>

<p>動画プレイヤーと、 <code>&lt;canvas&gt;</code> 要素は次のように記述します。</p>

<pre class="brush: html notranslate">&lt;video id="my-video" controls="true" width="480" height="270" crossorigin="anonymous"&gt;
  &lt;source src="http://jplayer.org/video/webm/Big_Buck_Bunny_Trailer.webm" type="video/webm"&gt;
  &lt;source src="http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v" type="video/mp4"&gt;
&lt;/video&gt;

&lt;canvas id="my-canvas" width="480" height="270"&gt;&lt;/canvas&gt;</pre>

<h4 id="JavaScript">JavaScript</h4>

<p>このコードはフレームの加工を扱います。</p>

<pre class="brush: js notranslate">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 &lt; 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;
  }
};  </pre>

<p>ページの読み込み後に、次のように呼び出してください。</p>

<pre class="brush: js notranslate">processor.doLoad()</pre>

<h4 id="Result" name="Result">結果</h4>

<p>{{EmbedLiveSample("Video_and_canvas", '100%', 580)}}</p>

<p>これは、キャンバスを使用して動画フレームを加工する方法を示すとてもシンプルな例です。効率をよくするために、対応しているブラウザーで実行する場合は {{domxref("Window.requestAnimationFrame", "requestAnimationFrame()")}}<code>setTimeout()</code> の代わりに使用することを検討したほうがいいでしょう。</p>

<div class="note">
<p><strong></strong>: 潜在的なセキュリティ上の問題により、動画がコードと異なるドメインより配信されている場合、動画を配信しているサーバーで <a href="/ja/docs/Web/HTTP/Access_control_CORS">CORS (オリジン間リソース共有)</a> を有効にする必要があります。</p>
</div>

<h3 id="Video_and_WebGL" name="Video_and_WebGL">動画と WebGL</h3>

<p><a href="/ja/docs/Web/WebGL">WebGL</a> はキャンバスを使用してハードウェアアクセラレーションによる三次元や二次元の描画を行う強力な API です。 {{htmlelement("video")}} 要素と組み合わせることで、動画をテクチャとして利用できます。つまり三次元空間上に動画を配置し、再生できます。</p>

<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample8/index.html', 670, 510) }}</p>

<div class="note">
<p><strong></strong>: <a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample8">このデモのソースコードは GitHub</a> にあります (<a href="https://mdn.github.io/webgl-examples/tutorial/sample8/">ライブで表示</a>も)。</p>
</div>

<h3 id="Playback_rate" name="Playback_rate">再生速度</h3>

<p>音声や動画の再生速度は {{htmlelement("audio")}} もしくは {{htmlelement("video")}} 要素の {{domxref("HTMLMediaElement.playbackRate", "playbackRate")}} と呼ばれる属性を使用して調整することができます。 <code>playbackRate</code> には再生速度の倍率を指定します。例えば 0.5 を指定すると半分の速度で、 2 を指定すると倍速で再生されます。</p>

<p>なお、 <code>playbackRate</code> プロパティは <code>&lt;audio&gt;</code><code>&lt;video&gt;</code> の両方で動作しますが、どちらの場合も、再生速度を変更するものの音程は<em>変更しません</em>。音声の高さを変更するには、 Web Audio API を使用する必要があります。 {{domxref("AudioBufferSourceNode.playbackRate")}} プロパティを参照してください。</p>

<h4 id="HTML_2">HTML</h4>

<pre class="brush: html notranslate">&lt;video id="my-video" controls
       src="http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v"&gt;
&lt;/video&gt;</pre>

<h4 id="JavaScript_2">JavaScript</h4>

<pre class="brush: js notranslate">var myVideo = document.getElementById('my-video');
myVideo.playbackRate = 2;</pre>

<div class="hidden">
<h6 id="Playable_code" name="Playable_code">再生可能なコード</h6>

<pre class="brush: html notranslate">&lt;video id="my-video" controls="true" width="480" height="270"&gt;
  &lt;source src="http://jplayer.org/video/webm/Big_Buck_Bunny_Trailer.webm" type="video/webm"&gt;
  &lt;source src="http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v" type="video/mp4"&gt;
&lt;/video&gt;
&lt;div class="playable-buttons"&gt;
  &lt;input id="edit" type="button" value="Edit" /&gt;
  &lt;input id="reset" type="button" value="Reset" /&gt;
&lt;/div&gt;
&lt;textarea id="code" class="playable-code"&gt;
var myVideo = document.getElementById('my-video');
myVideo.playbackRate = 2;&lt;/textarea&gt;
</pre>

<pre class="brush: js notranslate">var textarea = document.getElementById('code');
var reset = document.getElementById('reset');
var edit = document.getElementById('edit');
var code = textarea.value;

function setPlaybackRate() {
  eval(textarea.value);
}

reset.addEventListener('click', function() {
  textarea.value = code;
  setPlaybackRate();
});

edit.addEventListener('click', function() {
  textarea.focus();
})

textarea.addEventListener('input', setPlaybackRate);
window.addEventListener('load', setPlaybackRate);
</pre>
</div>

<p>{{ EmbedLiveSample('Playable_code', 700, 425) }}</p>

<div class="note">
<p><strong></strong>: <a href="http://jsbin.com/qomuvefu/2/edit">playbackRate のデモ</a>を試してみてください。</p>
</div>

<h2 id="Audio_manipulation" name="Audio_manipulation">音声の加工</h2>

<p><code>playbackRate</code> の一方で、音声を加工するためには <a href="/ja/docs/Web/API/Web_Audio_API">Web Audio API</a> を利用することが一般的です。</p>

<h3 id="Selecting_an_audio_source" name="Selecting_an_audio_source">音源の選択</h3>

<p>Web Audio API は、様々なソースから音声を受け取り、それを処理してを受信し、それを処理して音を処理した後に送信する出力機器を表す {{domxref("AudioDestinationNode")}} に送り出すことができます。</p>

<table class="standard-table">
 <thead>
  <tr>
   <th scope="col">この音声ソースの場合...</th>
   <th scope="col">この Web Audio ノード型を使用してくださいnode type</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>HTML の {{HTMLElement("audio")}} または {{HTMLElement("video")}} 要素の音声トラック</td>
   <td>{{domxref("MediaElementAudioSourceNode")}}</td>
  </tr>
  <tr>
   <td>メモリ内の生の音声データバッファー</td>
   <td>{{domxref("AudioBufferSourceNode")}}</td>
  </tr>
  <tr>
   <td>サイン波やその他の合成波形を生成するオシレーター</td>
   <td>{{domxref("OscillatorNode")}}</td>
  </tr>
  <tr>
   <td><a href="/ja/docs/Web/API/WebRTC_API">WebRTC</a> の音声トラック (例えば {{domxref("MediaDevices.getUserMedia", "getUserMedia()")}} を使用して取得できるマイク入力)</td>
   <td>{{domxref("MediaStreamAudioSourceNode")}}</td>
  </tr>
 </tbody>
</table>

<h3 id="Audio_filters" name="Audio_filters">音声フィルター</h3>

<p>Web Audio API では {{domxref("BiquadFilterNode")}} を利用することで様々なフィルターやエフェクトを利用できます。</p>

<h4 id="HTML_3">HTML</h4>

<pre class="brush: html notranslate">&lt;video id="my-video" controls
       src="myvideo.mp4" type="video/mp4"&gt;
&lt;/video&gt;</pre>

<h4 id="JavaScript_3">JavaScript</h4>

<pre class="brush: js notranslate">var context = new AudioContext(),
    audioSource = context.createMediaElementSource(document.getElementById("my-video")),
    filter = context.createBiquadFilter();
audioSource.connect(filter);
filter.connect(context.destination);

// Configure filter
filter.type = "lowshelf";
filter.frequency.value = 1000;
filter.gain.value = 25;</pre>

<div class="hidden">
<h6 id="Playable_code_2" name="Playable_code_2">Playable code</h6>

<pre class="brush: html notranslate">&lt;video id="my-video" controls="true" width="480" height="270" crossorigin="anonymous"&gt;
  &lt;source src="http://jplayer.org/video/webm/Big_Buck_Bunny_Trailer.webm" type="video/webm"&gt;
  &lt;source src="http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v" type="video/mp4"&gt;
&lt;/video&gt;
&lt;div class="playable-buttons"&gt;
  &lt;input id="edit" type="button" value="Edit" /&gt;
  &lt;input id="reset" type="button" value="Reset" /&gt;
&lt;/div&gt;
&lt;textarea id="code" class="playable-code"&gt;
filter.type = "lowshelf";
filter.frequency.value = 1000;
filter.gain.value = 25;&lt;/textarea&gt;</pre>

<pre class="brush: js notranslate">var context     = new AudioContext(),
    audioSource = context.createMediaElementSource(document.getElementById("my-video")),
    filter      = context.createBiquadFilter();
audioSource.connect(filter);
filter.connect(context.destination);

var textarea = document.getElementById('code');
var reset = document.getElementById('reset');
var edit = document.getElementById('edit');
var code = textarea.value;

function setFilter() {
  eval(textarea.value);
}

reset.addEventListener('click', function() {
  textarea.value = code;
  setFilter();
});

edit.addEventListener('click', function() {
  textarea.focus();
})

textarea.addEventListener('input', setFilter);
window.addEventListener('load', setFilter);
</pre>
</div>

<p>{{ EmbedLiveSample('Playable_code_2', 700, 425) }}</p>

<div class="note">
<p><strong></strong>: <a href="/docs/Web/HTTP/Access_control_CORS">CORS</a> が有効になっていない環境では、動画はコードと同じドメイン上になければなりません。これはセキュリティ上の問題を避けるためです。</p>
</div>

<h4 id="Common_audio_filters" name="Common_audio_filters">よく使われる音声フィルター</h4>

<p>このノードでよく利用されるフィルターは以下の通りです。</p>

<ul>
 <li>ローパス: 閾値に指定された周波数より低い音は通過させ、高いものは減衰させます。</li>
 <li>ハイパス: 閾値に指定された周波数より高い音は通過させ、低いものは減衰させます。</li>
 <li>バンドパス: 指定された周波数帯の音は通過させ、それ以外は減衰させます。</li>
 <li>ローシェルフ: 周波数に関わらず全ての音を通過させますが、閾値より低いものは増幅 (もしくは減衰) されます</li>
 <li>ハイシェルフ: 周波数に関わらず全ての音を通過させますが、閾値より高いものは増幅 (もしくは減衰) されます</li>
 <li>ピーキング: 周波数に関わらず全ての音を通過させますが、指定された周波数帯のものは増幅 (もしくは減衰) されます</li>
 <li>ノッチ: 指定された周波数帯を除き、全ての音を通過させます</li>
 <li>オールパス: 周波数に関わらず全ての音を通過させますが、幾つかの周波数間の相関係を変更します</li>
</ul>

<div class="note">
<p><strong></strong>: 詳しくは {{domxref("BiquadFilterNode")}} を参照してください。</p>
</div>

<h3 id="Convolutions_and_impulses" name="Convolutions_and_impulses">たたみ込みとインパルス</h3>

<p>{{domxref("ConvolverNode")}} を利用することで、音声に<strong>インパルス応答</strong>を適用することができます。インパルス応答とはハンドクラップのような短い音のインパルスから作成された音のことです。インパルス応答はインパルスが作られた環境 (例えばトンネル内で手を叩くことで発生するエコー) を示します。</p>

<h4 id="Example" name="Example"></h4>

<pre class="brush: js notranslate">var convolver = context.createConvolver();
convolver.buffer = this.impulseResponseBuffer;
// Connect the graph.
source.connect(convolver);
convolver.connect(context.destination);
</pre>

<p>適用例としてはこの <a href="https://codepen.io/a2sheppy/pen/JjPgVYL">Codepen</a> をご覧ください (ただし、とても、とてもくだらないです。小さな子どもが喜ぶくらいでしょう)。</p>

<h3 id="Spatial_audio" name="Spatial_audio">空間的な音</h3>

<p><strong>パンナーノード</strong>を使用することで、音源の位置を操作できます。パンナーノード—{{domxref("PannerNode")}}—は、ソースコーンの位置だけでなく、その方向も指定することができます。位置や方向は三次元空間上で指定します。</p>

<h4 id="Example_2" name="Example_2"></h4>

<pre class="brush: js notranslate">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);</pre>

<div class="note">
<p><strong></strong>: <a href="https://github.com/mdn/webaudio-examples/tree/master/panner-node">GitHub リポジトリに例</a>があります (<a href="https://mdn.github.io/webaudio-examples/panner-node/">ライブ版</a>も)。</p>
</div>

<h2 id="JavaScript_codecs" name="JavaScript_codecs">JavaScript によるコーデック</h2>

<p>JavasCript でより低レベルでの音声操作が可能です。これを利用することで、オーディオコーデックを自作することができます。</p>

<p>以下にフォーマットとそのコーデックのリストを示します。</p>

<ul>
 <li>AAC: <a href="https://github.com/audiocogs/aac.js">AAC.js</a></li>
 <li>ALAC: <a href="https://github.com/audiocogs/alac.js">alac.js</a></li>
 <li>FLAC: <a href="https://github.com/audiocogs/flac.js">flac.js</a></li>
 <li>MP3: <a href="https://github.com/audiocogs/mp3.js">mp3.js</a></li>
 <li>Opus: <a href="https://github.com/audiocogs/opus.js">Opus.js</a></li>
 <li>Vorbis: <a href="https://github.com/audiocogs/vorbis.js">vorbis.js</a></li>
</ul>

<div class="note">
<p><strong></strong>: AudioCogs で<a href="http://audiocogs.org/codecs/">いくつかのデモ</a>を試せます。 Audiocogs は JavaScript でのコーデック実装を行うためのフレームワークである <a href="http://audiocogs.org/codecs/">Aurora.js</a> を提供しています。</p>
</div>

<h2 id="Examples" name="Examples"></h2>

<ul>
 <li><a href="https://github.com/mdn/">様々な Web Audio API (およびその他) の例</a></li>
 <li><a href="https://github.com/chrisdavidmills/threejs-video-cube">THREE.js Video Cube example</a></li>
 <li><a href="http://chromium.googlecode.com/svn/trunk/samples/audio/convolution-effects.html">Convolution Effects in Real-Time</a></li>
</ul>

<h2 id="See_also" name="See_also">関連情報</h2>

<h3 id="Tutorials" name="Tutorials">チュートリアル</h3>

<ul>
 <li><a href="/ja/docs/Web/HTML/Manipulating_video_using_canvas">キャンバスを使用した動画の加工</a></li>
 <li><a href="/ja/Apps/Build/Manipulating_media/HTML5_playbackRate_explained">HTML5 playbackRate の解説</a></li>
 <li><a href="/ja/docs/Web/API/Web_Audio_API/Using_Web_Audio_API">Web Audio API の利用</a></li>
 <li><a href="/ja/docs/Web/API/Web_Audio_API/Web_audio_spatialisation_basics">Web audio spatialisation の基本</a></li>
 <li><a href="/ja/docs/Web/WebGL/Animating_textures_in_WebGL#Using_the_video_frames_as_a_texture">動画フレームの WebGL テクスチャとしての利用</a> (<a href="http://threejs.org">THREE.js</a> WebGL ライブラリ (及びその他) と <a href="http://stemkoski.github.io/Three.js/Video.html">この効果の実現</a>)</li>
 <li><a href="/ja/docs/Web/WebGL/Animating_textures_in_WebGL">WebGL におけるアニメーションテクスチャ</a></li>
 <li><a href="http://www.html5rocks.com/en/tutorials/webaudio/games/#toc-room">Developing Game Audio with the Web Audio API (Room effects and filters)</a></li>
</ul>

<h3 id="Reference" name="Reference">リファレンス</h3>

<ul>
 <li>{{htmlelement("audio")}} および {{htmlelement("video")}} 要素</li>
 <li>{{domxref("HTMLMediaElement")}} API</li>
 <li>{{htmlelement("canvas")}} 要素</li>
 <li><a href="/ja/docs/Web/API/Web_Audio_API">Web Audio API</a></li>
 <li><a href="/ja/docs/Web/API/AudioContext">AudioContext</a></li>
 <li>More info on <a href="/ja/docs/Web/API/AudioContext.createPanner">Spatial Audio</a></li>
 <li><a href="/ja/docs/Web/Media">ウェブメディア技術</a></li>
</ul>

<div>{{QuickLinksWithSubpages("/ja/docs/Web/Apps/Fundamentals/")}}</div>