Skip to content

Instantly share code, notes, and snippets.

@tylercubell
Created February 14, 2019 19:45
Show Gist options
  • Save tylercubell/3bdf6e4ce7691907d1f0175a2d8747c0 to your computer and use it in GitHub Desktop.
Save tylercubell/3bdf6e4ce7691907d1f0175a2d8747c0 to your computer and use it in GitHub Desktop.
GStreamer Python HLS to YouTube Live
import os, gi, time
gi.require_version("Gst", "1.0")
from gi.repository import GObject, Gst
Gst.init(None)
pipeline = Gst.Pipeline()
bus = pipeline.get_bus()
# Variables.
hls_uri = "your_hls_uri"
youtube_stream_key = "your_stream_key"
encoder_speed = "ultrafast"
# Video elements.
def pad_added(element, pad):
pad_type = pad.get_current_caps().get_structure(0).get_name()
if pad_type == "video/x-raw":
pad.link(videoconvert.get_static_pad("sink"))
if pad_type == "audio/x-raw":
pad.link(queue.get_static_pad("sink"))
uridecodebin = Gst.ElementFactory.make("uridecodebin", "uridecodebin")
uridecodebin.set_property("uri", hls_uri)
pipeline.add(uridecodebin)
uridecodebin.connect("pad-added", pad_added)
videoconvert = Gst.ElementFactory.make("videoconvert")
pipeline.add(videoconvert)
videoscale = Gst.ElementFactory.make("videoscale")
pipeline.add(videoscale)
videorate = Gst.ElementFactory.make("videorate")
pipeline.add(videorate)
x264enc = Gst.ElementFactory.make("x264enc")
x264enc.set_property("bitrate", 4000)
x264enc.set_property("tune", "zerolatency")
x264enc.set_property("key-int-max", 60)
x264enc.set_property("speed-preset", encoder_speed)
x264enc.set_property("option-string", "keyint=60:min-keyint=60")
pipeline.add(x264enc)
h264parse = Gst.ElementFactory.make("h264parse")
pipeline.add(h264parse)
flvmux = Gst.ElementFactory.make("flvmux")
flvmux.set_property("streamable", True)
pipeline.add(flvmux)
rtmpsink = Gst.ElementFactory.make("rtmpsink")
rtmpsink.set_property("location", "rtmp://a.rtmp.youtube.com/live2/" + youtube_stream_key)
pipeline.add(rtmpsink)
video_caps = Gst.Caps.from_string("video/x-raw,format=I420,width=1280,height=720,framerate=30/1")
videoconvert.link(videoscale)
videoscale.link(videorate)
videorate.link_filtered(x264enc, video_caps)
x264enc.link(h264parse)
h264parse.link(flvmux)
flvmux.link(rtmpsink)
# Audio elements.
queue = Gst.ElementFactory.make("queue")
pipeline.add(queue)
audioconvert = Gst.ElementFactory.make("audioconvert")
pipeline.add(audioconvert)
voaacenc = Gst.ElementFactory.make("voaacenc")
voaacenc.set_property("bitrate", 96000)
pipeline.add(voaacenc)
aacparse = Gst.ElementFactory.make("aacparse")
pipeline.add(aacparse)
audio_caps = Gst.Caps.from_string("audio/x-raw,rate=48000")
queue.link(audioconvert)
audioconvert.link_filtered(voaacenc, audio_caps)
voaacenc.link(aacparse)
aacparse.link(flvmux)
# Start pipeline.
pipeline.set_state(Gst.State.PLAYING)
while True:
try:
message = bus.timed_pop(Gst.SECOND)
if message == None:
pass
elif message.type == Gst.MessageType.EOS:
break
elif message.type == Gst.MessageType.ERROR:
error, debug = message.parse_error()
print(error, debug)
break
except KeyboardInterrupt:
break
pipeline.set_state(Gst.State.NULL)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment