딥러닝 음성합성 multi-speaker-tacotron(tacotron+deepvoice)설치 및 사용법

딥러닝 음성합성 multi-speaker-tacotron(tacotron+deepvoice)설치 및 사용법

 

 

작성자 : 클루닉스 서진우 (alang@clunix.com)

작성일 : 2018년 3월 1일

 

음성합성(TTS)을 위한 딥러닝 오픈 모델인 tacotron 과 deepvoice 를 결합한 multi-speaker-tacotron 에 대해

개발 환경 구현 및 실제 음성 합성을 위한 딥러닝 학습 방법에 대해 정리한 문서이다.

 

본 개발 환경을 구현하기 위해서는 기본적으로 python 3.6 과 cuda 8.0, cudnn 6.0, tensorflow 혹은 tensorflow-gpu 1.3.0

이 설치되어 있어야 한다.

만일 tensorflow 1.3.0 이외의 버전을 이용할 경우 에러가 발생하니 주의해야 한다.

 

이밖에 운영체제 레벨에서 필요한 유틸리티로 ffmpeg, sox 등이 있으면 전후처리를 하는데 도움이 많이 된다.

참고로 개발환경에 이용된 운영체제는 Centos 7.4 이다.

 

일반적인 딥러닝 환경 구성(os, cuda, python, 기타 python library, package)에 대한 설치 방법은 별도로 다룰 계획이다.

본 문서에서는 multi-speaker-tacotron 설치 및 이용 방법에 대해서만 설명하고자 한다.

 

참고로 Multi-speaker-tacotron 메인 홈페이지는 https://carpedm20.github.io/tacotron/ 이다.

 

1. 설치

 

작업을 위한 가상 Python 환경을 생성한다.

$ source /APP/DeepLn/profile.d/python36.sh

$ source /APP/DeepLn/profile.d/cuda8_env.sh

$ virtualenv tf-tacotran

 

Multi-speaker-tacotron 소스를 다운로드 받는다.

 

$ git clone https://github.com/carpedm20/multi-speaker-tacotron-tensorflow.git

 

간혹 다른 서버로 개발환경 전체를 복제하는 경우가 종종 있어 virtualenv 로 생성된 python 과 ms-tacotron 패키지를
병합해서 관리한다.

