使用媒体流扩展 (MSE) 显示 getUserMedia Stream 实时视频

2024-03-08

我正在尝试使用 getUserMedia 显示从网络摄像头获取的 MediaStream,并使用任何可能播放的机制将其中继到远程对等点(作为实验)。我没有直接使用 webRTC,因为我想控制原始数据。

我遇到的问题是我的视频元素不显示任何内容,并且我没有收到任何错误。我在 Elementary OS(基于 Ubuntu 14.04 的 Linux 操作系统)上使用 Chrome 版本 51.0.2704.103(64 位)。

作为旁注,如果我将所有 blob 记录到一个数组中,然后创建一个新的 blob 并将视频的 src 元素设置为 URL.createObjectUrl(blob),它将正确显示视频。

这是我尝试实现此目的的代码(减去中继,我只是尝试在本地播放它):

var ms = new MediaSource();
var video = document.querySelector("video"); 
video.src = window.URL.createObjectURL(ms);

ms.addEventListener("sourceopen", function() {
    var sourceBuffer = ms.addSourceBuffer('video/webm; codecs="vorbis,vp8"');

    navigator.getUserMedia({video: {width: 320, height: 240, framerate: 30}, audio: true}, function(stream) {
        var recorder = new MediaRecorder(stream);

        recorder.ondataavailable = function(event) {
            var reader = new FileReader();
            reader.addEventListener("loadend", function () {
                var uint8Chunk = new Uint8Array(reader.result);
                if (!sourceBuffer.updating) {
                    sourceBuffer.appendBuffer(uint8Chunk);
                }
                if (video.paused) video.play();
            });
            reader.readAsArrayBuffer(event.data);
        };

        recorder.start(10);
    }, function(error) {
        console.error(error);
    });
}, false);

这是我在 chrome://media-internal 中获得的信息:

render_id: 147
player_id: 0
pipeline_state: kPlaying
event: WEBMEDIAPLAYER_CREATED
url: blob:http%3A//localhost%3A8080/e5c51dd8-5709-4e6f-9457-49ac8c34756b
found_audio_stream: true
audio_codec_name: opus
found_video_stream: true
video_codec_name: vp8
duration: unknown
audio_dds: false
audio_decoder: OpusAudioDecoder
video_dds: false
video_decoder: FFmpegVideoDecoder

还有日志:

00:00:00 00 pipeline_state  kCreated
00:00:00 00 event   WEBMEDIAPLAYER_CREATED
00:00:00 00 url blob:http%3A//localhost%3A8080/e5c51dd8-5709-4e6f-9457-49ac8c34756b
00:00:00 00 pipeline_state  kInitDemuxer
00:00:01 603    found_audio_stream  true
00:00:01 603    audio_codec_name    opus
00:00:01 603    found_video_stream  true
00:00:01 603    video_codec_name    vp8
00:00:01 604    duration    unknown
00:00:01 604    pipeline_state  kInitRenderer
00:00:01 604    audio_dds   false
00:00:01 604    audio_decoder   OpusAudioDecoder
00:00:01 604    video_dds   false
00:00:01 604    video_decoder   FFmpegVideoDecoder
00:00:01 604    pipeline_state  kPlaying

更新:我尝试将数据发送到节点并使用 ffmpeg (fluent-ffmpeg) 将其保存到 webm 文件中,并且我可以在 VLC 中正确查看该文件。

更新 2:从节点流回后,我得到以下信息:Media segment did not contain any video coded frames, mismatching initialization segment. Therefore, MSE coded frame processing may not interoperably detect discontinuities in appended media. 。经过一些研究后,似乎 webm 文件必须分段才能工作,但是我还没有找到针对实时流执行此操作的方法(使用 ffmpeg 或其他工具)。这里有什么想法吗?


有点晚了,但你可以像这样尝试(在 Chrome 中):

<html>

<body>
    <video class="real1" autoplay controls></video>
    <video class="real2" controls></video>

    <script>
        const constraints = {video: {width: 320, height: 240, framerate: 30}, audio: true};

        const video1 = document.querySelector('.real1');
        const video2 = document.querySelector('.real2');

        var mediaSource = new MediaSource();
        video2.src = window.URL.createObjectURL(mediaSource);
        var sourceBuffer;
        mediaSource.addEventListener('sourceopen', function () {
            sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs=opus,vp8');
            console.log(sourceBuffer);
        })

        var isFirst = true;
        var mediaRecorder;
        var i = 0;
        function handleSuccess(stream) {
            video1.srcObject = stream;
            mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm; codecs=opus,vp8' });
            console.log(mediaRecorder.mimeType)
            mediaRecorder.ondataavailable = function (e) {
                var reader = new FileReader();
                reader.onload = function (e) {              
                    sourceBuffer.appendBuffer(new Uint8Array(e.target.result));
                }
                reader.readAsArrayBuffer(e.data);

                if (video2.paused) {
                    video2.play(0);
                }
            }
            mediaRecorder.start(20);
        }

        function handleError(error) {
            console.error('Reeeejected!', error);
        }
        navigator.mediaDevices.getUserMedia(constraints).
            then(handleSuccess).catch(handleError);
    </script>
</body>

</html>

我认为您错过了为记录器和 sourceBuffer 设置相同(支持的)编解码器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用媒体流扩展 (MSE) 显示 getUserMedia Stream 实时视频 的相关文章

随机推荐