logo hsb.horse
← ブログ一覧に戻る

ブログ

HTMLVideoElementから画像を生成するTypeScript実装

CanvasとVideoElementを使って、動画の現在フレームを画像として抽出するTypeScript実装。Promiseベースでblob生成する方法を整理。

公開日:

HTMLVideoElementの現在フレームを画像として抽出する実装をまとめる。

CanvasAPIを使って動画フレームをキャプチャし、Blob形式で取得する。

利用するAPI

  • HTMLCanvasElement
  • HTMLVideoElement
  • Promise API

実装

interface OutputImage {
type: "png" | "jpeg" | "webp";
quality?: number;
}
interface TransferOptions {
canvas: HTMLCanvasElement;
video: HTMLVideoElement;
output: OutputImage;
}
interface TransferredImage {
blob: Blob;
width: number;
height: number;
type: string;
}
function transferImage(options: TransferOptions): Promise<TransferredImage> {
const { canvas, video, output } = options;
const height = video.videoHeight;
const width = video.videoWidth;
return new Promise<TransferredImage>((resolve, reject) => {
const ctx = canvas.getContext("2d");
if (!ctx) {
reject(new Error("Context2D is not defined"));
return;
}
ctx.drawImage(video, 0, 0, width, height);
const type = `image/${output.type}`;
const q = output.quality || 1;
function toBlob(blob: Blob | null) {
if (blob) {
resolve({ blob, width, height, type });
} else {
reject(new Error("Failed to create blob from canvas"));
}
}
canvas.toBlob(toBlob, type, q);
});
}

ポイント

  1. video.videoHeightvideo.videoWidthで動画の解像度を取得
  2. ctx.drawImage(video, 0, 0, width, height)で現在フレームをCanvasに描画
  3. canvas.toBlobでCanvasの内容をBlob化
  4. Promiseで非同期処理をラップ

使用例

const video = document.querySelector('video');
const canvas = document.createElement('canvas');
const image = await transferImage({
canvas,
video,
output: { type: 'png', quality: 1 }
});
// image.blob を使って画像をダウンロードしたり、表示したりできる
const url = URL.createObjectURL(image.blob);

まとめ

HTMLVideoElementとCanvasAPIを組み合わせることで、動画の任意のフレームを画像として抽出できる。

サムネイル生成や動画プレビュー機能の実装に活用できる。