局势:
我需要做到以下几点:
<video>
获取视频和<canvas>
里面玩而已。第一部分是好的。对于第二部分,我设法记录的Blob,问题是,斑点是空的。
风景:
<video id="video" controls="true" src="http://upload.wikimedia.org/wikipedia/commons/7/79/Big_Buck_Bunny_small.ogv"></video>
<canvas id="myCanvas" width="532" height="300"></canvas>
编码:
// Init
console.log(MediaRecorder.isTypeSupported('video/webm')) // true
const canvas = document.querySelector("canvas")
const ctx = canvas.getContext("2d")
const video = document.querySelector("video")
// Start the video in the player
video.play()
// On play event - draw the video in the canvas
video.addEventListener('play', () => {
function step() {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
requestAnimationFrame(step)
}
requestAnimationFrame(step);
// Init stream and recorder
const stream = canvas.captureStream()
const recorder = new MediaRecorder(stream, {
mimeType: 'video/webm',
});
// Get the blob data when is available
let allChunks = [];
recorder.ondataavailable = function(e) {
console.log({e}) // img1
allChunks.push(e.data);
}
// Start to record
recorder.start()
// Stop the recorder after 5s and check the result
setTimeout(() => {
recorder.stop()
const fullBlob = new Blob(allChunks, { 'type' : 'video/webm' });
const downloadUrl = window.URL.createObjectURL(fullBlob)
console.log({fullBlob}) // img2
}, 5000);
})
结果:
在console.log
事件的这个ondataavailable
:
这是块的console.log
:
小提琴:
这里是的jsfiddle。您可以检查在控制台的结果:
https://jsfiddle.net/1b7v2pen/
BROWSERS行为:
这种行为(BLOB数据大小:0),它发生在Chrome和Opera。 在Firefox上它的表现略有不同。它记录了一个非常小的视频斑点(725个字节)。视频长度为5秒,因为它应该的,但它只是一个黑屏。
问题:
什么是记录的正确方法从画布流? 这是一个错误的代码? 你知道为什么一滴出来是空的?
谢谢!
MediaRecorder.stop()
是一种异步方法的。
在停止算法,也就是一个的RequestData电话,这本身将队列的任务时触发事件dataavailable与自上次事件等当前可用的数据。
这意味着,在同步你叫MediaRecorder#停止()抢下不会是你allChunks
阵列的一部分,但最后的数据。他们将成为后(通常在同一事件循环)没有那么长。
所以,当您要保存所有来自MediaRecorder制作的视频,一定要始终建立从MediaRecorder's onstop
事件的最后一滴,这将标志着该MediaRecorder实际上是结束,没有触发其最后dataavailable事件,而这一切都是好的。
还有一两件事,我错过了第一个,是你请求跨域视频。这样做,没有正确的跨域请求,会令你的画布(与MediaElement的)污染,所以你MediaStream将静音。
既然你正试图要求该视频来自维基,你可以简单地要求它作为一个跨源资源,但对于其他的资源,你必须确保服务器被配置为允许这些请求。
const canvas = document.querySelector("canvas")
const ctx = canvas.getContext("2d")
const video = document.querySelector("video")
// Start the video in the player
video.play()
// On play event - draw the video in the canvas
video.addEventListener('play', () => {
function step() {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
requestAnimationFrame(step)
}
requestAnimationFrame(step);
// Init stream and recorder
const stream = canvas.captureStream()
const recorder = new MediaRecorder(stream, {
mimeType: 'video/webm',
});
// Get the blob data when is available
let allChunks = [];
recorder.ondataavailable = function(e) {
allChunks.push(e.data);
}
recorder.onstop = (e) => {
const fullBlob = new Blob(allChunks, { 'type' : 'video/webm' });
const downloadUrl = window.URL.createObjectURL(fullBlob)
console.log({fullBlob})
console.log({downloadUrl})
}
// Start to record
recorder.start()
// Stop the recorder after 5s and check the result
setTimeout(() => {
recorder.stop()
}, 5000);
})
<!--add the 'crossorigin' attribute to your video -->
<video id="video" controls="true" src="https://upload.wikimedia.org/wikipedia/commons/7/79/Big_Buck_Bunny_small.ogv" crossorigin="anonymous"></video>
<canvas id="myCanvas" width="532" height="300"></canvas>
另外,我无法避免要注意的是,如果你不从你的画布做任何特别的图纸,你可能想直接保存视频源,或者至少,直接记录的<video>的captureStream MediaStream。