Как преобразовать массив данных PNG изображения в видео файл
Я получаю кадры от canvas
через canvas.getDataURL()
,
Тем не менее, теперь у меня есть массив изображений PNG, но я хочу видео файл.
Как мне это сделать?
var canvas = document.getElementById("mycanvaselementforvideocapturing");
var pngimages = [];
...
setInterval(function(){pngimages.push(canvas.toDataURL())}, 1000);
2 ответа
Для полной поддержки браузера вам необходимо отправить пакет изображений на сервер, а затем использовать некую серверную программу для кодирования.
Но в новейших браузерах canvas.captureStream
метод, был реализован. Он преобразует ваши холст рисунки в видеопоток webm, записываемый с MediaRecorder
, Однако все это еще не стабилизировано и будет доступно только в последних версиях браузеров, возможно, с некоторыми флагами, установленными в настройках пользователя (например, для chrome требуется "Экспериментальная веб-платформа").
var cStream,
recorder,
chunks = [];
rec.onclick = function() {
this.textContent = 'stop recording';
// set the framerate to 30FPS
var cStream = canvas.captureStream(30);
// create a recorder fed with our canvas' stream
recorder = new MediaRecorder(cStream);
// start it
recorder.start();
// save the chunks
recorder.ondataavailable = saveChunks;
recorder.onstop = exportStream;
// change our button's function
this.onclick = stopRecording;
};
function saveChunks(e) {
chunks.push(e.data);
}
function stopRecording() {
recorder.stop();
}
function exportStream(e) {
// combine all our chunks in one blob
var blob = new Blob(chunks)
// do something with this blob
var vidURL = URL.createObjectURL(blob);
var vid = document.createElement('video');
vid.controls = true;
vid.src = vidURL;
vid.onended = function() {
URL.revokeObjectURL(vidURL);
}
document.body.insertBefore(vid, canvas);
}
// make something move on the canvas
var x = 0;
var ctx = canvas.getContext('2d');
var anim = function() {
x = (x + 2) % (canvas.width + 100);
// there is no transparency in webm,
// so we need to set a background otherwise every transparent pixel will become opaque black
ctx.fillStyle = 'ivory';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'black';
ctx.fillRect(x - 50, 20, 50, 50)
requestAnimationFrame(anim);
};
anim();
<canvas id="canvas" width="500" height="200"></canvas>
<button id="rec">record</button>
И поскольку вы попросили добавить аудио к этому видео, обратите внимание, что вы можете использовать cStream.addTrack(anAudioStream.getAudioTracks()[0]);
перед звонком new MediaRecorder(cStream)
, но в настоящее время это будет работать только в Chrome, FF, похоже, имеет ошибку в MediaRecorder, которая заставляет его записывать только поток с дорожками, для которых он был определен... Обходной путь для FF - вызов new MediaStream([videoTrack, audioTrack]);
[большое спасибо @jib за то, что он дал мне знать, как его использовать...]
Редактировать: video.onend
-> video.onended
MediaRecorder
+ canvas.captureStream
Подход в ответе Кайидо определенно является подходом на данный момент - к сожалению, на момент написания он поддерживается только в Chrome и Firefox.
Другой подход, который будет работать, когда браузеры принимают поддержку кодирования webp (в настоящее время есть только в Chrome), заключается в следующем:
let frames = []; // <-- frames must be *webp* dataURLs
let webmEncoder = new Whammy.Video(fps);
frames.forEach(f => webmEncoder.add(f));
let blob = await new Promise(resolve => webmEncoder.compile(false, resolve));
let videoBlobUrl = URL.createObjectURL(blob);
Он использует библиотеку whammy, чтобы объединить несколько изображений webp в видео webm. В браузерах, которые поддерживают кодирование webp вы можете написать canvas.toDataURL("image/webp")
чтобы получить dataURL webp с холста. Это соответствующий отчет об ошибке для поддержки Firefox webp.
Один из кросс-браузерных подходов на момент написания статьи, похоже, заключается в использовании libwebp.js для преобразования png dataURLs в canvas.toDataURL()
в webp-изображения, а затем подает их в кодировщик wammy для получения окончательного webm-видео. К сожалению, процесс кодирования png ->webp очень медленный (несколько минут на несколько секунд видео на моем ноутбуке).
Изменить: я обнаружил, что с MediaRecorder
/captureStream
подход, вы можете получить низкое качество выходного видео по сравнению с ненормальным подходом. Таким образом, если нет какого-либо способа контролировать качество захваченного потока, whammy
подход кажется лучшим подходом, а два других являются запасными. Смотрите этот вопрос для более подробной информации. Используйте этот фрагмент, чтобы определить, поддерживает ли браузер webp
кодирование (и, следовательно, поддерживает фиктивный подход):
let webPEncodingIsSupported = document.createElement('canvas').toDataURL('image/webp').startsWith('data:image/webp');