$ mv multi-speaker-tacotron-tensorflow/* tf-tacotron

$ mv multi-speaker-tacotron-tensorflow/.git* tf-tacotron

가상환경을 적용한다.

$ source tf-tacotron/bin/activate

(tf-tacotron) [alang@GCT3DLM01 ~]$

 

Multi-speaker-tacotron 에 필요한 패키지를 설치 한다.

$ cd tf-tacotron

$ pip install -r requirements.txt

 

아래와 같이 많은 python package 가 설치될 것이다.

 

 

설치된 패키지를 확인한다.

$ pip freeze

Tensorflow 1.3.0 버전을 설치한다. GPGPU 가 장착된 시스템이라면 tensorflow-gpu 1.3.0 버전을 설치하도록 한다.

 

$ pip install tensorflow-gpu==1.3.0

Nltk의 punkt 데이터를 다운받는다

$ python -c “import nltk; nltk.download(‘punkt’)”

 

이것으로 기본적인 패키지 설치는 완료된다.

 

2. 전처리 사용 방법

 

 

일반적인 사용법은 tf-tacotron/datasets/<화자명>/audio 밑에 학습시킬 음성데이터를 복사해 둔다.

그리고 tf-tacotron/datasets/<화자명>/alignment.json 파일에 음성데이터와 해당 데이터의 text 에 해당하는 매핑 정보를
json 포맷으로 생성해야 한다.

 

/// 일반적 사용법

——————————————————————————–

 

datasets 디렉토리는 다음과 같이 구성되어야 합니다

 

datasets

├── son

│   ├── alignment.json

│   └── audio

│       ├── 1.mp3

│       ├── 2.mp3

│       ├── 3.mp3

│       └── …

└── 아무개

├── alignment.json

└── audio

├── 1.mp3

├── 2.mp3

├── 3.mp3

└── …

 

그리고 아무개/alignment.json는 아래와 같은 포멧으로 json 형태로 준비해 주세요.

 

{

“./datasets/아무개/audio/001.mp3”: “존경하는 국민 여러분”,

“./datasets/아무개/audio/002.mp3”: “국회의장과 국회의원 여러분”,

“./datasets/아무개/audio/003.mp3”: “저는 오늘”,

}

 

datasets와 아무개/alignment.json가 준비되면, 아래 명령어로 학습 데이터를 만드시면 됩니다:

 

python3 -m datasets.generate_data ./datasets/아무개/alignment.json

 

———————————————————————————

 

이 작업들은 수작업을 해야 하지만, 본 소스에는 이를 어느정도 자동화 시켜주는 스크립트를 제공한다.

자동화 스크립트는 tf-tacotron/scripts 디렉토리 밑에 존재한다.

 

$ cd tf-tacotron/scripts

기본 제공되는 스크립트는 손석희 앵커의 JTBC 뉴스룸의 브리핑 내용이다.

스크립트를 살펴 보면..

$ cat prepare_son.sh

—————————————————————————————————————————————————

#!/bin/sh

 

# 1. JTBC 홈페이지에서 뉴스룸의 앵커브리핑 영상과 음성원본파일을 다운받는다.

python -m datasets.jtbc.download

 

# 2. 한 방송 분량이 5분~10분정도의 내용으로 연속된 음성파일이다. 이를 한 문장열의 형태로 음성간 묵음을
기준으로 해서 파일을 분할한다.

python -m audio.silence –audio_pattern “./datasets/jtbc/audio/*.wav” –method=pydub

 

# 3. 분할된 wav 음성 파일을 구글의 STT(음성인식) API 를 통해 음성파일에 대한 text 를 추출한다.

python -m recognition.google –audio_pattern “./datasets/jtbc/audio/*.*.wav”

 

# 4. 구글 STT API 의 경우 정확도가 낮기 때문에 방송 대본을 비교해서 일정 score 이상의 내용만 선별한다.

python -m recognition.alignment –recognition_path “./datasets/jtbc/recognition.json” –score_threshold=0.5

 

# 5. 매 방송 시작 시 뉴스룸 앵커브리핑 MR 과 같이 음성이 섞이는 부분이 있는데 이부분을 학습 데이터에서 제거한다.

사실 이 부분은 download 단계에서 진행되기 보단 실제 학습 dataset 이 만들어진 이후 train 직전에 수행해야 한다.

rm datasets/jtbc/data/*.0000.npz

—————————————————————————————————————————————————

3. 설치 나 이용 과정에서 발생 문제 해결 방법

 

 

  • Download 스크립트 3단계 과정

3 단계에서 구글 STT 를 이용하기 위해서는 아래와 같은 사전 준비가 필요한다.

 

구글 음성인식 API 이용 방법

 

https://cloud.google.com/docs/authentication/getting-started

 

In GCP Console, navigate to the [Create service account key] page.

 

[Create service account key] Link 로 가서 google 서비스 계정 만들고,

카드 등록하고, 음성인식 서비스 활성화 한다.

 

1년간 무료라고 함..뭔가 찝찝..

 

Key 를 json 형태로 만들면.<XXXXX-XXXXXX-43211bc49356.json> 같은 파일을 다운로드 받을 수 있음.
작업 서버에 옮겨둠. ..

 

스크립트를 실행한다.

$ export GOOGLE_APPLICATION_CREDENTIALS=”<PATH>/XXXXX-XXXXXX-43211bc49356.json”

$ sh prepare_son.sh

 

  • Download 스크립트 4단계 과정

4단계 수행 시, unicodedecodeerror ‘cp949′ 에러가 발생하는 경우가 있다.

$ vi utils/__init__.py

89줄 : with open(path,encoding=encoding) as f:

을 with open(path,encoding=’UTF-8’) as f: 로 변경해 준다.

 

  • 학습 진행 시, attention 그래프에서 한글이 깨지는 문제

 

Matplopt 으로 그래프를 생성하는 데 그래프에 attention 에 따른 한글 TEXT (자음,모음) 가 표기되는데, 폰트 인식 문제로
깨지는 경우가 있다. 해결 방법은 아래와 같다.

 

$ fc-cache -fv

$ rm -rf ~/.cache/matplotlib/*

# cp ~/multi-speaker-tacotron-tensorflow/utils/NanumBarunGothic.ttf

~/python3.6/lib64/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf

 

# cp ~/multi-speaker-tacotron-tensorflow/utils/NanumBarunGothic.ttf /usr/share/fonts/nhn-nanum

4. 학습 및 이용 방법

 

 

Download 스크립트 단계가 완료되면 ./datasets/<화자>/alignment.json 파일이 생성되어 있을 것이다.

내용을 보면 아래와 같다.

 

$ cat datasets/son/alignment.json

 

{

“./datasets/son/audio/NB10584578.0001.wav”: “오늘 뉴스룸이 주목한 단어는 저돌입니다”,

“./datasets/son/audio/NB10584578.0005.wav”: “이렇게 얘기를 했습니다”,

“./datasets/son/audio/NB10584578.0007.wav”: “문구를 비대위원장이 저돌적으로 돌파 해야 할 과제는 과연 무엇인가”,

“./datasets/son/audio/NB10584578.0008.wav”: “첫 번째는 계파주의 청산입니다”,

“./datasets/son/audio/NB10584578.0010.wav”: “이런 보고서를 냈습니다”,

“./datasets/son/audio/NB10584578.0011.wav”: “계파정치 청산은 민주당의 미래를 위한 최우선 과제다”,

“./datasets/son/audio/NB10584578.0012.wav”: “아 이렇게 얘기했는데 그러나 아시는 것처럼 이 보고서는”,

“./datasets/son/audio/NB10584578.0013.wav”: “나갔다 집안 발 끝에 결국 채택되지 않았습니다”,

“./datasets/son/audio/NB10584578.0014.wav”: “아마 야당에서 한상진교수 좋아하는 사람 별로 없을 겁니다”,.

.

.

}

 

학습 데이터 셋을 생성한다.

$ python3 -m datasets.generate_data ./datasets/son/alignment.json

그럼 ./datasets/<화자>/data 디렉토리가 생기고, 그 안에 npz 포맷의 파일이 생성되어 있을 것이다.

손석희 데이터셋의 경우 Download 5단계 내용을 수행한다.

$ rm -f ./datasets/son/data/*.0000.npz

 

학습전에 hparams.py 파일에서 파라메터를 수정한다.

파라메터는 음성파일의 품질과 데이터셋의 정확도에 따라 몇 가지 조정이 가능한데, 이는 학습하는 데이터

에 따라 다를 수 있기 때문에 정확한 권장 값은 없다.

다만 손석희의 경우 아래 설정을 통해 의미있는 결과를 얻을 수 있었다.

 

$ vi hparams.py

 

‘cleaners’: ‘korean_cleaners’, #originally korean_cleaners

‘model_type’: ‘single’, # [single, simple, deepvoice]

‘attention_size’: f(256),

‘batch_size’: 32,

‘initial_learning_rate’: 0.002,

‘reduction_factor’: 4,

‘min_iters’: 20,

‘max_iters’: 200,

 

학습을 수행한다.

$ python3 train.py –data_path ./datasets/son

 

학습이 진행되면 logs/son_2018-01-28_16-53-12 식의 디렉토리가 생기고, 이 디렉토리에 500 step 마다 학습 결과에

해당하는 train, test 샘플 wav 파일과 그래프 파일인 png 확장 파일이 생긴다. 그리고 1000 step 마다 실제 음성합성에
이용할 수 있는 chkpt 파일이 생긴다.

 

$ eog test*000.png

 

또한 학습 진행 과정에서 학습 상태는 tensorboard 로 확인이 가능하다.

 

$ tensorboard –log_dir ./logs/son_2018-01-28_16-53-12

 

 

학습이 어느정도 정상적으로 이루어지고, Step 이 100,000 정도가 넘어가면 실제 합성을 해 볼 수가 있을 것이다.

음성 합성 방법은 아래와 같다.

 

$ python3 synthesizer.py –load_path logs/son-20171015 –text “이거 실화냐?”

그럼..기본적으로 tf-tacotron/samples 디렉토리 및에 wav, png 파일에 생성된다.

 

5. 학습 경험 정리

 

 

최소 손석희 데이터를 다운 받아 작업을 해보면 3만~4만 사이의 데이터를 얻을 수 있는데, 이를 가지고 그냥 작업을

하면 거의 원하는 결과를 얻기 힘들다. 실제 구글 STT API 를 통해 추출된 내용을 비교해보면 매우 참담했던 기억이

있다. 그렇다고, 이를 혼자서 수작업으로 다 수정하는 것은 무리라고 본다.

이리저리 다양한 방법으로 그나마 나은 데이터를 12000~13000 정도 선별한 후에야 정상적인 학습결과를 얻을 수

있었다.

 

개인적인 경험 상 단일 화자의 경우 일반적인 문장을 넣어 합성이 가능하게 할려면 적어도 정확도가 높은 데이터

10시간 분량은 필요했다. 다만 현실적으로 10시간 데이터를 확보하는 것이 매우 힘들었었다.

 

손석희의 경우 정확도 70% 이상의 데이터를 선별해서 데이터셋을 만들 경우 8~10시간 수준의 데이터를 확보 할 수

있었다. 손석희 데이터를 이용해서 단일 화자로 잘 학습되는 데이터 셋을 확보 한다.

 

이밖에 한국어 코퍼스 용으로 만들 여자 성우 데이터 (KSS.zip)의 경우 8시간 분량의 정확한 음성과 대본을 얻을 수

있었다. (다만, 정확한 음성과 TEXT 조합이지만, 파일 앞뒤에 불규칙적인 묵음이 상당수 존재하고, 대본 내용이 문어체와
구어체가 혼합되어 있어 다소 학습에 어려움이 존재하긴 함)

 

https://www.kaggle.com/bryanpark/korean-single-speaker-speech-dataset

 

이렇게 일정 분량이 확보된 데이터를 통해 1차 학습을 완료한 경우, 적은 분량 (1시간~4시간)의 데이터만 존재하는

화자의 음성도 학습이 가능했다.

예) 문재인 (1.8시간), 유인나 오디오북 (1시간), 유인나 볼륨을 높여라 방송(3시간)

 

Multi-speaker-tacotron 의 경우 단일 화자일 경우 hparams.py 에서 model_type 을 single 로, 다중 화자일 경우

Model_type 을 deepvoice 로 하여 학습을 하게 된다.

 

학습분량이 적은 화자의 경우 학습분량이 많은 화자의 데이터를 같이 학습하면 attention 을 형성할 수 있다.

다중화자 학습을 수행하는 방법은 아래와 같다

$ vi hparams.py

‘model_type’: ‘deepvoice’, # [single, simple, deepvoice]

 

$ python3 train.py –data_path ./datasets/moon,./datasets/son

 

 

개인적인 경우, 데이터가 적은 경우 유사한 문장열 길이의 데이터만을 모아서 학습을 하면 attention 을 형성하는데

효과가 있었다. 손석희, 문재인, 유인나(볼륨) 데이터의 경우 모두 문장열 길이의 차이가 크다.

이를 한번에 학습하는것 보다는 string_size 길이를 60~100, 100~140, 60~140으로 데이터를 나누어서 다중화자로

학습시키니깐 더 좋은 결과가 생성되었다.

 

또한 음성의 화체 (문어체, 구어체) 역시 학습 target 의 화자와 유사한 화체를 가진 데이터를 이용하는 것이 학습

결과에 영향을 주었다.

 

예를 들면 1시간 분량 데이터의 유인나 오디오북 데이터를 가지고 8시간 정도의 한국어 여자 코퍼스 데이터를

학습하는 경우와 10시간 분량의 손석희 데이터로 학습하는 경우, 손석희 데이터가 훨씬 좋은 결과를 나타내었다.

하지만 유인나 볼륨을 높여라 의 2~3시간 데이터 분량(정확도 낮음)의 경우 손석희 데이터보다 유사 화체를 가진

한국어 코퍼스 데이터를 사용하는 게 휠씬 좋은 결과를 얻을 수 있었다.

 

이 같은 방법으로 실제 합성에 성공하여 목소리는

손석희, 문재인, 유인나(볼륨버전), 유인나(오디오북버전), 한국어코퍼스 이다.

가장 난이도가 높았던 버전은 유인나(볼륨버전)이였다.

 

딥러닝 최적 개발 플랫폼 환경을 연구하기 위해 실제 딥러닝 응용을 다루어 볼 필요가 있어 10개월간 여러가지 모델을
Deploy 하면서 음성 합성 분야에 제일 많은 시간을 소비한 듯 합니다. Deploy 과정에서 좋은 소스를 공유해주신 개발자

분과 많은 정보를 공유해 주신 여러분들께 감사드립니다.

 

6. 음성 합성 결과 공유

 

 

아래는 그간 사내나 사외에서 딥러닝 플랫폼 관련 세미나를 할 때 참고하기 위해 만든 결과들입니다.

 

손석희 – 사내 세미나

 

문재인 – 사내 세미나

 

유인나(볼륨) – 딸에게 보내는 음성 편지

 

유인나(오디오북) – 해리포터

 

손석희 – 조선을 빛낸 100인의 위인

 

문재인 – 조선을 빛낸 100인의 위인

 

유인나(오디오북) – 조선을 빛낸 100인의 위인

 

한국어 코퍼스 – 조선을 빛낸 100인의 위인

서진우

슈퍼컴퓨팅 전문 기업 클루닉스/ 상무(기술이사)/ 정보시스템감리사/ 시스존 블로그 운영자

You may also like...

83 Responses

  1. Seungil Ko 말해보세요:

    안녕하세요 딥러닝을 공부하고 있는 학생입니다. 혹시 multi 학습과정에서 hparams.py 에 Single Speaker 에만 elif True 로 되어있는데 ‘model type’ : ‘deepvoice’ 로만 바꾸면 되나요??

  2. 김김동준 말해보세요:

    윈도우 환경에서는 제작할 수 없나요??

  3. 김김동준 말해보세요:

    윈도우 환경에서는 불가능한가요?

  4. 전승철 말해보세요:

    혹시 최종 학습모델 생성하셨을때 loss율이 어떻게됬는지 알려주실수있으신가요
    0.07에서 도저히 내려가지가않네요 ㅜ

    • 서진우 말해보세요:

      일단 음성과 txt 데이터 정확성이 제일 중요할듯 합니다. 그리고 single mode 보다는 deepvoice mode 수행했을때 더 loss를 줄일수 있었습니다. single 에서는 데이터 정확도가 높더라도 0.06 이하로 내려간 기억이 잘 안나네요.
      deepvocie 로 수행할때 가급적 문장길이가 유사한 데이터끼리 모아서 1명의 speaker dateset 을 만들었고요..이런 식으로 했을 경우 0.04까지고 내려간적이 있네요. 하지만 loss 가 적다해서 일반적인 품질이 좋은 것은 아니였습니다. 0.05~0.06 정도면 거의 비슷한 품질이 나왔습니다. 파라메터쪽에서는 learning rate, reduction_factor 0.02, 4 보단 0.01, 5 가 더 loss가 적었던거 같습니다.

  5. 김아무개 말해보세요:

    모델 학습을 끝내고 실제 음성합성을 해보았는데 이때, 결과 파일의 길이는 음성내용에 따라 다른 것이 아닌 고정된 것인가요? “안녕하십니까”를 합성했을 경우, 합성은 제대로 되었지만 음성파일의 길이가 12초로 안녕하십니까 이후 묵음구간이 포함되어 있더라구요. 음성파일의 길이를 텍스트에 맞게 조절할 수는 없는것인가요?

    • 서진우 말해보세요:

      synthesizer.py 파일을 열어보면

      78~79 줄 쯤에 librosa_trim=False, attention_trim=False 이 있습니다. 이값을 모두 True 로 변경해 주시고,
      마지막 줄에
      attention_trim=False 역시 attention_trim=True 로 변경해 주세요.

      그럼..음성 합성 시, 텍스트 길이에 맞게 음성 파일의 뒷 묵음 부분을 자동으로 처리해 버립니다.

  6. 권순용 말해보세요:

    안녕하세요. 모델 학습에서 Generated 32 batches of size 32 in 528.456sec이라고 뜨면서 그 이후step 1으로 넘어가기 전에 killed가 발생하는데 혹시 어떤 문제인지 알 수 있을까요?ㅠㅠ

    • 서진우 말해보세요:

      혹시 사용하시는 gpu 메모리 사양이 어떵게 되시나요? 보통 gtx 1080(8gb)으로 32 batch size로 했을때 1step 시 10초에서 30초 정도 소요되고 이후 계속 줄어서 1~2초 사이에 계산이 되어집니다. 만일 gpu 메모리가 낮은 사양이라면 batch size 를 16정도로 줄여보심이 좋을듯 합니다

  7. 방기덕 말해보세요:

    공유해 주신 내용이 많은 도움이 되었습니다.
    게시해주신 방법의 TTS를 구현하기 위한 최소 및 권장 사양을 문의 드립니다.
    학습 시스템의 사양과 학습 데이터의 양에 따라 다르겠지만 어느정도의 학습시간이 소요되었는지 궁금합니다.
    또, deepvoice를 수행할 때 1차학습을 위한 최소 시간, 2차 학습(다른 사람 목소리)를 위한 최소 시간에 대한 적절한 기준을 제시해 주실 수 있는지 문의 드립니다.
    감사합니다.

    • 서진우 말해보세요:

      1차 학습에는 10000건 이상의 학습데이터로 500k step 이상 진행하고 이걸로 50000건 정도 합성 데이터를 생성하여 deepvoice 로 다시 500k 정도 학습하는편입니다. 시간은 초기학습에 3-5일 정도.. 합성데이터 만드는데 1-2일정도..다시 학습하는데 3-5일 정도..소요되더군요..

  8. 제임스 림 말해보세요:

    안녕하세요. 공유하신 내용이 아주 훌륭합니다. 작업 완료된 샘플 또한 너무 좋네요. 발음도 상당히 좋아요. 샘플길이가 상당히 긴데 이건 긴 텍스트를 한 번에 합성하신 건가요? 만약 긴 문장을 한 번에 합성하신거라면 그 방법 있을까요? 한국어 코퍼스로도 1분 47초 길이네요.

    • 서진우 말해보세요:

      좋게 평가해 주셔서 감사합니다. 합성 문장 길이에 대해 문의하셨는데..한번에 합성한 것은 아닙니다.
      한번에 합성할 수 있는 최대 시간이 정해져 있기 때문에 그 이상의 문장 길이를 넣으면 화자의 발음 속도가 빨라지게 됩니다.
      그래서 긴 문장(책 한권을 통째로~) 합성에 맞게 응용개발을 하게 되었고, 처리 방식은..
      합성하고 싶은 문장 전체를 txt 파일에 담아서 입력하면 txt 파일의 한문장열씩 자동으로 입력 text 부분을 나누고,
      각 문장열마다 seqeunce id 를 부여하여 여러개의 task 로 분활하고 이 여러개의 task 를 task scheduler(grid engine)를 통해
      작업을 동시에 분산처리시킨뒤 결과가 나오면 seq id 에 맞게 다시 merge 하는 방식입니다.
      여러 문장을 동시에 합성할 경우에는 gpu 보다 cpu 가 효과적이여서 자체적으로 보유하고 있는 HPC(200core) 시스템에
      분산 처리 시키고 있습니다.(200개 문장열 합성에 30초 정도 소요된다고 보시면 됩니다.- 성경 창세기 합성에 1분 30초 정도 ..)

    • 제임스 림 말해보세요:

      좋은 답변 감사드립니다.

  9. 김동준 말해보세요:

    안녕하세요. 좋은 글 감사합니다..
    python3 -m datasets.generate_data ./datasets/YOUR_DATASET/alignment.json에서
    자꾸 audioread.NoBackendError가 뜨는데 뭐가 문제일까요…ㅠ?
    도움을 주실 수 있다면 감사하겠습니다..

  10. 박기윤 말해보세요:

    안녕하세요 train과정에서 궁금한게 있는데 , 데이터 대략 40000개를 한 5000개씩으로 나누어 train시켜도 괜찮을까요?
    그리고 훈련도중에 중단시키고 다시 이어서 훈련시키는 것이 가능한가요??ㅠ

    • 서진우 말해보세요:

      같은화자의 데이터라면 나누는것보다는 한번에 돌리는것이 좋을듯 합니다. 이어돌리는것은 가능하며 –load_path 옵션으로 기존 log 디렉토리를 적어주시면 됩니다

  11. 김난희 말해보세요:

    안녕하세요! 글 정말 잘 봤습니다. 많은 도움이 되었어요.
    궁금한 점이 있습니다.
    다중화자로 트레이닝을 다 하고, synthesizer.py로 음성 합성을 하면 보통 얼마정도의 시간이 걸리나요??
    저는 6분이상 걸리던데..ㅠ.ㅠ 혹시 더빠른 시간에 합성 결과를 받을 만한 팁이 있을까요?

    • 서진우 말해보세요:

      혹시 한 문장을 합성하는데 6분 걸린다는 건가요? H/W 사양에 따라 성능 차이는 있겠지만, 저의 경우ㅜ 일반적으로 길어도 1분 내외 였습니다. 간혹 최신 GPU 를 이용할 경우, CUDA8 에서 최신 GPU 종류가 없어 tensorflow 에서 gpu 장치 load 시에 시간이 걸리는 경우는 경험했지만, 6분 정도는 아니였습니다. 일단 CPU 사용이 어느정도 되신다면 CPU 만 이용해서 합성해 보시는 것이 좋을듯 하네요.
      CUDA_VISIBLE_DEVICES=”” python synthesizer.py ….

    • 김난희 말해보세요:

      늦었지만 친절한 답변 감사합니다. CPU로 돌리니 정말 10초 내외로 걸리네요! 잘 해결되었습니다.
      GPU load 시에 걸리는 문제때문에 오래 걸리는 것 같습니다.

      유인나 오디오북을 학습을 하고 싶은데,
      혹시 실례가 안된다면, 유인나 오디오북 데이터셋(텍스트, 오디오)파일을 어떻게 만들 수 있는지 여쭤볼 수 있을까요?

  12. 서진우 말해보세요:

    유인나 오디오북을 위한 자료는 유튜브에 올려진 유인나 오디오북 음성 자료를 받고 구글북스에 해당 원본도서를 구매해서 text를 얻은후 해당내용을 이용하여 만들어야 합니다. 다소 과정이 험난할수 있습니다. 저도 초기에는 이렇게 하다가 끝까지 수작업할 자신이 없어 초기 만든어놓은 데이터를 이용해 kaldi란 음성인식 모델로 유인나 오디오북 음성을 잘 학습시킨 stt를 만든후 이걸 이용해 가지고 있던 모든 오디오북의 text를 뽑아내는 방식으로 데이터셋을 만들었었죠. 이문서에 올린 샘플은 초기 완전 수작업 데이터셋으로만 학습한 결과입니다. 지금은 읽기 난해한 성경책도 통째로 넣으면 잘 읽는 수준까지는 학습이 되더군요.

    • 김난희 말해보세요:

      정말 친절한 답변 감사합니다!! 진행하면서 많은 도움이 될 것 같습니다.
      혹시 유인나 오디오북에 배경음이 있는 것은 따로 분리를 한 후에 학습을 하셨는지도 궁금합니다.

  13. 서진우 말해보세요:

    네 당연히 배경음을 제거해야 합니다. sox 의 noise 제거 기능으로 제거 하였습니다

    • 김난희 말해보세요:

      감사합니다! 친절히 잘 알려주셔서 진행 과정에 많은 도움을 받고 있습니다.ㅠㅠ

      sox를 써서 noise를 제거하는 과정을 공부하는 도중에, 배경음만 있는 파일이 따로 필요한 것으로 알게되었습니다. 혹시 배경음을 따로 찾을 수 있는지,아니면 위 과정이 맞는지도 여쭤봐도 괜찮을까요?

    • 서진우 말해보세요:

      제가 사용했던 sox로 nosie 를 제거한 방법입니다.

      // 원본 파일의 노이즈 프로필을 추출합니다.
      sox -n noiseprof noise.prof

      // 원본 파일의 노이즈를 제거하는 방법
      sox noisered noise.prof 0.21

      그럼..상당수의 BGM 이 제거된 output file 을 얻을 수 있습니다.
      그렇다고 아주 완벽하게 noise 가 제거 되진 않습니다.

      그래도 학습하기에 크게 무리 없는 상태를 확보할수 있습니다.
      이밖에 보다 완벽하게 noise 를 제거하기 위해서는 audacity 프로그램을 이용하는 방법도 있습니다.
      audacity 를 실행하고 효과 에 보면 noise 제거 기능이 있습니다. 음성 구간 별로 확실한 노이즈 구간을
      선택하여 프로필을 추출할수 있기 때문에 보다 품질 좋은 데이터 확보가 가능합니다.
      다만 꽤 수동 작업량이 많아지게 됩니다. 실제 두가지 작업을 다 해보았지만 audacity 로 노이즈 제거 작업에
      공을 들인 시간에 비해 최종 학습된 음성 품질에는 만족스럽지 못했었습니다.

    • 김난희 말해보세요:

      감사합니다! 시도해보니 잘 됩니다. 도움을 주셔서 감사합니다.

  14. 김상준 말해보세요:

    윈도우로 아나콘다로 하는데 requirements.txt 설치부터 에러 뜨네요 ㅠㅠ
    python setup.py egg_info 에 문제가 있다고 에러 뜨네요…

    • 서진우 말해보세요:

      제 개발환경이 리눅스라 windows 환경에서의 오류는 해결해본 경험이 없습니다.

  15. 장서윤 말해보세요:

    python -m datasets.son.download라고 입력하면 usr/bin/python no module named son이렇게 뜨네요 어떻게 해야 될까요

    • 서진우 말해보세요:

      일단 사용하시는 python 에 multi-speaker-tacotron 에서 요구하는 python package 가 모두 설치되어 있어야 합니다.
      pip install -r requirements.txt 를 수행해 주셔야 하고요..
      일단 위 오류 내용만 보아서는
      명령 수행한 위치에서 ./datasets/son/download.py 파일이 있는지 부터 확인해 주셔야 할듯 합니다.

  16. 김호연 말해보세요:

    안녕하세요, 합성 실패에 대한 원인을 잘 모르겠어서 댓글을 남기게 되었습니다. 알려주신 내용을 보면서 음성합성을 진행하고 있는데 현재까지의 결과는 손석희 데이터셋은 결과가 잘 나오는 것을 확인했지만 유인나와 한국어 코퍼스 음성합성을 한 결과가 좋지 않았습니다. 음성이 뚜렷하게 잘 나오지만 음성합성 시 적은 text와 다른 문장을 말합니다.

    현재 사용하고 있는 데이터셋은 1)한국어 코퍼스는 알려주신 방법으로 하였고 2)유인나 오디오북은 글과 댓글을 보면서 7시간 가량의 오디오를 작업하였습니다. 글자 길이는 손석희와 비슷한 길이로 하였습니다.

    질문드리고자 하는 내용은 아래와 같습니다.

    1. 지금은 json파일 내의 글자길이가 원인이라고 생각하여 이를 json 파일을 수정하여 재학습중이나 정확한 원인을 잘 모르겠습니다. 혹시 음성합성에서 잘못될 수 있는 원인이 있다면 어떤게 원인이 될 수 있을까요..?? 또 음성 합성 결과가 글자 길이에 따른 영향을 많이 받나요??

    2. 올려주신 내용 중에 string_size 를 나누어 다중화자로 학습하셨다고 하셨는데, 이때 string_size를 60 이상의 것들을 사용하였습니다. 혹시 오디오에 대한 문자열 길이가 많이 짧은 것은 사용하지 않는 것이 더 좋은가요?? 손석희 데이터에서는 이와 같은 짧은 문자열이 있어도 학습이 잘 되었지만 확실하게 모르겠어서 질문드립니다.

    • 서진우 말해보세요:

      일반적으로 tacotron 의 경우 대략 12초 정도의 음성 길이의 데이터는 학습이 가능합니다.
      다만 한두세글자의 음성데이터의 경우 학습이 어려웠던거 같습니다.
      (불가능한것은 아니고, 결국 해당 길이의 학습데이터가 많다면 그것도 충분히 가능하리라 보입니다.)
      제가 소개했던 방법중 유사한 음성길이를 맞추는 것은 적은 데이터 환경에서 특정 길이 문장에 한해 재대로된 음성 자체를 빠르게 확인할 수 있는 방법이지, 최종적으로 일반적인 문장에 대해 좋은 품질의 음성 결과를 얻기 위한 방법은 아닙니다.
      audio 와 text 의 학습데이터가 정확하지 않은 상황에서 데이터 수도 작은 경우, 해당 데이터중 가장 많은 데이터가 포함된 문장길이를 선별해서 학습할 경우 attention 형성에 유리하다는 것입니다.
      음성합성 시, 제 경험상 의미있는 재대로된 음성 자체가 합성되기 위해서 첫번째는 attention 을 형성해야 하는데, 유사 길이의 데이터로 학습데이터를 구성할 경우 적은 데이터 환경에서는 빠르게 attention 형성이 가능하다는 것이였습니다.
      다만, 그다음은 품질인데..품질은 결국 정확한 학습 데이터수 입니다.

      아주 좋은 품질의 결과를 얻기 위해서는 결국 정확하고 많은 데이터를 확보해야합니다. 가지고 있는 데이터 중 정확도가 비교적 높은 문장 길이 구간을 특정할 수 있다면, 해당 구간의 데이터를 선별해서 학습하고, 그 결과로 학습에 사용된 문장길이와 유사한 길이의 문장을 학습하면 꽤 좋은 결과를 얻을 수 있을 것입니다. 다만, 학습에 사용한 문장길이 보다 적거나 긴 문장에 대해서는 합성 결과가 좋지 않을 것입니다.

      즉 학습데이터의 문장 길이를 선별하는 방법은 보유하신 학습데이터의 상태가 열악한 경우, 사용해 볼수 있는 방법 중 하나입니다.

      결론은 유사 문장 길이로 학습데이터를 모았다고 하더라도 결국 모여진 학습데이터 수가 얼마나 되느냐가 중요합니다.

      코퍼스의 경우 전체 데이터가 1만이 조금 넘는 걸로 기억하고 있습니다. 이중 특정 문장 길이를 선별하시더라도
      선별된 데이터 수가 적어도 8000 이상은 유지해 주셔야 괜찮은 품질의 결과를 얻을수 있을 것입니다.
      (손석희 데이터는 워낙 많아서..중간길이만 선별해도 10000건 이상의 데이터 선별이 가능했었죠)

      유인나의 경우는 오디오북 특성상 특정길이로 한정해서 학습을 한다면 2000 정도의 데이터로도 합성이 가능했고, 4000
      정도에서는 나름 의미있는 결과를 얻을수는 있었습니다. 다만, 품질에는 한계가 있더군요.
      BGM 제거로 인해 noise 영향이 크더군요. 이 역시 데이터를 더 확보함에 따라 개선이 가능했었습니다.

    • 김호연 말해보세요:

      와…. 생각보다 고려해야할 것들이 많군요..ㅠㅠ 제세하고 좋은 답변 감사합니다!! 현재 말씀하신 것들을 토대로 데이터셋을 수정하면서 학습해보는 중입니다.

      그리고 하나 더 여쭤볼 것이 있는데 현재 저희가 화자를 4명으로 해서 학습을 하려고 하는데 3명까지는 잘되는데 4명으로하면 data_path에서 에러가 뜹니다. 혹시 4명이상으로 할때 따로 파라메터를 수정하거나 하는 부분이 있는건가요..?? 아니면 현재 사용하는 것이 화자가 3명으로 제한되어 있는 건가요..?

  17. 서진우 말해보세요:

    당연하겠지만, 음성합성 시 좋은 품질을 위해서는 보다 많은 학습 데이터 확보가 중요하였습니다. 최근에 kaldi 란 음성인식 모델로 특정화자의 일부 음성과 TEXT 데이터로 음성을 학습시킨 후, 해당 화자의 나머지 모든 음성데이터는 해당 음성인식기(STT)로 TEXT 데이터를 뽑아 내어, 최종 음성합성 학습 데이터를 확보하고 있습니다. 이와 관련된 글을 아래 링크에 올려두었습니다.

    http://nblog.syszone.co.kr/archives/9788

    참고로, 해당 글에 언급된 방법으로 학습시켜 생성한, 유인나 오디오북 버전의 성경 창세기 전반부 샘플이 포함되어 있습니다. 참고하세요.

  18. 서진우 말해보세요:

    김호연님, 화자수의 제한은 없는걸로 압니다. 일단 제가 가장 선호하는 화자수가 4명 입니다. 3명까지 무난히 하셨다면 화자수를 늘이는데 설정이나 명령방식의 특이점은 없을듯 합니다. 다만 고려하실 부분이 gpu 메모리 크기가 될듯 합니다. 화자수가 늘어나면 기본적으로 한번 처리할때 필요한 gpu 메모리 크기는 늘어날 필요가 있을수도 있습니다. 저의 경우 화자수 4명이고 batch size 32 로 할 경우 적어도 6G 이상은 필요했던거 같네요

  19. 선영 말해보세요:

    pre-trained 모델을 받으려고 하는 과정에서 에러가 나는데요.. 여러번 시도했으나, 원인을 못찾겠네요.. 혹시 아시나 해서 문의드립니다.
    ===========
    (py365) C:\Users\user\tts_son>python download.py son
    [!] The pre-trained models are being made available for research purpose only
    [!] 학습된 모델을 연구 이외의 목적으로 사용하는 것을 금지합니다.

    [?] Are you agree on this? 이에 동의하십니까? [y/n] y
    [*] son-20171015.tar.gz already exists
    Traceback (most recent call last):
    File “C:\ProgramData\Anaconda3\envs\py365\lib\tarfile.py”, line 1641, in gzopen
    t = cls.taropen(name, mode, fileobj, **kwargs)
    File “C:\ProgramData\Anaconda3\envs\py365\lib\tarfile.py”, line 1617, in taropen
    return cls(name, mode, fileobj, **kwargs)
    File “C:\ProgramData\Anaconda3\envs\py365\lib\tarfile.py”, line 1480, in __init__
    self.firstmember = self.next()
    File “C:\ProgramData\Anaconda3\envs\py365\lib\tarfile.py”, line 2295, in next
    tarinfo = self.tarinfo.fromtarfile(self)
    File “C:\ProgramData\Anaconda3\envs\py365\lib\tarfile.py”, line 1090, in fromtarfile
    buf = tarfile.fileobj.read(BLOCKSIZE)
    File “C:\ProgramData\Anaconda3\envs\py365\lib\gzip.py”, line 276, in read
    return self._buffer.read(size)
    File “C:\ProgramData\Anaconda3\envs\py365\lib\_compression.py”, line 68, in readinto
    data = self.read(len(byte_view))
    File “C:\ProgramData\Anaconda3\envs\py365\lib\gzip.py”, line 463, in read
    if not self._read_gzip_header():
    File “C:\ProgramData\Anaconda3\envs\py365\lib\gzip.py”, line 411, in _read_gzip_header
    raise OSError(‘Not a gzipped file (%r)’ % magic)
    OSError: Not a gzipped file (b'<m')

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
    File "download.py", line 122, in
    download_checkpoint(‘son’)
    File “download.py”, line 103, in download_checkpoint
    tar = tarfile.open(save_path, “r:gz”)
    File “C:\ProgramData\Anaconda3\envs\py365\lib\tarfile.py”, line 1587, in open
    return func(name, filemode, fileobj, **kwargs)
    File “C:\ProgramData\Anaconda3\envs\py365\lib\tarfile.py”, line 1645, in gzopen
    raise ReadError(“not a gzip file”)
    tarfile.ReadError: not a gzip file

    • 서진우 말해보세요:

      유명인 목소리인지라 공개에 문제가 있는걸로 알고 있습니다. 가이드에는있지만 다운로드가 안될것입니다.

  20. 장서윤 말해보세요:

    500step 진행될 때 자꾸 cancellederror (see above for traceback) enqueue operation was cancelled 이런 오류가 떠서 500step이상을 진행하지 못하고 있어요 어떻게 해야 할까요?

  21. 이동은 말해보세요:

    안녕하세요 공유해주신 내용 정말 너무 잘봤습니다. 감사합니다.
    질문드리고 싶은 내용은 손석희 앵커 데이터 학습시에 500 step마다 결과물의 음성파일과 함께 해당 align 파일이 생성되는데요
    이때 한글이 깨지는게 아니라 한글의 발음대로 영어로 표기되어 나타나있습니다.

    ex) 헌법 1조 1항은 누구든 예외가 될 수 없는 > heonbeob onejo onehangeun nuguden yeoga doel su eobsneun

    학습자체를 이런방식으로 하고 있는건지 아니면 align파일상에서만 이렇게 표기되는지에대해 코드상 놓치고 있는부분이 있는지 궁금합니다. 감사합니다.

  22. 오은택 말해보세요:

    손석희 데이터를 선별하신 과정이 궁금합니다! python3 -m recognition.alignment –recognition_path “./datasets/son/recognition.json” –score_threshold=0.5 이 코드에서 score_threshold를 바꿔주는건 별로 영향이 없을까요?

    • 서진우 말해보세요:

      값을 올려주면 그나마 정확도가 높은 문장을 선별해줍니다..stt 결과와 방송 대본을 비교해서 정확도를 선별하더군요.

  23. jin 말해보세요:

    $ source /APP/DeepLn/profile.d/python36.sh 입력시
    ‘$’은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는
    배치 파일이 아닙니다. 라고뜹니다,,
    앞의 $를 지우고해도 마찬가지구요,, 그외에 명령어도 이렇게 안됩니다
    ‘source’은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는
    배치 파일이 아닙니다.
    무엇이문제일까요 ㅜ

    • 서진우 말해보세요:

      $ 나 # 는 Linux prompt 표기 임으로 항상 제외하셔야 합니다. 또한 source /APP/DeepLn/profile.d/python36.sh 는 python 에 대한 profile 을 적용하라는 의미로 jin 님의 python 환경에 맞게 적용하셔야 합니다.
      본 문서의 내용을 그대로 하시기 보다는 의미 해석을 하셔서 님의 개발 환경에 맞게 적용해 주셔야 할듯 보입니다.

  24. hj 말해보세요:

    안녕하세요! 좋은 글 정말 감사합니다!

    글을 읽으면서 “이를 한번에 학습하는것 보다는 string_size 길이를 60~100, 100~140, 60~140으로 데이터를 나누어서 다중화자로 학습시키니깐 더 좋은 결과가 생성되었다.” 라는 부분을 좀 더 잘 이해하고 싶어서 댓글을 남기게 되었습니다.

    string size가 60~100인 데이터만 가지고 우선 training을 어느 정도 학습시키고(몇 스탭 정도 해야하는 지도 궁금합니다!) 중단한 뒤, 60~100인 데이터는 제거하고 새로 100~140인 데이터를 넣어서 어느 정도 학습을 시키고 중단한 뒤, 마지막으로 60~140 데이터 모두를 넣어 학습시킨다는 것으로 이해했습니다.

    제가 이해한 것이 맞나요?

  25. Phil 말해보세요:

    안녕하세요, 최근에 이 프로젝트를 해보고 있는데 전혀 사용되지 않는 .py 파일들이 있는 것을 혹시 눈치 채셨나요? 예를 들어, audio/get_duration.py, audio/google_speech.py에는 get_paths_by_pattern()이라는 정의되어 있지 않은 함수가 있고, audio/google_speech.py에는 get_audio_ids_from_paths()라는 정의되어 있지 않은 함수가 있고 등등…이 .py 파일들은 직접적으로 호출되지 않기 때문에 위의 작업들을 하는데 있어 아무런 오류를 내지 않지만…혹시나 인지하고 계신가싶어 여쭤봅니다.

    • 서진우 말해보세요:

      제가 기억하기에 학습에 요구되는 형태로 음성데이터가 준비되었을때는 상관없지만, 일반적인 음성파일을 가지고 학습데이터를 만들기 위해 음성파일 자체를 여러 단계를 통해 전처리를 해야할 필요가 있습니다. 그나마 mutlspeaker-tacotron 의 경우 이런 여러 단계의 전처리 과정을 하나의 전처리 코드로 통합하여 제공함으로 위 코드들은 실제 사용할 필요가 없을것입니다. 다만, 다른 tacotron 코드를 이용해서 학습할 경우 위 코드들이 필요할 경우가 발생할수도 있을듯 보이네요.

  26. Ed 말해보세요:

    안녕하세요. 실험 후기를 남겨주신게 너무나도 감사하다고 생각합니다. 다시한번 감사합니다.
    다름아니라 저는 r9y9의 deepvoice3를 이용해서 한국어 tts를 해보고있습니다.
    kss, nikl, 손석희 등으로 학습과 테스트를 하고 있지만, 모델이 많이 불안정해서 혼자 열심히 맨땅에 헤딩중입니다..

    궁금한게 정말 많지만 먼저 하나만 여쭤보고 싶습니다.
    손석희 데이터로 alignment.json을 만들다보면 wav파일에 대한 텍스트들을 살펴보면 1)단어만 들어있거나 2)문장이 미완성되있거나 3)띄어쓰기와 쉼표, 물음표, 마침표 등이 제대로 된건지? 하는 샘플들이 많이보이던데요.
    혹시 학습하시면서 저런 텍스트에 대해 어떻게 생각는지 궁금합니다. 특히나 3)의 경우가 너무 모르겠더라구요.
    마침표를 넣으면 attention에 도움이되는지.. 띄어쓰기의 정확성이 중요한지, 또한 손석희 앵커의 발화상태와 띄어씌기와의 관계가 중요한지..
    모델을 만져봐야되는지 데이터의 문제인지 참으로 어렵습니다.
    도움이되는 조언해주시면 감사합니다

    • 서진우 말해보세요:

      Deepvoice3 를 집중적으로 해보진 못했지만 tacotron의 경우 띄워쓰기가 어느정도 attention 에 영향을 주는걸로 보였습니다. 다만 tacotron을 이용하는 코드가 여러있는데 어떤것들은 기호들을 수용하는것도 있고 아예 학습데이터 생성시 제거해야하는것들도 있더군요..
      그래도 실제 데이터 품질에 따라 차이는 있겠지만 데이터품질이 그닥 좋지않은 경우 마침표 나 쉼표가 문장 중간이나 끝 부분의 잡음 처리에 도움이 되었던걸로 기억합니다

    • Ed 말해보세요:

      조언 말씀 감사드립니다.
      이것저것 시도를 해보고 있는데 마침표도 지금은 넣어보면서 해보는 중입니다.
      마침표가 그래서 어느정도 끝부분이 처리되는 느낌을 받았습니다. 띄어쓰기가 좀 문제내요^^;
      방향성을 어느정도 잡아주신거같아서 정말 감사드립니다..!

  1. 2019년 8월 8일

    […] […]

  2. 2022년 4월 19일

    […] + 여기서 자세히 보기 […]

  3. 2023년 6월 8일

    … [Trackback]

    […] Find More to that Topic: nblog.syszone.co.kr/archives/9416 […]

  4. 2023년 6월 12일

    … [Trackback]

    […] Find More Information here to that Topic: nblog.syszone.co.kr/archives/9416 […]

  5. 2023년 6월 22일

    … [Trackback]

    […] Information on that Topic: nblog.syszone.co.kr/archives/9416 […]

  6. 2023년 6월 23일

    … [Trackback]

    […] There you will find 15924 more Information on that Topic: nblog.syszone.co.kr/archives/9416 […]

  7. 2023년 8월 20일

    … [Trackback]

    […] There you will find 60700 more Information on that Topic: nblog.syszone.co.kr/archives/9416 […]

  8. 2023년 8월 20일

    … [Trackback]

    […] Find More to that Topic: nblog.syszone.co.kr/archives/9416 […]

  9. 2023년 8월 30일

    … [Trackback]

    […] Read More Info here on that Topic: nblog.syszone.co.kr/archives/9416 […]

  10. 2023년 9월 7일

    … [Trackback]

    […] Find More on that Topic: nblog.syszone.co.kr/archives/9416 […]

  11. 2023년 9월 12일

    … [Trackback]

    […] Read More on to that Topic: nblog.syszone.co.kr/archives/9416 […]

  12. 2023년 9월 15일

    … [Trackback]

    […] Read More Info here to that Topic: nblog.syszone.co.kr/archives/9416 […]

  13. 2023년 9월 18일

    … [Trackback]

    […] There you will find 93227 more Information to that Topic: nblog.syszone.co.kr/archives/9416 […]

  14. 2023년 9월 19일

    … [Trackback]

    […] Read More Information here to that Topic: nblog.syszone.co.kr/archives/9416 […]

  15. 2023년 10월 12일

    … [Trackback]

    […] Find More on to that Topic: nblog.syszone.co.kr/archives/9416 […]

  16. 2023년 11월 4일

    … [Trackback]

    […] There you will find 68233 additional Info on that Topic: nblog.syszone.co.kr/archives/9416 […]

  17. 2023년 11월 9일

    … [Trackback]

    […] Information to that Topic: nblog.syszone.co.kr/archives/9416 […]

  18. 2023년 11월 10일

    … [Trackback]

    […] Information to that Topic: nblog.syszone.co.kr/archives/9416 […]

  19. 2023년 11월 10일

    … [Trackback]

    […] Find More to that Topic: nblog.syszone.co.kr/archives/9416 […]

  20. 2023년 11월 16일

    … [Trackback]

    […] Information on that Topic: nblog.syszone.co.kr/archives/9416 […]

  21. 2023년 12월 2일

    … [Trackback]

    […] Read More Information here on that Topic: nblog.syszone.co.kr/archives/9416 […]

  22. 2023년 12월 3일

    … [Trackback]

    […] Read More here to that Topic: nblog.syszone.co.kr/archives/9416 […]

  23. 2023년 12월 11일

    … [Trackback]

    […] Find More on that Topic: nblog.syszone.co.kr/archives/9416 […]

  24. 2024년 2월 1일

    … [Trackback]

    […] Info on that Topic: nblog.syszone.co.kr/archives/9416 […]

  25. 2024년 2월 6일

    … [Trackback]

    […] Information to that Topic: nblog.syszone.co.kr/archives/9416 […]

  26. 2024년 2월 8일

    … [Trackback]

    […] Info to that Topic: nblog.syszone.co.kr/archives/9416 […]

  27. 2024년 2월 23일

    … [Trackback]

    […] Here you will find 6697 additional Info to that Topic: nblog.syszone.co.kr/archives/9416 […]

  28. 2024년 2월 27일

    … [Trackback]

    […] Find More on that Topic: nblog.syszone.co.kr/archives/9416 […]

  29. 2024년 3월 13일

    … [Trackback]

    […] Read More on that Topic: nblog.syszone.co.kr/archives/9416 […]

  30. 2024년 3월 28일

    … [Trackback]

    […] Find More on that Topic: nblog.syszone.co.kr/archives/9416 […]

김난희 에 응답 남기기 응답 취소