forked from fcode/delarte
118 lines
3.2 KiB
Python
118 lines
3.2 KiB
Python
# Licence: GNU AGPL v3: http://www.gnu.org/licenses/
|
|
# This file is part of [`delarte`](https://git.afpy.org/fcode/delarte.git)
|
|
|
|
"""delarte - ArteTV dowloader.
|
|
|
|
usage: delarte [-h|--help] - print this message
|
|
or: delarte program_page_url - show available versions
|
|
or: delarte program_page_url version - show available resolutions
|
|
or: delarte program_page_url version resolution - download the given video
|
|
"""
|
|
|
|
import sys
|
|
import time
|
|
|
|
from . import api
|
|
from . import hls
|
|
from . import muxing
|
|
from . import naming
|
|
from . import www
|
|
from . import cli
|
|
|
|
|
|
def _fail(message, code=1):
|
|
print(message, file=sys.stderr)
|
|
return code
|
|
|
|
|
|
def _print_available_renditions(config, f):
|
|
print(f"Available versions:", file=f)
|
|
for code, label in api.iter_renditions(config):
|
|
print(f"\t{code} - {label}", file=f)
|
|
|
|
|
|
def _print_available_variants(version_index, f):
|
|
print(f"Available resolutions:", file=f)
|
|
for code, label in hls.iter_variants(version_index):
|
|
print(f"\t{code} - {label}", file=f)
|
|
|
|
|
|
def create_progress():
|
|
"""Create a progress handler for input downloads."""
|
|
state = {
|
|
"last_update_time": 0,
|
|
"last_channel": None,
|
|
}
|
|
|
|
def progress(channel, current, total):
|
|
now = time.time()
|
|
|
|
if current == total:
|
|
print(f"\rDownloading {channel}: 100.0%")
|
|
state["last_update_time"] = now
|
|
elif channel != state["last_channel"]:
|
|
print(f"Dowloading {channel}: 0.0%", end="")
|
|
state["last_update_time"] = now
|
|
state["last_channel"] = channel
|
|
elif now - state["last_update_time"] > 1:
|
|
print(
|
|
f"\rDownloading {channel}: {int(1000.0 * current / total) / 10.0}%",
|
|
end="",
|
|
)
|
|
state["last_update_time"] = now
|
|
|
|
return progress
|
|
|
|
|
|
def main():
|
|
"""CLI command."""
|
|
parser = cli.Parser()
|
|
args = parser.get_args_as_list()
|
|
|
|
if not args or args[0] == "-h" or args[0] == "--help":
|
|
print(__doc__)
|
|
return 0
|
|
|
|
try:
|
|
www_lang, program_id = www.parse_url(args.pop(0))
|
|
except ValueError as e:
|
|
return _fail(f"Invalid url: {e}")
|
|
|
|
try:
|
|
config = api.load_config(www_lang, program_id)
|
|
except ValueError:
|
|
return _fail("Invalid program")
|
|
|
|
if not args:
|
|
_print_available_renditions(config, sys.stdout)
|
|
return 0
|
|
|
|
master_playlist_url = api.select_rendition(config, args.pop(0))
|
|
if master_playlist_url is None:
|
|
_fail("Invalid version")
|
|
_print_available_renditions(config, sys.stderr)
|
|
return 1
|
|
|
|
master_playlist = hls.load_master_playlist(master_playlist_url)
|
|
|
|
if not args:
|
|
_print_available_variants(master_playlist, sys.stdout)
|
|
return 0
|
|
|
|
remote_inputs = hls.select_variant(master_playlist, args.pop(0))
|
|
if remote_inputs is None:
|
|
_fail("Invalid resolution")
|
|
_print_available_variants(master_playlist, sys.stderr)
|
|
return 0
|
|
|
|
file_base_name = naming.build_file_base_name(config)
|
|
|
|
progress = create_progress()
|
|
|
|
with hls.download_inputs(remote_inputs, progress) as temp_inputs:
|
|
muxing.mux(temp_inputs, file_base_name, progress)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|