這個例子目前僅完全適用於火狐,因爲鉻乾脆停止時的標籤模糊畫布流... (可能與this bug,但很好,我計時器似乎是工作,但不是記錄...)
[編輯]:它實際上現在只能在Chrome,因爲他們有固定的this bug,但現在不是了在FF由於this one(由e10s引起的)。
似乎有不爲,讓你知道當一個幀已經被渲染到它,既不在MediaRecorder上MediaStream的任何事件。
甚至MediaStream的currentTime
屬性(目前僅在FF中可用)似乎沒有因captureStream()
方法中傳遞的fps參數而相應改變。
但是你似乎想要的是一個可靠的計時器,即噹噹前選項卡沒有被聚焦(這發生在rAF)時,它不會失去它的頻率。
幸運的是,WebAudio API也有一個基於硬件時鐘的high precision timer,而不是屏幕刷新率。
所以我們可以選擇一個替代的定時循環,即使標籤模糊也能保持其頻率。
/*
\t An alternative timing loop, based on AudioContext's clock
\t @arg callback : a callback function
\t \t with the audioContext's currentTime passed as unique argument
\t @arg frequency : float in ms;
\t @returns : a stop function
\t
*/
function audioTimerLoop(callback, frequency) {
// AudioContext time parameters are in seconds
var freq = frequency/1000;
var aCtx = new AudioContext();
// Chrome needs our oscillator node to be attached to the destination
// So we create a silent Gain Node
var silence = aCtx.createGain();
silence.gain.value = 0;
silence.connect(aCtx.destination);
onOSCend();
var stopped = false;
function onOSCend() {
osc = aCtx.createOscillator();
osc.onended = onOSCend;
osc.connect(silence);
osc.start(0);
osc.stop(aCtx.currentTime + freq);
callback(aCtx.currentTime);
if (stopped) {
osc.onended = function() {
return;
};
}
};
// return a function to stop our loop
return function() {
stopped = true;
};
}
function start() {
// start our loop @25fps
var stopAnim = audioTimerLoop(anim, 1000/25);
// maximum stream rate set as 25 fps
cStream = canvas.captureStream(25);
let chunks = [];
var recorder = new MediaRecorder(cStream);
recorder.ondataavailable = e => chunks.push(e.data);
recorder.onstop = e => {
// we can stop our loop
stopAnim();
var url = URL.createObjectURL(new Blob(chunks));
var v = document.createElement('video');
v.src = url;
v.controls = true;
document.body.appendChild(v);
}
recorder.start();
// stops the recorder in 20s, try to change tab during this time
setTimeout(function() {
recorder.stop();
}, 20000)
}
// make something move on the canvas
var ctx = canvas.getContext('2d');
var x = 0;
function anim() {
x = (x + 2) % (canvas.width + 100);
ctx.fillStyle = 'ivory';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'red';
ctx.fillRect(x - 50, 20, 50, 50)
};
start();
<canvas id="canvas" width="500" height="200"></canvas>
諾塔Bene的:
在這個例子中,我將頻率設置爲25fps的,但我們可以將其設置爲60fps的,它似乎甚至在我的舊筆記本電腦正常工作,至少用這樣一個簡單的動畫。
有趣的創意解決方案。我會試驗它。謝謝! – Brad