我正在尝试使用 gstreamer 流式传输我的 Raspberry Pi 相机。这是我的管道:
raspivid --nopreview -ih -hf -vf --width 800 --height 600 --framerate 20 --bitrate 2000000 --profile main --timeout 0 -g 4 -o - | gst-launch-1.0 -vvv fdsrc do-timestamp=true \
! h264parse ! omxh264dec ! clockoverlay time-format="%A | %d %B %Y | %H:%M:%S" ! omxh264enc target-bitrate=2000000 control-rate=1 ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=targethost port=8004 sync=false
Run Code Online (Sandbox Code Playgroud)
它有效......几乎。我可以在目标主机上接收流一秒钟左右,然后停止。Gstreamer 不输出任何错误,不退出,它只是停止发送 UDP 数据包。
我安装iptraf在我的 Pi 上,我可以看到大约 1000 个数据包后 UDP 数据包发送停止。它可能会停在 ~800 个数据包或 ~1500 个数据包处,大约是这些数字。
现在有趣的是,有时它的工作时间更长,比如几个小时。但有时它几乎立即停止。我现在观察了大约两天,可能是它在晚上工作得更好,也许是因为那时流是漆黑的,所以压缩得更好,它发送的数据包更少?我不知道。什么可以停止发送数据包而不会出现任何错误?有人知道这里发生了什么吗?
补充 #1: 另外,如果是基础设施问题,Pi 通过其 wi-fi 接口连接到本地网络,并且它实际上连接到 wi-fi 扩展器。所以这不是一个非常干净的设置,但它似乎在晚上工作,至少从最近两天来看,但即使会有一些带宽瓶颈,它可以像这样停止 UDP 流吗?这对我来说没有意义。
添加#2:
$ gst-launch-1.0 --version
gst-launch-1.0 version 1.14.4
GStreamer 1.14.4
Run Code Online (Sandbox Code Playgroud)
添加 #3:
我用GST_DEBUG=3. 当它停止时,它不会显示任何新消息,只是停止出现任何新消息。
这是完整的输出,直到流停止而没有任何进一步消息:https : //pastebin.com/raw/kTfbCW37(即使流在下面描述的某些配置中长时间正常工作,也会发生这些警告)。
我还发现带宽不是问题。我用它进行iperf了测量,流最多只使用了大约 1/10 的可用带宽。
我还发现,如果我将分辨率提高到--width 1920 --height 1080那么流似乎工作更长时间......(它在晚上的某个时间点停止)。所以发生了一些非常奇怪的事情。任何想法可能是什么或我还能做些什么来弄清楚发生了什么?
添加 #4:
我安装pv并把它放在raspivid和之间gstreamer。事实证明,这最终可能不是 gstreamer 的问题,因为看起来来自 raspivid 的流只是在某一点停止。一旦它停止在发送的 1.99GiB 数据(这让我认为这与旧的、已知的 raspivid 2GB 限制有关),但第二次它停止在发送的 775MiB 数据。
我在其他一些“嵌入式”设备上经历了类似的情况,所以我将分享当时获得的经验知识。
就我而言,我成功地通过以下方法建立了稳定的流:
在 之前添加队列元素udpsink。queue将“在源焊盘上创建一个新线程,以解耦接收器和源焊盘上的处理”,因此,理论上,如果 CPU 具有多个内核,它应该会带来好处。就我而言,queue“缓冲”高于默认值:
... ! queue max-size-time=5000000000 max-size-buffers=10000000 max-size-bytes=50000000 ! udpsink ...
Run Code Online (Sandbox Code Playgroud)增加元素buffer-size属性udpsink。例如,
... ! updsink buffer-size=50000000 ...
Run Code Online (Sandbox Code Playgroud)当 udpsink 无法足够快地处理数据包时,应允许内核缓冲更多数据包。
就我而言,上述设置稳定了流并缓解了基础设施瓶颈。
而且,正如 @vermeate 所建议的,额外的调试总是有帮助的:将 GST_DEBUG 级别设置为更高的值,尝试降低raspivid帧速率、比特率......并观察行为。