#javascript #firefox #chromium #capture #mediarecorder-api
#javascript #firefox #chromium #захват #mediarecorder-api
Вопрос:
Используя оригинал javascript
в MediaRecorder-examples/record-canvas-to-video.js
Требования к программному обеспечению
- Firefox 45. Это техническая демонстрация Firefox. Поэтому он может не работать в вашем браузере, если он не реализует то, что мы демонстрируем. На момент написания (январь 2016) вам необходимо загрузить либо Firefox Developer Edition, либо Firefox Nightly.
window.onload = function () {
var video = document.getElementById('video');
var canvas = document.getElementById('canvas');
var width = canvas.width;
var height = canvas.height;
var capturing = false;
video.width = width;
video.height = height;
// We need the 2D context to individually manipulate pixel data
var ctx = canvas.getContext('2d');
// Start with a black background
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, width, height);
// Since we're continuously accessing and overwriting the pixels
// object, we'll request it once and reuse it across calls to draw()
// for best performance (we don't need to create ImageData objects
// on every frame)
var pixels = ctx.getImageData(0, 0, width, height);
var data = pixels.data;
var numPixels = data.length;
var stream = canvas.captureStream(15);
var recorder = new MediaRecorder(stream);
recorder.addEventListener('dataavailable', finishCapturing);
startCapturing();
recorder.start();
setTimeout(function() {
recorder.stop();
}, 2000);
function startCapturing() {
capturing = true;
draw();
}
function finishCapturing(e) {
capturing = false;
var videoData = [ e.data ];
var blob = new Blob(videoData, { 'type': 'video/webm' });
var videoURL = URL.createObjectURL(blob);
video.src = videoURL;
video.play();
}
function draw() {
// We don't want to render again if we're not capturing
if(capturing) {
requestAnimationFrame(draw);
}
drawWhiteNoise();
}
function drawWhiteNoise() {
var offset = 0;
for(var i = 0; i < numPixels; i ) {
var grey = Math.round(Math.random() * 255);
// The data array has pixel values in RGBA order
// (Red, Green, Blue and Alpha for transparency)
// We will make R, G and B have the same value ('grey'),
// then skip the Alpha value by increasing the offset,
// as we're happy with the opaque value we set when painting
// the background black at the beginning
data[offset ] = grey;
data[offset ] = grey;
data[offset ] = grey;
offset ; // skip the alpha component
}
// And tell the context to draw the updated pixels in the canvas
ctx.putImageData(pixels, 0, 0);
}
};
выдает ошибки в chromium 55
Uncaught (in promise) DOMException: The play() request was interrupted by a new load request.
Failed to load resource: the server responded with a status of 416 (Requested Range Not Satisfiable)
хотя возвращает ожидаемый результат в firefox 52.
Настройка javascript
для использования в chromium путем нажатия Blob
на dataavailable
событие MediaRecorder
в массив, затем конкатенации больших двоичных объектов в stop
событии
window.onload = function () {
var blobs = [];
var video = document.getElementById('video');
var canvas = document.getElementById('canvas');
var width = canvas.width;
var height = canvas.height;
var capturing = false;
video.width = width;
video.height = height;
// We need the 2D context to individually manipulate pixel data
var ctx = canvas.getContext('2d');
// Start with a black background
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, width, height);
// Since we're continuously accessing and overwriting the pixels
// object, we'll request it once and reuse it across calls to draw()
// for best performance (we don't need to create ImageData objects
// on every frame)
var pixels = ctx.getImageData(0, 0, width, height);
var data = pixels.data;
var numPixels = data.length;
var stream = canvas.captureStream(15);
var recorder = new MediaRecorder(stream);
recorder.addEventListener('dataavailable', finishCapturing);
recorder.addEventListener('stop', function(e) {
video.oncanplay = video.play;
video.src = URL.createObjectURL(new Blob(blobs, {type:"video/webm"}));
});
startCapturing();
recorder.start();
setTimeout(function() {
capturing = false;
recorder.stop();
}, 2000);
function startCapturing() {
capturing = true;
draw();
}
function finishCapturing(e) {
blobs.push(e.data);
}
function draw() {
// We don't want to render again if we're not capturing
if(capturing) {
requestAnimationFrame(draw);
}
drawWhiteNoise();
}
function drawWhiteNoise() {
var offset = 0;
for(var i = 0; i < numPixels; i ) {
var grey = Math.round(Math.random() * 255);
// The data array has pixel values in RGBA order
// (Red, Green, Blue and Alpha for transparency)
// We will make R, G and B have the same value ('grey'),
// then skip the Alpha value by increasing the offset,
// as we're happy with the opaque value we set when painting
// the background black at the beginning
data[offset ] = grey;
data[offset ] = grey;
data[offset ] = grey;
offset ; // skip the alpha component
}
// And tell the context to draw the updated pixels in the canvas
ctx.putImageData(pixels, 0, 0);
}
};
визуализирует записанный поток аналогично firefox.
Однако настройки, внесенные для воспроизведения видео как в firefox, так и в chromium, отображаются с очевидной минимальной, хотя и заметной задержкой между объединенными большими двоичными объектами.
Как мы можем визуализировать то же визуальное воспроизведение canvas.captureStream()
записанного с использованием MediaRecorder()
<video>
элемента at?
Комментарии:
1. Пример, на который вы ссылаетесь, устарел (см. MDN для более современного примера , который также работает с Chrome), поэтому я думаю, вы можете сократить размер своего вопроса вдвое. s / blobs / chunks/
2. @jib Да, хотя заметили ли вы разницу в воспроизведении записанного
canvas
между firefox и chromium, chrome?
Ответ №1:
Здесь вы управляете анимацией из основного потока JS, поэтому возможно, что другие действия JS основного потока, такие как запуск ondataavailable
обратного вызова, могут нарушить синхронизацию настолько, чтобы быть заметными.
Попробуйте опустить частоту кадров (60) в canvas.captureStream()
вызове.
MDN говорит: «Если не задано, новый кадр будет записываться каждый раз при изменении холста; если установлено значение 0, будет записан один единственный кадр».
Мы надеемся, что это должно сделать вывод более невосприимчивым к таким прерываниям за счет незначительного сокращения его длины.
Вы также можете указать временной интервал с помощью метода start, например recorder.start(2000)
, чтобы ограничить время срабатывания dataavailable
события, чтобы избежать прерываний.
Комментарии:
1. Пропуск
60
в качестве параметра, поcanvas.captureStream()
-видимому, возвращает ожидаемый результат.