add x265 support

add --video-preset, an interface to x264 and x265 presets
add --probe, an interface to ffprobe
minor fixes
This commit is contained in:
Martinez 2015-12-24 16:43:57 +01:00
parent 08ee80454c
commit 5de735234d

View file

@ -28,7 +28,8 @@ command.encode_generic = Command('ffmpeg', '-i', 'INFILE', 'VIDEO', 'AUDIO', '-s
command.sub_vorbis = Command('-codec:a', 'libvorbis', '-qscale:a', 'QUALITY', 'NORMALIZE')
command.sub_pcm = Command('-codec:a', 'pcm_s16le', 'NORMALIZE')
command.sub_theora = Command('-codec:v', 'libtheora', '-qscale:v', 'QUALITY', 'VFILTER')
command.sub_x264 = Command('PIXFMT', '-codec:v', 'libx264', '-preset', 'slow', '-crf', 'QUALITY', '-profile:v', 'high', '-level', '4.2', 'VFILTER')
command.sub_x264 = Command('PIXFMT', '-codec:v', 'libx264', '-preset', 'PRESET', '-crf', 'QUALITY', '-profile:v', 'high', '-level', '4.2', 'VFILTER')
command.sub_x265 = Command('PIXFMT', '-codec:v', 'libx265', '-preset', 'PRESET', '-crf', 'QUALITY', 'VFILTER')
command.sub_normalize = Command('-filter:a', 'VOLUME')
command.sub_vfilter = Command('-filter:v', 'ARGS')
command.force_yuv420p = Command('-pix_fmt', 'yuv420p')
@ -40,18 +41,21 @@ command.sub_copy_video = Command('-codec:v', 'copy')
if __name__ == '__main__':
main = over.core.app.Main('over-video', 'Overwatch Video', version.str, 'AO-JSL', use_cfg_file=True)
main.add_option('audio', 'str', 'vorbis', 'Audio codec to use, either §mvorbis§/, §mpcm§/, §mcopy§/ or §mdrop§/.', short_name='a')
main.add_option('audio-quality', 'float', 2, 'Audio encoding quality with -1 being the worst and 10 being the best.', short_name='q')
main.add_option('video', 'str', 'x264', 'Video codec to use, either §mx264§/, §mtheora§/, §mcopy§/ or §mdrop§/.', short_name='v')
main.add_option('video-quality', 'float', 22, 'Video encoding quality. Use 0-10 for Theora (0 being the lowest, 5-7 is generally watchable) and 0-51 for x264 (0 being lossless, 18-28 is reasonable).', short_name='Q')
main.add_option('audio-quality', 'float', 4, 'Audio encoding quality with §m-1§/ being the worst and §m10§/ being the best.', short_name='q')
main.add_option('video', 'str', 'x264', 'Video codec to use, either §mx265§/, §mx264§/, §mtheora§/, §mcopy§/ or §mdrop§/.', short_name='v')
main.add_option('video-preset', 'str', 'slow', 'Video encoding preset, if supported by the selected encoder.', short_name='P')
main.add_option('video-quality', 'float', 22, 'Video encoding quality (CRF). Use §m0§/-§m10§/ for Theora (§m0§/ being the lowest, §m5§/-§m7§/ is generally watchable) and §m0§/-§m51§/ for x264/5 (§m0§/ being lossless, §m18§/-§m28§/ is reasonable).', short_name='Q')
main.add_option('normalize', 'bool', True, 'Normalize the audio track.', short_name='n')
main.add_option('normalize-target', 'float', -20.0, 'Target mean volume to target.')
main.add_option('normalize-override', 'float', 0.0, 'Volume correction to use instead of computing the required value in a (lengthy) pre-pass.', short_name='N')
main.add_option('ffmpeg-vfilter', 'str', '', 'Raw ffmpeg -filter:v options, e.g. "scale=1280:trunc(ow/a/2)*2,transpose=dir=1"', short_name='f')
main.add_option('move-source', 'str', '', 'Move source file to this directory after conversion.', short_name='m')
main.add_option('normalize-override', 'float', 0.0, 'Volume correction to use instead of computing the required value in a (lengthy) pre-pass.', short_name='N', use_cfg_file=False)
main.add_option('ffmpeg-vfilter', 'str', '', 'Raw ffmpeg -filter:v options, e.g. "§mscale=1280:trunc(ow/a/2)*2,transpose=dir=1§/"', short_name='f')
main.add_option('move-source', 'str', 'processed', 'Move source file to this directory after conversion. Use an empty string to disable.', short_name='m')
main.add_option('dump-commands', 'bool', False, 'Print ffmpeg commands that would be executed. If §B--§gnormalize§/ is in effect, the normalization pre-pass will still be performed so that the proper volume correction can be computed.', short_name='D')
main.add_option('probe', 'bool', False, 'Print the raw JSON output of ffprobe and exit.', short_name='p')
main.add_option('armed', 'bool', False, 'Perform the suggested action.', short_name='A', use_cfg_file=False)
main.enable_help('h')
main.add_help('Description', ['Over-Video is a simple video converter.'])
main.add_help('Good encoder settings', ['§Bx264§/: §B--§gvideo§/ §mx264§/ §B--§gvideo-preset§/ §mslow§/ §B--§gvideo-quality§/ §m22§/', '§Bx265§/: §B--§gvideo§/ §mx265§/ §B--§gvideo-preset§/ §mmedium§/ §B--§gvideo-quality§/ §m20§/'])
main.parse()
# --------------------------------------------------
@ -80,9 +84,11 @@ if __name__ == '__main__':
else:
video_words.append('§gcodec§/=§m%s§/' %(main.cfg.video))
video_words.append('§gquality§/=§m%.1f§/' %(main.cfg.video_quality))
if main.cfg.video_preset and main.cfg.video in ('x264', 'x265'):
video_words.append('§gpreset§/=§m%s§/' %(main.cfg.video_preset))
if main.cfg.ffmpeg_vfilter:
video_words.append('§gvfilter§/=§m%s§/' %(main.cfg.ffmpeg_vfilter))
@ -104,7 +110,7 @@ if __name__ == '__main__':
main.print('unknown audio codec', prefix.fail)
raise RuntimeError
if main.cfg.video not in ('drop', 'copy', 'theora', 'x264'):
if main.cfg.video not in ('drop', 'copy', 'theora', 'x264', 'x265'):
main.print('unknown video codec', prefix.fail)
raise RuntimeError
@ -131,8 +137,12 @@ if __name__ == '__main__':
command.identify.reset()
command.identify.INFILE = 'file:' + str(files.infile)
command.identify.run()
identify_raw = command.identify.get_all_output()
identify_dict = json.loads(identify_raw.decode('utf-8'))
identify_raw = command.identify.get_all_output().decode('utf-8')
identify_dict = json.loads(identify_raw)
if main.cfg.probe:
print(identify_raw)
continue
info = over.core.types.ndict()
@ -159,7 +169,13 @@ if __name__ == '__main__':
info.video_size_x = video['width']
info.video_size_y = video['height']
info.video_fps = over.core.text.Unit(parse_fps(video['r_frame_rate']), 'Hz')
info.video_bitrate = over.core.text.Unit(video['bit_rate'], 'b/s') if 'bit_rate' in video else '§r??§/'
if 'bit_rate' in video:
info.video_bitrate = over.core.text.Unit(video['bit_rate'], 'b/s')
elif 'tags' in video and 'BPS' in video['tags']:
info.video_bitrate = over.core.text.Unit(int(video['tags']['BPS']), 'b/s')
else:
info.video_bitrate = '§r??§/'
info.pixel_fmt = video['pix_fmt']
if audio_streams:
@ -282,6 +298,7 @@ if __name__ == '__main__':
elif main.cfg.video == 'x264':
command.sub_x264.reset()
command.sub_x264.QUALITY = main.cfg.video_quality
command.sub_x264.PRESET = main.cfg.video_preset
command.sub_x264.VFILTER = info.vfilter_command
if info.pixel_fmt in X264_BANNED_PIXFMTS:
@ -291,6 +308,14 @@ if __name__ == '__main__':
command.sub_x264.PIXFMT = None
encode_cmd.VIDEO = command.sub_x264
elif main.cfg.video == 'x265':
command.sub_x265.reset()
command.sub_x265.QUALITY = main.cfg.video_quality
command.sub_x265.PRESET = main.cfg.video_preset
command.sub_x265.VFILTER = info.vfilter_command
command.sub_x265.PIXFMT = None
encode_cmd.VIDEO = command.sub_x265
# --------------------------------------------------
# run the command if armed