Clean up RTMP and subprocess options a bit.

Also add --rtmp-timeout option.
This commit is contained in:
Christopher Rosell 2014-04-18 18:21:43 +02:00
parent 35ec9e7b04
commit e31c5c3c3a
6 changed files with 120 additions and 74 deletions

View File

@ -458,42 +458,32 @@ File output options
Stream transport options
^^^^^^^^^^^^^^^^^^^^^^^^
.. cmdoption:: -c, --cmdline
Print command-line used internally to play stream,
this may not be available on all streams
.. cmdoption:: -e, --errorlog
Log possible errors from internal command-line to a
temporary file, use when debugging
.. cmdoption:: -r path, --rtmpdump path
Specify location of rtmpdump executable, e.g.
``/usr/local/bin/rtmpdump``
.. cmdoption:: --rtmpdump-proxy host:port
Specify a proxy (SOCKS) that rtmpdump will use
.. cmdoption:: --hls-live-edge segments
How many segments from the end to start live streams
on, default is ``3``
.. versionadded:: 1.8.0
.. cmdoption:: --hls-segment-attempts attempts
How many attempts should be done to download each
segment, default is ``3``
.. versionadded:: 1.8.0
.. cmdoption:: --hls-segment-timeout timeout
Segment connect and read timeout, default is ``10.0``
.. versionadded:: 1.8.0
.. cmdoption:: --hls-timeout timeout
HLS read timeout, default is ``60.0``
Timeout for reading data from HLS streams,
default is ``60.0``
.. versionadded:: 1.8.0
.. cmdoption:: --hds-live-edge seconds
@ -514,6 +504,33 @@ Stream transport options
HDS streams manages this value automatically, use
``--hds-fragment-buffer`` to change it
.. cmdoption:: --rtmp-proxy host:port, --rtmpdump-proxy host:port
Specify a proxy (SOCKS) that RTMP streams will use
.. cmdoption:: --rtmp-rtmpdump path, --rtmpdump path, -r path
Specify location of the rtmpdump executable used by
RTMP streams, e.g. ``/usr/local/bin/rtmpdump``
.. cmdoption:: --rtmp-timeout timeout
Timeout for reading data from RTMP streams,
default is ``60.0``
.. versionadded:: 1.8.0
.. cmdoption:: --subprocess-cmdline, --cmdline, -c
Print command-line used internally to play stream,
this is only available for RTMP streams
.. cmdoption:: --subprocess-errorlog, --errorlog, -e
Log possible errors from internal subprocesses to a
temporary file, use when debugging rtmpdump related
issues
Plugin options
^^^^^^^^^^^^^^

View File

