Skip to content

Instantly share code, notes, and snippets.

@spscream
Created September 10, 2014 12:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spscream/4df7195a50b0e35ba63e to your computer and use it in GitHub Desktop.
Save spscream/4df7195a50b0e35ba63e to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import gi
import os
from datetime import datetime
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst, Gtk
from gi.repository import GdkX11, GstVideo
from gi.repository.Gtk import Window, VBox, HBox, DrawingArea, ToggleButton, Button, Statusbar
GObject.threads_init()
Gst.init(None)
"""
gst-launch-0.10 -ev \
udpsrc uri="udp://192.168.100.100:20000" ! tee name=source0 \
source0. ! queue ! tsdemux name=demuxer \
demuxer. ! "audio/mpeg" ! queue max-size-buffers=1200 max-size-time=0 max-size-bytes=0 ! tee name=audio0 \
demuxer. ! "video/x-h264" ! queue max-size-buffers=1200 max-size-time=0 max-size-bytes=0 ! tee name=video0 \
qtmux name=mp4muxer moov-recovery-file=/home/dvruser/gstreamer/records/cam0_rec_$DATE.moov dts-method=0 \
video0. ! queue ! h264parse ! mp4muxer. \
audio0. ! queue ! mpegaudioparse ! mp4muxer. \
mp4muxer. ! filesink location=/home/dvruser/gstreamer/records/cam0_rec_$DATE.mp4 \
video0. ! queue ! h264parse ! ffdec_h264 ! ffmpegcolorspace ! deinterlace ! xvimagesink \
#audio0. ! queue ! mpegaudioparse ! mad ! pulsesink device=$ADEVICE \
"""
SOURCE="rtmp://192.168.100.100:1935/cameras/cam0"
#SOURCE="rtmp://itv08.digizuite.dk/tv2b/ch1"
class YayMan:
def __init__(self):
self.make_gui()
self.src_bin = Gst.Bin.new("sourcebin")
self.source = Gst.ElementFactory.make("rtmpsrc", "rtmpsource")
self.source.set_property("location", SOURCE)
self.demux = Gst.ElementFactory.make("flvdemux", "demux")
self.demux.connect("pad-added", self.demuxer_callback)
self.atee = Gst.ElementFactory.make("tee", "atee")
self.vtee = Gst.ElementFactory.make("tee", "vtee")
# Audio
self.vq = Gst.ElementFactory.make("queue", "vq")
self.h264parse = Gst.ElementFactory.make("h264parse", "h264parse")
self.ffdec_h264 = Gst.ElementFactory.make("avdec_h264", "avdec_h264")
# Video
self.aq = Gst.ElementFactory.make("queue", "aq")
self.mpegaudioparse = Gst.ElementFactory.make("mpegaudioparse", "mpparse")
self.mad = Gst.ElementFactory.make("mad", "mad")
# Add to src_bin
self.src_bin.add(self.source)
self.src_bin.add(self.demux)
self.src_bin.add(self.atee)
self.src_bin.add(self.vtee)
self.src_bin.add(self.vq)
self.src_bin.add(self.h264parse)
self.src_bin.add(self.ffdec_h264)
self.src_bin.add(self.aq)
self.src_bin.add(self.mpegaudioparse)
self.src_bin.add(self.mad)
self.source.link(self.demux)
self.vtee.link(self.vq)
self.atee.link(self.aq)
self.vq.link(self.h264parse)
self.h264parse.link(self.ffdec_h264)
self.aq.link(self.mpegaudioparse)
self.mpegaudioparse.link(self.mad)
src_v_pad = Gst.GhostPad.new("video", self.ffdec_h264.get_static_pad("src"))
src_a_pad = Gst.GhostPad.new("audio", self.mad.get_static_pad("src"))
self.src_bin.add_pad(src_v_pad)
self.src_bin.add_pad(src_a_pad)
self.record = Gst.ElementFactory.make("camerabin","camera")
self.record_source = Gst.ElementFactory.make("rtmpsrc","recordsrc")
self.record_source.set_property("location", "rtmp://192.168.100.100:1935/cameras/cam0")
self.src_wrap = Gst.ElementFactory.make("wrappercamerabinsrc","wrap")
self.src_wrap.set_property("video-source", self.src_bin)
src_wrap_a_pad = Gst.GhostPad.new("audio", self.src_bin.get_static_pad("audio"))
self.src_wrap.add_pad(src_wrap_a_pad)
self.record.set_property("mode", 2)
self.record.set_property("location", self.record_location())
self.record.set_property("camera-source", self.src_wrap)
#self.record.set_property("audio-source", self.src_bin)
self.bus = self.record.get_bus()
self.bus.add_signal_watch()
self.bus.connect('message::error', self.on_error)
self.bus.enable_sync_message_emission()
self.bus.connect('sync-message::element', self.on_sync_message)
def demuxer_callback(self, demuxer, pad):
print (pad.get_property("template").name_template)
if pad.get_property("template").name_template == "audio":
atee_pad = self.atee.get_static_pad("sink")
pad.link(atee_pad)
elif pad.get_property("template").name_template == "video":
vtee_pad = self.vtee.get_static_pad("sink")
pad.link(vtee_pad)
def record_location(self):
today = datetime.today()
directory = "/home/dvruser/gstreamer/records/"+today.strftime("%d-%m-%y")
if not os.path.exists(directory):
os.makedirs(directory)
return directory + today.strftime("/%H:%M:%S") + "_rus_%d.flv"
def make_gui(self):
self.window = Window()
self.window.connect('destroy', self.quit)
self.window.set_default_size(640, 450)
self.vbox = VBox()
self.video_area = DrawingArea()
self.controls_box = HBox()
self.record_button = ToggleButton(label="Запись")
self.record_button.connect("toggled", self.toggle_record_cb)
self.translator_button = ToggleButton(label="Запись переводчика")
self.translator_button.connect("toggled", self.toggle_translator_cb)
self.statusbar = Statusbar()
self.vbox.pack_start(self.video_area, True, True, 0)
self.controls_box.pack_start(self.record_button, False, False, 0)
self.controls_box.pack_start(self.translator_button, False, False, 0)
self.controls_box.pack_start(self.statusbar, True, True, 0)
self.vbox.pack_start(self.controls_box, False, False, 0)
self.window.add(self.vbox)
def run(self):
self.window.show_all()
self.xid = self.video_area.get_property('window').get_xid()
self.record.set_state(Gst.State.PLAYING)
def quit(self, window):
self.record.set_state(Gst.State.NULL)
Gtk.main_quit()
def on_sync_message(self, bus, msg):
if msg.get_structure().get_name() == 'prepare-window-handle':
print('prepare-window-handle')
msg.src.set_property('force-aspect-ratio', True)
msg.src.set_window_handle(self.xid)
def on_error(self, bus, msg):
print('on_error():', msg.parse_error())
def toggle_record_cb(self, widget, data=None):
if (widget.get_active()):
self.record.set_property("location", self.record_location())
self.record.emit("start-capture")
else:
self.record.emit("stop-capture")
print (widget.get_active())
def toggle_translator_cb(self, widget, data=None):
print (widget.get_active())
if __name__ == "__main__":
yayman = YayMan()
yayman.run()
try:
Gtk.main()
except KeyboardInterrupt:
print("Ctrl^C. Exiting...")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment