Transformers documentation

텍스트 음성 변환

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

텍스트 음성 변환

Text-to-speech(TTS)는 텍스트에서 자연스러운 음성으로 생성하는 작업으로, 여러 언어와 여러 화자에 대한 음성을 생성할 수 있습니다. 현재 🤗 Transformers에는 Dia, CSM, Bark, MMS, VITS, SpeechT5와 같은 여러 text-to-speech 모델이 제공됩니다.

"text-to-audio" 파이프라인(또는 별칭인 "text-to-speech")을 사용하면 오디오를 쉽게 생성할 수 있습니다. "text-to-speech" 파이프라인을 CSM과 함께 사용하는 예시는 다음과 같습니다:

>>> from transformers import pipeline

>>> pipe = pipeline("text-to-audio", model="sesame/csm-1b")
>>> output = pipe("Hello from Sesame.")

노트북에서 생성된 오디오를 청취하는 데 사용할 수 있는 코드 스니펫입니다:

>>> from IPython.display import Audio
>>> Audio(output["audio"], rate=output["sampling_rate"])

기본적으로 CSM은 무작위 음성을 사용합니다. 채팅 템플릿 사전의 일부로 참조 오디오를 제공하여 음성 클로닝을 수행할 수 있습니다:

>>> import soundfile as sf
>>> import torch
>>> from datasets import Audio, load_dataset
>>> from transformers import pipeline

>>> pipe = pipeline("text-to-audio", model="sesame/csm-1b")

>>> ds = load_dataset("hf-internal-testing/dailytalk-dummy", split="train")
>>> ds = ds.cast_column("audio", Audio(sampling_rate=24000))
>>> conversation = [
...     {
...         "role": "0",
...         "content": [
...             {"type": "text", "text": "What are you working on?"},
...             {"type": "audio", "path": ds[0]["audio"]["array"]},
...         ],
...     },
...     {"role": "0", "content": [{"type": "text", "text": "How much money can you spend?"}]},
... ]
>>> output = pipe(conversation)

Dia와 같은 일부 모델은 웃음, 한숨, 울음 같은 비언어적 표현이나 음악까지 생성하도록 조건을 설정할 수 있습니다. 아래는 이러한 예시입니다:

>>> from transformers import pipeline

>>> pipe = pipeline("text-to-speech", model="nari-labs/Dia-1.6B-0626")
>>> text = "[S1] (clears throat) Hello! How are you? [S2] I'm good, thanks! How about you?"
>>> output = pipe(text)

와 와 같은 스피커 태그를 받아 고유한 목소리 간의 대화를 생성할 수 있다는 점에 유의하세요.

CSM과 다른 사전 학습된 TTS 모델이 할 수 있는 것의 더 많은 예제는 오디오 과정을 참고하세요.

TTS 모델을 파인튜닝하려는 경우, 현재 🤗 Transformers에서 사용할 수 있는 텍스트-음성 변환 모델은 SpeechT5, FastSpeech2Conformer, Dia, CSM이며, 향후 더 많은 모델이 추가될 예정입니다. SpeechT5는 음성-텍스트 변환 데이터와 텍스트-음성 변환 데이터의 조합으로 사전 학습되어, 텍스트와 음성이 공유하는 통합된 숨겨진 표현 공간을 학습할 수 있습니다. 이는 동일한 사전 학습 모델을 다양한 작업에 대해 파인튜닝할 수 있음을 의미합니다. 또한, SpeechT5는 x-vector 화자 임베딩을 통해 여러 화자를 지원합니다.

이 가이드의 나머지 부분은 다음을 수행하는 방법을 보여줍니다:

  1. 영어 음성으로 처음 학습된 SpeechT5를 VoxPopuli 데이터셋의 네덜란드어(nl) 언어 하위 집합으로 fine-tune합니다.
  2. 정제된 모델을 추론에 사용하는 방법은 두 가지가 있습니다. 파이프라인을 사용하는 방법과 직접 사용하는 방법입니다.

