当前位置: 首页 > 知识库问答 >
问题:

使用带socket.io的媒体源无法从媒体记录器跳转到流

施利
2023-03-14

下面的代码在先加载视频观察客户端,然后再加载网络摄像头客户端的情况下工作,但是,如果顺序被切换或以任何方式中断流(例如,通过刷新任一客户端),流将失败,媒体源将其就绪状态更改为关闭。

我的假设是,在开始时接收的视频需要初始化头来启动,因为流是在中段读取的,所以它从来没有得到所说的初始化头。我甚至不确定如何将这样的头添加到webm文件中。

我试图改变源缓冲区上的序列模式,但什么也没做。我已经尝试重新启动录像机,这是有效的,但我的最终计划是有多个观察客户机,每次重新连接时重新启动录像机并不是最佳的。

摄像机客户端

main();
function main() {
    if (hasGetUserMedia()) {
        const constraints = {
            video: {
                facingMode: 'environment',
                frameRate: {
                    ideal: 10,
                    max: 15
                }
            },
            audio: true
        };

        navigator.mediaDevices.getUserMedia(constraints).
        then(stream => {
            setupRecorder(stream);
        });
    }
}

function setupRecorder(stream) {
    let mediaRecorder = new MediaRecorder(stream, {
        mimeType: 'video/webm; codecs="opus, vp9"'
    });

    mediaRecorder.ondataavailable = e => {
        var blob = e.data;
        socket.emit('video', blob);
    }

    mediaRecorder.start(500);
}
var sourceBuffer;
var queue = [];
var mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', sourceOpen, false);
main();

socket.on('stream', data => {
    if (mediaSource.readyState == "open") {
        if (sourceBuffer.updating || queue.length > 0) {
            queue.push(data.video);
        } else {
            sourceBuffer.appendBuffer(data.video);
        }
    }
});

function main() {
    videoElement = document.querySelector('#video');
    videoElement.src = URL.createObjectURL(mediaSource);
}

function sourceOpen(e) {
    console.log('open');
    sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="opus, vp9"');
    sourceBuffer.addEventListener('updateend', () => {
        console.log(sourceBuffer.updating, mediaSource.readyState);

        if (queue.length > 0 && !sourceBuffer.updating) {
            sourceBuffer.appendBuffer(queue.shift());
        }
    });
}

所以代码,实际上,只是以一种不正确的方式工作,所以套接字发送的服务器没有问题。它要么与MediaRecorder有关,要么与MediaSource有关。

共有1个答案

汪阳辉
2023-03-14

我的假设是,在开始时接收的视频需要初始化头来启动,因为流是在中段读取的,所以它从来没有得到所说的初始化头。

正确!

要解决这个问题,您需要对WebM格式略知一二。WebM只是Matroska(MKV)的一个子集。Matroska是用于在EBML中存储媒体的模式规范。EBML是一种二进制文件格式,可以有任意块。把它想象成二进制XML。

这意味着您可以使用EBML Viewer之类的工具来检查WebM文件,并参考Matroska规范来了解发生了什么。例如:

这是对预先录制的WebM文件的检查。它将在浏览器中发挥良好。您会注意到有些元素是嵌套的。

每个WebM文件中都有两个顶级元素。ebml,它定义了这个二进制文件;segment,它包含后面的所有内容。

在所有这些元数据之后,您可以找到clusterclustercluster等。

换句话说,您的代码应该执行以下操作:

  • 将第一个群集之前的所有数据保存为“初始化数据”。
  • 之后在群集上拆分。

在回放时:

  • 首先加载以前保存的“初始化数据”。
  • 之后开始在集群中加载,从流中需要的任何位置开始。

现在,谁的集群需要一个关键帧位是重要的。据我所知,没有办法配置MediaRecorder来实现这一点,浏览器对此特别挑剔。至少,您必须重新复用服务器端...您甚至可能需要重新编码。另请参见:使用关键帧集群将FFMPEG编码为MPEG-DASH-或WebM-for MediaSource API

用socket.io使用媒体源

我应该指出,你甚至不需要MediaSource。你绝对不需要socket.io。它可以像通过普通的HTTP流输出这些数据一样简单。这可以直接加载在 元素中。(无论如何,如果需要额外的控制,请使用MediaSource,但这并不是必需的。)

 类似资料:
  • 41 多媒体源 下面是目前可用的多媒体源的描述 amovie 它同于movie源,除了它选择一个默认音频流。 movie 从影片内容中读取音频和/或视频流 接受下面的参数: filename 要被读取的资源名(不限于文件,可以是设备或者一些协议下的流). format_name, f 对要读取的影片指定格式,可以是容器或者输入设备,如果没有指定,将从影片名中猜测。 seek_point, sp 指

  • 如果可能的话,我需要一些意见或建议。我有一个使用语音识别api和媒体记录器的应用程序。该应用程序的要点是当用户说“注意”时,它会记录语音消息,直到用户说“完成”。之后,应用程序将语音消息保存到手机中。 我目前有一个带有按钮(记录、保存、停止、完成)的弹出框,用户可以手动按下按钮来记录他们的语音信息。我正在考虑完全改造用户拥有完全语音控制的应用程序。所以基本上,它越免提越好。 我从这里开始研究连续语

  • 媒体组件包括哪些大型媒体对象,比如图片、视频、音频,等等。 Material 盒子 Material 盒子是来源于Lightbox 插件的 material design。当用户单击图片它会变大。Material 盒子平滑的使图片居中并且变大。再次单击还原。或者通过ESC键。 创建上面图片的效果,只要增加一个 materialboxed 类到图片标签中。 <img class="materialb

  • 图片 saveImageToPhotosAlbum 基础库 2.0.7 开始支持,iOS版本 2.10.7,Android版本2.11.43 saveImageToPhotosAlbum(Object object) 保存图片到系统相册。 参数 Object object 属性 类型 默认值 必填 说明 filePath string 是 图片文件路径,可以是临时文件路径或永久文件路径,不支持网络

  • 问题内容: 我需要帮助从外部服务器获取的音频文件的身份验证标头。所以现在我正在尝试使用Ajax,我可以很好地抓取文件,但是无法将它们设置为播放器的媒体源。您如何将ajax加载的文件设置为音频源? 编辑 最后修复它,以防有人以这种方式回来。 不得不执行asynch:false,否则我会得到一小部分音频,而不是全部音频。尽管删除了异步,最终使调试变得更加容易。 问题答案: 不得不执行asynch:fa

  • 1367[AWT-EventQueue-0]信息uk.co.caprica.vlcj.binding.libvlcfactory-libvlc:c:\program files\videolan\vlc\libvlc.dll 2061[AWT-EventQueue-0]错误uk.co.caprica.vlcj.player.DefaultMediaPlayer-未能为“SimpleMedia[mr