Posted at

WebAssemblyでCanvasをWebM動画に変換する

生のRGBAバッファをWebMに変換してくれるwebm-wasmを使いました。


デモ

Goボタンをクリック時に、Canvasを動的に作成して、WebAssemblyでWebMに変換して、WebM動画をvideoタグで表示しています。

デモ

ソースコード

See the Pen Simple webm wasm demo by John Doe (@04) on CodePen.



1. ワーカーの準備をする

// ワーカーで`webm-wasm.js`ファイルをロードする

const worker = new Worker("../dist/webm-worker.umd.js");
// `.wasm`ファイルのパスをワーカーに送る
worker.postMessage("../dist/webm-wasm.wasm");
// ワーカーの準備が出来るまで待つ
await nextEvent(worker, "message");


2. フレームレートや画質などの情報を送る

worker.postMessage({ timebaseDen: framerate, width, height, bitrate });


3. Canvasを描画し、フレームデータをワーカーに送信

    const gradient = ctx.createLinearGradient(

(1 / 4) * width,
0,
(3 / 4) * width,
0
);
gradient.addColorStop(0, "#000");
gradient.addColorStop(1, "#fff");
const maxFrames = 2 * framerate;
for (let i = 0; i < maxFrames; i++) {
ctx.fillStyle = `hsl(${(i * 360) / maxFrames}, 100%, 50%)`;
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = gradient;
ctx.fillRect((1 / 4) * width, (1 / 4) * height, width / 2, height / 2);
const imageData = ctx.getImageData(0, 0, width, height);
// 生の画像データをワーカーに送信
worker.postMessage(imageData.data.buffer, [imageData.data.buffer]);
}
// 全ての画像データを送信したらnullを送信
worker.postMessage(null);


4. WebMに変換されるまで待機

const webm = (await nextEvent(worker, "message")).data;


5. 作成したWebM動画を再生

    const blob = new Blob([webm], { type: "video/webm" });

const url = URL.createObjectURL(blob);
const video = document.createElement("video");
video.src = url;
document.body.append(video);
video.play();


5.1 またはWebM動画をダウンロード

a要素のdownload属性でダウンロード


JavaScriptでファイルダウンロード処理を実現する

https://qiita.com/wadahiro/items/eb50ac6bbe2e18cf8813


GUIからダウンロード