[졸업프로젝트] 침묵 / 비침묵 분류

krkorklo·2022년 2월 3일
0

졸업프로젝트

목록 보기
6/7

detect_nonsilent

지난번에 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': '비침묵'}

이렇게 원하는 결과가 출력된다👍

물론 비침묵 구간이 너무 많아서 어떻게 처리해야하나 약간 고민이긴한데...
어차피 필요없는 부분은 비언어 분류 모델에 적용하면 정확도때문에 제외되지 않을까 싶다.

0개의 댓글