Javascript 如何正确地从画布记录流?
情况:Javascript 如何正确地从画布记录流?,javascript,html,vue.js,html5-canvas,web-mediarecorder,Javascript,Html,Vue.js,Html5 Canvas,Web Mediarecorder,情况: <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.isTyp
<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);
})
我需要做以下工作:
- 从
中获取视频并在
中播放 - 将画布中的流记录为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);
})
结果:
<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);
})
这是ondataavailable
事件的console.log
:
这是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);
})
这是JsFiddle。您可以在控制台中检查结果:
浏览器行为:
<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);
})
这种行为(Blob数据大小:0)发生在Chrome和Opera上
在firefox上,它的行为略有不同。
它记录一个非常小的视频块(725字节)。视频长度应该是5秒,但它只是一个黑屏
问题:
<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);
})
从画布记录流的正确方法是什么
代码中有什么错误吗
你知道为什么这一团是空的吗
谢谢 MediaRecorder.stop()是一种异步方法
在stop算法中,有一个对requestData的调用,requestData本身会将一个任务排队,以使用自上次此类事件以来的当前可用数据触发一个事件dataavailable
这意味着,在调用MediaRecorder#stop()之后,最后捕获的数据将不会成为allChunks
数组的一部分。不久之后,它们将变为(通常在同一事件循环中)
因此,当您准备保存从MediaRecorder录制的录音时,请确保始终从事件生成最后一个Blob,这将表示MediaRecorder实际上已结束,已触发其最后一个dataavailable事件,并且一切正常
一开始我遗漏了一件事,那就是你正在请求一个跨域视频。这样做,如果没有正确的跨源请求,将使画布(和MediaElement)受到污染,因此您的MediaStream将被静音
由于您试图请求的视频来自wikimedia,您可以简单地将其作为跨源资源请求,但对于其他资源,您必须确保服务器配置为允许这些请求
const canvas=document.querySelector(“canvas”)
const ctx=canvas.getContext(“2d”)
const video=document.querySelector(“视频”)
//在播放器中启动视频
视频播放()
//播放事件-在画布中绘制视频
video.addEventListener('play',()=>{
函数步骤(){
ctx.drawImage(视频,0,0,canvas.width,canvas.height)
requestAnimationFrame(步骤)
}
请求动画帧(步骤);
//初始化流和记录器
const stream=canvas.captureStream()
常量记录器=新媒体记录器(流{
mimeType:“视频/webm”,
});
//获取blob数据(如果可用)
让allChunks=[];
recorder.ondataavailable=功能(e){
allChunks.push(如数据);
}
recorder.onstop=(e)=>{
const fullBlob=新Blob(所有块,{'type':'video/webm'});
const downloadUrl=window.URL.createObjectURL(fullBlob)
console.log({fullBlob})
console.log({downloadUrl})
}
//开始记录
recorder.start()
//5秒后停止记录器并检查结果
设置超时(()=>{
录音机停止
}, 5000);
})
From,您似乎需要向流中添加一个或多个曲目。有趣。感谢@Geert Jan的指点。尽管captureStream文档中没有提到这一点:它似乎应该是现成的。谢谢@kaido的回答!我已经尝试过了,并将blob的创建移到了onstop
事件中。不幸的是,这个斑点仍然是空的。正如您在这里看到的:@FrancescoMussi您在这把小提琴中使用了一个跨源视频。那肯定不行,因为你的画布被污染了。添加注释作为编辑。非常感谢@kaido!你的两个建议就是解决问题的办法!现在一切都很好!