streamlink/src/livestreamer/cli.py

203 lines
6.3 KiB
Python
Raw Normal View History

2011-08-15 04:37:22 +02:00
#!/usr/bin/env python3
import sys, os, argparse, subprocess
2011-10-26 03:23:43 +02:00
import livestreamer
from livestreamer.compat import input, stdout, is_win32
2011-08-15 04:37:22 +02:00
2012-06-14 01:53:00 +02:00
exampleusage = """
example usage:
$ livestreamer twitch.tv/onemoregametv
Found streams: 240p, 360p, 480p, 720p, best, iphonehigh, iphonelow, live
$ livestreamer twitch.tv/onemoregametv 720p
Stream now playbacks in player (default is VLC).
"""
2012-05-28 01:47:48 +02:00
parser = livestreamer.utils.ArgumentParser(description="CLI program that launches streams from various streaming services in a custom video player",
2012-06-14 01:53:00 +02:00
fromfile_prefix_chars="@",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=exampleusage, add_help=False)
2011-08-15 04:37:22 +02:00
parser.add_argument("url", help="URL to stream", nargs="?")
2012-05-28 01:47:48 +02:00
parser.add_argument("stream", help="Stream quality to play, use 'best' for highest quality available", nargs="?")
2012-06-14 01:53:00 +02:00
parser.add_argument("-h", "--help", action="store_true", help="Show this help message and exit")
parser.add_argument("-l", "--plugins", action="store_true", help="Print all currently installed plugins")
2012-06-14 01:53:00 +02:00
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")
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")
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")
2011-08-15 04:37:22 +02:00
2012-03-21 16:31:41 +01:00
RCFILE = os.path.expanduser("~/.livestreamerrc")
2011-08-15 04:37:22 +02:00
def exit(msg):
sys.exit(("error: {0}").format(msg))
2011-08-15 04:37:22 +02:00
def msg(msg):
sys.stdout.write(msg + "\n")
def write_stream(fd, out, progress):
written = 0
while True:
data = fd.read(8192)
if len(data) == 0:
break
try:
out.write(data)
except IOError:
break
written += len(data)
if progress:
sys.stderr.write(("\rWritten {0} bytes").format(written))
if progress and written > 0:
sys.stderr.write("\n")
fd.close()
if out != stdout:
out.close()
def check_output(output, force):
if os.path.isfile(output) and not force:
2012-05-28 01:47:48 +02:00
sys.stderr.write(("File {0} already exists! Overwrite it? [y/N] ").format(output))
try:
answer = input()
except:
sys.exit()
answer = answer.strip().lower()
if answer != "y":
sys.exit()
try:
out = open(output, "wb")
except IOError as err:
exit(("Failed to open file {0} - ").format(output, err))
return out
def output_stream(stream, args):
progress = False
out = None
try:
fd = stream.open()
except livestreamer.StreamError as err:
exit(("Could not open stream - {0}").format(err))
if args.output:
if args.output == "-":
out = stdout
else:
out = check_output(args.output, args.force)
progress = True
elif args.stdout:
out = stdout
else:
cmd = args.player + " -"
2012-06-14 01:03:44 +02:00
if args.quiet_player:
pout = open(os.devnull, "w")
perr = open(os.devnull, "w")
else:
pout = sys.stderr
perr = sys.stdout
player = subprocess.Popen(cmd, shell=True, stdout=pout, stderr=perr,
stdin=subprocess.PIPE)
out = player.stdin
if not out:
exit("Failed to open a valid stream output")
if is_win32:
import msvcrt
msvcrt.setmode(out.fileno(), os.O_BINARY)
try:
write_stream(fd, out, progress)
except KeyboardInterrupt:
sys.exit()
2011-08-15 04:37:22 +02:00
def handle_url(args):
2012-05-24 15:07:03 +02:00
try:
channel = livestreamer.resolve_url(args.url)
except livestreamer.NoPluginError:
exit(("No plugin can handle URL: {0}").format(args.url))
2011-08-15 04:37:22 +02:00
try:
streams = channel.get_streams()
except livestreamer.StreamError as err:
exit(str(err))
except livestreamer.PluginError as err:
2012-05-24 15:07:03 +02:00
exit(str(err))
2011-08-15 04:37:22 +02:00
2012-04-21 20:35:43 +02:00
if len(streams) == 0:
2012-05-24 15:07:03 +02:00
exit(("No streams found on this URL: {0}").format(args.url))
2011-08-15 04:37:22 +02:00
keys = list(streams.keys())
keys.sort()
validstreams = (", ").join(keys)
if args.stream:
if args.stream in streams:
stream = streams[args.stream]
if args.cmdline:
if isinstance(stream, livestreamer.stream.StreamProcess):
msg(stream.cmdline())
else:
2012-05-28 01:47:48 +02:00
exit("Stream does not use a command-line")
2011-08-15 04:37:22 +02:00
else:
output_stream(stream, args)
2011-08-15 04:37:22 +02:00
else:
2012-05-28 01:47:48 +02:00
msg(("Invalid stream quality: {0}").format(args.stream))
msg(("Valid streams: {0}").format(validstreams))
2011-08-15 04:37:22 +02:00
else:
msg(("Found streams: {0}").format(validstreams))
2011-08-15 04:37:22 +02:00
def print_plugins():
2011-10-26 03:23:43 +02:00
pluginlist = list(livestreamer.get_plugins().keys())
msg(("Installed plugins: {0}").format(", ".join(pluginlist)))
2011-08-15 04:37:22 +02:00
def main():
arglist = sys.argv[1:]
2012-03-21 16:31:41 +01:00
if os.path.exists(RCFILE):
arglist.insert(0, "@" + RCFILE)
args = parser.parse_args(arglist)
2011-08-15 04:37:22 +02:00
livestreamer.options.set("errorlog", args.errorlog)
livestreamer.options.set("rtmpdump", args.rtmpdump)
livestreamer.options.set("jtvcookie", args.jtv_cookie)
2011-08-15 04:37:22 +02:00
if args.url:
handle_url(args)
elif args.plugins:
print_plugins()
else:
parser.print_help()