- implemented --move-source: Move source file to this directory after conversion.

- bugfixes
- changed the x264 container from mp4 to mkv (through ffmpeg, no external dependency was added)
This commit is contained in:
Overwatch 2014-08-18 21:58:31 +02:00
parent 5d1dd9f0a6
commit 691244db41

View file

@ -4,11 +4,11 @@
import json import json
import os import os
import over import over
import pathlib
import re import re
import subprocess import subprocess
import tempfile import tempfile
import time import time
import pathlib # FIXME sort
from aux import Command, parse_fps from aux import Command, parse_fps
@ -31,18 +31,19 @@ command.normalize = Command('-filter:a', 'VOLUME')
if __name__ == '__main__': if __name__ == '__main__':
main = over.core.app.Main('Over-Video', '0.1', 'AWARE-Overwatch Joint Software License', '~/.over/video.cfg') main = over.core.app.Main('Over-Video', '0.1', 'AWARE-Overwatch Joint Software License', '~/.over/video.cfg')
main.add_option('profile', 'str', 'x264', 'Encoding profile to use. Available are either §mtheora§/ for Theora and Vorbis in an Ogg container, §mx264§/ for H.264 and Vorbis in an MP4 container, or §mwav§/ which just extracts audio into a wav for further processing.') main.add_option('profile', 'str', 'x264', 'Encoding profile to use. Available are either §mtheora§/ for Theora and Vorbis in an Ogg container, §mx264§/ for H.264 and Vorbis in a Matroska container, or §mwav§/ which just extracts audio into a wav for further processing.')
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='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='v')
main.add_option('audio-quality', 'float', 2, 'Audio encoding quality with -1 being the worst and 10 being the best.', 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='a')
main.add_option('normalize', 'bool', True, 'Normalize the audio track.', short_name='N') main.add_option('normalize', 'bool', True, 'Normalize the audio track.', short_name='N')
main.add_option('normalize-mean', 'float', -20.0, 'Target mean volume to target.', short_name='n') main.add_option('normalize-target', 'float', -20.0, 'Target mean volume to target.', short_name='n')
main.add_option('move-source', 'str', '', 'Move source file to this directory after conversion.', short_name='m')
main.add_option('dump-commands', 'bool', False, 'Print ffmpeg commands that would be executed. Implies §B--no-§garmed§/. 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('dump-commands', 'bool', False, 'Print ffmpeg commands that would be executed. Implies §B--no-§garmed§/. 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('armed', 'bool', False, 'Perform the suggested action.', short_name='A', use_cfg_file=False) main.add_option('armed', 'bool', False, 'Perform the suggested action.', short_name='A', use_cfg_file=False)
main.enable_help('h') main.enable_help('h')
main.add_help('Description', ['Over-Video is a simple video converter.']) main.add_help('Description', ['Over-Video is a simple video converter.'])
main.parse() main.parse()
_print('using profile §b%s§/: video_quality=%.1f, audio_quality=%.1f, normalize=%s' %(main.cfg.profile, main.cfg.video_quality, main.cfg.audio_quality, '%.1f dB' %(main.cfg.normalize_mean) if main.cfg.normalize else 'None')) _print('using profile §b%s§/: video_quality=%.1f, audio_quality=%.1f, normalize=%s' %(main.cfg.profile, main.cfg.video_quality, main.cfg.audio_quality, '%.1f dB' %(main.cfg.normalize_target) if main.cfg.normalize else 'None'))
if not main.targets: if not main.targets:
_print("no files specified", prefix.warn) _print("no files specified", prefix.warn)
@ -86,13 +87,13 @@ if __name__ == '__main__':
info.video_size_x = video['width'] info.video_size_x = video['width']
info.video_size_y = video['height'] info.video_size_y = video['height']
info.video_fps = over.core.textui.Unit(parse_fps(video['r_frame_rate']), 'Hz') info.video_fps = over.core.textui.Unit(parse_fps(video['r_frame_rate']), 'Hz')
info.video_bitrate = over.core.textui.Unit(audio['bit_rate'], 'b/s') info.video_bitrate = over.core.textui.Unit(video['bit_rate'], 'b/s') if 'bit_rate' in video else "§r??§/"
info.audio_codec = audio['codec_name'] info.audio_codec = audio['codec_name']
info.audio_channels = audio['channels'] info.audio_channels = audio['channels']
info.audio_samplerate = over.core.textui.Unit(audio['sample_rate'], 'Hz') info.audio_samplerate = over.core.textui.Unit(audio['sample_rate'], 'Hz')
info.audio_language = audio['tags']['language'] info.audio_language = audio['tags']['language'] if 'language' in audio['tags'] else 'und'
info.audio_bitrate = over.core.textui.Unit(audio['bit_rate'], 'b/s') info.audio_bitrate = over.core.textui.Unit(audio['bit_rate'], 'b/s') if 'bit_rate' in audio else "§r??§/"
_print('§mvideo§/: size=§b%d§/x§b%d§/ px, framerate=%s, codec=%s, bitrate=%s' %(info.video_size_x, info.video_size_y, info.video_fps, info.video_codec, info.video_bitrate)) _print('§mvideo§/: size=§b%d§/x§b%d§/ px, framerate=%s, codec=%s, bitrate=%s' %(info.video_size_x, info.video_size_y, info.video_fps, info.video_codec, info.video_bitrate))
_print('§caudio§/: channels=§b%d§/, samplerate=%s, codec=%s, bitrate=%s, language=%s' %(info.audio_channels, info.audio_samplerate, info.audio_codec, info.audio_bitrate, info.audio_language)) _print('§caudio§/: channels=§b%d§/, samplerate=%s, codec=%s, bitrate=%s, language=%s' %(info.audio_channels, info.audio_samplerate, info.audio_codec, info.audio_bitrate, info.audio_language))
@ -127,7 +128,7 @@ if __name__ == '__main__':
if b'mean_volume: ' in output: if b'mean_volume: ' in output:
info.mean_volume = float(re.findall(b'mean_volume: (-\d+\.\d+) dB', output)[0]) info.mean_volume = float(re.findall(b'mean_volume: (-\d+\.\d+) dB', output)[0])
info.volume_correction = info.mean_volume - main.cfg.normalize_mean info.volume_correction = main.cfg.normalize_target - info.mean_volume
else: else:
_print('§runexpected ffmpeg output§/, dump follows', prefix.fail, suffix=':\n') _print('§runexpected ffmpeg output§/, dump follows', prefix.fail, suffix=':\n')
print(output) print(output)
@ -142,7 +143,7 @@ if __name__ == '__main__':
info.tmp_file = tempfile.mktemp(suffix='.ogv', dir='.') info.tmp_file = tempfile.mktemp(suffix='.ogv', dir='.')
elif main.cfg.profile == 'x264': elif main.cfg.profile == 'x264':
encode_cmd = command.encode_x264 encode_cmd = command.encode_x264
info.tmp_file = tempfile.mktemp(suffix='.mp4', dir='.') info.tmp_file = tempfile.mktemp(suffix='.mkv', dir='.')
elif main.cfg.profile == 'wav': elif main.cfg.profile == 'wav':
encode_cmd = command.encode_wav encode_cmd = command.encode_wav
info.tmp_file = tempfile.mktemp(suffix='.wav', dir='.') info.tmp_file = tempfile.mktemp(suffix='.wav', dir='.')
@ -193,8 +194,22 @@ if __name__ == '__main__':
new_filename = pathlib.Path(tgt).stem + pathlib.Path(info.tmp_file).suffix new_filename = pathlib.Path(tgt).stem + pathlib.Path(info.tmp_file).suffix
if main.cfg.dump_commands: path_tgt_dir = pathlib.Path(main.cfg.move_source)
_print('will execute §Bmv "%s" "%s"§/' %(info.tmp_file, new_filename), prefix.start) path_tgt = pathlib.Path(tgt)
path_tgt_new = path_tgt_dir / path_tgt
if path_tgt != path_tgt_new:
if main.cfg.armed:
_print("moving §B%s§/ -> §B%s§/" %(path_tgt, path_tgt_new))
path_tgt.rename(path_tgt_new)
elif main.cfg.dump_commands:
_print('will execute §Bmv "%s" "%s"§/' %(path_tgt, path_tgt_new), prefix.start)
old_name = pathlib.Path(info.tmp_file)
new_name = pathlib.Path(new_filename)
if main.cfg.armed: if main.cfg.armed:
pathlib.Path(info.tmp_file).rename(new_filename) _print("moving §B%s§/ -> §B%s§/" %(old_name, new_name))
old_name.rename(new_name)
elif main.cfg.dump_commands:
_print('will execute §Bmv "%s" "%s"§/' %(old_name, new_name), prefix.start)