시작하기 전에 필요한 라이브러리가 모두 설치되어 있는지 확인하세요:

pip install transformers datasets soundfile librosa torchcodec speechbrain accelerate

아직 모든 SpeechT5 기능이 공식 릴리스에 병합되지 않았으므로, 🤗Transformers를 소스에서 설치하세요:

pip install git+https://github.com/huggingface/transformers.git

이 가이드를 따르려면 GPU가 필요합니다. 노트북에서 작업 중이라면, GPU가 사용 가능한지 확인하려면 다음 줄을 실행하세요:

!nvidia-smi

또는 AMD GPU의 경우:

!rocm-smi

Hugging Face 계정에 로그인하여 모델을 업로드하고 커뮤니티와 공유하는 것을 권장합니다. 프롬프트가 표시되면 로그인할 토큰을 입력하세요:

>>> from huggingface_hub import notebook_login

>>> notebook_login()

데이터셋 로드

VoxPopuli는 2009~2020년 유럽 의회 행사 녹음에서 가져온 데이터로 구성된 대규모 다국어 음성 코퍼스입니다. 15개 유럽 언어에 대한 라벨이 붙은 오디오-전사 데이터를 포함합니다. 이 가이드에서는 네덜란드어 하위 집합을 사용하지만, 다른 하위 집합을 자유롭게 선택할 수 있습니다.

VoxPopuli를 비롯한 기타 자동 음성 인식(ASR) 데이터셋은 TTS 모델 학습에 가장 적합한 옵션이 아닐 수 있습니다. 과도한 배경 소음과 같은 ASR에 유리한 특징은 일반적으로 TTS에서는 바람직하지 않습니다. 그러나 최고 품질의 다국어, 다화자 TTS 데이터셋을 찾는 것은 상당히 어려울 수 있습니다.

데이터를 로드해 보겠습니다:

>>> from datasets import load_dataset, Audio

>>> dataset = load_dataset("qmeeus/voxpopuli", "nl", split="train")
>>> len(dataset)
20968

20968개의 예시는 fine-tuning에 충분합니다. SpeechT5는 오디오 데이터의 샘플링 레이트가 16 kHz여야 하므로, 데이터셋의 예시가 이 요구 사항을 충족하는지 확인하세요:

dataset = dataset.cast_column("audio", Audio(sampling_rate=16000))

데이터 전처리

사용할 모델 체크포인트를 정의하고 적절한 프로세서를 로드하는 것으로 시작해 보겠습니다:

>>> from transformers import SpeechT5Processor

>>> checkpoint = "microsoft/speecht5_tts"
>>> processor = SpeechT5Processor.from_pretrained(checkpoint)

SpeechT5 토큰화를 위한 텍스트 정리

텍스트 데이터를 정리하는 것부터 시작합니다. 텍스트를 처리하려면 프로세서의 토크나이저 부분이 필요합니다:

>>> tokenizer = processor.tokenizer

데이터셋 예시에는 전사 내용이 포함된 text 기능이 있습니다. SpeechT5 토크나이저에는 숫자를 나타내는 토큰이 없으므로, 텍스트에 포함된 숫자는 <unk> 토큰으로 변환됩니다. 데이터셋에 숫자가 포함되어 있다면, 이를 문자 형태로 정규화하는 것을 고려해 보세요.

SpeechT5는 영어로 학습되었기 때문에 네덜란드 데이터셋의 특정 문자를 인식하지 못할 수 있습니다. 그대로 두면 이러한 문자는 <unk> 토큰으로 변환됩니다. 그러나 네덜란드어에서는 à와 같은 특정 문자를 사용하여 음절의 강세를 나타냅니다. 텍스트의 의미를 보존하기 위해 이 문자를 일반적인 a로 대체할 수 있습니다.

지원되지 않는 토큰을 식별하려면, 문자를 토큰으로 처리하는 SpeechT5Tokenizer를 사용하여 데이터셋의 모든 고유 문자를 추출합니다. 이를 위해 extract_all_chars 매핑 함수를 작성하여 모든 예시의 전사 내용을 하나의 문자열로 연결한 뒤, 이를 문자 집합으로 변환합니다. 매핑 함수에서 모든 전사 내용을 한 번에 사용할 수 있도록 dataset.map()에서 batched=True와 batch_size=-1을 설정해야 합니다.

>>> def extract_all_chars(batch):
...     all_text = " ".join(batch["text"])
...     vocab = list(set(all_text))
...     return {"vocab": [vocab], "all_text": [all_text]}


>>> vocabs = dataset.map(
...     extract_all_chars,
...     batched=True,
...     batch_size=-1,
...     keep_in_memory=True,
...     remove_columns=dataset.column_names,
... )

>>> dataset_vocab = set(vocabs["vocab"][0])
>>> tokenizer_vocab = {k for k, _ in tokenizer.get_vocab().items()}

이제 두 개의 문자 집합을 갖게 됩니다. 하나는 데이터셋의 어휘를, 다른 하나는 토크나이저의 어휘를 포함합니다. 데이터셋에서 지원되지 않는 문자를 식별하려면 이 두 집합의 차이를 구할 수 있습니다. 결과 집합에는 데이터셋에는 있지만 토크나이저에는 없는 문자가 포함됩니다.

>>> dataset_vocab - tokenizer_vocab
{' ', 'à', 'ç', 'è', 'ë', 'í', 'ï', 'ö', 'ü'}

이전 단계에서 식별된 지원되지 않는 문자를 처리하려면, 이러한 문자를 유효한 토큰으로 매핑하는 함수를 정의하세요. 토크나이저에서 공백은 이미 ▁로 대체되어 있으므로 별도로 처리할 필요가 없습니다.

>>> replacements = [
...     ("à", "a"),
...     ("ç", "c"),
...     ("è", "e"),
...     ("ë", "e"),
...     ("í", "i"),
...     ("ï", "i"),
...     ("ö", "o"),
...     ("ü", "u"),
... ]


>>> def cleanup_text(inputs):
...     for src, dst in replacements:
...         inputs["text"] = inputs["text"].replace(src, dst)
...     return inputs


>>> dataset = dataset.map(cleanup_text)

이제 텍스트의 특수 문자를 처리했으므로, 이제 오디오 데이터에 초점을 맞춰야 할 때입니다.

연사

VoxPopuli 데이터셋에는 여러 화자의 음성 데이터가 포함되어 있습니다. 데이터셋에 몇 명의 화자가 포함되어 있는지 확인하려면, 고유한 화자의 수와 각 화자가 데이터셋에 기여한 예시의 수를 세면 됩니다. 데이터셋에는 총 20,968개의 예시가 포함되어 있으며, 이 정보는 데이터 내 화자와 예시의 분포를 더 잘 이해하는 데 도움이 됩니다.

>>> from collections import defaultdict

>>> speaker_counts = defaultdict(int)

>>> for speaker_id in dataset["speaker_id"]:
...     speaker_counts[speaker_id] += 1

히스토그램을 그리면 각 화자의 데이터 양을 파악할 수 있습니다.

>>> import matplotlib.pyplot as plt

>>> plt.figure()
>>> plt.hist(speaker_counts.values(), bins=20)
>>> plt.ylabel("Speakers")
>>> plt.xlabel("Examples")
>>> plt.show()
Speakers histogram

히스토그램을 살펴보면, 데이터셋의 화자 중 약 3분의 1은 100개 미만의 예시를 가지고 있으며, 약 10명의 화자는 500개 이상의 예시를 가지고 있습니다. 학습 효율을 높이고 데이터셋을 균형 있게 만들기 위해, 예시가 100개에서 400개 사이인 화자로 데이터를 제한할 수 있습니다.

>>> def select_speaker(speaker_id):
...     return 100 <= speaker_counts[speaker_id] <= 400


>>> dataset = dataset.filter(select_speaker, input_columns=["speaker_id"])

남은 화자가 몇 명인지 확인해 보겠습니다:

>>> len(set(dataset["speaker_id"]))
42

남은 예제가 몇 개인지 확인해 보겠습니다:

>>> len(dataset)
9973

약 40명의 고유 화자로부터 약 10,000개 미만의 예제가 남게 되며, 이는 충분해야 합니다.

샘플 수가 적은 화자의 경우, 샘플 길이가 길면 실제로는 더 많은 오디오가 사용 가능한 경우가 있습니다. 그러나 각 화자의 오디오 총량을 결정하려면 전체 데이터셋을 스캔해야 하며, 이는 각 오디오 파일을 로드하고 디코딩하는 데 시간이 많이 소요되는 과정입니다. 따라서 이 단계는 여기에서 건너뛰었습니다.

스피커 임베딩

여러 화자를 구별할 수 있도록 TTS 모델을 설정하려면, 각 예제에 대해 화자 임베딩을 생성해야 합니다. 화자 임베딩은 특정 화자의 음성 특성을 포착하는 모델의 추가 입력입니다. 이러한 화자 임베딩을 생성하려면 SpeechBrain의 사전 학습된 spkrec-xvect-voxceleb 모델을 사용하세요.

입력 오디오 웨이브폼을 받아 해당 스피커 임베딩을 포함하는 512개 요소의 벡터를 출력하는 함수 create_speaker_embedding()을 생성하세요.

>>> import os
>>> import torch
>>> from speechbrain.inference.classifiers import EncoderClassifier
>>> from accelerate import Accelerator

>>> spk_model_name = "speechbrain/spkrec-xvect-voxceleb"
>>> device = Accelerator().device
>>> speaker_model = EncoderClassifier.from_hparams(
...     source=spk_model_name,
...     run_opts={"device": device},
...     savedir=os.path.join("/tmp", spk_model_name),
... )


>>> def create_speaker_embedding(waveform):
...     with torch.no_grad():
...         speaker_embeddings = speaker_model.encode_batch(torch.tensor(waveform))
...         speaker_embeddings = torch.nn.functional.normalize(speaker_embeddings, dim=2)
...         speaker_embeddings = speaker_embeddings.squeeze().cpu().numpy()
...     return speaker_embeddings

speechbrain/spkrec-xvect-voxceleb 모델은 VoxCeleb 데이터셋의 영어 음성으로 학습된 반면, 이 가이드의 학습 예제는 네덜란드어라는 점을 유의해야 합니다. 네덜란드어 데이터셋에 대해 이 모델이 여전히 합리적인 화자 임베딩을 생성할 것으로 생각하지만, 이 가정이 모든 경우에 성립하지는 않을 수 있습니다.

최적의 결과를 위해, 먼저 대상 음성으로 X-vector 모델을 학습하는 것을 권장합니다. 이를 통해 모델이 네덜란드어에 존재하는 고유한 음성 특성을 더 잘 포착할 수 있도록 보장됩니다.

데이터셋 처리

마지막으로, 모델이 기대하는 형식으로 데이터를 처리해 보겠습니다. 단일 예시를 입력으로 받아 SpeechT5Processor 객체를 사용하여 입력 텍스트를 토큰화하고 대상 오디오를 log-mel spectrogram으로 로드하는 prepare_dataset 함수를 생성합니다. 또한 화자 임베딩을 추가 입력으로 추가해야 합니다.

>>> def prepare_dataset(example):
...     audio = example["audio"]

...     example = processor(
...         text=example["text"],
...         audio_target=audio["array"],
...         sampling_rate=audio["sampling_rate"],
...         return_attention_mask=False,
...     )

