diff --git a/aux.py b/aux.py new file mode 100644 index 0000000..6870cd0 --- /dev/null +++ b/aux.py @@ -0,0 +1,31 @@ +#! /bin/env python3 +# encoding: utf-8 + +class Command: + def __init__(self, sequence): + self.__dict__["sequence"] = list(sequence) + + def __setattr__(self, name, value): + found = False + + for i, word in enumerate(self.sequence): + if word == name: + self.sequence[i] = value + found = True + + if not found: + raise AttributeError("Command has no attribute \'%s\'" %(name)) + + def dump(self, sequence=None): + out = [] + + if not sequence: + sequence = self.sequence + + for item in sequence: + if type(item) is list: + out += self.dump(item) + else: + out.append(str(item)) + + return out diff --git a/over-video.py b/over-video.py old mode 100644 new mode 100755 index 10b68c0..510f01a --- a/over-video.py +++ b/over-video.py @@ -1,11 +1,53 @@ #! /bin/env python3 # encoding: utf-8 -# ffmpeg -i 2518* -codec:v libtheora -qscale:v 3 -codec:a libvorbis -qscale:a 2 output.ogv -# ffmpeg -i 2518* -c:v libx264 -preset slow -crf 22 -profile:v high -level 4.2 -codec:a libvorbis -qscale:a 2 output.mp4 - -# ffmpeg -i 2518* -af "volumedetect" -f null /dev/null | parse mean_volume: -22.8 dB -# -filter:a "volume=2.8dB" - +import json +import os import over +import re +import subprocess +from aux import Command + +# -------------------------------------------------- + +prefix = over.core.textui.prefix +_print = over.core.textui.Output("over.video") + +# -------------------------------------------------- + +command = over.core.types.ndict() +command.identify = ("ffprobe", "-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", "INFILE") +command.normalize_prepass = ("ffmpeg", "-i", "INFILE", "-af", "volumedetect", "-f", "null", "/dev/null") +command.encode_theora = ("ffmpeg", "-i", "INFILE", "-codec:v", "libtheora", "-qscale:v", "VQ", "-codec:a", "libvorbis", "-qscale:a", "AQ", "NORMALIZE", "OUTFILE") +command.encode_x264 = ("ffmpeg", "-i", "INFILE", "-c:v", "libx264", "-preset", "slow", "-crf", "VQ", "-profile:v", "high", "-level", "4.2", "-codec:a", "libvorbis", "-qscale:a", "AQ", "NORMALIZE", "OUTFILE") +command.normalize = ("-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, or §mx264§/ for H.264 and Vorbis in an MP4 container.") + 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("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() + + for tgt in main.targets: + if not os.path.exists(tgt) or os.path.isdir(tgt): + _print("target §y%s§/ §ris not a readable file§/, skipping" %(tgt), prefix.fail) + continue + + _print("processing §B%s§/" %(tgt), prefix.start) + + identify_cmd = Command(command.identify) + identify_cmd.INFILE = tgt + identify_raw = subprocess.check_output(identify_cmd.dump()).decode("utf-8") + identify_dict = json.loads(identify_raw) + + print(identify_dict)