diff --git a/python/elearning.py b/python/elearning.py index 1fbb355..580eb0d 100755 --- a/python/elearning.py +++ b/python/elearning.py @@ -7,6 +7,7 @@ import requests import subprocess import argparse +import tempfile import pathlib import getpass import json @@ -29,7 +30,7 @@ parser = argparse.ArgumentParser( Download all video lessons from an elearning course. The videos are taken at the original quality and encoded - using h.265 slow profile, 96kb/s opus for audio, via ffmpeg. + using x265 slow profile, 96kb/s opus for audio, via ffmpeg. You can run the program multiple times to keep the archive in sync with elearning: existing files won't be replaced or @@ -282,23 +283,30 @@ def save_video(infos, files, args): printr('# skipping', end='\n\n') return - ffmpeg = [ + # where to save the stream + tmp = pathlib.Path(tempfile.gettempdir()) + original = (tmp / filename).with_suffix('.mkv') + + base = [ 'ffmpeg', '-hide_banner', '-loglevel', 'error', '-stats' - ] + inputs + maps + args.ffmpeg + [ + ] + download = base + inputs + maps + ['-y', original] + + convert = base + args.ffmpeg + [ + # source + '-i', original, + '-map', '0', # video '-c:v', 'libx265', '-preset', 'slow', '-crf', '23', - '-x265-params', 'log-level=error', # audio '-c:a', 'libopus', '-b:a', '96k', - # metadata '-metadata', 'title=' + info['description'], '-metadata', 'AUTHOR=' + info['userId'], '-metadata', 'DATE=' + info['createdAt'], '-metadata', 'IDS=' + ids, - # output (dir / filename).with_suffix('.mkv') ] @@ -307,8 +315,22 @@ def save_video(infos, files, args): printr('# downloading "{description}" ' '- {duration:.1f}min'.format_map(info)) printr('# by {userId}, {views} views'.format_map(info)) - subprocess.run(ffmpeg) - printr() + + # retry on failure + for _ in range(3): + try: + print('# copying') + subprocess.run(download, check=True) + print('# converting') + subprocess.run(convert, check=True) + print() + break + except subprocess.CalledProcessError: + if input('Conversion failed, retry? [Y/n]') == 'n': + break + + # remove original file + original.unlink(missing_ok=True) def get_filenames(dir): @@ -322,8 +344,11 @@ def get_filenames(dir): for file in dir.glob('*.mkv'): ffprobe = ['ffprobe', file, '-show_format', '-of', 'json'] output = subprocess.run(ffprobe, capture_output=True).stdout - metadata = json.loads(output)['format'] - files[metadata['tags']['IDS']] = file + try: + metadata = json.loads(output)['format'] + files[metadata['tags']['IDS']] = file + except KeyError: + pass return files