如何将视频(在磁盘上)转换为 rtsp 流

sha*_*mer 5 python opencv rtsp gstreamer

我的本地磁盘上有一个视频文件,我想从中创建一个 rtsp 流,我将在我的一个项目中使用它。一种方法是从 vlc 创建一个 rtsp 流,但我想用代码来做(python 会更好)。我已经尝试过这样的 opencv 的 VideoWritter

import cv2

_dir = "/path/to/video/file.mp4"
cap = cv2.VideoCapture(_dir)

framerate = 25.0
out = cv2.VideoWriter(
    "appsrc ! videoconvert ! x264enc noise-reduction=10000 speed-preset=ultrafast tune=zerolatency ! rtph264pay config-interval=1 pt=96 ! tcpserversink host=127.0.0.1 port=5000 sync=false",
    0,
    framerate,
    (1920, 1080),
)


counter = 0
while cap.isOpened():
    ret, frame = cap.read()
    if ret:
        out.write(frame)
        print(f"Read {counter} frames",sep='',end="\r",flush=True)
        counter += 1
        if cv2.waitKey(1) & 0xFF == ord("q"):
            break
    else:
        break

cap.release()
out.release()
Run Code Online (Sandbox Code Playgroud)

但是当我像这样在 vlc 上流式传输它时

vlc -v rtsp://127.0.0.1:5000 我得到

[00007fbb307a3e18] access_realrtsp access error: cannot connect to 127.0.0.1:5000
[00007fbb2c189f08] core input error: open of `rtsp://127.0.0.1:5000' failed
[00007fbb307a4278] live555 demux error: Failed to connect with rtsp://127.0.0.1:5000
Run Code Online (Sandbox Code Playgroud)

Gstreamer 是另一种选择,但因为我从未使用过它,所以如果有人指出我正确的方向,那就太好了。

Dus*_*vic 10

您尝试通过 TCP 服务器公开RTP协议,但请注意 RTP 不是RTSP,并且 RTP(和 RTCP)只能是 RTSP 的一部分。

无论如何,有一种方法可以通过使用 GStreamer 的GstRtspServer和Gstreamer 的Python 接口(包)使用 GStreamer和 Python创建RTSP 服务器gi

假设你的机器上已经有 Gstreamer,首先安装 gi python 包,然后安装 Gstreamer RTSP 服务器(这不是标准 Gstreamer 安装的一部分)。

通过简单的 RTSP 服务器公开 mp4 容器文件的 Python 代码

#!/usr/bin/env python

import sys
import gi

gi.require_version('Gst', '1.0')
gi.require_version('GstRtspServer', '1.0')
from gi.repository import Gst, GstRtspServer, GObject, GLib

loop = GLib.MainLoop()
Gst.init(None)

class TestRtspMediaFactory(GstRtspServer.RTSPMediaFactory):
    def __init__(self):
        GstRtspServer.RTSPMediaFactory.__init__(self)

    def do_create_element(self, url):
        #set mp4 file path to filesrc's location property
        src_demux = "filesrc location=/path/to/dir/test.mp4 ! qtdemux name=demux"
        h264_transcode = "demux.video_0"
        #uncomment following line if video transcoding is necessary
        #h264_transcode = "demux.video_0 ! decodebin ! queue ! x264enc"
        pipeline = "{0} {1} ! queue ! rtph264pay name=pay0 config-interval=1 pt=96".format(src_demux, h264_transcode)
        print ("Element created: " + pipeline)
        return Gst.parse_launch(pipeline)

class GstreamerRtspServer():
    def __init__(self):
        self.rtspServer = GstRtspServer.RTSPServer()
        factory = TestRtspMediaFactory()
        factory.set_shared(True)
        mountPoints = self.rtspServer.get_mount_points()
        mountPoints.add_factory("/stream1", factory)
        self.rtspServer.attach(None)

if __name__ == '__main__':
    s = GstreamerRtspServer()
    loop.run()
Run Code Online (Sandbox Code Playgroud)

注意

  • 此代码将公开stream1在默认端口 8554 上命名的 RTSP 流
  • 我曾经qtdemux从 MP4 容器中获取视频。您也可以扩展管道以提取音频(并通过 RTSP 服务器公开它)
  • 要减少 CPU 处理,您只能提取视频而不对其进行解码并将其再次编码为 H264。但是,如果需要转码,我会留下一个注释行来完成这项工作(但它可能会阻塞功能较弱的 CPU)。

你可以用 VLC 玩这个

vlc -v rtsp://127.0.0.1:8554/stream1
Run Code Online (Sandbox Code Playgroud)

或使用 Gstreamer

gst-launch-1.0 playbin uri=rtsp://127.0.0.1:8554/stream1
Run Code Online (Sandbox Code Playgroud)

但是,如果您实际上不需要 RTSP 而只是遵循 Gstreamer 管道(利用rtpbin的端到端 RTP将完成这项工作

gst-launch-1.0 -v rtpbin name=rtpbin \ 
filesrc location=test.mp4 ! qtdemux name=demux \
demux.video_0 ! decodebin ! x264enc ! rtph264pay config-interval=1 pt=96 ! rtpbin.send_rtp_sink_0 \
rtpbin.send_rtp_src_0 ! udpsink host=127.0.0.1 port=5000 sync=true async=false
Run Code Online (Sandbox Code Playgroud)

和 VLC 可以玩

vlc -v rtp://127.0.0.1:5000
Run Code Online (Sandbox Code Playgroud)