Hey hey! Tonight I feel like trying a very quick script generation: the goal will be to have an NVP command that I can use simply to renormalize the sound stream in a given input video file. This could be very handy to post-process my devlog recordings for instance.
nvp norm-sound -i my_video.mkv
psr = context.build_parser("norm-sound") psr.add_str("-i", "--input", dest="input_file")("input video file to normalize") psr.add_str("-o", "--output", dest="output_file")("Output file to generate.") psr.add_float("-g", "--gain", dest="gain")("Volume gain factor")
if cmd == "norm-sound": file = self.get_param("input_file") out_file = self.get_param("output_file", None) # return self.concat_media(files, out_file) logger.info("Should normalize sound for %s", file) return True
D:\Temp\Videos\youtube>nvp norm-sound -i 0010_rendernode_impl_session01.mkv 2023/02/20 21:11:49 [__main__] INFO: Should normalize sound for 0010_rendernode_impl_session01.mkv D:\Temp\Videos\youtube>
psr.add_float("-g", "--gain", dest="gain", default=1.0)("Volume gain factor")
if cmd == "norm-sound": file = self.get_param("input_file") out_file = self.get_param("output_file", None) gain = self.get_param("gain") return self.norm_sound(file, out_file, gain)
norm_sound()
method only setup the default output file for now: def norm_sound(self, input_file, out_file, gain): """Normalize the audio stream from a given input media file using the user provided gain""" if out_file is None: # folder = self.get_parent_folder(input_file) # fname = self.get_filename(input_file) ext = self.get_path_extension(input_file) out_file = self.set_path_extension(input_file, f"_normed{ext}") logger.info("Should norm sound in %s and write %s", input_file, out_file) return True
def norm_sound(self, input_file, out_file, gain): """Normalize the audio stream from a given input media file using the user provided gain""" if out_file is None: # folder = self.get_parent_folder(input_file) # fname = self.get_filename(input_file) ext = self.get_path_extension(input_file) out_file = self.set_path_extension(input_file, f"_normed{ext}") logger.info("Should norm sound in %s and write %s", input_file, out_file) tools: ToolsManager = self.get_component("tools") ffmpeg_path = tools.get_tool_path("ffmpeg") filter_str = f"[0:a]aformat=fltp:44100:stereo,volume={gain:.2f},loudnorm=I=-18:TP=-1.7:LRA=10" cmd = [ffmpeg_path, "-threads", "8", "-i", input_file] cmd += ["-filter_complex", f"{filter_str}"] cmd += ["-c:v", "copy", "-y", out_file] logger.info("Executing command: %s", cmd) res, rcode, outs = self.execute(cmd) if not res: logger.error("Sound normalization failed with return code %d:\n%s", rcode, outs) return False logger.info("Done writting file.") return True
nvp norm-sound -i 0010_rendernode_impl_session01.mkv -g 2.0
$ ffmpeg -i input.mp3 -af loudnorm=I=-16:LRA=11:TP=-1.5 output.mp3
def norm_sound(self, input_file, out_file, gain): """Normalize the audio stream from a given input media file using the user provided gain""" if out_file is None: # folder = self.get_parent_folder(input_file) # fname = self.get_filename(input_file) ext = self.get_path_extension(input_file) out_file = self.set_path_extension(input_file, f".lnorm{ext}") logger.info("Should norm sound in %s and write %s", input_file, out_file) tools: ToolsManager = self.get_component("tools") ffmpeg_path = tools.get_tool_path("ffmpeg") # filter_str = f"[0:a]aformat=fltp:44100:stereo,volume={gain:.2f},loudnorm=I=-18:TP=-1.7:LRA=10" filter_str = f"[0:a]aformat=fltp:44100:stereo,volume={gain:.2f},loudnorm=I=-16:LRA=11:TP=-1.5" cmd = [ffmpeg_path, "-threads", "8", "-i", input_file] cmd += ["-filter_complex", f"{filter_str}"] cmd += ["-c:v", "copy", "-y", out_file] logger.info("Executing command: %s", cmd) res, rcode, outs = self.execute(cmd) if not res: logger.error("Sound normalization failed with return code %d:\n%s", rcode, outs) return False logger.info("Done writting file.") return True
psr = context.build_parser("convert") psr.add_flag("-c", "--concat-only", dest="concat_only")("Only perform the GOPRO concatenation part.") psr.add_flag("-s", "--stabilize", dest="stabilize")("Stabilize the video") psr.add_str("-l", "--lens", dest="correct_lens", default="auto")("Lens correction to apply") psr.add_flag("-n", "--norm-audio", dest="normalize_audio")("Normalize audio stream") psr.add_flag("-p", "--sharpen", dest="sharpen")("Sharpen the image") psr.add_float("-g", "--gain", dest="gain", default=1.0)("Volume gain factor") psr.add_int("--crf", dest="crf", default=21)( "Video CRF value (selecthighest value that provide acceptable quality. 29 <=> x264 value 23" ) psr.add_str( "--preset", dest="preset", default="slow", choices=["ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow"], )("Video compression preset")
cmd += f"-ignore_unknown -map 0 -dn -c:v libx265 -crf {crf} -preset {preset} -c:a libvorbis -qscale:a 5 -scodec copy".split()
nvp vconv convert --crf 25 --preset slower -g 1.8 -n
nvp vconv convert --crf 28 --preset medium -g 1.8 -n
vconv convert
script to efficiently compress my devlog videos, all good 😉.