前に Audio API で音を作ったので、音を足した動画にしてみます。
参考リンク
MDN
- 音 – AudioContext
- 映像 – HTMLCanvasElement – captureStream
- ストリーム – MediaStream – MediaStreamTrack
- レコーダー – MediaRecorder
音と映像を重ねる
AudioContext
は AudioDestinationNode
の代わりにMediaStreamAudioDestinationNode
に繋いで stream
を取得します。
canvas
からも stream
を取得して track
を抜き出して重ねます。
図にするとこんな感じ。
コードを抜き出すとこんな感じです。
getAudioTrack()
は以前のコードの destination
を変更してトラックを抜き出したもので、メインは 36 - 39
行目です。
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
const getAudioTrack = () => { const audioContext = new AudioContext(); const t0 = audioContext.currentTime; let t = 0; const oscillator = audioContext.createOscillator(); const gain = audioContext.createGain(); oscillator.type = "square"; [440, 480, 440, 480, 420, 500, 420, 500].forEach((s) => { const vol = 1; const hz = s; const d = (60 / 80) * (4 / 4); const sm = d / 3 > 0.08 ? 0.08 : Number((d / 3).toFixed(5)); oscillator.frequency.setValueAtTime(hz, t0 + t); gain.gain.setValueCurveAtTime([vol * 0.03, vol * 0.025], t0 + t, sm); gain.gain.setValueCurveAtTime( [vol * 0.025, vol * 0.01], t0 + t + d - sm, sm ); t += d; }); oscillator.start(t0); oscillator.stop(t0 + t); oscillator.connect(gain); var dist = audioContext.createMediaStreamDestination(); gain.connect(dist); return dist.stream.getTracks()[0]; }; let recorder: MediaRecorder; export const rec = () => { const canvas = document.getElementsByTagName("canvas")[0]; const ms = new MediaStream(); ms.addTrack(canvas.captureStream().getTracks()[0]); ms.addTrack(getAudioTrack()); recorder = new MediaRecorder(ms); const rec: { data: Array<Blob>; type: string } = { data: [], type: "" }; recorder.ondataavailable = (e) => { rec.type = e.data.type; rec.data.push(e.data); }; recorder.onstop = () => { console.log("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.start(); }; |
recorder
を外に出してるのは stop
するためです。
実際に録画してみると、音が終了したところで動画は終わっています。
トラックの1つが終了するとそこまでになるのかな。終了方法を少し考えないといけなさそうです。
ともあれ音付きの動画になりました。
動画や音は別ファイルから読み込んでもいいし、音を使って canvas
を操作して動画にしてもいい。色々と遊べそうです。