이번에는 데이터 셋 제작하는 방법에 대해서 설명해보겠다.

 

이 프로젝트에서는 input값으로 캐릭터 보이스와 그 음성의 text정보가 필요하다.

즉, (speech, text) 쌍이 필요하다. 

 

데이터 셋 제작에는 3개의 과정이 필요하다.

  1. 원하는 캐릭터의 음성을 동영상에서 잘라 내기(음성 추출)
  2. 잡음, 배경음 제거
  3. 캐릭터의 음성을 text로 변환

차례차례 한번 살펴보자.

 

1. 음성 추출

동영상에서 음성을 추출하기 위해서 'shotcut'이라는 툴을 사용했다.

https://shotcut.org

'shotcut'은 무료 동영상 편집 프로그램으로, 전문적인 영상편집 지식이 없어도 사용하는데 무리가 없었다.

인터페이스가 직관적이라서 shotcut에 대한 별도의 정보나 공부 없어도 편하게 사용 가능하다.

 

사실 내가 원하는 편집 프로그램은 

오디오 파형이 제공되고, 미세하게 자르기가 가능하고, 잘라서 나온 것을 그대로 내보내기 가능한 프로그램을 원했다.

내가 못찾는건지는 모르겠지만 무료 프로그램 중에서 저 3가지를 모두 만족하는 것은 찾지 못했다.

(지금이라도 찾으면 바로 갈아타기 가능)

그래서 차선책으로 위의 1, 2번째 조건을 만족하는 shotcut으로 선택한 것이다.

 

편집 순서는

1. shotcut프로그램 창을 2개를 연다. (하나는 동영상 구간 나누기용, 나머지는 출력용)

2. 동영상을 열고, 밑의 타임 라인에 집어넣는다.

3. 캐릭터가 말하는 장면(구간)을 찾는다.

4. 재생 헤드 위치에서 자르기를 사용하여 구간을 나눈다.

5. 자른 구간을 복사한 후, 다른 shotcut창에 붙여넣기를 한다.

6. 출력을 누른 후, 출력 형식을 'wav', 샘플 레이트를 22050HZ로 맞춘다.

(tacotron 구현체 대부분의 권장 sample_rate가 22050HZ라서)

7. 파일 내보내기를 클릭한다.

이 순서대로 진행했다. 

(만약 다른 편집 프로그램을 사용한다고 하더라도 편집 순서는 위와 다를 게 없을 것이다.)

 

 

 

구간 나누기
출력(wav, 22050HZ)

 

 

저장할 때의 wav파일 이름은 통일성과 나중에 편집하기 편하게 '회수_몇번째.wav'로 지었다.

ex) 1화의 41번째 음성이면 1_041.wav

(1화에 999개 이상 뽑을 일이 없다. 사실 많아봤자 200개가 안될거다. 그래서 '041'이런 식으로 앞에 0을 채워 넣어 3자리로 만들었다.)

 

이 작업에서 음성의 앞뒤 여유를 0.2~0.3초 주는 것을 추천한다. 너무 공백이 길면 학습에 악영향을 미치고, 너무 공백이 짧아버리면 발음 시작 전의 숨소리가 잘리거나, 끝부분 음성이 부자연스럽기 때문이다. 

 

음성을 자르는 기준은 

문장 단위, 가능하면 2~4초 이내로 정했다. 음성이 너무 길면 학습에 어려움이 있고, 너무 짧게(단어로)잘라버리면 단어와 단어 사이의 관계가 학습이 제대로 안될 것 같아서 이렇게 기준을 세웠다. 

(참고로 다른 음성데이터(kss)도 대부분 2~4초더라)

단답이나 단어만 나오는 경우는 일단 수집? 했다. 음성 하나가 아까운지라....ㅎㅎ

 

데이터 수집을 하다보니까 내가 지금 수집한 데이터가 몇 개고, 총시간이 얼마인지 궁금해졌다. 일일이 드래그하고 보기 귀찮아서 함수를 하나 만들었다. (사실 배경음악 제거 작업을 하려고 만든 클래스에 메서드 추가한 거지만..) 

클래스 인자로는 음성데이터(wav파일들)이 있는 경로를 주면 된다.

folderinfo함수를 실행하면 wav파일 디렉터리의 wav파일들의 개수, 총 시간, 용량 등을 info.txt에 저장한다.

(클래스 이름이 wav_spleeter인거는 스포?이니 다음 글에서 설명하겠다!)

 

 

import os
import wave
import datetime


# filelist -> wav file list (str)
# filenum -> wav file count (int)
# partnum -> ani part num list (int)
# path -> dataset path (str)
# total_time -> wav file total time

class wav_spleeter():
    def __init__(self, path):
        self.path = path
        self.spl_path = path+"\\spleeter_out\\"
        self.filelist = [wav for wav in os.listdir(path) if wav.endswith(".wav")]
        self.filenum = len(self.filelist)
        self.partnum = list(set(int(i.split('_')[0]) for i in self.filelist))
        self.partnum.sort()
        self.total_time = 0

        print(self.partnum)
        os.chdir(self.path)
        print(self.filelist)
        print(f'파일이 {self.filenum}개 있습니다.')

        for i in self.filelist:
            a = wave.open(i, 'rb')
            self.total_time += a.getnframes() / a.getframerate()

        print(self.total_time)
        print(f'total time : {datetime.timedelta(seconds=self.total_time)}')

    def folderinfo(self):
        info = os.popen('dir').read()
        f = open("info.txt", 'w')
        print(info)
        f.write(f'wav file total time : {datetime.timedelta(seconds=self.total_time)}\n\n')
        f.write(f'file_num = {self.filenum}\n\n')
        f.write(info)
        f.close()

 

 

 

정말 이 음성 추출 작업이 고단하고 시간을 제일 많이 잡아먹는다. 내경우는 목표의 절반을 하는데 3주 조금 더 걸렸다..

절반 해서 나온 파일 수는 약 700개, 총 음성 시간은 약 30분 정도이다. 

내 예상으로는 다 하면 약 1시간 정도 나올 것 같다.