フレーム画像を表示するデモ
https://scrapbox.io/files/6419d5cc0f9a06001cfcc089.png
調整が必要な部分
React
レンダリングのタイミングを見る
ファイルを切り出す
といっても・・・
メモリの読み書き
mp4ファイルを常にすべてメモリに持っておく必要はない
必要なバイトを適宜読み出し、キャッシュに格納すればOK。
では、どのバイトが必要なのか?
→
ffmpeg
コマンドを調整する
ffmpeg.wasmがメモリ上ではなくOPFSを読み書きできるように調整する。
WebWorkerにフックを作ってそこでOPFSとアプリ、wasmの仲介をやろう
FileReaderでもいい
ffmpeg.wasmがファイルへのアクセスを要求するときに、それをFileオブジェクトやOPFSから読み込むように変更する必要がある
FileReaderオブジェクトは、読み込んだファイルデータをArrayBufferに変換するためのAPIを提供していますが、どの位置のバイトを読んだのかを正確に把握することはできません。つまり、FileReaderオブジェクトは、ファイルをまるごと読み込んでArrayBufferに変換するため、ファイルの先頭から順番にデータを読み取り、ArrayBufferに格納します。したがって、ファイルの先頭から4バイト目を読み取るというような操作に対応することはできません。
ただし、JavaScriptには、Blob.slice()メソッドを使用することで、指定された範囲のバイト配列を切り出すことができます。このため、FileReaderオブジェクトを使用して、ファイル全体を読み込んだ後に、必要な位置のデータをArrayBufferに格納することも可能です。
以下は、Blob.slice()メソッドを使用して、指定された範囲のバイト配列を切り出すJavaScriptコードの例です。
code:file.js
const fileInput = document.querySelector('inputtype="file"'); const file = fileInput.files0; const reader = new FileReader();
reader.onloadend = function() {
const buffer = reader.result;
const arrayBuffer = new ArrayBuffer(file.size);
const dataView = new DataView(arrayBuffer);
const bytes = new Uint8Array(buffer);
const startByte = 3; // 先頭から3バイト目からデータを読み取る
const endByte = 7; // 先頭から7バイト目までのデータを読み取る
const chunkSize = endByte - startByte + 1;
const chunk = bytes.slice(startByte, endByte + 1);
const chunkArray = new Uint8Array(chunk);
for(let i = 0; i < chunkSize; i++) {
dataView.setUint8(startByte + i, chunkArrayi); }
// dataViewに読み込んだデータが格納される(先頭から3〜7バイト目のデータ)
};
reader.readAsArrayBuffer(file);
この方法を使って、PartialなArrayBufferをffmpeg.wasmなどに渡しても、取得していないバイトへのアクセスが行われない限り問題はない?
はい、その通りです。上記の方法を使用してPartialなArrayBufferを生成した場合、そのArrayBufferを外部ライブラリなどに渡す際には、外部ライブラリが読み込んでいないバイトへのアクセスが行われない限り、問題はありません。
ffmpeg.wasmなどの外部ライブラリは、通常、ArrayBufferを入力として受け取り、指定された範囲のデータのみを処理するため、読み込まれていないバイトにはアクセスしません。つまり、FileReaderを使用して読み込んだファイルデータから、必要な範囲のArrayBufferを切り出し、外部ライブラリに渡すことができます。
ただし、外部ライブラリによっては、渡されたArrayBufferの先頭から順番にデータを処理する必要がある場合があります。この場合、外部ライブラリが読み込んでいない範囲のデータにアクセスする可能性があるため、注意が必要です。しかし、このような場合でも、通常はArrayBufferの先頭から順番にデータを処理するため、処理する必要のない範囲のデータにアクセスすることはありません