Skip to content

Instantly share code, notes, and snippets.

@antiboredom
Created October 5, 2020 19:07
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antiboredom/8808d04c86ee13e5cf55b1347e043e20 to your computer and use it in GitHub Desktop.
Save antiboredom/8808d04c86ee13e5cf55b1347e043e20 to your computer and use it in GitHub Desktop.
Create a supercut of a video using only the quiet bits
import argparse
import re
import os
import subprocess
from moviepy.editor import VideoFileClip, concatenate_videoclips
def get_silences(filename, db, duration):
args = "ffmpeg -nostats -i {} -af silencedetect=noise={}dB:d={} -f null -".format(
filename, db, duration
)
# > output.txt 2>&1
results = subprocess.getoutput(args)
outname = filename + ".silences.txt"
with open(outname, "w") as outfile:
outfile.write(results)
return outname
def parse_silences(filename):
with open(filename, "r") as infile:
lines = infile.readlines()
out = []
start = None
end = None
for l in lines:
if "silencedetect" not in l:
continue
if start is None:
results = re.search(r"silence_start: ([0-9.]+)", l)
if results:
start = float(results.group(1))
else:
results = re.search(r"silence_end: ([0-9.]+)", l)
if results:
end = float(results.group(1))
out.append((start, end))
start = None
end = None
return out
def compose(videofile, silences):
filename, file_extension = os.path.splitext(videofile)
movie = VideoFileClip(videofile)
clips = []
for start, end in silences:
duration = end - start
clip = movie.subclip(start, end)
clips.append(clip)
outname = filename + "_silences" + file_extension
final_clip = concatenate_videoclips(clips)
final_clip.write_videofile(
outname,
codec="libx264",
temp_audiofile="temp-audio.m4a",
remove_temp=True,
audio_codec="aac",
)
return outname
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Create a supercut of silences in a video"
)
parser.add_argument("path", nargs="+", help="Path of a file or a folder of files.")
parser.add_argument("--db", dest="db", default="-30", help="Decibal level")
parser.add_argument(
"--duration", dest="duration", default="1", help="Silence duration"
)
args = parser.parse_args()
videofile = args.path[0]
silence_file = get_silences(videofile, args.db, args.duration)
silences = parse_silences(silence_file)
compose(videofile, silences)
@antiboredom
Copy link
Author

This script create a supercut of the quiet bits of a video file, using ffmpeg to find silences and moviepy to stitch things together. To run, first install moviepy:

pip install moviepy

Also make sure that you have ffmpeg installed. On a mac:

brew install ffmpeg

Then call the script like so:

python silences.py video.mp4 --db=-30 --duration=1

This will extract all the silences quieter than -30dB and longer than 1 second. You may need to play around with the db and duration parameters to get desirable results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment