-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathsplit_audio.py
More file actions
127 lines (104 loc) · 4.2 KB
/
split_audio.py
File metadata and controls
127 lines (104 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import os
import librosa
import argparse
from utils import vad_audio_segment
FFMPEG_BIN = 'ffmpeg'
def convert2wav(audio_file, wav_file):
try:
cmd = '{} -i {} -acodec pcm_s16le -ar 16000 -ac 1 {} -y -loglevel panic'.format(
FFMPEG_BIN, audio_file, wav_file)
os.system(cmd)
return True
except Exception as error:
print('Error: {}'.format(repr(error)))
return False
def trim_audio_ffmpeg(src_file, start_tm, end_tm, dst_file):
osrate = args.osr
if not os.path.exists(src_file):
return False
try:
cmd = '{} -i {} -ar {} -ac 1 -filter "aresample=isr=44100:osr={}:dither_method=triangular_hp:resampler=swr:filter_type=cubic" -ss {:.2f} -to {:.2f} {} ' \
'-y -loglevel panic'.format(FFMPEG_BIN, src_file, osrate, osrate, start_tm, end_tm, dst_file)
os.system(cmd)
return True
except Exception as error:
print('Error: {}'.format(repr(error)))
return False
def get_duration(wave_file, samplerate=16000):
y, fs = librosa.load(wave_file, sr=samplerate)
n_frames = len(y)
audio_length = n_frames * (1 / fs)
return audio_length
def audio_split(arguments):
audio_file = args.input
min_silence = args.sil
min_duration = args.min
max_duration = args.max
convert_file = audio_file[:-4] + '_convert.wav'
if not convert2wav(audio_file, convert_file):
return
print("Reading from {}".format(audio_file))
dur = get_duration(convert_file)
print("Audio duration is {}s".format(dur))
segments = vad_audio_segment(convert_file)
if len(segments) == 0:
print("No segments to split")
return
try:
os.remove(convert_file)
except:
pass
# make a segment using min/max length
final_list = []
temp_segment = segments[0]
for x in segments[1:]:
cur_duration = x[1] - x[0]
temp_duration = temp_segment[1] - temp_segment[0]
# try to split on silences no shorter than min duration
if x[0] - temp_segment[1] <= min_silence:
temp_segment[1] = x[1]
continue
if cur_duration + temp_duration > max_duration:
final_list.append(temp_segment)
temp_segment = x
else:
temp_segment[1] = x[1]
final_list.append(temp_segment)
if final_list[-1][1] - final_list[-1][0] <= min_duration:
mean_time = (final_list[-2][0] + final_list[-1][1]) / 2
final_list[-2][1] = mean_time
final_list[-1][0] = mean_time
# split audio
split_dir = audio_file[:-4] + '_split'
os.makedirs(split_dir, exist_ok=True)
final_list[0][0] = 0
final_list[-1][1] = dur
print("Chunks will be saved to {}".format(split_dir))
for i, seg in enumerate(final_list):
stime, etime = seg
if i == 0:
etime = (etime + final_list[i+1][0]) / 2
elif i == len(final_list)-1:
stime = (stime + final_list[i-1][1]) / 2
else:
stime = (stime + final_list[i - 1][1]) / 2
etime = (etime + final_list[i + 1][0]) / 2
split_audio_file = "{}_{}.wav".format(
os.path.basename(audio_file)[:-4],
i+1)
split_audio_path = os.path.join(split_dir, split_audio_file)
trim_audio_ffmpeg(audio_file, stime, etime, split_audio_path)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--inp', type=str, required=True, help="Path to audio file (with extension)")
parser.add_argument('-m', '--min', type=float, default=60.0, help="Min chunk length (s)")
parser.add_argument('-M', '--max', type=float, default=180.0, help="Max chunk length (s)")
parser.add_argument('-s', '--sil', type=float, default=1.0, help="Min silence to split on (s)")
parser.add_argument('-S', '--osr', type=int, default=22050, help="Output sample rate (Hz)")
args = parser.parse_args()
try:
audio_split(args)
except IndexError:
print("Error: min silence likely too long. Reduce --sil value and rerun")
else:
print("Done")