Downloader: Implement a very basic proof of concept version

Missing a LOT of tankiness, ways to configure, conversion to bustime, etc.
pull/2/head
Mike Lang 6 years ago
parent 8993773a22
commit 10241b6190

@ -1,6 +1,8 @@
import logging import logging
import argh
from downloader.main import main from downloader.main import main
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
main() argh.dispatch_command(main)

@ -1,4 +1,53 @@
import hashlib
import logging
import os
import time
from base64 import b64encode
def main(): import twitch
pass
def download_segments(base_dir, name, uri):
# NOTE: This function is not written to be resilient, do not rely on it.
# There's no retry, no atomic rename for file writing, file name format is bad,
# skips segments with missing info, doesn't confirm lengths, other issues.
# Doesn't use monotonic time.
INTERVAL = 2
prev_segments = []
while True:
last_check = time.time()
logging.info("Getting playlist")
playlist = twitch.get_media_playlist(uri)
for segment in playlist.segments:
if segment.uri in prev_segments:
continue
if not segment.date:
logging.warning("Segment has no date given, skipping")
continue
segment_data = twitch.get_segment(segment.uri)
segment_hash = hashlib.sha256(segment_data).digest()
filename = os.path.join(
base_dir, name,
"{}-{}".format(segment.date, segment.duration),
"{}.ts".format(b64encode(segment_hash, "-_")),
)
logging.info("Writing segment {}".format(filename))
if not os.path.exists(os.path.dirname(filename)):
os.makedirs(os.path.dirname(filename))
with open(filename, 'w') as f:
f.write(segment_data)
prev_segments = [segment.uri for segment in playlist.segments]
# Wait up to 2s until 2s after last_check
elapsed = time.time() - last_check
time.sleep(max(0, INTERVAL - elapsed))
def main(channel, base_dir=".", qualities=""):
qualities = qualities.split(",") if qualities else []
master_playlist = twitch.get_master_playlist(channel)
uris = twitch.get_media_playlist_uris(master_playlist, qualities)
if len(uris) != 1:
raise NotImplementedError
(name, uri), = uris.items()
download_segments(base_dir, name, uri)

@ -72,7 +72,7 @@ def get_media_playlist_uris(master_playlist, target_qualities):
raise ValueError("Master playlist has no variants") raise ValueError("Master playlist has no variants")
for variant in master_playlist.playlists: for variant in master_playlist.playlists:
if any(media.uri for media in variant.medias): if any(media.uri for media in variant.media):
logging.warning("Variant has a rendition with its own URI: {}".format(variant)) logging.warning("Variant has a rendition with its own URI: {}".format(variant))
by_name = {variant_name(variant): variant for variant in master_playlist.playlists} by_name = {variant_name(variant): variant for variant in master_playlist.playlists}

Loading…
Cancel
Save