我可以从 javascript 中隐藏的 canvas 捕获流吗?
Can I capture stream from a hidden canvas in javascript?
我目前正在开发一个 API 将 videoTrack 作为输入并 return 处理过的 videoTrack。我已经设法在 canvas 上绘制处理后的视频,并希望使用 canvas.captureStream()
从中捕获视频流。
事实证明,只有当我将 canvas 加载到 DOM document.body.appendChild(myTempCanvas)
并保持显示时,我才能捕获非空白流,如果我隐藏了 canvas myTempCanvas.style.display="none"
.
那么有什么方法可以捕获流并隐藏 canvas 吗?
示例:如果取消注释行 canvas.style.display = "none";
,则 output_video 也会变为空白。
<!DOCTYPE html>
<html lang="en">
<head>
<title>Demo</title>
</head>
<body>
<div class="container">
<video autoplay class="input_video" ></video>
<canvas class="output_canvas"></canvas>
<video autoplay class="output_video" ></video>
</div>
<script>
const video = document.getElementsByClassName("input_video")[0];
const canvas = document.getElementsByClassName("output_canvas")[0];
const output_video = document.getElementsByClassName("output_video")[0];
let imageCapture = null;
let tmpStream = null;
navigator.mediaDevices.getUserMedia({
video: true
})
.then((stream) => {
imageCapture = new ImageCapture(stream.getVideoTracks()[0]);
window.requestAnimationFrame(frameloop);
tmpStream = canvas.captureStream(20);
// canvas.style.display = "none";
output_video.srcObject = tmpStream;
})
function frameloop() {
imageCapture.grabFrame()
.then(imageBitmap => {
drawCanvas(canvas, imageBitmap);
window.requestAnimationFrame(frameloop);
})
}
/* Utils */
function drawCanvas(canvas, img) {
canvas.width = getComputedStyle(canvas).width.split('px')[0];
canvas.height = getComputedStyle(canvas).height.split('px')[0];
let ratio = Math.min(canvas.width / img.width, canvas.height / img.height);
let x = (canvas.width - img.width * ratio) / 2;
let y = (canvas.height - img.height * ratio) / 2;
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height,
x, y, img.width * ratio, img.height * ratio);
}
</script>
</body>
</html>
</script>
</body>
</html>
在您的 drawCanvas
函数中,您将 canvas 宽度和高度设置为其计算的 CSS 宽度和高度。
当您通过 display:none
隐藏 canvas 时,或者未将其附加到文档中时,这些值将为 "0px"
,因为 canvas 不在 [=23= 中]OM.
宽度或高度为零的 canvas 无法生成任何输出。
设置 canvas 宽度或高度是一个非常慢的操作,在 Chrome 中,每次这样做都会分配一个全新的图像位图,添加到所有 canvas上下文的默认值。
所以永远不要在所有帧中设置 canvas 宽度或高度,只有当它确实发生变化时,并且不要将它设置为你的 <canvas>
元素的计算大小,将它设置为你的大小输入图像,然后相应地设置 CSS 大小。
我目前正在开发一个 API 将 videoTrack 作为输入并 return 处理过的 videoTrack。我已经设法在 canvas 上绘制处理后的视频,并希望使用 canvas.captureStream()
从中捕获视频流。
事实证明,只有当我将 canvas 加载到 DOM document.body.appendChild(myTempCanvas)
并保持显示时,我才能捕获非空白流,如果我隐藏了 canvas myTempCanvas.style.display="none"
.
那么有什么方法可以捕获流并隐藏 canvas 吗?
示例:如果取消注释行 canvas.style.display = "none";
,则 output_video 也会变为空白。
<!DOCTYPE html>
<html lang="en">
<head>
<title>Demo</title>
</head>
<body>
<div class="container">
<video autoplay class="input_video" ></video>
<canvas class="output_canvas"></canvas>
<video autoplay class="output_video" ></video>
</div>
<script>
const video = document.getElementsByClassName("input_video")[0];
const canvas = document.getElementsByClassName("output_canvas")[0];
const output_video = document.getElementsByClassName("output_video")[0];
let imageCapture = null;
let tmpStream = null;
navigator.mediaDevices.getUserMedia({
video: true
})
.then((stream) => {
imageCapture = new ImageCapture(stream.getVideoTracks()[0]);
window.requestAnimationFrame(frameloop);
tmpStream = canvas.captureStream(20);
// canvas.style.display = "none";
output_video.srcObject = tmpStream;
})
function frameloop() {
imageCapture.grabFrame()
.then(imageBitmap => {
drawCanvas(canvas, imageBitmap);
window.requestAnimationFrame(frameloop);
})
}
/* Utils */
function drawCanvas(canvas, img) {
canvas.width = getComputedStyle(canvas).width.split('px')[0];
canvas.height = getComputedStyle(canvas).height.split('px')[0];
let ratio = Math.min(canvas.width / img.width, canvas.height / img.height);
let x = (canvas.width - img.width * ratio) / 2;
let y = (canvas.height - img.height * ratio) / 2;
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height,
x, y, img.width * ratio, img.height * ratio);
}
</script>
</body>
</html>
</script>
</body>
</html>
在您的 drawCanvas
函数中,您将 canvas 宽度和高度设置为其计算的 CSS 宽度和高度。
当您通过 display:none
隐藏 canvas 时,或者未将其附加到文档中时,这些值将为 "0px"
,因为 canvas 不在 [=23= 中]OM.
宽度或高度为零的 canvas 无法生成任何输出。
设置 canvas 宽度或高度是一个非常慢的操作,在 Chrome 中,每次这样做都会分配一个全新的图像位图,添加到所有 canvas上下文的默认值。
所以永远不要在所有帧中设置 canvas 宽度或高度,只有当它确实发生变化时,并且不要将它设置为你的 <canvas>
元素的计算大小,将它设置为你的大小输入图像,然后相应地设置 CSS 大小。