问题描述
我们正在开发一种软件,用于使用GStreamer使用RTSP传输来自两个不同摄像机的视频。为了简化获取过程,我们将OpenCV与Python 3配合使用。
问题是:我们想将流推送到UDP接收器,然后将其作为RTSP流通过LAN重新发布,而不是在另一台PC上读取。但是我们无法使它正常工作。
这是获取摄像机图像并以udpsink
开始流式传输的Python代码。在这种情况下,我们正在访问本地网络摄像头,以便任何人都可以直接测试代码。
import cv2
import time
from multiprocessing import Process
def send():
video_writer = cv2.VideoWriter(
'appsrc ! '
'videoconvert ! '
'x264enc tune=zerolatency speed-preset=superfast ! '
'rtph264pay ! '
'udpsink host=127.0.0.1 port=5000',cv2.CAP_GSTREAMER,1,(640,480),True)
video_getter = cv2.VideoCapture(0)
while True:
if video_getter.isOpened():
ret,frame = video_getter.read()
video_writer.write(frame)
# cv2.imshow('send',data_to_stream)
time.sleep(0.1)
if __name__ == '__main__':
s = Process(target=send)
s.start()
s.join()
cv2.destroyAllWindows()
运行此命令时,我们只会收到一个警告:
[ WARN:0] global ../modules/videoio/src/cap_gstreamer.cpp (935) open OpenCV | GStreamer warning: Cannot query video position: status=0,value=-1,duration=-1
然后,我们尝试使用GStreamer中的examples/test-launch
通过LAN重新将流作为RTSP重新发布
./test-launch " udpsrc port=5000 ! h264parse ! rtph264pay name=pay0 pt=96"
stream ready at rtsp://127.0.0.1:8554/test
然后VLC无法在此地址打开流。
~$ vlc -v rtsp://127.0.0.1:8554/test
VLC media player 3.0.11 Vetinari (revision 3.0.11-0-gdc0c5ced72)
[000055f5dacf3b10] main libvlc: Running vlc with the default interface. Use 'cvlc' to use vlc without interface.
Qt: Session management error: None of the authentication protocols specified are supported
[00007f5ea40010f0] live555 demux error: Failed to connect with rtsp://127.0.0.1:8554/test
[00007f5ea4003120] satip stream error: Failed to setup RTSP session
我想这与我们的管道有关,但是我真的不知道它可能是什么。 任何帮助将不胜感激。预先感谢。
解决方法
您可以在VideoWriter中删除rtph264pay,然后python脚本发送h264数据,并进行测试启动以接收h264数据,先进行rtp打包,然后再进行rtsp。
因此VideoWriter应该是:
video_writer = cv2.VideoWriter(
'appsrc ! '
'videoconvert ! '
'x264enc tune=zerolatency speed-preset=superfast ! '
'udpsink host=127.0.0.1 port=5000',cv2.CAP_GSTREAMER,1,(640,480),True)
,
我注意到与该主题相关的大多数问题最终都是由他们自己的作者回答的,就像这两个问题
How to Stream PC Webcam with RTSP and Gstreamer on Python
Write OpenCV frames into Gstreamer RTSP server pipeline
它实际上显示了这些问题的具体程度,这就是为什么我决定在这里分享我的想法的原因。目前,这并不是一个完美的解决方案,但它是一种“可行的”方法。
感谢kqmh00
的支持,因为它给了我一些见识。
首先,我退后一步,在Python之外使用videotestsrc
尝试了一个更简单的示例。经过几次尝试,这些是有效的管道
发件人
gst-launch-1.0 videotestsrc is-live=true ! video/x-raw ! videoconvert ! x264enc tune=zerolatency speed-preset=superfast ! udpsink host=127.0.0.1 port=30000
代祷
./test-launch "udpsrc port=30000 ! h264parse ! rtph264pay name=pay0 pt=96"
接收器
vlc -v rtsp://127.0.0.1:8854/test
好的。它仅证明了可以通过不带rtph264pay
的UDP发送视频,test-launch
会接收该视频,并以RTP打包格式将其重新发送为RTSP。
接下来,我再次尝试了Python。搜索类似的问题后,我发现this one启发了我正在使用的实际管道,即:
pipeline = (
"appsrc format=GST_FORMAT_TIME ! "
"video/x-raw,format=BGR,width=1280,height=720 ! "
"videoconvert ! "
"video/x-raw,format=I420 ! "
"x264enc tune=zerolatency speed-preset=superfast byte-stream=true threads=2 ! "
"video/x-h264,stream-format=(string)byte-stream ! "
"mpegtsmux alignment=7 ! "
"udpsink host=127.0.0.1 port=30000"
)
除video_writer
之外,其余的Python代码都是相同的,它们已使用正确的框架宽度和高度进行了更新:
video_writer = cv2.VideoWriter(
pipeline,(1280,720),True)
其他管道( Intercessor 和 Receiver )保持不变。这样,我就可以检索一些漂亮的单色图像(它们完全是灰色或绿色),但是至少我可以检索到一些东西。
VLC 会引发很多错误,例如
[h264 @ 0x7ff8e0001da0] Invalid NAL unit 0,skipping.
[h264 @ 0x7ff8e0001da0] top block unavailable for requested intra mode -1
[h264 @ 0x7ff8e0001da0] error while decoding MB 1 0,bytestream 112420
可能是缺少某些设置或必须明确设置某些属性。我会继续挖掘,但随时可以在此处添加任何可能的改进。