<input type="file">
を介して選択されたビデオファイルのスナップショットを、バックグラウンドでサイレントにビデオ内の特定の時間に取得するにはどうすればよいですか(つまり、目に見える要素、ちらつき、音などはありません)。
4つの主要なステップがあります。
<canvas>
_要素と_<video>
_要素を作成します。URL.createObjectURL
_によって生成されたビデオファイルのsrc
を_<video>
_要素にロードし、発生する特定のイベントをリッスンしてロードされるのを待ちます。これは非常に簡単です。1つの_<canvas>
_要素と1つの_<video>
_要素を作成し、それらを_<body>
_に追加するだけです(または実際にはどこでも問題ありません)。
_var canvasElem = $( '<canvas class="snapshot-generator"></canvas>' ).appendTo(document.body)[0];
var $video = $( '<video muted class="snapshot-generator"></video>' ).appendTo(document.body);
_
ビデオ要素には属性muted
があることに注意してください。 autoplay
やcontrols
のような他の属性を入れないでください。また、どちらもクラス_snapshot-generator
_を持っていることに注意してください。これは、両方のスタイルを設定して、邪魔にならないようにするためです。
_.snapshot-generator {
display: block;
height: 1px;
left: 0;
object-fit: contain;
position: fixed;
top: 0;
width: 1px;
z-index: -1;
}
_
一部のブラウザは_display: none
_に設定して動作しますが、他のブラウザはページに表示されない限り深刻な問題が発生するため、基本的に非表示になるようにごくわずかにします。 (ただし、ビューポートの外に移動しないでください。移動すると、ページに見苦しいスクロールバーが表示される場合があります。)
ここで物事がトリッキーになり始めます。いつ続行するかを知るには、イベントを聞く必要があります。ブラウザーが異なれば、異なるイベント、異なる時間、異なる順序で発生するため、労力を節約できます。ビデオの準備が整う前に常に少なくとも1回は発生する必要がある3つのイベントがあります。彼らです:
これらのイベントのイベントハンドラーを設定し、発生したイベントの数を追跡します。 3つすべてが起動したら、次に進む準備ができています。これらのイベントの一部は複数回発生する可能性があるため、発生した各タイプの最初のイベントのみを処理し、後続の発生を破棄する必要があることに注意してください。これを処理するjQueryの_.one
_を使用しました。
_var step_2_events_fired = 0;
$video.one('loadedmetadata loadeddata suspend', function() {
if (++step_2_events_fired == 3) {
// Ready for next step
}
}).prop('src', insert_source_here);
_
ソースは、URL.createObjectURL(file)
を介して作成されたオブジェクトURLである必要があります。ここで、file
はファイルオブジェクトです。
この段階は前の段階と似ています。時間を設定してから、イベントをリッスンします。前のコードのif
ブロック内:
_$video.one('seeked', function() {
// Ready for next step
}).prop('currentTime', insert_time_here_in_seconds);
_
幸い、今回のイベントは1つだけなので、かなり明確で簡潔です。最後に...
この部分では、_<canvas>
_要素を使用してスクリーンショットを取得しています。 seeked
イベントハンドラー内:
_canvas_elem.height = this.videoHeight;
canvas_elem.width = this.videoWidth;
canvas_elem.getContext('2d').drawImage(this, 0, 0);
var snapshot = canvas_elem.toDataURL();
// Remove elements as they are no longer needed
$video.remove();
$(canvas_elem).remove();
_
適切な画像を取得するには、キャンバスがビデオのサイズと一致する必要があります(not_<video>
_要素)。また、キャンバスの内部_.height
_および_.width
_プロパティを設定していますキャンバスの高さ/幅のCSSスタイル値ではありません。
スナップショットの値はデータURIであり、基本的には_data:image/jpeg;base64
_で始まり、次にbase64データが続く文字列です。
最終的なJSコードは次のようになります。
_var step_2_events_fired = 0;
$video.one('loadedmetadata loadeddata suspend', function() {
if (++step_2_events_fired == 3) {
$video.one('seeked', function() {
canvas_elem.height = this.videoHeight;
canvas_elem.width = this.videoWidth;
canvas_elem.getContext('2d').drawImage(this, 0, 0);
var snapshot = canvas_elem.toDataURL();
// Delete the elements as they are no longer needed
$video.remove();
$(canvas_elem).remove();
}).prop('currentTime', insert_time_here_in_seconds);
}
}).prop('src', insert_source_here);
_
あなたはbase64にあなたのイメージを持っています!これをサーバーに送信し、_<img>
_要素のsrc
などとして配置します。
たとえば、バイナリにデコードしてファイルに直接書き込むことができます(最初にプレフィックスを削除します)、これがJPEG画像ファイルになります。
これを使用して、アップロード中にビデオのプレビューを提供することもできます。 _<img>
_のsrc
として配置する場合は、完全なデータURI(プレフィックスを削除しないでください)。