如何使用gstreamer预缓冲传入的网络流?

Nir*_*Nir 5 python gstreamer

我正在使用gstreamer通过网络传输音频.我的目标看似简单:将输入流预缓冲到某个时间/字节阈值,然后开始播放.我可能会忽略gstreamer的一个非常简单的功能,但到目前为止,我还没有找到办法做到这一点.

我的(简化)管道如下所示:udpsrc -> alsasink.到目前为止,我实现目标的所有尝试都是在两者之间使用队列元素:

  1. 在两者之间添加队列元素.
  2. 使用该min-threshold-time属性.这实际上有效,但问题是,它使所有传入的数据在队列中花费指定的最小时间,而不仅仅是开头,这不是我想要的.
  3. 为了解决上一个问题,我试图让数据在第一次进入音频接收器时通知我的代码,认为这是取消设置我之前设置的min-time属性的时间,从而实现了"预缓"行为.

这是我尝试的代码的粗略等价物:

def remove_thresh(pad, info, queue):
    pad.remove_data_probe(probe_id)
    queue.set_property("min-threshold-time", 0)

queue.set_property("min-threshold-time", delay)
queue.set_property("max-size-time", delay * 2)
probe_id = audiosink.get_pad("sink").add_data_probe(remove_thresh, queue)
Run Code Online (Sandbox Code Playgroud)

这不起作用有两个原因:

  1. 我的回调比delay我提供的变量更早被调用.
  2. 调用之后,队列中存储的所有数据都将丢失.播放开始,好像队列根本不在那里.

我想我对这件事的运作方式有一个根本的误解.有谁知道我做错了什么,或者可以提供(可能)更好的方法来做到这一点?我在这里使用python,但欢迎使用任何语言的任何解决方案.

谢谢.

rub*_*uza 3

GStreamer 中已经实现了缓冲。某些元素(例如队列)能够构建此缓冲区并发布有关缓冲区级别(队列状态)的总线消息。

那么,想要具有更高网络弹性的应用程序应该侦听这些消息,并在缓冲区级别不够高时暂停播放(通常是在低于 100% 时)。

因此,您所要做的就是在队列缓冲时将管道设置为PAUSED状态。在您的情况下,您只想缓冲一次,因此可以使用任何逻辑(也许设置标志变量仅在第一次暂停管道)。

  1. 将队列的“max-size-bytes”属性设置为您想要的值。
  2. 当缓冲区已满时,可以监听“溢出”信号来通知您,也可以使用 gst_message_parse_buffering () 来查找缓冲级别。
  3. 一旦缓冲区已满,请将管道设置为PLAYING状态,然后忽略所有进一步的缓冲消息。

最后,有关完整的流式传输示例,您可以参考本教程: https: //gstreamer.freedesktop.org/documentation/tutorials/basic/streaming.html 该代码是用 C 编写的,但演练应该可以帮助您实现您想要的。