python/elearning.py: retry on failure

This commit is contained in:
Michele Guerini Rocco 2020-12-11 14:14:36 +01:00
parent 3acadee72f
commit 2375f24870
Signed by: rnhmjoj
GPG Key ID: BFBAF4C975F76450

View File

@ -7,6 +7,7 @@
import requests import requests
import subprocess import subprocess
import argparse import argparse
import tempfile
import pathlib import pathlib
import getpass import getpass
import json import json
@ -29,7 +30,7 @@ parser = argparse.ArgumentParser(
Download all video lessons from an elearning course. Download all video lessons from an elearning course.
The videos are taken at the original quality and encoded 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 You can run the program multiple times to keep the archive
in sync with elearning: existing files won't be replaced or 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') printr('# skipping', end='\n\n')
return return
ffmpeg = [ # where to save the stream
tmp = pathlib.Path(tempfile.gettempdir())
original = (tmp / filename).with_suffix('.mkv')
base = [
'ffmpeg', '-hide_banner', 'ffmpeg', '-hide_banner',
'-loglevel', 'error', '-loglevel', 'error',
'-stats' '-stats'
] + inputs + maps + args.ffmpeg + [ ]
download = base + inputs + maps + ['-y', original]
convert = base + args.ffmpeg + [
# source
'-i', original,
'-map', '0',
# video # video
'-c:v', 'libx265', '-preset', 'slow', '-crf', '23', '-c:v', 'libx265', '-preset', 'slow', '-crf', '23',
'-x265-params', 'log-level=error',
# audio # audio
'-c:a', 'libopus', '-b:a', '96k', '-c:a', 'libopus', '-b:a', '96k',
# metadata # metadata
'-metadata', 'title=' + info['description'], '-metadata', 'title=' + info['description'],
'-metadata', 'AUTHOR=' + info['userId'], '-metadata', 'AUTHOR=' + info['userId'],
'-metadata', 'DATE=' + info['createdAt'], '-metadata', 'DATE=' + info['createdAt'],
'-metadata', 'IDS=' + ids, '-metadata', 'IDS=' + ids,
# output # output
(dir / filename).with_suffix('.mkv') (dir / filename).with_suffix('.mkv')
] ]
@ -307,8 +315,22 @@ def save_video(infos, files, args):
printr('# downloading "{description}" ' printr('# downloading "{description}" '
'- {duration:.1f}min'.format_map(info)) '- {duration:.1f}min'.format_map(info))
printr('# by {userId}, {views} views'.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): def get_filenames(dir):
@ -322,8 +344,11 @@ def get_filenames(dir):
for file in dir.glob('*.mkv'): for file in dir.glob('*.mkv'):
ffprobe = ['ffprobe', file, '-show_format', '-of', 'json'] ffprobe = ['ffprobe', file, '-show_format', '-of', 'json']
output = subprocess.run(ffprobe, capture_output=True).stdout output = subprocess.run(ffprobe, capture_output=True).stdout
metadata = json.loads(output)['format'] try:
files[metadata['tags']['IDS']] = file metadata = json.loads(output)['format']
files[metadata['tags']['IDS']] = file
except KeyError:
pass
return files return files