지난번에 Spleeter 사용하면서 마주쳤던 문제 중 하나가 비언어 분류 모델에 어떤 값을 입력해주어야 하는가 였다.
그래서 찾아보던 중...
pydub.silence의 detect_nonsilent 함수를 발견했다❗️
https://github.com/jiaaro/pydub/blob/master/pydub/silence.py
위 파이썬 파일에 잘 설명되어 있는데,
detect_nonsilent 함수는 입력값으로 주어진 audio의 모든 nonsilence section milliseconds의 [start, end]를 리턴해준다.
바로 사용해보자.
pip install pydub
우선 라이브러리를 설치하고 사용한다.
def create_json(audio_file):
intervals_jsons = []
min_silence_length = 70
intervals = detect_nonsilent(audio_file,
min_silence_len=min_silence_length,
silence_thresh=-32.64)
if intervals[0][0] != 0:
intervals_jsons.append({'start':0,'end':intervals[0][0]/1000,'tag':'침묵'})
non_silence_start = intervals[0][0]
before_silence_start = intervals[0][1]
for interval in intervals:
interval_audio = audio_file[interval[0]:interval[1]]
if (interval[0] - before_silence_start) >= 2000:
intervals_jsons.append({'start':non_silence_start/1000,'end':(before_silence_start+200)/1000,'tag':'비침묵'})
non_silence_start = interval[0]-200
intervals_jsons.append({'start':before_silence_start/1000,'end':interval[0]/1000,'tag':'침묵'})
before_silence_start = interval[1]
if non_silence_start != len(audio_file):
intervals_jsons.append({'start':non_silence_start/1000,'end':len(audio_file)/1000,'tag':'비침묵'})
return intervals_jsons
nonsilence section들을 사용해 json 파일을 만드는 함수다.
침묵 구간이 너무 촘촘하게 설정되어 있길래 일단 2초 이상의 침묵구간만 실제(?) 침묵 구간으로 생각하기로 했다.
def match_target_amplitude(sound, target_dBFS):
change_in_dBFS = target_dBFS - sound.dBFS
return sound.apply_gain(change_in_dBFS)
사운드의 진폭을 맞춰주는 함수이다.
두 함수를 적용해서 침묵 / 비침묵 구간을 뽑아내보자❗️
sound = AudioSegment.from_file("audio.wav", "wav")
normalized_sound = match_target_amplitude(sound, -20.0)
json = create_json(normalized_sound)
{'start': 0, 'end': 1.185, 'tag': '침묵'}
{'start': 1.185, 'end': 1.399, 'tag': '비침묵'}
{'start': 1.199, 'end': 3.362, 'tag': '침묵'}
{'start': 3.162, 'end': 4.421, 'tag': '비침묵'}
{'start': 4.221, 'end': 6.544, 'tag': '침묵'}
{'start': 6.344, 'end': 7.64, 'tag': '비침묵'}
{'start': 7.44, 'end': 15.435, 'tag': '침묵'}
{'start': 15.235, 'end': 15.646, 'tag': '비침묵'}
{'start': 15.446, 'end': 18.083, 'tag': '침묵'}
{'start': 17.883, 'end': 19.618, 'tag': '비침묵'}
{'start': 19.418, 'end': 28.026, 'tag': '침묵'}
{'start': 27.826, 'end': 29.352, 'tag': '비침묵'}
{'start': 29.152, 'end': 44.122, 'tag': '침묵'}
{'start': 43.922, 'end': 45.715, 'tag': '비침묵'}
{'start': 45.515, 'end': 48.091, 'tag': '침묵'}
{'start': 47.891, 'end': 48.293, 'tag': '비침묵'}
{'start': 48.093, 'end': 50.734, 'tag': '침묵'}
{'start': 50.534, 'end': 61.625, 'tag': '비침묵'}
{'start': 61.425, 'end': 63.488, 'tag': '침묵'}
{'start': 63.288, 'end': 81.078, 'tag': '비침묵'}
{'start': 80.878, 'end': 83.274, 'tag': '침묵'}
{'start': 83.074, 'end': 85.178, 'tag': '비침묵'}
{'start': 84.978, 'end': 88.589, 'tag': '침묵'}
{'start': 88.389, 'end': 92.546, 'tag': '비침묵'}
{'start': 92.346, 'end': 95.575, 'tag': '침묵'}
{'start': 95.375, 'end': 97.555, 'tag': '비침묵'}
{'start': 97.355, 'end': 114.882, 'tag': '침묵'}
{'start': 114.682, 'end': 119.001, 'tag': '비침묵'}
{'start': 118.801, 'end': 122.277, 'tag': '침묵'}
{'start': 122.077, 'end': 122.493, 'tag': '비침묵'}
{'start': 122.293, 'end': 134.72, 'tag': '침묵'}
{'start': 134.52, 'end': 134.937, 'tag': '비침묵'}
{'start': 134.737, 'end': 148.505, 'tag': '침묵'}
{'start': 148.305, 'end': 148.864, 'tag': '비침묵'}
{'start': 148.664, 'end': 154.504, 'tag': '침묵'}
{'start': 154.304, 'end': 158.986, 'tag': '비침묵'}
{'start': 158.786, 'end': 161.034, 'tag': '침묵'}
{'start': 160.834, 'end': 242.744, 'tag': '비침묵'}
이렇게 원하는 결과가 출력된다👍
물론 비침묵 구간이 너무 많아서 어떻게 처리해야하나 약간 고민이긴한데...
어차피 필요없는 부분은 비언어 분류 모델에 적용하면 정확도때문에 제외되지 않을까 싶다.