← 記事一覧へ

FFmpeg.wasmのreadFile結果をBlobに渡すとTS2345になる話

typescriptffmpeg

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> になって解決
  • アサーションで黙らせるよりコピーの方が安全