WEBサイト制作・アプリ開発・システム開発・ブランディングデザイン制作に関するご相談はお気軽にご連絡ください。
構想段階からじっくりとヒアリングし、お客様の課題にあわせたアプローチ手法でお客様の“欲しかった”をカタチにしてご提案いたします。
Blog スタッフブログ
JavaScript
WEB制作
システム開発
[JavaScript]選択した動画ファイルからサムネイルを取得
こんにちは、株式会社MIXシステム開発担当のBloomです。
早速本題の選択した動画ファイルからサムネイルを取得する手順について、
お仕事の中で得た知見を共有させていただきたいと思います。
サムネイルの生成方法
ブラウザ上でユーザがアップロードした動画ファイルを用いてサムネイルを生成する場合、次のフローに則って行います。
- <input type=”file”>要素からファイルを選択
- 選択された動画を新規生成した<video>要素で再生
- 再生後、さらに新規生成した<canvas>要素で描画
- 描画後にtoDataURL()関数を利用して画像blobを取得、適宜<img>要素へ適応
それでは実際に構築してみましょう。
<head>
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js" integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous"></script>
<style>
img.thumbnail
{
max-width: 640px;
max-height: 480px;
}
</style>
</head>
<body>
<form>
<label for="select-file">Select Video file</label>
<input type="file" id="select-file" name="file" onchange="makeThumbnail(this);">
</form>
<img class="thumbnail">
</body>
<script>
function makeThumbnail(_this) {
// 1.ファイルを選択
var file = $(_this).prop('files')[0];
var fileReader = new FileReader();
fileReader.onload = function() {
var blob = new Blob([fileReader.result], {type: file.type});
var url = URL.createObjectURL(blob);
var video = document.createElement('video');
var thumbnailFrame = 0; // サムネイル取得秒指定
var retryCount = 10; // サムネイル生成失敗許容回数
var currentCount = 0;
// timeupdateイベントで動画の再生を検知しています
var timeupdate = function() {
if (snapImage()) {
video.removeEventListener('timeupdate', timeupdate);
video.pause();
}
else if (currentCount == retryCount) {
// サムネイル生成失敗
console.log("make thumbnail failed");
video.removeEventListener('timeupdate', timeupdate);
video.pause();
}
}
video.addEventListener('canplay', function() {
if (video.duration > thumbnailFrame) {
video.currentTime = thumbnailFrame;
}
else {
video.currentTime = video.duration / 2;
}
});
var snapImage = function() {
// 3.再生後、さらに新規生成した<canvas>要素で描画
var canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
// 4.描画後にtoDataURL()関数を利用して画像blobを取得、適宜<img>要素へ適応
var image = canvas.toDataURL("image/png");
var success = image.length > 100000;
if (success) {
var img = $(".thumbnail");
img.attr('src', image);
setTimeout(() => { // Safari対策
URL.revokeObjectURL(url);
}, 2000);
}
else {
currentCount+=1;
}
return success;
}
// 2.選択された動画を新規生成した<video>要素で再生
video.addEventListener('timeupdate', timeupdate);
video.preload = 'meta';
video.src = url;
// Safari / IE11
video.muted = true;
video.playsInline = true;
video.currentTime = thumbnailFrame;
video.play();
}
fileReader.readAsArrayBuffer(file);
}
</script>
実行結果
これで簡単にサムネイルが生成できました。
画像blobをそのまま<input type=”hidden”>要素のvalueへ格納することでフォームでそのまま送信することもできます。良かったですね。
注意点
2.の行程において必ず<video>要素による再生処理を必要とするため、ブラウザが対応していないコーデックの動画が選択された場合はサムネイルの生成に失敗します。
一般的なH.264形式はほとんどのブラウザで対応していますが、現在iOS端末カメラアプリのデフォルト設定となるHEVC(H.265)形式は現在Safariを含む一部のブラウザでしか対応していないためご注意ください。