...     # strip off the batch dimension
...     example["labels"] = example["labels"][0]

...     # use SpeechBrain to obtain x-vector
...     example["speaker_embeddings"] = create_speaker_embedding(audio["array"])

...     return example

단일 예시를 확인하여 처리가 올바른지 검증합니다:

>>> processed_example = prepare_dataset(dataset[0])
>>> list(processed_example.keys())
['input_ids', 'labels', 'stop_labels', 'speaker_embeddings']

Speaker embeddings는 512개 요소의 벡터여야 합니다:

>>> processed_example["speaker_embeddings"].shape
(512,)

는 80개의 mel 빈을 가진 log-mel 스펙트로그램이어야 합니다.

>>> import matplotlib.pyplot as plt

>>> plt.figure()
>>> plt.imshow(processed_example["labels"].T)
>>> plt.show()
Log-mel spectrogram with 80 mel bins

참고: 이 스펙트로그램이 혼란스럽게 느껴진다면, 저주파를 아래에, 고주파를 위에 배치하는 플롯의 관례에 익숙하기 때문일 수 있습니다. 그러나 matplotlib 라이브러리를 사용하여 스펙트로그램을 이미지로 플롯할 때 y축이 뒤집히므로, 스펙트로그램이 upside down으로 보입니다.

이제 처리 함수를 전체 데이터셋에 적용합니다. 이 과정에는 5~10분이 소요됩니다.

>>> dataset = dataset.map(prepare_dataset, remove_columns=dataset.column_names)

데이터셋의 일부 예시가 모델이 처리할 수 있는 최대 입력 길이(600 토큰)를 초과한다는 경고가 표시됩니다. 해당 예시를 데이터셋에서 제거합니다. 여기서 한 발 더 나아가, 더 큰 배치 크기를 허용하기 위해 200 토큰을 초과하는 모든 예시를 제거합니다.

>>> def is_not_too_long(input_ids):
...     input_length = len(input_ids)
...     return input_length < 200


>>> dataset = dataset.filter(is_not_too_long, input_columns=["input_ids"])
>>> len(dataset)
8259

다음으로, 기본적인 train/test split을 생성합니다:

>>> dataset = dataset.train_test_split(test_size=0.1)

데이터 콜레이터

여러 예시를 하나의 배치로 결합하려면 사용자 정의 데이터 콜레이터를 정의해야 합니다. 이 콜레이터는 패딩 토큰으로 더 짧은 시퀀스를 패딩하여 모든 예시가 동일한 길이를 갖도록 보장합니다. 스펙트로그램 라벨의 경우, 패딩된 부분은 특수 값 -100으로 대체됩니다. 이 특수 값은 모델이 스펙트로그램 손실을 계산할 때 해당 스펙트로그램 부분을 무시하도록 지시합니다.

>>> from dataclasses import dataclass
>>> from typing import Any, Dict, List, Union


>>> @dataclass
... class TTSDataCollatorWithPadding:
...     processor: Any

...     def __call__(self, features: list[dict[str, Union[list[int], torch.Tensor]]]) -> dict[str, torch.Tensor]:
...         input_ids = [{"input_ids": feature["input_ids"]} for feature in features]
...         label_features = [{"input_values": feature["labels"]} for feature in features]
...         speaker_features = [feature["speaker_embeddings"] for feature in features]

...         # collate the inputs and targets into a batch
...         batch = processor.pad(input_ids=input_ids, labels=label_features, return_tensors="pt")

...         # replace padding with -100 to ignore loss correctly
...         batch["labels"] = batch["labels"].masked_fill(batch.decoder_attention_mask.unsqueeze(-1).ne(1), -100)

...         # not used during fine-tuning
...         del batch["decoder_attention_mask"]

