python/elearning.py: retry on failure
This commit is contained in:
parent
3acadee72f
commit
2375f24870
@ -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
|
||||||
|
try:
|
||||||
metadata = json.loads(output)['format']
|
metadata = json.loads(output)['format']
|
||||||
files[metadata['tags']['IDS']] = file
|
files[metadata['tags']['IDS']] = file
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
return files
|
return files
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user