Files
nonsilencer/jumpcutter.py
2020-05-10 11:06:47 +02:00

65 lines
2.2 KiB
Python
Executable File

#!/usr/bin/python3
import subprocess as sp
from shlex import quote
import re
import argparse
import sys, os
FFMPEG_SILENCEDETECT_COMMAND = "ffmpeg -y -hide_banner -nostats -i {filename} -af silencedetect=d=0.3 -map 0 -map -0:v -f wav /dev/null"
SILENCE_START_RE = re.compile("^\[silencedetect @ 0x[0-9a-f]+\] silence_start: ([\d\.]+)$")
SILENCE_END_RE = re.compile("^\[silencedetect @ 0x[0-9a-f]+\] silence_end: ([\d\.]+) \| silence_duration: ([\d\.]+)$")
def cut(in_file, out_file="out_file.mkv", silences=[]):
betweens = ""
for silence in silences:
betweens += f"between(t,{silence[0]},{silence[1]})+"
betweens = betweens[:-1] if betweens else betweens
video_filter = f"select='{betweens}',setpts=N/FRAME_RATE/TB"
audio_filter = f"aselect='{betweens}',asetpts=N/SR/TB"
command = ["ffmpeg", "-i", in_file, "-vf", video_filter, "-af", audio_filter, out_file]
sp.run(command)
def detect_silence(filename):
output = sp.run(FFMPEG_SILENCEDETECT_COMMAND.format(filename=quote(filename)), shell=True, stderr=sp.PIPE).stderr
total_silence = 0
talking = []
current_silence = ["0", None]
for line in output.split(b"\n"):
line = line.strip()
line = line.decode("utf8")
if not "silencedetect" in line:
continue
if match := SILENCE_START_RE.match(line):
print("Silence start at", match[1])
current_silence[1] = match[1]
talking.append(tuple(current_silence))
elif match := SILENCE_END_RE.match(line):
print("Silence end at", match[1])
current_silence[0] = match[1]
total_silence += float(match.group(2))
print("Total:", total_silence)
return talking
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--output-format", "-f")
parser.add_argument("infiles", nargs="+")
args = parser.parse_args()
for f in args.infiles:
if not os.path.isfile(f):
print(f"{f} not found, skipping...", file=sys.stderr)
continue
new_filename = os.path.splitext(f)[0]+".mkv"
talking = detect_silence(f)
cut(f, new_filename, talking)