...         # round down target lengths to multiple of reduction factor
...         if model.config.reduction_factor > 1:
...             target_lengths = torch.tensor([len(feature["input_values"]) for feature in label_features])
...             target_lengths = target_lengths.new(
...                 [length - length % model.config.reduction_factor for length in target_lengths]
...             )
...             max_length = max(target_lengths)
...             batch["labels"] = batch["labels"][:, :max_length]

...         # also add in the speaker embeddings
...         batch["speaker_embeddings"] = torch.tensor(speaker_features)

...         return batch

SpeechT5에서는 모델의 decoder 부분에 입력되는 데이터가 2분의 1로 줄어듭니다. 즉, target sequence에서 짝수 번째 timestep을 모두 제거합니다. 이후 decoder는 원래 길이의 2배인 sequence를 예측합니다. 원래 target sequence의 길이가 홀수일 수 있으므로, data collator는 배치의 최대 길이를 2의 배수로 아래로 반올림하도록 처리합니다.

>>> data_collator = TTSDataCollatorWithPadding(processor=processor)

모델 학습

프로세서 로딩에 사용한 것과 동일한 체크포인트에서 사전 학습된 모델을 로드합니다:

>>> from transformers import SpeechT5ForTextToSpeech

>>> model = SpeechT5ForTextToSpeech.from_pretrained(checkpoint)

use_cache=True 옵션은 gradient checkpointing과 호환되지 않습니다. 학습 시에는 이 옵션을 비활성화하세요.

>>> model.config.use_cache = False

학습 인수를 정의합니다. 여기서는 학습 과정에서 평가 지표를 계산하지 않습니다. 대신 손실만 확인합니다:

>>> from transformers import Seq2SeqTrainingArguments

>>> training_args = Seq2SeqTrainingArguments(
...     output_dir="speecht5_finetuned_voxpopuli_nl",  # change to a repo name of your choice
...     per_device_train_batch_size=4,
...     gradient_accumulation_steps=8,
...     learning_rate=1e-5,
...     warmup_steps=500,
...     max_steps=4000,
...     gradient_checkpointing=True,
...     fp16=True,
...     eval_strategy="steps",
...     per_device_eval_batch_size=2,
...     save_steps=1000,
...     eval_steps=1000,
...     logging_steps=25,
...     report_to="trackio",
...     load_best_model_at_end=True,
...     greater_is_better=False,
...     label_names=["labels"],
...     push_to_hub=True,
... )

Trainer 객체를 인스턴스화하고 모델, 데이터셋, 데이터 콜레이터를 전달합니다.

>>> from transformers import Seq2SeqTrainer

>>> trainer = Seq2SeqTrainer(
...     args=training_args,
...     model=model,
...     train_dataset=dataset["train"],
...     eval_dataset=dataset["test"],
...     data_collator=data_collator,
...     processing_class=processor,
... )

이제 학습을 시작할 준비가 되었습니다. 학습에는 몇 시간이 소요됩니다. GPU에 따라 학습을 시작할 때 CUDA "out-of-memory" 오류가 발생할 수 있습니다. 이 경우 per_device_train_batch_size를 2의 배수로 점진적으로 줄이고, gradient_accumulation_steps를 2배로 늘려 이를 상쇄할 수 있습니다.

>>> trainer.train()

pipeline에서 체크포인트를 사용하려면, 프로세서를 체크포인트와 함께 저장했는지 확인하세요:

>>> processor.save_pretrained("YOUR_ACCOUNT_NAME/speecht5_finetuned_voxpopuli_nl")

최종 모델을 🤗 Hub에 업로드하세요:

>>> trainer.push_to_hub()

추론

파이프라인을 사용한 추론

좋습니다. 이제 모델을 fine-tuning 했으므로 추론에 사용할 수 있습니다. 먼저, 해당 pipeline과 함께 모델을 사용하는 방법을 살펴보겠습니다. 다음 "text-to-speech" pipeline을 체크포인트로 생성해 보겠습니다:

>>> from transformers import pipeline

