diff --git a/over-video.py b/over-video.py index b0ae972..188c6d0 100755 --- a/over-video.py +++ b/over-video.py @@ -4,11 +4,11 @@ import json import os import over +import pathlib import re import subprocess import tempfile import time -import pathlib # FIXME sort from aux import Command, parse_fps @@ -31,18 +31,19 @@ command.normalize = Command('-filter:a', 'VOLUME') if __name__ == '__main__': 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('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-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('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.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: _print("no files specified", prefix.warn) @@ -86,13 +87,13 @@ if __name__ == '__main__': info.video_size_x = video['width'] info.video_size_y = video['height'] 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_channels = audio['channels'] info.audio_samplerate = over.core.textui.Unit(audio['sample_rate'], 'Hz') - info.audio_language = audio['tags']['language'] - info.audio_bitrate = over.core.textui.Unit(audio['bit_rate'], 'b/s') + 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') 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('§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: 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: _print('§runexpected ffmpeg output§/, dump follows', prefix.fail, suffix=':\n') print(output) @@ -142,7 +143,7 @@ if __name__ == '__main__': info.tmp_file = tempfile.mktemp(suffix='.ogv', dir='.') elif main.cfg.profile == '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': encode_cmd = command.encode_wav 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 - if main.cfg.dump_commands: - _print('will execute §Bmv "%s" "%s"§/' %(info.tmp_file, new_filename), prefix.start) + path_tgt_dir = pathlib.Path(main.cfg.move_source) + 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: - 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)