I'd like to create a stream over network where on main computer I'd like to have a window with stream and button that allows me to record the stream and save it to a file.
As a source I have following(testing purpose):
gst-launch-1.0 -e -vvvv videotestsrc ! video/x-raw, width=1280, height=1024 ! x264enc ! rtph264pay pt=96 config-interval=1 ! udpsink host=127.0.0.1 port=5000
And on the other side I have a small window in Gtk and I made a widget: (the input method is _on_realize())
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
gi.require_version('Gtk', '3.0')
from gi.repository import (Gst, Gtk, GObject)
class GstWidget(Gtk.Box):
def __init__(self, pipeline):
super().__init__()
# Only setup the widget after the window is shown
self.connect('realize', self._on_realize)
def on_message(self, bus: Gst.Bus, message: Gst.Message, loop: GObject.MainLoop):
mtype = message.type
"""
Gstreamer Message Types and how to parse
"""
if mtype == Gst.MessageType.EOS:
print("End-of-stream\n")
loop.quit()
elif mtype == Gst.MessageType.ERROR:
err, debug = message.parse_error()
print("Warning: %s: %s\n" % (err, debug))
loop.quit()
elif mtype == Gst.MessageType.WARNING:
err, debug = message.parse_warning()
print("Error: %s: %s\n" % (err, debug))
return True
def send_eos(self):
current_state = self.file_valve.get_property("drop")
new_state = not current_state
self.file_valve.set_property("drop" , new_state)
print("Valve set from {} to {}".format(current_state, new_state))
def create_pipeline(self):
# Create elements
udpsrc = Gst.ElementFactory.make("udpsrc","udp_src")
rtph264depay = Gst.ElementFactory.make("rtph264depay", "rtph264depay")
avdec_h264 = Gst.ElementFactory.make("avdec_h264", "avdec_h264")
self.textoverlay = Gst.ElementFactory.make("textoverlay","textoverlay")
tee = Gst.ElementFactory.make("tee", "tee")
stream_queue = Gst.ElementFactory.make("queue")
stream_videoconvert = Gst.ElementFactory.make("videoconvert","videoconvert")
stream_gtksink = Gst.ElementFactory.make("gtksink","gtksink")
file_queue = Gst.ElementFactory.make("queue")
self.file_valve = Gst.ElementFactory.make("valve", "valve")
file_x264enc = Gst.ElementFactory.make("x264enc", "x264enc")
file_avimux = Gst.ElementFactory.make("avimux","avimux")
self.file_filesink = Gst.ElementFactory.make("filesink","filesink")
# Make sure every element is created
if (not udpsrc or
not rtph264depay or
not avdec_h264 or
not self.textoverlay or
not tee or
not stream_queue or
not stream_videoconvert or
not stream_gtksink or
not file_queue or
not self.file_valve or
not file_x264enc or
not file_avimux or
not self.file_filesink):
return None, None
# Configure elements
udpsrc.set_property("port", 5000)
caps = Gst.caps_from_string("application/x-rtp, payload=96, media=video, clock-rate=90000")
udpsrc.set_property("caps", caps)
self.file_valve.set_property("drop", "false")
self.file_filesink.set_property("location", "default.avi")
self.file_filesink.set_property("sync", 1)
self.file_filesink.set_property("async", 0)
self.textoverlay.set_property("text",'Hello!')
# Add elements to bin(pipeline)
pipeline = Gst.Pipeline()
pipeline.add(udpsrc)
pipeline.add(rtph264depay)
pipeline.add(avdec_h264)
pipeline.add(self.textoverlay)
pipeline.add(tee)
pipeline.add(stream_queue)
pipeline.add(stream_videoconvert)
pipeline.add(stream_gtksink)
pipeline.add(file_queue)
pipeline.add(self.file_valve)
pipeline.add(file_x264enc)
pipeline.add(file_avimux)
pipeline.add(self.file_filesink)
# Link elements together
# First part
ret = udpsrc.link(rtph264depay)
ret = ret and rtph264depay.link(avdec_h264)
ret = ret and avdec_h264.link(self.textoverlay)
ret = ret and self.textoverlay.link(tee)
# Stream part
ret = ret and stream_queue.link(stream_videoconvert)
ret = ret and stream_videoconvert.link(stream_gtksink)
# # File part
ret = ret and file_queue.link(self.file_valve)
ret = ret and self.file_valve.link(file_x264enc)
ret = ret and file_x264enc.link(file_avimux)
ret = ret and file_x264enc.link(self.file_filesink)
# Request pads from Tee & get pads from Queues
tee_pad_stream = tee.get_request_pad("src_%u")
tee_pad_file = tee.get_request_pad("src_%u")
stream_queue_pad = stream_queue.get_static_pad("sink")
file_queue_pad = file_queue.get_static_pad("sink")
# # Link pads
tee_pad_stream.link(stream_queue_pad)
tee_pad_file.link(file_queue_pad)
bus = pipeline.get_bus()
bus.add_signal_watch()
loop = GObject.MainLoop()
bus.connect("message", self.on_message, loop)
return pipeline, stream_gtksink
def render_text(self, text):
self.textoverlay.set_property("text", text)
def _on_realize(self, widget):
self.pipeline, self.gtksink = self.create_pipeline()
if self.pipeline is None:
return
self.pack_start(self.gtksink.props.widget, True, True, 0)
self.gtksink.props.widget.show()
# Start the video
self.pipeline.set_state(Gst.State.PLAYING)
I can see the stream with text ("Hello,"). file is create but it's empty. I can't figure out what I'm doing wrong. I tried
gst-launch-1.0 -e -vvvv udpsrc port=5000 ! application/x-rtp, payload=96, media=video, clock-rate=90000 ! rtph264depay ! avdec_h264 ! textoverlay text="Hello!" ! queue ! valve ! x264enc ! avimux ! filesink location="default.avi"
When I tried the same command from Python it didn't work, what I did: Instead of linking the tee I put there directly the queue(file_queue) but still not output.
After a searching for many hours I found quite nice solution which worked for me. I just added start/stop recording. I still use different sink for the stream I also kept most of my code. For those who wants to stream and save to file once button is pressed: https://gist.github.com/NBonaparte/89fb1b645c99470bc0f6
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.