Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何正确地从画布记录流?_Javascript_Html_Vue.js_Html5 Canvas_Web Mediarecorder - Fatal编程技术网

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

就这样。第一部分没问题。 对于第二部分,我设法记录了一个Blob,问题是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!你的两个建议就是解决问题的办法!现在一切都很好!