API Guide

This API is what powers the Command-Line Interface but is also available to developers that wish to make use of the data Livestreamer can retrieve in their own application.

Extracting streams

The simplest use of the Livestreamer API looks like this:

>>> import livestreamer
>>> streams = livestreamer.streams("http://twitch.tv/day9tv")

This simply attempts to find a plugin and use it to extract streams from the URL. This works great in simple cases but if you want more fine tuning you need to use a session object instead.

The returned value is a dict containing Stream objects:

>>> streams
{'best': <HLSStream('http://video11.fra01.hls.twitch.tv/ ...')>,
 'high': <HLSStream('http://video11.fra01.hls.twitch.tv/ ...')>,
 'low': <HLSStream('http://video11.fra01.hls.twitch.tv/ ...')>,
 'medium': <HLSStream('http://video11.fra01.hls.twitch.tv/ ...')>,
 'mobile': <HLSStream('http://video11.fra01.hls.twitch.tv/ ...')>,
 'source': <HLSStream('http://video11.fra01.hls.twitch.tv/ ...')>,
 'worst': <HLSStream('http://video11.fra01.hls.twitch.tv/ ...')>}

If no plugin for the URL is found, a NoPluginError will be raised. If an error occurs while fetching streams, a PluginError will be raised.

Opening streams to read data

Now that you have extracted some streams we might want to read some data from one of them. When you call open() on a stream, a file-like object will be returned, which you can call .read(size) and .close() on.

>>> stream = streams["source"]
>>> fd = stream.open()
>>> data = fd.read(1024)
>>> fd.close()

If an error occurs while opening a stream, a StreamError will be raised.

Inspecting streams

It’s also possible to inspect streams internal parameters, see Stream subclasses to see what attributes are available for inspection for each stream type.

For example this is a HLSStream object which contains a url attribute.

>>> stream.url
'http://video38.ams01.hls.twitch.tv/hls11/ ...'

Session object

The session allows you to set various options and is more efficient when extracting streams more than once. You start by creating a Livestreamer object:

>>> from livestreamer import Livestreamer
>>> session = Livestreamer()

You can then extract streams like this:

>>> streams = session.streams("http://twitch.tv/day9tv")

or set options like this:

>>> session.set_option("rtmp-rtmpdump", "/path/to/rtmpdump")

See Livestreamer.set_option() to see which options are available.

Examples

Simple player

This example uses the PyGObject module to playback a stream using the GStreamer framework.

#!/usr/bin/env python

from __future__ import print_function

import sys

import gi

from gi.repository import GObject as gobject, Gst as gst
from livestreamer import Livestreamer, StreamError, PluginError, NoPluginError


def exit(msg):
    print(msg, file=sys.stderr)
    sys.exit()


class LivestreamerPlayer(object):
    def __init__(self):
        self.fd = None
        self.mainloop = gobject.MainLoop()

        # This creates a playbin pipeline and using the appsrc source
        # we can feed it our stream data
        self.pipeline = gst.ElementFactory.make("playbin", None)
        self.pipeline.set_property("uri", "appsrc://")

        # When the playbin creates the appsrc source it will call
        # this callback and allow us to configure it
        self.pipeline.connect("source-setup", self.on_source_setup)

        # Creates a bus and set callbacks to receive errors
        self.bus = self.pipeline.get_bus()
        self.bus.add_signal_watch()
        self.bus.connect("message::eos", self.on_eos)
        self.bus.connect("message::error", self.on_error)

    def exit(self, msg):
        self.stop()
        exit(msg)

    def stop(self):
        # Stop playback and exit mainloop
        self.pipeline.set_state(gst.State.NULL)
        self.mainloop.quit()

        # Close the stream
        if self.fd:
            self.fd.close()

    def play(self, stream):
        # Attempt to open the stream
        try:
            self.fd = stream.open()
        except StreamError as err:
            self.exit("Failed to open stream: {0}".format(err))

        # Start playback
        self.pipeline.set_state(gst.State.PLAYING)
        self.mainloop.run()

    def on_source_setup(self, element, source):
        # When this callback is called the appsrc expects
        # us to feed it more data
        source.connect("need-data", self.on_source_need_data)

    def on_source_need_data(self, source, length):
        # Attempt to read data from the stream
        try:
            data = self.fd.read(length)
        except IOError as err:
            self.exit("Failed to read data from stream: {0}".format(err))

        # If data is empty it's the end of stream
        if not data:
            source.emit("end-of-stream")
            return

        # Convert the Python bytes into a GStreamer Buffer
        # and then push it to the appsrc
        buf = gst.Buffer.new_wrapped(data)
        source.emit("push-buffer", buf)

    def on_eos(self, bus, msg):
        # Stop playback on end of stream
        self.stop()

    def on_error(self, bus, msg):
        # Print error message and exit on error
        error = msg.parse_error()[1]
        self.exit(error)


def main():
    if len(sys.argv) < 3:
        exit("Usage: {0} <url> <quality>".format(sys.argv[0]))

    # Initialize and check GStreamer version
    gi.require_version("Gst", "1.0")
    gobject.threads_init()
    gst.init(None)

    # Collect arguments
    url = sys.argv[1]
    quality = sys.argv[2]

    # Create the Livestreamer session
    livestreamer = Livestreamer()

    # Enable logging
    livestreamer.set_loglevel("info")
    livestreamer.set_logoutput(sys.stdout)

    # Attempt to fetch streams
    try:
        streams = livestreamer.streams(url)
    except NoPluginError:
        exit("Livestreamer is unable to handle the URL '{0}'".format(url))
    except PluginError as err:
        exit("Plugin error: {0}".format(err))

    if not streams:
        exit("No streams found on URL '{0}'".format(url))

    # Look for specified stream
    if quality not in streams:
        exit("Unable to find '{0}' stream on URL '{1}'".format(quality, url))

    # We found the stream
    stream = streams[quality]

    # Create the player and start playback
    player = LivestreamerPlayer()

    # Blocks until playback is done
    player.play(stream)

if __name__ == "__main__":
    main()