forked from fcode/delarte
Barbagus
6b8f2232c4
Implemented modules: - api: deals with ArteTV JSON API - hls: deals with HLS protocol - muxing: deals with the stream multiplexing - naming: deals with output file naming - www: deals with ArteTV web interface
118 lines
3.3 KiB
Python
118 lines
3.3 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
|
|
|
|
|
|
def fail(message, code=1):
|
|
"""Print a message to STDERR and return a given exit code."""
|
|
print(message, file=sys.stderr)
|
|
return code
|
|
|
|
|
|
def print_available_versions(config, f):
|
|
"""Print available program versions."""
|
|
print(f"Available versions:", file=f)
|
|
for code, label in api.iter_versions(config):
|
|
print(f"\t{code} - {label}", file=f)
|
|
|
|
|
|
def print_available_resolutions(version_index, f):
|
|
"""Print available version resolutions."""
|
|
print(f"Available resolutions:", file=f)
|
|
for code, label in hls.iter_resolutions(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."""
|
|
args = sys.argv[1:]
|
|
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_versions(config, sys.stdout)
|
|
return 0
|
|
|
|
version_index_url = api.select_version(config, args.pop(0))
|
|
if version_index_url is None:
|
|
fail("Invalid version")
|
|
print_available_versions(config, sys.stderr)
|
|
return 1
|
|
|
|
version_index = hls.load_version_index(version_index_url)
|
|
|
|
if not args:
|
|
print_available_resolutions(version_index, sys.stdout)
|
|
return 0
|
|
|
|
remote_inputs = hls.select_resolution(version_index, args.pop(0))
|
|
if remote_inputs is None:
|
|
fail("Invalid resolution")
|
|
print_available_resolutions(version_index, 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())
|