传输的 getUserMedia / MediaRecorder 视频格式大于请求的格式。怎么说?
transmitted getUserMedia / MediaRecorder video format larger than requested format. How to tell?
背景:
On Windows 10 我在 Google Chrome (v71) 中使用 getUserMedia (gUM) and MediaRecorder 来捕获和编码视频流。
- 我正在使用 gUM 的约束参数来告诉它我想要 352x288 的视频格式。
我请求 video/webm; codecs="avc1.42E01E"
作为编码流的 MIME 类型(即 Matroska 中的 H.264)。
我选择笔记本电脑内置的廉价网络摄像头作为视频源。它叫做 "EasyCamera" 由 DMAX-AVC 制作。很想叫它 CheezyCamera.
视频流生成得很好。
问题:
流中编码视频的尺寸是 440x360 而不是我请求的 352x288。此信息嵌入在记录的流中,并且仅对该数据的消费者可见。使用各种 API 显示 gUM 流、MediaRecorder 和 <video>
元素元数据都认为维度是我要求的维度。
当然,网络摄像头、gUM 和 MediaRecorder 将约束参数视为建议,并且可以自由地响应不同的内容。在这种情况下,当我请求 352x288 时,他们会以 440x360 响应。该系统按设计运行;那不是我的问题。
澄清一下,意外的 440x360 尺寸仅对录制流的消费者可见。我希望找到一种方法来了解制作方网络摄像头、gUM 和 MediaEncoder 信号链产生的分辨率与我要求的不同。
流消费者如何知道流维度?它们位于 'PixelWidth' 和 'PixelHeight' Matroska 盒子中,并且被烘焙到 H.264 流中。 (奇怪的是,考虑到这是一个软件选择的分辨率,它不是16x16宏块的整数。当然它仍然有效。)
我无法在浏览器中解析记录的数据,因为它存储在不透明的 blob 中。
当我使用不同的、更好的网络摄像头(罗技 C615)时,我的编码视频流是我请求的大小。
我的问题:
在网络摄像头/gUM/MediaRecorder/<video>
信号链中是否有任何方法可以在实际记录流的浏览器中找到编码流的实际尺寸 ?也就是说,我可以在不解码生成的流的情况下找到信号链对我的请求维度的响应吗?
使用 MediaStream.getVideoTracks()
method to get the video track (MediaStreamTrack), then use MediaStreamTrack.getSettings()
to get MediaTrackSettings 对象,其中包含流的视频的高度和宽度。
因此,如果我请求指定为约束的高度为 0 的视频,我将获得高度为 1 像素的视频。在流式传输时,我们可以检索我请求的高度和我作为输出获得的高度。
function handleMediaStream(mystream){
let videoStreamTrack = mystream.getVideoTracks()[0];
let constraints = videoStreamTrack.getConstraints();
console.log(constraints.width, constraints.height);
// outputs: 640 0
let settings = videoStreamTrack.getSettings();
console.log(settings.width, settings.height);
// outputs: 640 1
}
let videoConstraints = { width: 640, height: 0 }
navigator.mediaDevices.getUserMedia({ video: videoConstraints })
.then(function create_media_recorder(mystream) {
handleMediaStream(mystream);
});
您可能需要像 this test
中那样使用 exact
约束关键字
const sdPalConstraints = {
video: {width: {exact: 352}, height: {exact: 288}}
};
// Assuming |video| exists and represents a <video> element.
navigator.mediaDevices.getUserMedia(sdPalConstraints)
.then(stream) => {video.srcObject = stream};
这不能保证网络摄像头将以该分辨率进行流式传输,但如果生成的分辨率与请求的分辨率不同,VideoTrackAdapter 将参与为您(以及 MediaRecorder)进行调整。
我试过这个问题的其他回答者提供的各种东西后,我没有成功解决这个问题。
我断定这是网络摄像头到 Google Chrome 到 gUM 的信号链中某处的错误。
背景:
On Windows 10 我在 Google Chrome (v71) 中使用 getUserMedia (gUM) and MediaRecorder 来捕获和编码视频流。
- 我正在使用 gUM 的约束参数来告诉它我想要 352x288 的视频格式。
我请求
video/webm; codecs="avc1.42E01E"
作为编码流的 MIME 类型(即 Matroska 中的 H.264)。我选择笔记本电脑内置的廉价网络摄像头作为视频源。它叫做 "EasyCamera" 由 DMAX-AVC 制作。很想叫它 CheezyCamera.
视频流生成得很好。
问题:
流中编码视频的尺寸是 440x360 而不是我请求的 352x288。此信息嵌入在记录的流中,并且仅对该数据的消费者可见。使用各种 API 显示 gUM 流、MediaRecorder 和 <video>
元素元数据都认为维度是我要求的维度。
当然,网络摄像头、gUM 和 MediaRecorder 将约束参数视为建议,并且可以自由地响应不同的内容。在这种情况下,当我请求 352x288 时,他们会以 440x360 响应。该系统按设计运行;那不是我的问题。
澄清一下,意外的 440x360 尺寸仅对录制流的消费者可见。我希望找到一种方法来了解制作方网络摄像头、gUM 和 MediaEncoder 信号链产生的分辨率与我要求的不同。
流消费者如何知道流维度?它们位于 'PixelWidth' 和 'PixelHeight' Matroska 盒子中,并且被烘焙到 H.264 流中。 (奇怪的是,考虑到这是一个软件选择的分辨率,它不是16x16宏块的整数。当然它仍然有效。)
我无法在浏览器中解析记录的数据,因为它存储在不透明的 blob 中。
当我使用不同的、更好的网络摄像头(罗技 C615)时,我的编码视频流是我请求的大小。
我的问题:
在网络摄像头/gUM/MediaRecorder/<video>
信号链中是否有任何方法可以在实际记录流的浏览器中找到编码流的实际尺寸 ?也就是说,我可以在不解码生成的流的情况下找到信号链对我的请求维度的响应吗?
使用 MediaStream.getVideoTracks()
method to get the video track (MediaStreamTrack), then use MediaStreamTrack.getSettings()
to get MediaTrackSettings 对象,其中包含流的视频的高度和宽度。
因此,如果我请求指定为约束的高度为 0 的视频,我将获得高度为 1 像素的视频。在流式传输时,我们可以检索我请求的高度和我作为输出获得的高度。
function handleMediaStream(mystream){
let videoStreamTrack = mystream.getVideoTracks()[0];
let constraints = videoStreamTrack.getConstraints();
console.log(constraints.width, constraints.height);
// outputs: 640 0
let settings = videoStreamTrack.getSettings();
console.log(settings.width, settings.height);
// outputs: 640 1
}
let videoConstraints = { width: 640, height: 0 }
navigator.mediaDevices.getUserMedia({ video: videoConstraints })
.then(function create_media_recorder(mystream) {
handleMediaStream(mystream);
});
您可能需要像 this test
中那样使用exact
约束关键字
const sdPalConstraints = {
video: {width: {exact: 352}, height: {exact: 288}}
};
// Assuming |video| exists and represents a <video> element.
navigator.mediaDevices.getUserMedia(sdPalConstraints)
.then(stream) => {video.srcObject = stream};
这不能保证网络摄像头将以该分辨率进行流式传输,但如果生成的分辨率与请求的分辨率不同,VideoTrackAdapter 将参与为您(以及 MediaRecorder)进行调整。
我试过这个问题的其他回答者提供的各种东西后,我没有成功解决这个问题。
我断定这是网络摄像头到 Google Chrome 到 gUM 的信号链中某处的错误。