Further to the long answer above. I ended up doing the below in a pinch
Then you run it like split.py {input.wav or mp3} 1 .3 where the last two are the minimum length of the silence and the threshold respectively.
This is only tested on windows. Since the Original says ffmpeg.exe. YMMV
It tends to just create chunks of the length of your minimum silence length if the threshold is too high? or low? so you have to play with it and watch the resulting .bat length for clues. shorter is better usually. There are likely better solutions using more modern libraries. I can think of one already but no time right now.
This is just a fix for the other one, in modern python, but I'll leave the previous answer up for old python users
import subprocess as sp
import sys
import numpy
FFMPEG_BIN = "ffmpeg.exe"
print ('ASplit.py <src.mp3> <silence duration in seconds> <threshold amplitude 0.0 .. 1.0>')
src = sys.argv[1]
dur = float(sys.argv[2])
thr = int(float(sys.argv[3]) * 65535)
f = open('%s-out.bat' % src, 'wb')
tmprate = 16000
len2 = dur * tmprate
buflen = int(len2 * 2)
# t * rate * 16 bits
oarr = numpy.arange(1, dtype='int16')
# just a dummy array for the first chunk
command = [ FFMPEG_BIN,
'-i', src,
'-f', 's16le',
'-acodec', 'pcm_s16le',
'-ar', str(tmprate), # ouput sampling rate
'-ac', '1', # '1' for mono
'-'] # - output to stdout
pipe = sp.Popen(command, stdout=sp.PIPE, bufsize=10**8)
tf = True
pos = 0
opos = 0
part = 0
try:
while tf:
raw = pipe.stdout.read(buflen)
if raw == '':
tf = False
break
arr = numpy.frombuffer(raw, dtype="int16")
rng = numpy.concatenate([oarr, arr])
mx = numpy.amax(rng)
if mx <= thr:
# the peak in this range is less than the threshold value
trng = (rng <= thr) * 1
# effectively a pass filter with all samples <= thr set to 0 and > thr set to 1
sm = numpy.sum(trng)
# i.e. simply (naively) check how many 1's there were
# print(f"sm {sm} len2 {len2}")
if sm >= len2:
part += 1
apos = pos + dur * 0.5
#print( mx, sm, len2, apos)
f.write(f'ffmpeg -i "{src}" -ss {opos} -to {apos} -c copy -y "{src}-p{part}.wav"\r\n'.encode() )
opos = apos
pos += dur
oarr = arr
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except BaseException as err:
print(f"Unexpected {err}=, {type(err)}=")
part += 1
f.write(f'ffmpeg -i "{src}" -ss {opos} -to {pos} -c copy -y "{src}-p{part}.wav"\r\n'.encode())
f.close()