GLSL
などで動かした canvas
上の絵を動画にしてみたい。
MediaRecorder API
を軽く触ってみます。
動作環境は Chrome
、開発に React (Next.js)
、GLSL
は gl-react を使っています。
メイン要素と注意点
MediaRecorder API を使いますが、IE
や Safari
で未対応のようです。
canvas
からのデータ取得で captureStream()
を使いますが、これもモバイル環境での動作が保証されていない感じです。
環境によって動かないことを念頭に置いておきましょう。
Typescript
MediaRecorder
は型定義されていません。
名前 'MediaRecorder' が見つかりません。ts(2304)
@types から定義を追加します。
1 |
npm i @types/dom-mediacapture-record |
また canvas (HTMLCanvasElement)
の captureStream
も未定義なので拡張します。
プロパティ 'captureStream' は型 'HTMLCanvasElement' に存在しません。ts(2339)
1 2 3 4 5 |
declare global { interface HTMLCanvasElement { captureStream(frameRate?: number): MediaStream; } } |
実装
よくある感じの書き方で簡単に実装できます。
チャンクをまとめるところとか、やたら既視感がある。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
function record() { const canvas = document.getElementsByTagName("canvas")[0]; if (!canvas) { console.log(canvas, "CANVAS NOT FOUND."); return; } //canvas -> stream -> MediaRecorder const stream = canvas.captureStream(); const recorder = new MediaRecorder(stream, { mimeType: "video/webm;codecs=vp9", }); const rec: { data: Array<Blob>; type: string } = { data: [], type: "" }; recorder.ondataavailable = (e) => { rec.type = e.data.type; rec.data.push(e.data); }; recorder.onstop = () => { const blob = new Blob(rec.data, { type: rec.type }); const url = window.URL.createObjectURL(blob); const a = document.createElement("a"); a.download = "movie.webm"; a.href = url; a.click(); }; recorder.onstart = () => { setTimeout(() => { recorder.stop(); }, 10000); }; recorder.start(); } |
canvas
が変化するときにキャプチャされるので静止画だとデータなしになります。
適当に時間で動く GLSL
を使って動かします。
1 2 3 4 5 6 7 8 9 10 |
precision highp float; varying vec2 uv; uniform sampler2D t; uniform float time; void main(){ float _t=(cos(time*.1)+3.)*.25; vec4 c=texture2D(t,uv*_t); gl_FragColor=c; } |
ここから音を足したり、mediaDevices
を使ったり、何かと使えそうですが動作環境が気にもなる。とりあえずもう少し色々試してみよう。