123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- import os
- import json
- import subprocess
- def probe_file(p):
- args = [
- 'ffprobe',
- '-loglevel', 'error',
- '-show_streams', '-show_format',
- '-print_format', 'json',
- '-i', p
- ]
- p = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- if p.returncode != 0:
- raise RuntimeError(p.stderr.replace('\n', ' '))
- data = json.loads(p.stdout)
- return data
- def extract_stream_props(probe):
- dur = int(round(float(probe['format']['duration'])))
- br = int(probe['format']['bit_rate'])
- title = None
- if 'tags' in probe['format']:
- tags = probe['format']['tags']
- if 'title' in tags:
- title = tags['title']
- for s in probe['streams']:
- if s['codec_type'] == 'video':
- return {
- 'title': title,
- 'res_w': s['width'],
- 'res_h': s['height'],
- 'duration_sec': dur,
- 'bitrate_bps': br,
- 'codec': s['codec_name'],
- }
- def reencode(src, dest, target_br_kbps, preset='veryfast', maxheight=1080, dryrun=False):
- baseargs = [
- 'ffmpeg',
- '-i', src,
- '-c:v', 'libx265',
- '-preset', preset,
- '-vf', 'scale=-1:\'min(%s,ih)\'' % maxheight,
- '-b:v', '%sk' % target_br_kbps,
- '-y',
- ]
- p1args = baseargs + [
- '-x265-params', 'pass=1',
- '-an',
- '-f', 'null',
- '/dev/null'
- ]
- p2args = baseargs + [
- '-map', '0',
- '-x265-params', 'pass=2',
- '-c:a', 'aac',
- '-b:a', '400k',
- '-c:s', 'copy',
- #'-c:d', 'copy',
- #'-c:t', 'copy',
- dest
- ]
- print('PASS1', ' '.join(p1args))
- if not dryrun:
- res1 = subprocess.run(p1args)
- res1.check_returncode()
- print('PASS2', ' '.join(p2args))
- if not dryrun:
- res2 = subprocess.run(p2args)
- res2.check_returncode()
- # Do cleanup
- if not dryrun:
- destdir = os.path.dirname(os.path.realpath(dest))
- for f in os.listdir(destdir):
- if f.startswith('x265_2pass.log'):
- os.unlink(os.path.join(destdir, f))
|