【发布时间】: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 录制(我正在尝试替换)那么流畅。
【问题讨论】:
标签: javascript electron getusermedia mediastream mediadevices