电子屏幕录制卡在 <10fps
Posted
技术标签:
【中文标题】电子屏幕录制卡在 <10fps【英文标题】:Electron screen recording stuck at <10fps 【发布时间】:2022-01-07 13:13:07 【问题描述】:目标:
我想运行一个记录特定窗口约 2 分钟视频的电子应用程序。窗口是图像,而不是文本,所以我想要高清和 >=60 帧每秒。我只需要它在窗口平台上工作。捕获音频会很好,但不是我的首要任务。
我的尝试:
我查看了一些在线示例并想出了如何:
我使用electron的desktopCapturer.getSources()
来查找我感兴趣的具体窗口源
然后我使用navigator.mediaDevices.getUserMedia()
将该窗口源转换为MediaStream
。
然后我使用MediaRecorder
从MediaStream
收集记录块
我将块聚合到 Blob
,转换为 ArrayBuffer
,然后是 Buffer
。
由于MediaRecorder
不支持.mp4
,我使用基于ffmpeg
构建的npm 包将webm 缓冲区转换为mp4 缓冲区。
我使用 node 的 fs
将 webm 和 mp4 缓冲区写入 2 个文件。
这工作正常。 mp4 文件存在一些元数据问题,导致某些视频播放器无法播放,而其他视频播放器可以播放;我不太关心这个。 webm 视频播放良好。
问题:
录制的帧速率非常低。文件属性没有提到每秒帧数或比特率,这些字段只是空白。但它似乎每秒 5 帧。如果可能的话,我想要至少 30 个或更多。
我console.log
mediaStream 的视频轨道的帧速率为 30。我将写入文件短路,只是将 mediaStream 流式传输到 <video>
元素,但我仍然得到低帧,所以 MediaRecorder
,并且写入文件不负责。
简单示例:
const desktopCapturer = require('electron');
let source, stream, track;
desktopCapturer.getSources(types: ['window']).then(async sources =>
// Get the stream
source = sources.find(source => source.name === 'My Window');
stream = await navigator.mediaDevices.getUserMedia(
audio: false,
video:
mandatory:
chromeMediaSource: "desktop",
chromeMediaSourceId: source.id,
,
,
);
// Print some info about the stream
track = stream.getVideoTracks()[0];
let obj =
settings: track.getSettings(),
constraints: track.getConstraints(),
capabilities: track.getCapabilities(),
;
console.log(JSON.stringify(obj, null, 2));
// Project to a <video> element
let video = document.querySelector('video');
if (!video)
video = document.createElement('video');
document.body.appendChild(video);
video.srcObject = stream;
video.onloadedmetadata = () => video.play();
);
Track 控制台日志:
"settings":
"aspectRatio": 1.7777777777777777,
"deviceId": "window:4982682:0",
"frameRate": 30,
"height": 1440,
"resizeMode": "crop-and-scale",
"width": 2560
,
"constraints":
"deviceId":
"exact": "window:4982682:0"
,
"capabilities":
"aspectRatio":
"max": 2560,
"min": 0.0006944444444444445
,
"deviceId": "window:4982682:0",
"facingMode": [],
"frameRate":
"max": 30,
"min": 0
,
"height":
"max": 1440,
"min": 1
,
"resizeMode": [
"none",
"crop-and-scale"
],
"width":
"max": 2560,
"min": 1
Chrome 浏览器示例:
我尝试在 chrome 浏览器中做同样的事情并遇到同样的问题。所以它似乎不是电子特定的。如果我选择与使用电子记录相同的窗口,则 chrome 具有相同的
// Run this in the dev console
stream = await navigator.mediaDevices.getDisplayMedia();
let video = document.querySelector('video');
if (!video)
video = document.createElement('video');
document.body.appendChild(video);
video.srcObject = stream;
video.onloadedmetadata = () => video.play();
[编辑] 部分修复:
禁用窗口的“后台录制”设置后,我看到流的 fps 有了很大的提高。不过,它仍然不如内置窗口的 xbox-game-bar 录制(我正在尝试替换)那么流畅。
【问题讨论】:
【参考方案1】:您对 .getUserMedia() 的调用提到了有关源设备的一些视频限制。要控制帧率,向约束对象添加
frameRate: min: 10, ideal: 60, max: 60
也可以使用其他限制条件,例如大小。 See this.
最好使用 min / Ideal / max 而不是仅仅说
frameRate: 60
如果你给出一个最小/理想/最大范围,即使捕捉无法保持更高的帧速率,你也会得到一些东西。
您在 MediaRecorder 构造函数中设置压缩视频数据流的带宽。你没有问这个。
【讨论】:
也许我误解了在线文档/解释,但我的理解是frameRate
约束对网络摄像头有效,但对屏幕截图无效。当我尝试使用它时,我得到"Unknown name of constraint detected" / "frameRate"
错误
你是对的。这是一个相关的问题。 ***.com/questions/70142727/…
maxFrameRate
,就像您链接的问题一样,确实会影响流 fps。但是当我将minFrameRate
设置为 60 或 120 时,它并没有什么不同。而且它明显比 widow 的 xbox-game-bar 录音更不稳定。以上是关于电子屏幕录制卡在 <10fps的主要内容,如果未能解决你的问题,请参考以下文章