简体   繁体   English

python 中的 gstreamer 管道未正确保存.mp4 视频

[英]gstreamer pipeline in python not saving .mp4 video correctly

I have a script in Python where I record the stream from four cameras to mp4 through gstreamer.我在 Python 中有一个脚本,我在其中通过 gstreamer 从四个摄像机记录 stream 到 mp4。 I define a signal so that the capture terminates if Ctrl-C is pressed, and it works fine.我定义了一个信号,以便在按下 Ctrl-C 时终止捕获,并且它工作正常。 In the gstreamer pipeline itself, I have a property added at the source numbuffers = 600 because I want the capture to stop after 600 frames anyway if I don't press Ctrl-C before then.在 gstreamer 管道本身中,我在源numbuffers = 600处添加了一个属性,因为如果在那之前我不按 Ctrl-C,我希望捕获在 600 帧之后停止。

My problem is this, if I interrupt through the keyboard all four mp4 videos are saved correctly, but if I let it finish by itself after the 600 frames the second to fourth videos are fine while the first video will have "no playable stream", even if having the same size as the other videos.我的问题是,如果我通过键盘中断所有四个 mp4 视频都正确保存,但是如果我让它在 600 帧后自行完成,第二到第四个视频很好,而第一个视频将有“不可播放的流”,即使与其他视频大小相同。

I don't understand why only the first video is not saved or closed correctly, any hints?我不明白为什么只有第一个视频没有正确保存或关闭,有什么提示吗? This is my code:这是我的代码:

import gi
import signal
import threading
import logging
from time import time, sleep
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject

logging.basicConfig(level=logging.INFO)

def on_message(bus: Gst.Bus, message: Gst.Message, loop: GObject.MainLoop):
    mtype = message.type
    """
        Gstreamer Message Types and how to parse
    """
    if mtype == Gst.MessageType.EOS:
        logging.info("End-of-stream\n")
        loop.quit()

    elif mtype == Gst.MessageType.ERROR:
        err, debug = message.parse_error()
        logging.info("Warning: %s: %s\n" % (err, debug))
        loop.quit()

    elif mtype == Gst.MessageType.WARNING:
        err, debug = message.parse_warning()
        logging.info("Error: %s: %s\n" % (err, debug))

    return True


def signal_handler(signal, frame):
    for i in range(0,n_cams):
        pipelines[i].send_event(Gst.Event.new_eos())

signal.signal(signal.SIGINT, signal_handler)

# Initialize
GObject.threads_init()
Gst.init(None)

n_cams = 4
buses = []
pipelines = []

for i in range(0,n_cams):
    logging.info("Starting camera " + str(i))

    command = ("nvarguscamerasrc sensor-id={} num-buffers=600 ! "
            "video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, format=(string)NV12, framerate=(fraction)30/1 ! "
            "queue max-size-buffers=4 leaky=2 ! "
            "nvv4l2h265enc control-rate=1 bitrate=8000000 ! video/x-h265, stream-format=(string)byte-stream ! "
            "h265parse ! qtmux ! filesink location=test_{}.mp4").format(i)

    logging.info("Parse launch " + command)
    pipelines.append(Gst.parse_launch(command))


loop = GObject.MainLoop()

for i in range(0,n_cams):
    buses.append(pipelines[i].get_bus())
    buses[i].add_signal_watch()
    buses[i].connect("message", on_message, loop)

logging.info("Starting pipelines")

for i in range(0,n_cams):
    pipelines[i].set_state(Gst.State.PLAYING)

loop.run()

# stop
for i in range(0,n_cams):
    pipelines[i].send_event(Gst.Event.new_eos())
    pipelines[i].set_state(Gst.State.NULL)

I think you are getting lucky in the ctrl-c case in the first place.我认为您首先在 ctrl-c 案例中很幸运。 In the ctrl-case when you send an EOS, you should wait for the EOS to reach the bus before setting the pipeline sate to NULL.在发送 EOS 的 ctrl 情况下,您应该等待 EOS 到达总线,然后再将管道状态设置为 NULL。

Similar problem with your actual described problem.与您实际描述的问题类似的问题。 You have 4 pipelines but only one main loop.您有 4 个管道,但只有一个主循环。 You quit the loop after the first pipeline reaches EOS.在第一个管道到达 EOS 后退出循环。 Instead you should wait until all pipelines have reached EOS.相反,您应该等到所有管道都达到 EOS。

Ps I think the send_event after # stop does not actually do anything. Ps 我认为# stop之后的 send_event 实际上并没有做任何事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM