mirror of
https://github.com/streamlink/streamlink
synced 2024-11-16 05:03:49 +01:00
Make the library more thread safe.
This commit is contained in:
parent
27cb393603
commit
84a935a1d4
@ -60,9 +60,10 @@ Using livestreamer as a library
|
||||
-------------------------------
|
||||
Livestreamer is also a library. Short example:
|
||||
|
||||
import livestreamer
|
||||
from livestreamer import *
|
||||
|
||||
url = "http://twitch.tv/day9tv"
|
||||
livestreamer = Livestreamer()
|
||||
channel = livestreamer.resolve_url(url)
|
||||
streams = channel.get_streams()
|
||||
|
||||
|
@ -1,29 +1,83 @@
|
||||
from . import plugins, stream
|
||||
from . import plugins
|
||||
from .compat import urlparse
|
||||
from .logger import Logger
|
||||
from .options import Options
|
||||
from .plugins import PluginError, NoStreamsError, NoPluginError
|
||||
from .stream import StreamError
|
||||
|
||||
def resolve_url(url):
|
||||
parsed = urlparse(url)
|
||||
import pkgutil
|
||||
import imp
|
||||
|
||||
if len(parsed.scheme) == 0:
|
||||
url = "http://" + url
|
||||
class Livestreamer(object):
|
||||
def __init__(self):
|
||||
self.options = Options({
|
||||
"rtmpdump": None,
|
||||
"errorlog": False
|
||||
})
|
||||
self.plugins = {}
|
||||
self.logger = Logger()
|
||||
self.load_builtin_plugins()
|
||||
|
||||
for name, plugin in plugins.get_plugins().items():
|
||||
if plugin.can_handle_url(url):
|
||||
obj = plugin(url)
|
||||
return obj
|
||||
def set_option(self, key, value):
|
||||
self.options.set(key, value)
|
||||
|
||||
raise plugins.NoPluginError()
|
||||
def get_option(self, key):
|
||||
return self.options.get(key)
|
||||
|
||||
def get_plugins():
|
||||
return plugins.get_plugins()
|
||||
def set_plugin_option(self, plugin, key, value):
|
||||
if plugin in self.plugins:
|
||||
plugin = self.plugins[plugin]
|
||||
plugin.set_option(key, value)
|
||||
|
||||
PluginError = plugins.PluginError
|
||||
NoStreamsError = plugins.NoStreamsError
|
||||
NoPluginError = plugins.NoPluginError
|
||||
StreamError = stream.StreamError
|
||||
def get_plugin_option(self, plugin, key):
|
||||
if plugin in self.plugins:
|
||||
plugin = self.plugins[plugin]
|
||||
return plugin.get_option(key)
|
||||
|
||||
plugins.load_plugins(plugins)
|
||||
def set_loglevel(self, level):
|
||||
self.logger.set_level(level)
|
||||
|
||||
__all__ = ["resolve_url", "get_plugins",
|
||||
"PluginError", "NoStreamsError", "NoPluginError",
|
||||
"StreamError"]
|
||||
def set_logoutput(self, output):
|
||||
self.logger.set_output(output)
|
||||
|
||||
def resolve_url(self, url):
|
||||
parsed = urlparse(url)
|
||||
|
||||
if len(parsed.scheme) == 0:
|
||||
url = "http://" + url
|
||||
|
||||
for name, plugin in self.plugins.items():
|
||||
if plugin.can_handle_url(url):
|
||||
obj = plugin(url)
|
||||
return obj
|
||||
|
||||
raise NoPluginError
|
||||
|
||||
def get_plugins(self):
|
||||
return self.plugins
|
||||
|
||||
def load_builtin_plugins(self):
|
||||
for loader, name, ispkg in pkgutil.iter_modules(plugins.__path__):
|
||||
file, pathname, desc = imp.find_module(name, plugins.__path__)
|
||||
self.load_plugin(name, file, pathname, desc)
|
||||
|
||||
def load_plugins(self, path):
|
||||
for loader, name, ispkg in pkgutil.iter_modules(path):
|
||||
file, pathname, desc = imp.find_module(name, path)
|
||||
self.load_plugin(name, file, pathname, desc)
|
||||
|
||||
def load_plugin(self, name, file, pathname, desc):
|
||||
module = imp.load_module(name, file, pathname, desc)
|
||||
|
||||
plugin = module.__plugin__
|
||||
plugin.module = module.__name__
|
||||
plugin.session = self
|
||||
|
||||
self.plugins[module.__name__] = plugin
|
||||
|
||||
if file:
|
||||
file.close()
|
||||
|
||||
|
||||
__all__ = ["PluginError", "NoStreamsError", "NoPluginError", "StreamError",
|
||||
"Livestreamer"]
|
||||
|
@ -1,8 +1,12 @@
|
||||
import sys, os, argparse, subprocess
|
||||
import livestreamer
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
from livestreamer import *
|
||||
from livestreamer.compat import input, stdout, is_win32
|
||||
from livestreamer.logger import Logger
|
||||
from livestreamer.stream import StreamProcess
|
||||
from livestreamer.utils import ArgumentParser
|
||||
|
||||
exampleusage = """
|
||||
example usage:
|
||||
@ -15,34 +19,51 @@ Stream now playbacks in player (default is VLC).
|
||||
|
||||
"""
|
||||
|
||||
logger = Logger("cli")
|
||||
livestreamer = Livestreamer()
|
||||
logger = livestreamer.logger.new_module("cli")
|
||||
|
||||
msg_output = sys.stdout
|
||||
parser = livestreamer.utils.ArgumentParser(description="CLI program that launches streams from various streaming services in a custom video player",
|
||||
fromfile_prefix_chars="@",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=exampleusage, add_help=False)
|
||||
parser = ArgumentParser(description="CLI program that launches streams from various streaming services in a custom video player",
|
||||
fromfile_prefix_chars="@",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=exampleusage, add_help=False)
|
||||
|
||||
parser.add_argument("url", help="URL to stream", nargs="?")
|
||||
parser.add_argument("stream", help="Stream quality to play, use 'best' for highest quality available", nargs="?")
|
||||
parser.add_argument("stream", help="Stream quality to play, use 'best' for highest quality available",
|
||||
nargs="?")
|
||||
|
||||
parser.add_argument("-h", "--help", action="store_true", help="Show this help message and exit")
|
||||
parser.add_argument("-u", "--plugins", action="store_true", help="Print all currently installed plugins")
|
||||
parser.add_argument("-l", "--loglevel", metavar="level", help="Set log level, valid levels: none, error, warning, info, debug", default="info")
|
||||
parser.add_argument("-h", "--help", action="store_true",
|
||||
help="Show this help message and exit")
|
||||
parser.add_argument("-u", "--plugins", action="store_true",
|
||||
help="Print all currently installed plugins")
|
||||
parser.add_argument("-l", "--loglevel", metavar="level",
|
||||
help="Set log level, valid levels: none, error, warning, info, debug",
|
||||
default="info")
|
||||
|
||||
playeropt = parser.add_argument_group("player options")
|
||||
playeropt.add_argument("-p", "--player", metavar="player", help="Command-line for player, default is 'vlc'", default="vlc")
|
||||
playeropt.add_argument("-q", "--quiet-player", action="store_true", help="Hide all player console output")
|
||||
playeropt.add_argument("-p", "--player", metavar="player",
|
||||
help="Command-line for player, default is 'vlc'",
|
||||
default="vlc")
|
||||
playeropt.add_argument("-q", "--quiet-player", action="store_true",
|
||||
help="Hide all player console output")
|
||||
|
||||
outputopt = parser.add_argument_group("file output options")
|
||||
outputopt.add_argument("-o", "--output", metavar="filename", help="Write stream to file instead of playing it")
|
||||
outputopt.add_argument("-f", "--force", action="store_true", help="Always write to file even if it already exists")
|
||||
outputopt.add_argument("-O", "--stdout", action="store_true", help="Write stream to stdout instead of playing it")
|
||||
outputopt.add_argument("-o", "--output", metavar="filename",
|
||||
help="Write stream to file instead of playing it")
|
||||
outputopt.add_argument("-f", "--force", action="store_true",
|
||||
help="Always write to file even if it already exists")
|
||||
outputopt.add_argument("-O", "--stdout", action="store_true",
|
||||
help="Write stream to stdout instead of playing it")
|
||||
|
||||
pluginopt = parser.add_argument_group("plugin options")
|
||||
pluginopt.add_argument("-c", "--cmdline", action="store_true", help="Print command-line used internally to play stream, this may not be available on all streams")
|
||||
pluginopt.add_argument("-e", "--errorlog", action="store_true", help="Log possible errors from internal command-line to a temporary file, use when debugging")
|
||||
pluginopt.add_argument("-r", "--rtmpdump", metavar="path", help="Specify location of rtmpdump")
|
||||
pluginopt.add_argument("-j", "--jtv-cookie", metavar="cookie", help="Specify JustinTV cookie to allow access to subscription channels")
|
||||
pluginopt.add_argument("-c", "--cmdline", action="store_true",
|
||||
help="Print command-line used internally to play stream, this may not be available on all streams")
|
||||
pluginopt.add_argument("-e", "--errorlog", action="store_true",
|
||||
help="Log possible errors from internal command-line to a temporary file, use when debugging")
|
||||
pluginopt.add_argument("-r", "--rtmpdump", metavar="path",
|
||||
help="Specify location of rtmpdump")
|
||||
pluginopt.add_argument("-j", "--jtv-cookie", metavar="cookie",
|
||||
help="Specify JustinTV cookie to allow access to subscription channels")
|
||||
|
||||
RCFILE = os.path.expanduser("~/.livestreamerrc")
|
||||
|
||||
@ -54,7 +75,7 @@ def msg(msg):
|
||||
|
||||
def set_msg_output(output):
|
||||
msg_output = output
|
||||
logger.set_output(output)
|
||||
livestreamer.set_logoutput(output)
|
||||
|
||||
def write_stream(fd, out, progress):
|
||||
written = 0
|
||||
@ -119,7 +140,7 @@ def output_stream(stream, args):
|
||||
|
||||
try:
|
||||
fd = stream.open()
|
||||
except livestreamer.StreamError as err:
|
||||
except StreamError as err:
|
||||
exit(("Could not open stream - {0}").format(err))
|
||||
|
||||
logger.debug("Pre-buffering 8192 bytes")
|
||||
@ -180,16 +201,16 @@ def output_stream(stream, args):
|
||||
def handle_url(args):
|
||||
try:
|
||||
channel = livestreamer.resolve_url(args.url)
|
||||
except livestreamer.NoPluginError:
|
||||
except NoPluginError:
|
||||
exit(("No plugin can handle URL: {0}").format(args.url))
|
||||
|
||||
logger.info("Found matching plugin {0} for URL {1}", channel.module, args.url)
|
||||
|
||||
try:
|
||||
streams = channel.get_streams()
|
||||
except livestreamer.StreamError as err:
|
||||
except StreamError as err:
|
||||
exit(str(err))
|
||||
except livestreamer.PluginError as err:
|
||||
except PluginError as err:
|
||||
exit(str(err))
|
||||
|
||||
if len(streams) == 0:
|
||||
@ -204,7 +225,7 @@ def handle_url(args):
|
||||
stream = streams[args.stream]
|
||||
|
||||
if args.cmdline:
|
||||
if isinstance(stream, livestreamer.stream.StreamProcess):
|
||||
if isinstance(stream, StreamProcess):
|
||||
msg(stream.cmdline())
|
||||
else:
|
||||
exit("Stream does not use a command-line")
|
||||
@ -233,10 +254,10 @@ def main():
|
||||
if args.stdout or args.output == "-":
|
||||
set_msg_output(sys.stderr)
|
||||
|
||||
livestreamer.options.set("errorlog", args.errorlog)
|
||||
livestreamer.options.set("rtmpdump", args.rtmpdump)
|
||||
livestreamer.options.set("jtvcookie", args.jtv_cookie)
|
||||
logger.set_level(args.loglevel)
|
||||
livestreamer.set_option("errorlog", args.errorlog)
|
||||
livestreamer.set_option("rtmpdump", args.rtmpdump)
|
||||
livestreamer.set_plugin_option("justintv", "cookie", args.jtv_cookie)
|
||||
livestreamer.set_loglevel(args.loglevel)
|
||||
|
||||
if args.url:
|
||||
handle_url(args)
|
||||
|
@ -4,47 +4,50 @@ class Logger(object):
|
||||
Levels = ["none", "error", "warning", "info", "debug"]
|
||||
Format = "[{module}][{level}] {msg}\n"
|
||||
|
||||
output = sys.stdout
|
||||
level = 0
|
||||
def __init__(self):
|
||||
self.output = sys.stdout
|
||||
self.level = 0
|
||||
|
||||
@classmethod
|
||||
def set_level(cls, level):
|
||||
def new_module(self, module):
|
||||
return LoggerModule(self, module)
|
||||
|
||||
def set_level(self, level):
|
||||
try:
|
||||
index = Logger.Levels.index(level)
|
||||
except ValueError:
|
||||
return
|
||||
|
||||
cls.level = index
|
||||
self.level = index
|
||||
|
||||
@classmethod
|
||||
def set_output(cls, output):
|
||||
cls.output = output
|
||||
def set_output(self, output):
|
||||
self.output = output
|
||||
|
||||
def __init__(self, module):
|
||||
self.module = module
|
||||
|
||||
def msg(self, level, msg, *args):
|
||||
if Logger.level < level or level > len(Logger.Levels):
|
||||
def msg(self, module, level, msg, *args):
|
||||
if self.level < level or level > len(Logger.Levels):
|
||||
return
|
||||
|
||||
msg = msg.format(*args)
|
||||
|
||||
self.output.write(Logger.Format.format(module=self.module,
|
||||
self.output.write(Logger.Format.format(module=module,
|
||||
level=Logger.Levels[level],
|
||||
msg=msg))
|
||||
self.output.flush()
|
||||
|
||||
class LoggerModule(object):
|
||||
def __init__(self, manager, module):
|
||||
self.manager = manager
|
||||
self.module = module
|
||||
|
||||
def error(self, msg, *args):
|
||||
self.msg(1, msg, *args)
|
||||
self.manager.msg(self.module, 1, msg, *args)
|
||||
|
||||
def warning(self, msg, *args):
|
||||
self.msg(2, msg, *args)
|
||||
self.manager.msg(self.module, 2, msg, *args)
|
||||
|
||||
def info(self, msg, *args):
|
||||
self.msg(3, msg, *args)
|
||||
self.manager.msg(self.module, 3, msg, *args)
|
||||
|
||||
def debug(self, msg, *args):
|
||||
self.msg(4, msg, *args)
|
||||
|
||||
self.manager.msg(self.module, 4, msg, *args)
|
||||
|
||||
__all__ = ["Logger"]
|
||||
|
@ -1,14 +1,12 @@
|
||||
options = {
|
||||
"rtmpdump": None,
|
||||
"errorlog": False,
|
||||
"jtvcookie": None
|
||||
}
|
||||
class Options(object):
|
||||
def __init__(self, defaults={}):
|
||||
self.options = defaults
|
||||
|
||||
def set(key, value):
|
||||
options[key] = value
|
||||
def set(self, key, value):
|
||||
self.options[key] = value
|
||||
|
||||
def get(key):
|
||||
if key in options:
|
||||
return options[key]
|
||||
def get(self, key):
|
||||
if key in self.options:
|
||||
return self.options[key]
|
||||
|
||||
__all__ = ["get", "set"]
|
||||
__all__ = ["Options"]
|
||||
|
@ -1,20 +1,24 @@
|
||||
import pkgutil
|
||||
import imp
|
||||
|
||||
from livestreamer.logger import Logger
|
||||
|
||||
plugins_loaded = {}
|
||||
from livestreamer.options import Options
|
||||
|
||||
class Plugin(object):
|
||||
options = Options()
|
||||
|
||||
def __init__(self, url):
|
||||
self.url = url
|
||||
self.args = None
|
||||
self.logger = Logger("plugin." + self.module)
|
||||
self.logger = self.session.logger.new_module("plugin." + self.module)
|
||||
|
||||
@classmethod
|
||||
def can_handle_url(self, url):
|
||||
def can_handle_url(cls, url):
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def set_option(cls, key, value):
|
||||
cls.options.set(key, value)
|
||||
|
||||
@classmethod
|
||||
def get_option(cls, key):
|
||||
return cls.options.get(key)
|
||||
|
||||
def get_streams(self):
|
||||
ranking = ["iphonelow", "iphonehigh", "240p", "320k", "360p", "850k",
|
||||
"480p", "1400k", "720p", "2400k", "hd", "1080p", "live"]
|
||||
@ -39,18 +43,4 @@ class NoStreamsError(PluginError):
|
||||
class NoPluginError(PluginError):
|
||||
pass
|
||||
|
||||
def load_plugins(plugins):
|
||||
for loader, name, ispkg in pkgutil.iter_modules(plugins.__path__):
|
||||
file, pathname, desc = imp.find_module(name, plugins.__path__)
|
||||
imp.load_module(name, file, pathname, desc)
|
||||
return plugins_loaded
|
||||
|
||||
def get_plugins():
|
||||
return plugins_loaded
|
||||
|
||||
def register_plugin(name, klass):
|
||||
plugins_loaded[name] = klass
|
||||
klass.module = name
|
||||
|
||||
__all__ = ["Plugin", "PluginError", "NoStreamsError", "NoPluginError",
|
||||
"load_plugins", "get_plugins", "register_plugin"]
|
||||
__all__ = ["Plugin", "PluginError", "NoStreamsError", "NoPluginError"]
|
||||
|
@ -1,12 +1,16 @@
|
||||
from livestreamer.plugins import Plugin, PluginError, NoStreamsError, register_plugin
|
||||
from livestreamer.plugins import Plugin, PluginError, NoStreamsError
|
||||
from livestreamer.stream import RTMPStream
|
||||
from livestreamer.utils import swfverify, urlget
|
||||
from livestreamer.compat import urllib, str
|
||||
from livestreamer import options
|
||||
from livestreamer.options import Options
|
||||
|
||||
import xml.dom.minidom, re, sys, random
|
||||
|
||||
class JustinTV(Plugin):
|
||||
options = Options({
|
||||
"cookie": None
|
||||
})
|
||||
|
||||
StreamInfoURL = "http://usher.justin.tv/find/{0}.xml?type=any&p={1}&b_id=true&chansub_guid={2}&private_code=null&group=&channel_subscription={2}"
|
||||
MetadataURL = "http://www.justin.tv/meta/{0}.xml?on_site=true"
|
||||
SWFURL = "http://www.justin.tv/widgets/live_embed_player.swf"
|
||||
@ -19,7 +23,7 @@ class JustinTV(Plugin):
|
||||
return url.rstrip("/").rpartition("/")[2]
|
||||
|
||||
def _get_metadata(self, channel):
|
||||
cookie = options.get("jtvcookie")
|
||||
cookie = self.options.get("cookie")
|
||||
|
||||
if cookie:
|
||||
headers = {"Cookie": cookie}
|
||||
@ -64,7 +68,7 @@ class JustinTV(Plugin):
|
||||
|
||||
|
||||
chansub = None
|
||||
if options.get("jtvcookie"):
|
||||
if self.options.get("cookie") is not None:
|
||||
self.logger.debug("Attempting to authenticate using cookie")
|
||||
|
||||
metadata = self._get_metadata(channelname)
|
||||
@ -101,7 +105,7 @@ class JustinTV(Plugin):
|
||||
for child in node.childNodes:
|
||||
info[child.tagName] = self._get_node_text(child)
|
||||
|
||||
stream = RTMPStream({
|
||||
stream = RTMPStream(self.session, {
|
||||
"rtmp": ("{0}/{1}").format(info["connect"], info["play"]),
|
||||
"swfUrl": self.SWFURL,
|
||||
"swfhash": swfhash,
|
||||
@ -128,4 +132,5 @@ class JustinTV(Plugin):
|
||||
|
||||
return self._get_streaminfo(channelname)
|
||||
|
||||
register_plugin("justintv", JustinTV)
|
||||
|
||||
__plugin__ = JustinTV
|
||||
|
@ -1,5 +1,5 @@
|
||||
from livestreamer.compat import urllib, bytes, str
|
||||
from livestreamer.plugins import Plugin, PluginError, NoStreamsError, register_plugin
|
||||
from livestreamer.plugins import Plugin, PluginError, NoStreamsError
|
||||
from livestreamer.stream import RTMPStream
|
||||
from livestreamer.utils import urlget, swfverify
|
||||
|
||||
@ -93,7 +93,7 @@ class OwnedTV(Plugin):
|
||||
name = streamel.getAttribute("label").lower().replace(" ", "_")
|
||||
playpath = streamel.getAttribute("name")
|
||||
|
||||
stream = RTMPStream({
|
||||
stream = RTMPStream(self.session, {
|
||||
"rtmp": ("{0}/{1}").format(base, playpath),
|
||||
"live": True,
|
||||
"swfhash": swfhash,
|
||||
@ -113,4 +113,4 @@ class OwnedTV(Plugin):
|
||||
|
||||
return streams
|
||||
|
||||
register_plugin("own3dtv", OwnedTV)
|
||||
__plugin__ = OwnedTV
|
||||
|
@ -1,5 +1,5 @@
|
||||
from livestreamer.compat import str
|
||||
from livestreamer.plugins import Plugin, PluginError, NoStreamsError, register_plugin
|
||||
from livestreamer.plugins import Plugin, PluginError, NoStreamsError
|
||||
from livestreamer.stream import RTMPStream
|
||||
from livestreamer.utils import urlget, swfverify, verifyjson
|
||||
|
||||
@ -49,7 +49,7 @@ class SVTPlay(Plugin):
|
||||
if not ("url" in video and "playerType" in video and video["playerType"] == "flash"):
|
||||
continue
|
||||
|
||||
stream = RTMPStream({
|
||||
stream = RTMPStream(self.session, {
|
||||
"rtmp": video["url"],
|
||||
"pageUrl": self.PageURL,
|
||||
"swfhash": swfhash,
|
||||
@ -61,4 +61,4 @@ class SVTPlay(Plugin):
|
||||
|
||||
return streams
|
||||
|
||||
register_plugin("svtplay", SVTPlay)
|
||||
__plugin__ = SVTPlay
|
||||
|
@ -1,5 +1,5 @@
|
||||
from livestreamer.compat import str, bytes
|
||||
from livestreamer.plugins import Plugin, PluginError, NoStreamsError, register_plugin
|
||||
from livestreamer.plugins import Plugin, PluginError, NoStreamsError
|
||||
from livestreamer.stream import RTMPStream
|
||||
from livestreamer.utils import urlget
|
||||
|
||||
@ -41,7 +41,7 @@ class UStreamTV(Plugin):
|
||||
fmsurl = get_amf_value(data, "fmsUrl")
|
||||
|
||||
if playpath:
|
||||
stream = RTMPStream({
|
||||
stream = RTMPStream(self.session, {
|
||||
"rtmp": ("{0}/{1}").format(cdnurl or fmsurl, playpath),
|
||||
"pageUrl": self.url,
|
||||
"swfUrl": self.SWFURL,
|
||||
@ -51,4 +51,4 @@ class UStreamTV(Plugin):
|
||||
|
||||
return streams
|
||||
|
||||
register_plugin("ustreamtv", UStreamTV)
|
||||
__plugin__ = UStreamTV
|
||||
|
@ -1,5 +1,5 @@
|
||||
from livestreamer.compat import str, bytes, parse_qs
|
||||
from livestreamer.plugins import Plugin, PluginError, NoStreamsError, register_plugin
|
||||
from livestreamer.plugins import Plugin, PluginError, NoStreamsError
|
||||
from livestreamer.stream import HTTPStream
|
||||
from livestreamer.utils import urlget, verifyjson
|
||||
|
||||
@ -76,7 +76,7 @@ class Youtube(Plugin):
|
||||
if not "url" in streaminfo:
|
||||
continue
|
||||
|
||||
stream = HTTPStream(streaminfo["url"][0])
|
||||
stream = HTTPStream(self.session, streaminfo["url"][0])
|
||||
|
||||
if streaminfo["itag"][0] in formatmap:
|
||||
quality = formatmap[streaminfo["itag"][0]]
|
||||
@ -87,4 +87,4 @@ class Youtube(Plugin):
|
||||
|
||||
return streams
|
||||
|
||||
register_plugin("youtube", Youtube)
|
||||
__plugin__ = Youtube
|
||||
|
@ -1,4 +1,3 @@
|
||||
from . import options
|
||||
from .utils import urlopen
|
||||
from .compat import str, is_win32
|
||||
|
||||
@ -11,15 +10,20 @@ class StreamError(Exception):
|
||||
pass
|
||||
|
||||
class Stream(object):
|
||||
def __init__(self, session):
|
||||
self.session = session
|
||||
|
||||
def open(self):
|
||||
raise NotImplementedError
|
||||
|
||||
class StreamProcess(Stream):
|
||||
def __init__(self, params):
|
||||
self.params = params or {}
|
||||
def __init__(self, session, params={}):
|
||||
Stream.__init__(self, session)
|
||||
|
||||
self.params = params
|
||||
self.params["_bg"] = True
|
||||
self.params["_err"] = open(os.devnull, "w")
|
||||
self.errorlog = options.get("errorlog")
|
||||
self.errorlog = self.session.options.get("errorlog")
|
||||
|
||||
def cmdline(self):
|
||||
return str(self.cmd.bake(**self.params))
|
||||
@ -45,10 +49,10 @@ class StreamProcess(Stream):
|
||||
return stream.process.stdout
|
||||
|
||||
class RTMPStream(StreamProcess):
|
||||
def __init__(self, params):
|
||||
StreamProcess.__init__(self, params)
|
||||
def __init__(self, session, params):
|
||||
StreamProcess.__init__(self, session, params)
|
||||
|
||||
self.rtmpdump = options.get("rtmpdump") or (is_win32 and "rtmpdump.exe" or "rtmpdump")
|
||||
self.rtmpdump = self.session.options.get("rtmpdump") or (is_win32 and "rtmpdump.exe" or "rtmpdump")
|
||||
self.params["flv"] = "-"
|
||||
|
||||
try:
|
||||
@ -75,7 +79,9 @@ class RTMPStream(StreamProcess):
|
||||
return False
|
||||
|
||||
class HTTPStream(Stream):
|
||||
def __init__(self, url):
|
||||
def __init__(self, session, url):
|
||||
Stream.__init__(self, session)
|
||||
|
||||
self.url = url
|
||||
|
||||
def open(self):
|
||||
|
Loading…
Reference in New Issue
Block a user