Created
November 20, 2023 15:36
-
-
Save kainabel/843ea04c3a47129abd851a2fe2c6caee to your computer and use it in GitHub Desktop.
FFmpeg silence detect wrapper - prints human-readable timecodes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import argparse | |
import re | |
import subprocess | |
import sys | |
def format_time(s): | |
(h, s) = divmod(s, 3600) | |
(m, s) = divmod(s, 60) | |
h = int(h) | |
m = int(m) | |
# NOTE: Seconds are zero-padded to 8 characters | |
# to account for the decimal point and fractional part | |
return f'{h:02}:{m:02}:{s:08.5f}' | |
parser = argparse.ArgumentParser() | |
parser.add_argument( | |
'file', | |
help='input file', | |
) | |
parser.add_argument( | |
'-n', | |
'--noise', | |
default=0.001, | |
help='noise tolerance', | |
) | |
parser.add_argument( | |
'-d', | |
'--duration', | |
default=2, | |
help='silence duration until notification', | |
) | |
parser.add_argument( | |
'-m', | |
'--mono', | |
action='store_true', | |
help='process each channel separately', | |
) | |
args = parser.parse_args() | |
if args.mono: | |
mono_arg = 'y' | |
else: | |
mono_arg = 'n' | |
p = subprocess.Popen([ | |
'ffmpeg', | |
'-i', args.file, | |
'-af', f'silencedetect=noise={args.noise}:duration={args.duration}:mono={mono_arg}', | |
'-f', 'null', | |
'-', | |
], encoding='utf-8', errors='replace', stderr=subprocess.PIPE) | |
stderr = [] | |
for line in p.stderr: | |
line = line.rstrip('\n') | |
stderr.append(line) | |
if not line.startswith('[silencedetect'): | |
continue | |
m = re.search(r'silence_start: ([\d.]+)', line) | |
if m: | |
start = format_time(float(m.group(1))) | |
print(f'silence: {start} - ', end='') | |
m = re.search(r'silence_end: ([\d.]+) \| silence_duration: ([\d.]+)', line) | |
if m: | |
end = format_time(float(m.group(1))) | |
duration = format_time(float(m.group(2))) | |
print(f'{end} (duration: {duration})') | |
p.wait() | |
if p.returncode != 0: | |
print('\n'.join(stderr)) | |
print(f'ffmpeg exited with return code {p.returncode}', file=sys.stderr) | |
sys.exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment