Skip to content

[Question]: WriteGear GStreamer Outputs Darkened RTSP Video #433

Open
@QZL12138

Description

@QZL12138

Issue guidelines

Issue Checklist

  • I have searched open or closed issues for my problem and found nothing related or helpful.
  • I have read the Documentation and found nothing related to my problem.
  • I have gone through the Bonus Examples and FAQs and found nothing related or helpful.

Describe your Question

Hello, after using VideoGear's gstreamer pipeline to pull a local RTSP stream, I use WriteGear GStreamer to push the result to my local streaming server. When playing with VLC, I find that the first 5 seconds or so of the picture are relatively dark and have some mosaic artifacts, and then suddenly return to normal. I'm a beginner; can you help me point out what I'm doing wrong?

Terminal log output(Optional)

18:14:21 ::    Helper     ::   INFO   :: Running VidGear Version: 0.3.3
18:14:21 ::    Helper     :: WARNING  :: Specified directory `/tmp/pycharm_project_977/appsrc ! videoconvert ! queue ! nvh265enc  zerolatency=true ! h265parse  ! rtspclientsink location=rtsp:/127.0.0.1:8554/live` doesn't exists or valid.
18:14:21 ::   WriteGear   ::   INFO   :: `appsrc ! videoconvert ! queue ! nvh265enc  zerolatency=true ! h265parse  ! rtspclientsink location=rtsp://127.0.0.1:8554/live/test2 latency=0 protocols=tcp name=sink` isn't a valid system path or directory. Skipped!
18:14:21 ::   WriteGear   ::  DEBUG   :: Output Parameters: `{'-gst_pipeline_mode': True}`
18:14:21 ::    Helper     ::  DEBUG   :: Found GStreamer version:1.20.3
18:14:21 ::   WriteGear   ::  DEBUG   :: GStreamer Pipeline Mode successfully activated!
18:14:21 ::   WriteGear   ::  DEBUG   :: Non-Compression Mode is successfully configured in GStreamer Pipeline Mode.
18:14:21 ::   WriteGear   :: CRITICAL :: Compression Mode is disabled, Activating OpenCV built-in Writer!
18:14:22 ::   WriteGear   ::  DEBUG   :: InputFrame => Height:720 Width:1280 Channels:3 Datatype:uint8
18:14:22 ::   WriteGear   ::  DEBUG   :: FILE_PATH: appsrc ! videoconvert ! queue ! nvh265enc  zerolatency=true ! h265parse  ! rtspclientsink location=rtsp://127.0.0.1:8554/live/test2 latency=0 protocols=tcp name=sink, FOURCC = 1196444237, FPS = 25, WIDTH = 1280, HEIGHT = 720, BACKEND = 1800
error: XDG_RUNTIME_DIR not set in the environment.
18:14:23 ::   WriteGear   ::   INFO   :: RGBA and 16-bit grayscale video frames are not supported by OpenCV yet. Kindly switch on `compression_mode` to use them!

Python Code(Optional)

import datetime
import time
import subprocess

from vidgear.gears import VideoGear

def get_rtsp_pipeline(rtsp_url):
    try:
        cmd = [
            "ffprobe", "-v", "error",
            "-select_streams", "v:0",
            "-show_entries", "stream=codec_name",
            "-of", "default=noprint_wrappers=1",
            rtsp_url
        ]
        out = subprocess.check_output(cmd, encoding='utf-8')
        if "h264" in out:
            return (
                "rtspsrc location={} latency=0 do-retransmission=false udp-reconnect=false ! "
                "application/x-rtp,media=video,encoding-name=H264 ! "
                "rtph264depay ! "
                "h264parse ! "
                "nvh264dec ! "
                "cudaconvert ! "
                "video/x-raw(memory:CUDAMemory), format=BGR  ! "
                "cudadownload ! "
                "appsink "
            ).format(rtsp_url)
        elif "hevc" in out or "h265" in out:
            return (
                "rtspsrc location={} latency=0 do-retransmission=false udp-reconnect=false ! "
                "application/x-rtp,media=video,encoding-name=H265 ! "
                "rtph265depay ! "
                "h265parse ! "
                "nvh265dec ! "
                "cudaconvert ! "
                "video/x-raw(memory:CUDAMemory), format=BGR  ! "
                "cudadownload ! "
                "appsink "
            ).format(rtsp_url)
        else:
            raise RuntimeError("未知或不支持的编码格式: " + out)
    except subprocess.CalledProcessError as e:
        raise RuntimeError(f"ffprobe 执行失败: {e}")
    except Exception as ex:
        raise RuntimeError(f"获取RTSP管道失败: {ex}")

