Webサイトのメインビジュアルに動画を再生する機会も多くなってきました。
そうなると、困った事態になることも増えてきます。
最近あったのが、「動画(の再生)をもっとゆっくりにして欲しい」という依頼。…ゆっくりですか。
今回の場合は、動画を撮影・編集してくれた人にお願いして、通常の速度より緩やかな動きになるように動画を作成していただくことになりました。
問題は「ゆっくり」というのがどの程度の早さなのか、ということ。
「ゆっくり」が通常の再生速度の半分なのか、4分の1なのか、4分の3なのか…。数値化されていない指示なので、そのまま動画を作ってくれる人に伝えられません。
動画編集は時間のかかる作業なので、「ごめん、半分の速度だと遅すぎたから 4分の3の速度にして作り直して」なんて気軽に言ってはいけません。
とはいえ、クライアントに「どれぐらいの速度ですか?」と聞いてもちゃんとした答えが返ってくるとは限りません。
クライアントも伝えたいと思っても、どう表現していいのか分からないこともあるでしょうし、修正された動画を見たら「思ったより早かった」なんてこともあるでしょう。
そこで、JavaScriptの出番です。
JavaScriptで動画の再生速度を制御して、実際にクライアントでどれぐらいの速度がイメージされている「ゆっくり」であるか見てもらい、その速度を基準にして動画を作る、という流れでこの「ゆっくり問題」を解決しました。
今回は、このとき使用した「動画をJavaScriptで制御する」実装を解説します。
処理の流れ
動画のvideo要素と、動画の速度をコントロールするbutton要素を取得します。
動画のメタデータが読み込まれたタイミングでloadedmetadata
イベントが発生します。
これを検知するようにaddEventListener()
メソッドを設定します。
取得したbutton要素がクリックされたら処理を実行できるように、click
イベントを検知するaddEventListener()
メソッドを設定します。
クリックされたボタン要素に設定しているdata属性から、変更したい再生速度を取得します。
取得した変更したい再生速度を、video要素の playbackRate
プロパティに設定して、再生速度を変更します。
HTMLについて
今回、動画とコントロールのHTMLは以下のようにしました。
<div class="video-wrap">
<video id="targetVideo" width="640" height="360" muted autoplay playsinline autoplay controls>
<source src="assets/video/video01.mp4" type="video/mp4">
</video>
</div>
<ul class="video-nav">
<li><button data-speed="0.25" class="video-speed">0.25倍</button></li>
<li><button data-speed="0.5" class="video-speed">0.5倍</button></li>
<li><button data-speed="0.75" class="video-speed">0.75倍</button></li>
<li><button data-speed="1" class="video-speed">等倍</button></li>
</ul>
それぞれの要素について、簡単に説明します。
video要素
<div class="video-wrap">
<video id="targetVideo" width="640" height="480" muted autoplay playsinline controls>
<source src="assets/video/video01.mp4" type="video/mp4">
</video>
</div>
今回は動画の再生速度の確認だけなので、video要素には消音を指定するmuted
属性、自動で再生を開始する指定のautoplay
属性を設定しています。
また、短い動画なので繰り返し再生して確認できるようにするため、ブラウザ標準のコントロールを表示するcontrols
属性も設定しています。
video要素を囲むdiv要素はレイアウト目的の要素なので、動画の再生には影響しません。
button要素
<ul class="video-nav">
<li><button data-speed="0.25" class="video-speed">1/4の速度</button></li>
<li><button data-speed="0.5" class="video-speed">半分の速度</button></li>
<li><button data-speed="0.75" class="video-speed">3/4の速度</button></li>
<li><button data-speed="1" class="video-speed">通常の速度</button></li>
</ul>
動画の速度を指定するために、button要素を使います。
ここではdata属性にdata-speed
を設定しており、それぞれに動画の再生速度を以下のようにを指定しています。
data-speed="0.25"
:1/4の速度data-speed="0.5"
:半分の速度data-speed="0.75"
0.75:3/4の速度data-speed="1"
:通常の速度
また、JavaScriptでbutton要素を取得しやすいようにclass属性video-speed
も設定しています。
処理の説明
STEP1 video要素とbutton要素を取得する
まずは、テーブルを変化させる関数をHTMLの読み込みと解析が完了した後で実行するように、イベントリスナーを設定します。
今回は関数名をvideoPlayRateController()
とします。
document.addEventListener('DOMContentLoaded', videoPlayRateController);
次に、関数videoPlayRateController()
を定義して、video要素とbutton要素を取得します。
取得した要素は、それぞれ変数videoElement
、speedButtons
に格納します。
function videoPlayRateController() {
// video要素を取得する
const videoElement = document.getElementById('targetVideo');
// button要素を取得する
const speedButtons = document.querySelectorAll('.video-speed');
}
STEP2 video要素にイベントリスナーを設定する
動画はファイル容量が大きく、通常ダウンロードが完了するまで時間がかかります。そのため、addEventListener()
メソッドでloadedmetadata
イベントを監視して、メタデータが読み込まれたタイミングで処理が実行されるようにします。
// 動画のメタデータが読み込まれたら処理を実行する
videoElement.addEventListener('loadedmetadata', function() {
});
loadedmetadata
イベントについては、MDNが参考になります。
button要素にイベントリスナーを設定する
動画のメタデータが読み込まれたら、button要素に addEventListener()
メソッドでclick
イベントを検知するようにします。
button要素はquerySelectorAll()
メソッドを使って取得していますので、forEach()
メソッドで取得したすべてのbutton要素にイベントリスナーを設定していきます。
// 動画のメタデータが読み込まれたら処理を実行する
videoElement.addEventListener('loadedmetadata', function() {
// 取得したすべてのbutton要素をループ処理する
speedButtons.forEach(item => {
// button要素のclickイベントにイベントリスナーを設定する
item.addEventListener('click', function () {
});
});
});
クリックされたbutton要素から、変更したい再生速度を取得する
次に、クリックされたbutton要素のdataset
プロパティを取得して、変数button
へ格納します。
item.addEventListener('click', function () {
// クリックされた要素のdatasetプロパティを取得して、変数buttonへ格納する
const button = this.dataset;
});
this
はクリックされたbutton要素になりますので、this.dataset
はクリックされたbutton要素の dataset
プロパティを参照することになります。
dataset
プロパティについてはMDNが参考になります。
取得したbutton
をconsole.log()
で出力すると、開発ツールのコンソールへ以下のようにカスタム属性のデータが出力されます。
button要素にはカスタム属性でdata-speed
が設定されています。dataset
プロパティで取得したデータは、接頭辞の data-
を削除した名前がキーとなりますので、 button.speed
でカスタム属性の値を参照できます。
例えば、console.log(button.speed)
とすると、 コンソールへ以下のようにカスタム属性の値だけが出力されます。
これで、変更したい変更速度を取得できますので、動画の再生速度を変える準備ができました。
取得した再生速度をvideo要素に反映する
動画の再生速度は、video要素の playbackRate
プロパティに設定すると変更できます。
playbackRate
プロパティはMDNが参考になります。
取得した再生速度を video要素のplaybackRate
プロパティに設定します。
item.addEventListener('click', function () {
const button = this.dataset;
// video要素のplaybackRateプロパティに、指定された再生速度を設定する
videoElement.playbackRate = button.speed;
});
これで一通り、機能を実装することができました。
完成したコード
完成したコードは以下のようになります。
function videoPlayRateController() {
// video要素を取得する
const videoElement = document.getElementById('targetVideo');
// button要素を取得する
const speedButtons = document.querySelectorAll('.video-speed');
// 動画のメタデータが読み込まれたら処理を実行する
videoElement.addEventListener('loadedmetadata', function() {
// 取得したすべてのbutton要素をループ処理する
speedButtons.forEach(item => {
// button要素のclickイベントにイベントリスナーを設定する
item.addEventListener('click', function () {
// クリックされた要素のdatasetプロパティを取得して、変数buttonへ格納する
let button = this.dataset;
// video要素のplaybackRateプロパティに、指定された再生速度を設定する
videoElement.playbackRate = button.speed;
});
});
});
}
document.addEventListener('DOMContentLoaded', videoPlayRateController);
デモ
実際にどんな風に動作するのか、確認するためのデモページを用意しました。
以下のリンクから見ることができます。
https://tech-blog.tomono.jp/demo/changing-video-playback-speed/
まとめ
JavaScriptで再生速度を制御しましたが、あくまで簡易的に再生速度を変更しているため、場合によってはカクカクしてしまうことがあります。
クライアントとのすり合わせができたら、ちゃんと動画作った方が無難です。
今回は再生速度を「ゆっくり」に変更しましたが、指定を変えれば「倍速再生」なんてこともできますので、いろいろ試してみるのもいいですね。