【发布时间】:2019-03-16 18:59:31
【问题描述】:
它遵循我试图以正确方式实现的设计:我有一个 JavaScript 对等体,它正在向Native Code 对等体发送视频轨道。在传输过程中的某个时刻(实际上是在建立连接后立即,但可能在任何时候)我想在 JS 对等端启动秒表并执行一些临时操作,实际上是在覆盖视频播放的画布上进行一些渲染.在本机对等端,我希望能够在秒表在 JS 对等点上启动的那一刻同步,并只考虑在那一刻之后记录的接收到的帧,执行一些其他类型的处理。我现在在做什么(脆弱和有限的解决方案):
- 一旦节点连接,跟踪
RTCPeerConnection.iceConnectionState,我就在 JS 节点上启动秒表; - 一旦第一个
webrtc::VideoFrame到达 Native 对等体,我就会存储帧时间垃圾; - 在 Native peer 上,我使用第一帧时间戳来计算相对时间,这与秒表允许我在 JS peer 上使用的方式类似。
这种设计是有限制的,因为我可能想在任何时刻进行同步,而不仅仅是在对等连接建立时,而且还很脆弱,因为我认为 WebRTC 协议允许出于任何原因(延迟或传输错误)丢弃第一个接收到的帧)。理想情况下,我想在 JS 对等点中选择的同步点获取时间戳,将其发送到本机对等点并能够比较 webrtc::VideoFrame 时间戳。我无法天真地做到这一点,因为VideoFrame::timestamp_us() 显然有一些我不知道的偏差。我也无法解释VideoFrame::timestamp(),它在api/video/video_frame.h 中的记录很差,VideoFrame::ntp_time_ms() 已被弃用,实际上总是返回-1。我应该怎么做才能在两个对等点之间完成这种同步?
【问题讨论】:
-
我建议带内信号。无论如何,您打算使用画布操作 JS 端。当您想要开始同步时,您可以简单地使用画布 setPixelData() 发送一个全黑帧。本机客户端可以识别这样的帧,跳过它(你不想闪烁,是吗?)并切换到“其他类型的处理”。
-
我根本不是在处理 JS 侧视频,它只是画布中的叠加层。视频轨道是来自我使用
getUserMedia()获得的网络摄像头的流。同步信号应该尽可能谨慎:黑帧肯定不好,而且我可能会很不幸完全错过它。在想到它之前,我需要证明对来自getUserMedia()的视频轨道的视频操作实际上是可能的。但说真的:我认为我制定了一个名为 Web Real-Time Communication 的标准,应该真正为我提供一些便利,以按照我描述的方式同步两个对等流。 -
@AlexCohn 非常有趣:我发现通过将
MediaStreamTrack重定向到画布元素并使用HTMLCanvasElement.captureStream()捕获它是可能的。 MS Edge 尚不支持此功能,这意味着对我来说还不是一个好的解决方案。不过,我真的认为在 Native Code peer 中应该有一些其他的解决方案:如果webrtc::VideoFrame保留了 RTP 时间戳,并且这将与 JS 端Date.now()相媲美,那么这个问题实际上是不费吹灰之力的。 -
恐怕 JS 无法访问 VideoFrame 内部,因此无法访问其时间戳。至于带外同步,我会选择简单的UTC。视频帧的传输时间应远小于标准视频中帧之间的 200 毫秒,因此您不会错过发送方和接收方之间的任何一帧。至于本地时钟偏差,这在现代连接设备上可能可以忽略不计,但即使不是,也有众所周知的算法来补偿它。
-
@AlexCohn 是的,我知道 JS 无法访问内部(虽然是 changing):我在谈论本机代码方面也没有暴露远程对等时间戳或估计的偏差(不在至少是一种显而易见的方式,并且 API 并没有真正记录在案)。我在webrtc-discuss 中提出了同样的问题:我仍然希望一些实际从事内部工作的开发人员能够提供一些支持。
标签: javascript c++ video-streaming webrtc audio-video-sync