@ -39,16 +39,17 @@ class Livestreamer(object):
def __init__(self):
self.http = api.HTTPSession()
self.options = Options({
"rtmpdump": is_win32 and "rtmpdump.exe" or "rtmpdump",
"rtmpdump-proxy": None,
"ringbuffer-size": 1024 * 1024 * 16, # 16 MB
"hds-live-edge": 10.0,
"hds-fragment-buffer": 10,
"hls-live-edge": 3,
"hls-segment-attempts": 3,
"hls-segment-timeout": 10.0,
"hls-timeout": 60.0,
"errorlog": False,
"rtmp-timeout": 60.0,
"rtmp-rtmpdump": is_win32 and "rtmpdump.exe" or "rtmpdump",
"rtmp-proxy": None,
"ringbuffer-size": 1024 * 1024 * 16, # 16 MB
"subprocess-errorlog": False
})
self.plugins = {}
self.logger = Logger()
@ -65,9 +66,6 @@ class Livestreamer(object):
**Available options**:
======================= =========================================
errorlog (bool) Log errors from subprocesses to
a file located in the temp directory
hls-live-edge (int) How many segments from the end
to start live streams on, default: ``3``
@ -77,7 +75,8 @@ class Livestreamer(object):
hls-segment-timeout (float) Segment connect and read timeout,
default: ``10.0``
hls-timeout (float) HLS read timeout, default: ``60.0``
hls-timeout (float) Timeout for reading data from
HLS streams, default: ``60.0``
hds-fragment-buffer (int) Specify the maximum amount of
fragments to buffer, this controls the
@ -119,19 +118,36 @@ class Livestreamer(object):
can be either a .pem file (str) or a
.crt/.key pair (tuple)
subprocess-errorlog (bool) Log errors from subprocesses to
a file located in the temp directory
ringbuffer-size (int) The size of the internal ring
buffer used by most stream types,
default: ``16777216`` (16MB)
rtmpdump (str) Specify the location of the
rtmpdump executable, e.g.
``/usr/local/bin/rtmpdump``
rtmp-proxy (str) Specify a proxy (SOCKS) that RTMP
streams will use
rtmp-rtmpdump (str) Specify the location of the
rtmpdump executable used by RTMP streams,
e.g. ``/usr/local/bin/rtmpdump``
rtmp-timeout (float) Timeout for reading data from
RTMP streams, default: ``60.0``
rtmpdump-proxy (str) Specify a proxy (SOCKS) that
rtmpdump will use
======================= =========================================
"""
# Backwards compatibility
if key == "rtmpdump":
key = "rtmp-rtmpdump"
elif key == "rtmpdump-proxy":
key = "rtmp-proxy"
elif key == "errorlog":
key = "subprocess-errorlog"
if key == "http-proxy":
if not re.match("^http(s)?://", value):
value = "http://" + value

View File

@ -9,8 +9,7 @@ from time import sleep
import re
class RTMPStream(StreamProcess):
"""
RTMP stream handler using rtmpdump.
"""RTMP stream using rtmpdump.
*Attributes:*
@ -19,24 +18,23 @@ class RTMPStream(StreamProcess):
__shortname__ = "rtmp"
def __init__(self, session, params, redirect=False, timeout=30):
StreamProcess.__init__(self, session, params, timeout)
def __init__(self, session, params, redirect=False):
StreamProcess.__init__(self, session, params)
self.cmd = self.session.options.get("rtmpdump")
self.cmd = self.session.options.get("rtmp-rtmpdump")
self.timeout = self.session.options.get("rtmp-timeout")
self.redirect = redirect
self.logger = session.logger.new_module("stream.rtmp")
def __repr__(self):
return ("<RTMPStream({0!r}, redirect={1!r}, "
"timeout={2!r})>").format(self.params, self.redirect,
self.timeout)
return ("<RTMPStream({0!r}, redirect={1!r}>").format(self.params,
self.redirect)
def __json__(self):
return dict(type=RTMPStream.shortname(),
params=self.params)
return dict(type=RTMPStream.shortname(), params=self.params)
def open(self):
if self.session.options.get("rtmpdump-proxy"):
if self.session.options.get("rtmp-proxy"):
if not self._supports_param("socks"):
raise StreamError("Installed rtmpdump does not support --socks argument")
@ -111,9 +109,10 @@ class RTMPStream(StreamProcess):
try:
help = cmd(help=True, _err_to_out=True)
except sh.ErrorReturnCode as err:
raise StreamError(("Error while checking rtmpdump compatibility: {0}").format(str(err.stdout, "ascii")))
err = str(err.stdout, "ascii")
raise StreamError("Error while checking rtmpdump compatibility: {0}".format(err))
for line in help.split("\n"):
for line in help.splitlines():
m = re.match("^--(\w+)", line)
if not m:

View File

@ -26,14 +26,14 @@ class StreamProcessIO(StreamIOThreadWrapper):
class StreamProcess(Stream):
def __init__(self, session, params=None, timeout=30):
def __init__(self, session, params=None, timeout=60.0):
Stream.__init__(self, session)
if not params:
params = {}
self.params = params
self.errorlog = self.session.options.get("errorlog")
self.errorlog = self.session.options.get("subprocess-errorlog")
self.timeout = timeout
def open(self):
@ -58,7 +58,8 @@ class StreamProcess(Stream):
if not process_alive:
if self.errorlog:
raise StreamError(("Error while executing subprocess, error output logged to: {0}").format(tmpfile.name))
raise StreamError(("Error while executing subprocess, "
"error output logged to: {0}").format(tmpfile.name))
else:
raise StreamError("Error while executing subprocess")
@ -69,7 +70,7 @@ class StreamProcess(Stream):
try:
cmd = sh.create_command(self.cmd)
except sh.CommandNotFound as err:
raise StreamError(("Unable to find {0} command").format(str(err)))
raise StreamError("Unable to find {0} command".format(err))
return cmd

View File

@ -170,18 +170,6 @@ outputopt.add_argument("-O", "--stdout", action="store_true",
help="Write stream to stdout instead of playing it")
streamopt = parser.add_argument_group("stream transport options")
streamopt.add_argument("-c", "--cmdline", action="store_true",
help="Print command-line used internally to play "
"stream, this may not be available on all streams")
streamopt.add_argument("-e", "--errorlog", action="store_true",
help="Log possible errors from internal command-line "
"to a temporary file, use when debugging rtmpdump "
"related issues")
streamopt.add_argument("-r", "--rtmpdump", metavar="path",
help="Specify location of rtmpdump executable, "
"e.g. /usr/local/bin/rtmpdump")
streamopt.add_argument("--rtmpdump-proxy", metavar="host:port",
help="Specify a proxy (SOCKS) that rtmpdump will use")
streamopt.add_argument("--hls-live-edge", type=int, metavar="segments",
help="How many segments from the end to start "
"live streams on, default is 3")
@ -191,7 +179,9 @@ streamopt.add_argument("--hls-segment-attempts", type=int, metavar="attempts",
streamopt.add_argument("--hls-segment-timeout", type=float, metavar="timeout",
help="Segment connect and read timeout, default is 10.0")
streamopt.add_argument("--hls-timeout", type=float, metavar="timeout",
help="HLS read timeout, default is 60.0")
help="Timeout for reading data from HLS streams, "
"default is 60.0")
streamopt.add_argument("--hds-live-edge", type=float, metavar="seconds",
help="Specify the time live HDS streams will start "
"from the edge of stream, default is 10.0")
@ -204,6 +194,23 @@ streamopt.add_argument("--ringbuffer-size", metavar="size", type=int,
"ringbuffer, default is 16777216 (16MB). "
"HDS streams manages this value automatically, "
"use --hds-fragment-buffer to change it")
streamopt.add_argument("--rtmp-proxy", "--rtmpdump-proxy", metavar="host:port",
help="Specify a proxy (SOCKS) that RTMP streams will use")
streamopt.add_argument("--rtmp-rtmpdump", "--rtmpdump", "-r", metavar="path",
help="Specify location of the rtmpdump executable "
"used by RTMP streams, e.g. /usr/local/bin/rtmpdump")
streamopt.add_argument("--rtmp-timeout", type=float, metavar="timeout",
help="Timeout for reading data from RTMP streams, "
"default is 60.0")
streamopt.add_argument("--subprocess-cmdline", "--cmdline", "-c",
action="store_true",
help="Print command-line used internally to play "
"stream, this is only available for RTMP streams")
streamopt.add_argument("--subprocess-errorlog", "--errorlog", "-e",
action="store_true",
help="Log possible errors from internal subprocesses "
"to a temporary file, use when debugging rtmpdump "
"related issues")
pluginopt = parser.add_argument_group("plugin options")
pluginopt.add_argument("--plugin-dirs", metavar="directory", type=comma_list,

View File

@ -326,7 +326,7 @@ def handle_stream(plugin, streams, stream_name):
# Print internal command-line if this stream
# uses a subprocess.
if args.cmdline:
if args.subprocess_cmdline:
if isinstance(stream, StreamProcess):
try:
cmdline = stream.cmdline()
@ -568,7 +568,7 @@ def setup_console():
console.set_output(sys.stderr)
# We don't want log output when we are printing JSON or a command-line.
if not (args.json or args.cmdline or args.quiet):
if not (args.json or args.subprocess_cmdline or args.quiet):
console.set_level(args.loglevel)
if args.quiet_player:
@ -630,15 +630,6 @@ def setup_livestreamer():
def setup_options():
"""Sets Livestreamer options."""
livestreamer.set_option("errorlog", args.errorlog)
if args.rtmpdump:
livestreamer.set_option("rtmpdump", args.rtmpdump)
if args.rtmpdump_proxy:
livestreamer.set_option("rtmpdump-proxy", args.rtmpdump_proxy)
if args.hls_live_edge:
livestreamer.set_option("hls-live-edge", args.hls_live_edge)
@ -661,6 +652,20 @@ def setup_options():
if args.ringbuffer_size:
livestreamer.set_option("ringbuffer-size", args.ringbuffer_size)
if args.rtmp_proxy:
livestreamer.set_option("rtmp-proxy", args.rtmp_proxy)
if args.rtmp_rtmpdump:
livestreamer.set_option("rtmp-rtmpdump", args.rtmp_rtmpdump)
if args.rtmp_timeout:
livestreamer.set_option("rtmp-timeout", args.rtmp_timeout)
livestreamer.set_option("subprocess-errorlog", args.subprocess_errorlog)
def setup_plugin_options():
"""Sets Livestreamer plugin options."""
if args.jtv_cookie:
livestreamer.set_plugin_option("justintv", "cookie",
args.jtv_cookie)
@ -767,6 +772,7 @@ def main():
elif args.url:
with ignored(KeyboardInterrupt):
setup_options()
setup_plugin_options()
handle_url()
elif args.twitch_oauth_authenticate:
authenticate_twitch_oauth()