>>> pipe = pipeline("text-to-speech", model="YOUR_ACCOUNT_NAME/speecht5_finetuned_voxpopuli_nl")

narrate할 네덜란드어 텍스트를 선택하세요. 예:

>>> text = "hallo allemaal, ik praat nederlands. groetjes aan iedereen!"

pipeline를 사용하여 SpeechT5를 사용하려면 화자 임베딩이 필요합니다. 테스트 데이터셋의 예시에서 가져오겠습니다:

>>> example = dataset["test"][304]
>>> speaker_embeddings = torch.tensor(example["speaker_embeddings"]).unsqueeze(0)

이제 텍스트와 화자 임베딩을 pipeline에 전달하면 나머지는 자동으로 처리됩니다:

>>> forward_params = {"speaker_embeddings": speaker_embeddings}
>>> output = pipe(text, forward_params=forward_params)
>>> output
{'audio': array([-6.82714235e-05, -4.26525949e-04,  1.06134125e-04, ...,
        -1.22392643e-03, -7.76011671e-04,  3.29112721e-04], dtype=float32),
 'sampling_rate': 16000}

그 후 결과를 청취할 수 있습니다:

>>> from IPython.display import Audio
>>> Audio(output['audio'], rate=output['sampling_rate'])

수동으로 추론 실행

pipeline을 사용하지 않고도 동일한 추론 결과를 얻을 수 있지만, 더 많은 단계가 필요합니다.

🤗 Hub에서 모델을 로드합니다:

>>> model = SpeechT5ForTextToSpeech.from_pretrained("YOUR_ACCOUNT/speecht5_finetuned_voxpopuli_nl")

테스트 데이터셋에서 예시를 선택하고 화자 임베딩을 얻습니다.

>>> example = dataset["test"][304]
>>> speaker_embeddings = torch.tensor(example["speaker_embeddings"]).unsqueeze(0)

입력 텍스트를 정의하고 토큰화합니다.

>>> text = "hallo allemaal, ik praat nederlands. groetjes aan iedereen!"
>>> inputs = processor(text=text, return_tensors="pt")

모델을 사용하여 스펙트로그램을 생성합니다:

>>> spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings)

원하시면 스펙트로그램을 시각화해 보세요:

>>> plt.figure()
>>> plt.imshow(spectrogram.T)
>>> plt.show()
Generated log-mel spectrogram

마지막으로, vocoder를 사용하여 스펙트로그램을 소리로 변환합니다.

>>> with torch.no_grad():
...     speech = vocoder(spectrogram)

>>> from IPython.display import Audio

>>> Audio(speech.numpy(), rate=16000)

경험상 이 모델에서 만족스러운 결과를 얻는 것은 어려울 수 있습니다. 화자 임베딩의 품질이 중요한 요인으로 보입니다. SpeechT5는 영어 x-vectors로 사전 학습되었기 때문에, 영어 화자 임베딩을 사용할 때 가장 좋은 성능을 발휘합니다. 합성된 음성 품질이 좋지 않다면 다른 화자 임베딩을 사용해 보세요.

학습 기간을 늘리면 결과의 품질이 향상될 가능성이 높습니다. 그럼에도 불구하고, 음성 언어는 명확하게 영어가 아니라 네덜란드어이며, 화자의 음성 특성은 잘 포착되었습니다(예시의 원본 오디오와 비교해 보세요). 또한 실험해 볼 수 있는 것 중 하나는 모델의 구성입니다. 예를 들어, config.reduction_factor = 1을 사용해 결과가 개선되는지 확인해 보세요.

마지막으로, 윤리적 고려 사항을 반드시 검토해야 합니다. TTS 기술은 다양한 유용한 용도로 활용될 수 있지만, 누군가의 목소리를 해당 당사자의 지식이나 동의 없이 모방하는 등 악용될 수도 있습니다. TTS를 신중하고 책임감 있게 사용해 주세요.

Update on GitHub