FFmpeg.wasmのreadFile結果をBlobに渡すとTS2345になる話
FFmpeg.wasm(@ffmpeg/ffmpeg)で変換した結果を Blob にしてダウンロードさせようとしたら、TypeScriptに怒られた。
const data = await ffmpeg.readFile("output.mp4"); // FileData = Uint8Array | string
const blob = new Blob([data], { type: "video/mp4" });
// TS2345: Argument of type 'FileData' is not assignable to parameter of type 'BlobPart'原因
TypeScript 5.7以降、Uint8Array はジェネリクス Uint8Array<TArrayBuffer> になった。FFmpeg.wasmの readFile が返すのは Uint8Array<ArrayBufferLike> で、これは中身が SharedArrayBuffer の可能性を含む。一方 BlobPart が受け付けるのは ArrayBuffer ベースのビューだけなので、型が合わない。
解決策
new Uint8Array() でコピーすると、新しい ArrayBuffer ベースの Uint8Array<ArrayBuffer> になる。
const data = await ffmpeg.readFile("output.mp4");
const bytes = new Uint8Array(data as Uint8Array);
const blob = new Blob([bytes], { type: "video/mp4" });as unknown as BlobPart のような型アサーションでも通るが、SharedArrayBufferが実際に来た場合の安全性を考えるとコピーが素直。動画1本分のコピーコストは、ダウンロード1回の操作では体感できない。
まとめ
- TS 5.7+の
Uint8Array<ArrayBufferLike>はBlobPartに直接渡せない new Uint8Array(data)でコピーすればUint8Array<ArrayBuffer>になって解決- アサーションで黙らせるよりコピーの方が安全