メディアの操作について
javascriptでメディアを取り扱う方法を試してみます。
ここでいうメディアは、文字列以外のデータとして、画像(canvas含む)、音声、動画、等のファイルです。
一つ一つ試しながら理解してみます。
音声や動画ファイルの再生について
サーバ上にある音声ファイル(mp3やwav等)の再生方法は多岐に渡ります。
audioタグ(DOM要素の埋め込み)を書く方法や、Web Audio APIを使う方法
ここでは、audioを使って再生を制御する方法を試してみます。
具体的には、音声ファイルの場合は、次のように書きます。
audioオブジェクトを使う為のDOM要素と、src属性でサーバ上の音声ファイルを定義します。
<audio src="test.mp3">
ただし、このDOM要素だけをHTML上に書いても何もなりません。
サーバ側に「test.mp3」という音声ファイルを置き、下記のHTMLを書いてみました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>
<audio src="test.mp3">
</body>
</html>
サーバ上のHTMLはこちら(test1.html)
画面にアクセスしてみると、音声も再生されず、画面上にも何も表示されません。
上記のHTMLはHTML5の audioタグを指定しているだけなので、実際に音声を再生させたり停止させたりするには、属性を追加しなければならないです。
また、音声ファイルに対してその他の処理をするには、javascript側でAPIを呼んで処理をするプログラムを書く必要があります。
audioについて – controls属性について
では、上記HTMLに対して、少し手を加えてみます。
先程ののDOM要素に対して、controls属性をつけてみます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>
<audio controls src="test.mp3">
</body>
</html>
サーバ上のHTMLはこちら(test2.html)
実際に画面にアクセスしてみると、音声を再生する為の
再生ボタン
再生秒数
再生位置を示すバー
ボリューム
再生速度(chromeの場合)
のユーザインタフェースが表示され、音声の再生が可能になります。
注意点としては、音声の再生が可能にはなりますが、
最近の流れとして、スマホやタブレットでの再生、またOSのandroidやiOSでの再生事情を考慮すると
再生可否が担保できなかったり、再生用のユーザインタフェースが統一されていなかったりと、
色々と注意する点があるので、本実装に採用するかどうかはプロジェクトの方針によって決定するとよいと思います。
実際に、chromeとfirefoxでの表示の違いは以下のようになります。
chrome
firefox
では、ここで少し拡張をしてみます。
複数の音声を再生する為、サーバ側にtest2.mp3とtest3.mp3を置き、下記のHTMLを作成してアクセスしてみます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>
<audio controls src="test.mp3">
<audio controls src="test2.mp3">
<audio controls src="test3.mp3">
</body>
</html>
サーバ上のHTMLはこちら(test3.html)
実際にアクセスしてみるとわかりますが、
上記のHTMLの書き方では、再生欄が3つ表示されるわけではありません。
この動きを解決するには、次のようにします。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>
<audio controls>
<source src="test.mp3">
</audio>
<audio controls>
<source src="test2.mp3">
</audio>
<audio controls>
<source src="test3.mp3">
</audio>
</body>
</html>
サーバ上のHTMLはこちら(test4.html)
画面にアクセスすると、音声ファイルに応じた、再生欄が3つ表示されます。
それぞれのファイルに応じた秒数が表示されているので、ファイルごとに再生欄が出し分けられていることがわかります。
また、もしsrc属性に、ブラウザがサポートしないファイルを指定した場合、
再生ができない旨を表示する必要があります。
その場合は次のように書きます。
<audio controls>
<source src="test.mp3">
<div>非サポートのファイルです</div>
</audio>
上記のように書くと、ブラウザがmp3の再生に対応していない場合、「非サポートのファイルです」という表示になります。
タイプ選択について
メディアがブラウザで再生できるかを確認する方法があります。
実際の場面では、どんな種類のメディアファイルを扱うかはプロジェクトの方針により決まりますが、
例えばユーザからなんらかのファイルを受け付け、それを再生するような場面があった場合、
そのメディアが再生可能かどうかを確認するというケースがあります。
そのような場合には、
HTMLMediaElementインターフェイスのメソッド「canPlayType」を使って調べることができます。
canPlayTypeはプログラムの実行環境でそのメディアが再生できるかを返します。
例えば、前述のサンプルに対して、再生可否を調べるには以下のように下記ます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>
<audio controls id="audiodata1">
<source src="test.mp3">
</audio>
<div id="playability_result"></div>
<script type="text/javascript">
// 音声1のDOM要素を取得
let audiodata1 = document.getElementById("audiodata1");
// 音声1の再生可否を取得
let isPlayability1 = audiodata1.canPlayType('audio/mp3');
// 音声1のDOM要素を取得し、画面に出力する
let playability_result = document.getElementById("playability_result");
playability_result.innerHTML += '再生可否 isPlayability1 -> ' + isPlayability1 + '<br />';
</script>
</body>
</html>
サーバ上のHTMLはこちら(test5.html)
画面にアクセスすると、対象のファイルが再生可能かどうかが表示されます。
今回の例では「probably」と表示され、再生ができることがわかります。
再生の制御について
画面上の audio タグから、メディアファイル(音声、映像)を制御することができます。
メソッドとして用意されているものは、下記です。
canPlayType()
load()
pause()
play()
captureStream()
一番最後の「captureStream」については、映像のファイルに対してのメソッドなので、
音声ファイルには使えません。
では、上記でサンプルで書いたコードに、playメソッドを使うように改修してみます。
下記HTMLを用意しました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>
<audio controls id="audiodata1">
<source src="test.mp3">
</audio>
<div id="sound_play">音声を再生する</div>
<script type="text/javascript">
// 音声再生のDOM要素を取得
let sound_play_button = document.getElementById('sound_play');
// 音声再生イベント
sound_play_button.addEventListener('click', function() {
// 音声1のDOM要素を取得
let audiodata1 = document.getElementById("audiodata1");
// 再生
audiodata1.play();
}, false);
</script>
</body>
</html>
サーバ上のHTMLはこちら(test6.html)
画面にアクセスし「音声を再生する」をクリックすると、
<audio controls id="audiodata1">
<source src="test.mp3">
</audio>
で指定したaudiodata1のDOM要素の音声が再生されます。
再生以外のその他のメソッドも試してみます。
次のHTMLを用意しました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>
<audio controls id="audiodata1">
<source src="test.mp3">
</audio>
<div id="sound_play">音声を再生する</div>
<div id="sound_pause">音声を一時停止する</div>
<script type="text/javascript">
// 音声制御のDOM要素を取得
let button_play = document.getElementById('sound_play');
let button_pause = document.getElementById('sound_pause');
// 音声再生イベント
button_play.addEventListener('click', function() {
// 音声1のDOM要素を取得
let audiodata1 = document.getElementById("audiodata1");
// 再生
audiodata1.play();
}, false);
// 音声再生イベント
button_pause.addEventListener('click', function() {
// 音声1のDOM要素を取得
let audiodata1 = document.getElementById("audiodata1");
// 再生
audiodata1.pause();
}, false);
</script>
</body>
</html>
サーバ上のHTMLはこちら(test7.html)
画面にアクセスし、音声を再生した後、「音声を一時停止する」をクリックすると、再生は一時停止します。
また「音声を一時停止する」をクリックすると再生は再開されます。
実際のアプリケーションでは、一時停止した後に、「音声を一時停止する」の文言を切り替えて、
「再生を再開する」旨の表示に切り替えるように工夫をします。
また、メソッドの他に、プロパティもあります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>
<audio controls id="audiodata1">
<source src="test.mp3">
</audio>
<div id="sound_play">音声を再生する</div>
<div id="sound_pause">音声を一時停止する</div>
<div id="sound_volume_up">音量を上げる</div>
<div id="sound_volume_down">音量を下げる</div>
<script type="text/javascript">
// 音声制御のDOM要素を取得
let button_play = document.getElementById('sound_play');
let button_pause = document.getElementById('sound_pause');
let button_volume_up = document.getElementById('sound_volume_up');
let button_volume_down = document.getElementById('sound_volume_down');
// 再生イベント
button_play.addEventListener('click', function() {
let audiodata1 = document.getElementById("audiodata1");
audiodata1.play();
}, false);
// 一時停止イベント
button_pause.addEventListener('click', function() {
let audiodata1 = document.getElementById("audiodata1");
audiodata1.pause();
}, false);
// 音量を上げる
button_volume_up.addEventListener('click', function() {
let audiodata1 = document.getElementById("audiodata1");
audiodata1.volume += 0.1;
}, false);
// 音量を下げる
button_volume_down.addEventListener('click', function() {
let audiodata1 = document.getElementById("audiodata1");
audiodata1.volume -= 0.1;
}, false);
</script>
</body>
</html>
サーバ上のHTMLはこちら(test8.html)
画面にアクセスして、音声を再生した後、音量を上げる(または下げる) をクリックすると、音量が調整できます。
上記の例はほんの一例ですが、その他にもプロパティが用意されています。
これらはHTMLMediaElementのインタフェイスとして定義されています。
各プロパティの意味や使用方法はここでは書きませんが、実際の開発時には各プロパティを調査したうえで実装をします。
audioTracks
autoplay
buffered
controls
controlsList
crossOrigin
currentSrc
currentTime
defaultMuted
defaultPlaybackRate
disableRemotePlayback
duration
ended
loop
muted
paused
playbackRate
played
preload
preservesPitch
seekable
seeking
src
srcObject
textTracks
videoTracks
volume
error
networkState
readyState
(上記は、全てのプロパティを列挙はしていません)
上記のプロパティがどのような値を保持し、どのような値が取得できるのかを試してみます。
以下、プロパティの内容を出力するサンプルを書きました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>
<audio controls id="audiodata1">
<source src="test.mp3">
</audio>
<div id="sound_play">サウンドを再生する</div>
<div id="sound_pause">サウンドを一時停止する</div>
<div id="sound_volume_up">音量を上げる</div>
<div id="sound_volume_down">音量を下げる</div>
<hr>
プロパティ出力<br />
<div id="property_result"></div>
<script type="text/javascript">
// サウンド制御のDOM要素を取得
let button_play = document.getElementById('sound_play');
let button_pause = document.getElementById('sound_pause');
let button_volume_up = document.getElementById('sound_volume_up');
let button_volume_down = document.getElementById('sound_volume_down');
// 再生イベント
button_play.addEventListener('click', function() {
let audiodata1 = document.getElementById("audiodata1");
audiodata1.play();
display_property();
}, false);
// 一時停止イベント
button_pause.addEventListener('click', function() {
let audiodata1 = document.getElementById("audiodata1");
audiodata1.pause();
display_property();
}, false);
// 音量を上げる
button_volume_up.addEventListener('click', function() {
let audiodata1 = document.getElementById("audiodata1");
audiodata1.volume += 0.1;
display_property();
}, false);
// 音量を下げる
button_volume_down.addEventListener('click', function() {
let audiodata1 = document.getElementById("audiodata1");
audiodata1.volume -= 0.1;
display_property();
}, false);
function display_property()
{
let property_result = document.getElementById("property_result");
let audiodata_property = document.getElementById("audiodata1");
// 一旦表示を初期化する
property_result.innerHTML = '';
property_result.innerHTML += "audioTracks -> " + audiodata_property.audioTracks + '<br />';
property_result.innerHTML += "autoplay -> " + audiodata_property.autoplay + '<br />';
property_result.innerHTML += "buffered -> " + audiodata_property.buffered + '<br />';
property_result.innerHTML += "controls -> " + audiodata_property.controls + '<br />';
property_result.innerHTML += "controlsList -> " + audiodata_property.controlsList + '<br />';
property_result.innerHTML += "crossOrigin -> " + audiodata_property.crossOrigin + '<br />';
property_result.innerHTML += "currentSrc -> " + audiodata_property.currentSrc + '<br />';
property_result.innerHTML += "currentTime -> " + audiodata_property.currentTime + '<br />';
property_result.innerHTML += "defaultMuted -> " + audiodata_property.defaultMuted + '<br />';
property_result.innerHTML += "defaultPlaybackRate -> " + audiodata_property.defaultPlaybackRate + '<br />';
property_result.innerHTML += "disableRemotePlayback -> " + audiodata_property.disableRemotePlayback + '<br />';
property_result.innerHTML += "duration -> " + audiodata_property.duration + '<br />';
property_result.innerHTML += "ended -> " + audiodata_property.ended + '<br />';
property_result.innerHTML += "loop -> " + audiodata_property.loop + '<br />';
property_result.innerHTML += "muted -> " + audiodata_property.muted + '<br />';
property_result.innerHTML += "paused -> " + audiodata_property.paused + '<br />';
property_result.innerHTML += "playbackRate -> " + audiodata_property.playbackRate + '<br />';
property_result.innerHTML += "played -> " + audiodata_property.played + '<br />';
property_result.innerHTML += "preload -> " + audiodata_property.preload + '<br />';
property_result.innerHTML += "preservesPitch -> " + audiodata_property.preservesPitch + '<br />';
property_result.innerHTML += "seekable -> " + audiodata_property.seekable + '<br />';
property_result.innerHTML += "seeking -> " + audiodata_property.seeking + '<br />';
property_result.innerHTML += "src -> " + audiodata_property.src + '<br />';
property_result.innerHTML += "srcObject -> " + audiodata_property.srcObject + '<br />';
property_result.innerHTML += "textTracks -> " + audiodata_property.textTracks + '<br />';
property_result.innerHTML += "videoTracks -> " + audiodata_property.videoTracks + '<br />';
property_result.innerHTML += "volume -> " + audiodata_property.volume + '<br />';
property_result.innerHTML += "error -> " + audiodata_property.error + '<br />';
property_result.innerHTML += "networkState -> " + audiodata_property.networkState + '<br />';
property_result.innerHTML += "readyState -> " + audiodata_property.readyState + '<br />';
}
</script>
</body>
</html>
サーバ上のHTMLはこちら(test9.html)
画面にアクセスして、音声を再生、一時停止、等の操作をしたタイミングで、
各プロパティの値が更新されて内容を確認できます。