class Reconnecting_VideoGear:
    def __init__(self, cam_address,  reset_attempts=50, reset_delay=5):
        self.cam_address = cam_address
        self.reset_attempts = reset_attempts
        self.reset_flag = 0
        self.reset_delay = reset_delay
        self.options = {'THREADED_QUEUE_MODE': False}
        self.source = None
        self.frame = None
        self.running = True
        self._start_source()

    def _start_source(self):
        try:
            pipeline = get_rtsp_pipeline(self.cam_address)
            self.source = VideoGear(
                source=pipeline,**self.options
            ).start()
        except Exception as e:
            print(f"拉流/解析失败: {e}")
            self.source = None

    def read(self):
        if self.source is None:
            if self.reset_flag < self.reset_attempts:
                print(
                    f"未能初始化视频源,重试剩余 {self.reset_attempts - self.reset_flag} 次 at {datetime.datetime.now().strftime('%m-%d-%Y %I:%M:%S%p')}"
                )
                time.sleep(self.reset_delay)
                self.reset_flag += 1
                self._start_source()
            return None

        if self.running and self.reset_flag < self.reset_attempts:
            frame = self.source.read()
            if frame is None:
                self.source.stop()
                self.source = None
                self.reset_flag += 1
                print(
                    f"丢帧,重试剩余 {self.reset_attempts - self.reset_flag} 次 at {datetime.datetime.now().strftime('%m-%d-%Y %I:%M:%S%p')}"
                )
                time.sleep(self.reset_delay)
                self._start_source()
                return None  # 返回上一次有效帧,或None
            else:
                self.reset_flag = 0  # 只要成功读取就清零
                self.frame = frame
                return frame
        else:
            return None

    def stop(self):
        self.running = False
        self.reset_flag = self.reset_attempts
        self.frame = None
        if self.source is not None:
            self.source.stop()
            self.source = None


import time
from vidgear.gears import  WriteGear
from Reconnecting_VideoGear import Reconnecting_VideoGear
from ultralytics import YOLO

def main():

    stream = Reconnecting_VideoGear(
        cam_address="rtsp://127.0.0.1:8554/live/test",
        reset_attempts=3,
        reset_delay=5,
    )


    output_params = {"-gst_pipeline_mode": True}
    # 构建 GStreamer 推流管道
    gst_pipeline = (
        "appsrc ! "
        "videoconvert ! "
        "queue ! "
        "nvh265enc  zerolatency=true ! "
        "h265parse  ! "
        "rtspclientsink "
        "location=rtsp://127.0.0.1:8554/live/test2 "
        "latency=0 "
        "protocols=tcp "
        "name=sink"
    )

    writer = WriteGear(
        output=gst_pipeline, compression_mode=False, logging=True, **output_params
    )

    model = YOLO("yolo11m.pt")
    while True:

        frame = stream.read()

        # 增加一个判断是否重试次数已用尽
        if stream.reset_flag >= stream.reset_attempts:
            print("重试次数已用尽,退出主循环")
            break

        if frame is None:
            print("未获取到帧,等待重试...")
            time.sleep(0.1)
            continue
        results = model(frame, stream=True,verbose=False)
        for result in results:
            annotated_frame = result.plot()
            writer.write(annotated_frame)

    # 释放资源
    stream.stop()
    writer.close()


if __name__ == "__main__":
    main()

VidGear Version

0.3.3

Python version

3.10

Operating System version

ubuntu20.04

Any other Relevant Information?

The above is a video I recorded of the live broadcast footage. During the first 1-5 seconds, the video is dark and has some mosaic artifacts, but it returns to normal at the 6th second.

mmexport1748959081963.mp4

Metadata

Metadata

Assignees

No one assigned

    Labels

    QUESTION ❓User asked about the working/usage of VidGear APIs.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions