Skip to content

Instantly share code, notes, and snippets.

@ozzieperez
Last active May 11, 2020 16:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ozzieperez/3d4db1973e617624cf3fb5eda306ccec to your computer and use it in GitHub Desktop.
Save ozzieperez/3d4db1973e617624cf3fb5eda306ccec to your computer and use it in GitHub Desktop.
Bash script to split an mp3 file from silent sections
#!/bin/bash
# file name to be split
input=$1
# text to prepend to the file name of the slices
prepend=$2
# counter for the slices
slice_counter=1
# current start
start=0
# current end
end=0
# saves a parsed section between silences
split ()
{
local offset=`echo "$start" | bc`
local length=`echo "$end - $start + 0.25" | bc -l | awk '{printf "%.3f\n", $0}'`
local output=`echo $prepend$slice_counter.mp3`
echo 'output: ' $output
ffmpeg -ss $offset -t $length -i $input $output
}
# create info file from input
echo `ffmpeg -i $input -af silencedetect=noise=-30dB:d=0.5 -f null - 2> _silenceinfo_.txt`
# filter info file for silence breakpoints
echo `cat _silenceinfo_.txt | grep silencedetect > _breakpoints_.txt`
echo "CREATED TEMP FILES"
# Link filedescriptor 10 with stdin
exec 10<&0
# stdin replaced with a file supplied as a first argument
exec < '_breakpoints_.txt'
# read breakpoints line by line
while read LINE; do
if [[ $LINE = *"silence_start"* ]]; then
end=`echo $LINE | awk '{print $5}'`
split
((slice_counter++))
fi
if [[ $LINE = *"silence_end"* ]]; then
start=`echo $LINE | awk '{print $5}'`
fi
done
# restore stdin from filedescriptor 10
# and close filedescriptor 10
exec 0<&10 10<&-
# clean up, delete files
echo `rm _silenceinfo_.txt`
echo `rm _breakpoints_.txt`
echo "DELETED TEMP FILES"
###########################################
# Inspired by this answer on SO:
# https://stackoverflow.com/a/36077309
###########################################
@thomasmichaelwallace
Copy link

Just wanted to say thank you for sharing this- helped me a lot!

If you ever come back to it, you might want to change L18 to the following, or else it will fail with sub-second slices:

local length=`echo "$end - $start + 0.25" | bc -l | awk '{printf "%.3f\n", $0}'`

@ozzieperez
Copy link
Author

@thomasmichaelwallace ✌️thanks, appreciate the feedback. just updated it.

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