Gstreamer in Python exits instantly, but is fine o

2019-08-26 11:39发布

I am trying to build a program or robot that can generate audio and video on the fly and stream it to a rtmp server such a Twitch or Youtube. I have found that I can pull in streams of video and audio using Gstreamer. I also have found that Gstreamer has a library in Python which is good because my robot is already written in Python.

The problem is, when testing with the testvideosrc input, I can make the command work just fine with both audio and video on the command line, but it exits immediately when trying to run it.

The code is

# Command Trying to Replicate in Python
# gst-launch-1.0 videotestsrc is-live=true ! videoconvert ! x264enc bitrate=1000 tune=zerolatency ! queue ! flvmux name=mux ! rtmpsink location='rtmp://live.twitch.tv/app/STREAM_KEY_HERE' audiotestsrc is-live=true ! audioconvert ! audioresample ! audio/x-raw,rate=48000 ! voaacenc bitrate=96000 ! audio/mpeg ! aacparse ! audio/mpeg, mpegversion=4 ! mux.

# ORIGINAL (UNEDITED) COMMAND - gst-launch-1.0 videotestsrc is-live=true ! videoconvert ! x264enc bitrate=1000 tune=zerolatency ! video/x-h264 ! h264parse ! video/x-h264 ! queue ! flvmux name=mux ! rtmpsink location='rtmp://live.twitch.tv/app/STREAM_KEY_HERE' audiotestsrc is-live=true ! audioconvert ! audioresample ! audio/x-raw,rate=48000 ! voaacenc bitrate=96000 ! audio/mpeg ! aacparse ! audio/mpeg, mpegversion=4 ! mux.

STREAM_URL = "rtmp://REDACTED"

# For StackExchange - gst-launch-1.0 videotestsrc is-live=true ! autovideoconvert ! x264enc bitrate=1000 tune=zerolatency ! queue ! flvmux name=mux ! rtmpsink location='rtmp://live.twitch.tv/app/STREAM_KEY_HERE' audiotestsrc is-live=true ! audioconvert ! audioresample ! audio/x-raw,rate=48000 ! voaacenc bitrate=96000

# Imports
import gi
import time
from gi.repository import GObject, Gst
import os

# OS Variables and Requirements
gi.require_version('Gst', '1.0')
os.environ["GST_DEBUG"] = "4" # Enable Debug

# Initialize GStreamer
Gst.init(None) # gst-launch-1.0 !
pipeline = Gst.Pipeline()

# Create Video Source (Video Test Source)
videosrc = Gst.ElementFactory.make("videotestsrc") # videotestsrc is-live=true !
#videosrc.set_property('pattern', 18)
videosrc.set_property('is-live', True)
pipeline.add(videosrc)

# Convert Video (to x264enc?)
videoconvert = Gst.ElementFactory.make('autovideoconvert') # videoconvert
pipeline.add(videoconvert)

# IDK
idk = Gst.ElementFactory.make("x264enc") # x264enc bitrate=1000 tune=zerolatency
idk.set_property('bitrate', 1000)
idk.set_property('tune', 'zerolatency')
pipeline.add(idk)

# Queue Data
queueRTMP = Gst.ElementFactory.make("queue") # queue
pipeline.add(queueRTMP)

# Convert to Mux
flvmux = Gst.ElementFactory.make("flvmux", "mux") # flvmux name=mux
pipeline.add(flvmux)

# Stream to RTMP Server
rtmpsink = Gst.ElementFactory.make("rtmpsink") # rtmpsink location='rtmp://live.twitch.tv/app/STREAM_KEY_HERE'
rtmpsink.set_property("location", STREAM_URL)
pipeline.add(rtmpsink)

#  audiotestsrc is-live=true ! audioconvert ! audioresample ! audio/x-raw,rate=48000 ! voaacenc bitrate=96000 ! audio/mpeg ! aacparse ! audio/mpeg, mpegversion=4 ! mux.

videosrc.link(videoconvert)
videoconvert.link(idk)
idk.link(queueRTMP)
queueRTMP.link(flvmux)
flvmux.link(rtmpsink)

pipeline.set_state(Gst.State.PLAYING)

Out of what I tried to fix it is, originally I could not get the stream to work because I had an extra "sink" in it. The only difference between this file and the one with the "sink" problem is that "autovideoconvert" was "videoconvert". This command works fine when run in the command line.

Sink Problem Error Message:

0:00:00.038202264 25199      0x272a370 INFO        GST_ELEMENT_PADS gstelement.c:892:gst_element_get_static_pad: no such pad 'sink' in element "videotestsrc0"

Now, there is no error message with having "autovideoconvert". Instead, the program just exits even when the stream is in the playing state.

The sink problem is shown to be solved with this message in the log:

0:00:00.039500044 25214      0x2568d40 INFO                GST_PADS gstpad.c:2388:gst_pad_link_full: linked videoconvert0:src and '':sink_internal, successful

The last state changing message that shows up in the log is below:

0:00:00.043316535 25214      0x2568d40 INFO              GST_STATES gstelement.c:2328:gst_element_continue_state:<videoscale0> completed state change to PLAYING
0:00:00.043341987 25214      0x2568d40 INFO              GST_STATES gstelement.c:2233:_priv_gst_element_state_changed:<videoscale0> notifying about state-changed PAUSED to PLAYING (VOID_PENDING pending)

These are all when the log level is set to 4. What I cannot understand is, what am I doing wrong to make the command work, but not the Python version of the command. It is bonus if anyone happens to know how to change the keyframe interval. Youtube does not want to cooperate unless I can set it to 4 seconds and faster. Thanks!

1条回答
Deceive 欺骗
2楼-- · 2019-08-26 12:14
  1. The error with the pad seems obvious. Without looking at the pipleline if its correct - no such pad 'sink' in element "videotestsrc0": So this is not s sink but a src element. And naturally these don't have sink pads as they are sources.

  2. I have no idea how the rest of your app looks like. But "running" a pipeline is a non-blocking call. So if you don't have a proper application loop or just wait after the call by other means the application may immediately exit.

  3. x264enc key-int-max=<max-number-of-frames>. Or idk.set_property('key-int-max', 60).

查看更多
登录 后发表回答