1. ホーム
  2. python

[解決済み] 動画(ディスク)をrtspストリームに変換する方法

2022-02-19 04:35:10

質問事項

私はローカルディスクにビデオファイルを持っていて、そこからrtspストリームを作成したいのですが、これは私のプロジェクトの1つで使用するつもりです。一つの方法は、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()

しかし、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

Gstreamerも選択肢の一つですが、私は使ったことがないので、誰かが正しい方向を示してくれるとうれしいです。

どのように解決するのですか?

を公開しようとしました。 RTP プロトコルは、TCP サーバーを経由していますが、RTP は RTSP であり、RTP(およびRTCP)はRTSPの一部でしかありえない。

とにかく GStreamerとPythonを使ったRTSPサーバー を使うことで、GStreamerの GstRtspServer と Gstreamer 用の Python インターフェース ( 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()

注意点

  • という RTSP ストリームを公開します。 stream1 をデフォルトのポート 8554 で使用します。
  • 私が使用したのは qtdemux MP4コンテナから動画を取得します。上記のパイプラインを拡張して、音声も抽出することができます (そしてそれを RTSP サーバ経由で公開することもできます)。
  • CPUの処理を減らすために、デコードせずに動画だけを取り出し、再度H264にエンコードすることができます。しかし、トランスコーディングが必要な場合は、コメント行を1つ残しておくと、それが可能になる(ただし、性能の低い CPU には負担がかかるかもしれない)。

VLCで再生することができます

vlc -v rtsp://127.0.0.1:8554/stream1

またはGstreamerで

gst-launch-1.0 playbin uri=rtsp://127.0.0.1:8554/stream1

しかし RTSPは必要ないが、エンドツーエンドのRTPは必要である場合。 以下のGstreamerパイプライン( rtpbin を実行します。

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

で、VLCで再生することができます。

vlc -v rtp://127.0.0.1:5000