Explorando a Interface de Programação do Tortoise TTS: Uma Análise Técnica

Explorando a Interface de Programação do Tortoise TTS: Uma Análise Técnica

O Tortoise TTS representa um sistema avançado para a conversão de texto em fala (TTS), centralizado na classe SpeechSynthesizer. Esta classe abrange toda a pipeline de síntese, oferecendo diversas opções de configuração. Este artigo explora em detalhe a estrutura da classe SpeechSynthesizer, seus métodos cruciais, as técnicas para obtenção de espaços latentes condicionais, as configurações predefinidas e a implementação de geração em tempo real. O sistema adota uma arquitetura modular, orquestrando modelos autorregressivos, de difusão, CLVP e vocoders para permitir funcionalidades como clonagem de voz, síntese personalizada e geração de áudio em fluxo contínuo.

Funcionalidades da Classe Essencial SpeechSynthesizer

A classe SpeechSynthesizer serve como o ponto de entrada principal no ecossistema Tortoise TTS. Ela encapsula a totalidade do processo de conversão de texto em áudio, disponibilizando uma gama abrangente de configurações e uma interface de programação versátil. Como a principal API do Tortoise TTS, esta classe gerencia a colaboração entre múltiplos modelos de redes neurais, tais como modelos autorregressivos, modelos de difusão, modelos CLVP e vocoders.

Arquitetura e Componentes Fundamentais

A concepção da classe SpeechSynthesizer segue uma arquitetura modular, fragmentando a complexa cadeia de processamento TTS em constituintes autônomos, cada qual com uma responsabilidade funcional específica:

Parâmetros de Inicialização Detalhados

O construtor da classe SpeechSynthesizer oferece uma variedade de opções de configuração, permitindo que os desenvolvedores personalizem o comportamento do TTS conforme suas necessidades:

Parâmetro Tipo Padrão Descrição
batch_size_ar int None Tamanho do lote para geração autorregressiva; otimizado automaticamente para GPU.
path_to_models str MODELS_PATH Diretório onde os pesos dos modelos são armazenados.
redaction_enabled bool True Ativa a funcionalidade de censura textual (conteúdo entre parênteses é removido).
use_key_value_cache bool False Habilita o cache de chave-valor para acelerar a inferência.
deepspeed_optimization bool False Ativa otimizações com DeepSpeed.
fp16_enabled bool False Utiliza ponto flutuante de meia precisão (FP16).
target_device torch.device None Dispositivo de execução (CUDA/MPS/CPU); selecionado automaticamente.

Análise das Funções dos Métodos Chave

1. Método extract_speaker_embeddings

Este método transforma amostras de voz em vetores latentes condicionais, sendo fundamental para a clonagem e controle de estilo de voz:

def extract_speaker_embeddings(self, audio_references, include_mels=False):
    """
    Converte uma coleção de amostras de áudio de voz em um par de vetores latentes condicionais:
    (embedding_autoregressivo, embedding_difusao).
    
    Args:
        audio_references: Uma lista contendo duas ou mais amostras de áudio de referência,
                          cada uma com aproximadamente 10 segundos de duração.
        include_mels: Booleano para indicar se os espectrogramas MEL também devem ser retornados.
    
    Returns: Uma tupla de embeddings latentes que codificam as características vocais.
    """

O fluxo de processamento abrange as seguintes etapas:

  1. Normalização e formatação dos segmentos de áudio.
  2. Extração das condições para o modelo autorregressivo.
  3. Derivação das condições para o modelo de difusão.
  4. Codificação de características em múltiplas escalas.

2. Método generate_speech_with_preset

Este método oferece uma interface conveniente com configurações predefinidas, permitindo diferentes compromissos entre qualidade e velocidade:

def generate_speech_with_preset(self, input_text, quality_preset='standard', **extra_args):
    """
    Realiza a conversão de texto para fala utilizando configurações predefinidas.
    
    Args:
        input_text: O conteúdo textual a ser sintetizado.
        quality_preset: O nome da predefinição de qualidade (e.g., 'ultra_rapido', 'rapido', 'padrao', 'alta_qualidade').
        **extra_args: Argumentos adicionais que serão passados para o método de síntese principal.
    
    Returns: Os dados da forma de onda de áudio gerada.
    """

As predefinições suportadas são:

Predefinição Iterações de Difusão Amostras Autorregressivas Cenário de Uso
ultra_rapido 30 16 Aplicações em tempo real, velocidade máxima.
rapido 50 32 Equilíbrio entre velocidade e qualidade.
padrao 100 64 Saída de qualidade padrão.
alta_qualidade 200 128 Qualidade superior, processamento mais lento.

3. Método Principal synthesize_audio

Este é o método completo de conversão de texto em fala, permitindo controle granular sobre os parâmetros:

def synthesize_audio(self, input_text, speaker_references=None, precomputed_embeddings=None, num_outputs=1, 
                     show_progress=True, fixed_seed=None, yield_state_info=False, **extra_options):
    """
    Método abrangente para a conversão de texto em áudio.
    
    Args:
        input_text: O texto a ser transformado em fala.
        speaker_references: Uma lista de amostras de áudio para referenciar a voz.
        precomputed_embeddings: Vetores latentes condicionais já calculados.
        num_outputs: O número de amostras de áudio a serem geradas.
        show_progress: Booleano para exibir informações de progresso durante a síntese.
        fixed_seed: Um valor de semente para garantir a reprodutibilidade.
        yield_state_info: Indica se o estado determinístico deve ser retornado junto ao áudio.
    
    Returns: Os dados de áudio gerados ou uma tupla (áudio, estado_deterministico).
    """

Detalhes da Implementação Técnica

Fluxo de Trabalho Colaborativo entre Múltiplos Modelos

A classe SpeechSynthesizer coordena a operação conjunta de vários modelos de redes neurais. O fluxo completo de TTS se desenrola da seguinte forma:

  1. Processamento do Texto de Entrada: O texto é limpo, normalizado e transformado em uma sequência de tokens.
  2. Extração de Condicionamento de Voz: Se fornecidas amostras de referência de voz, embeddings latentes são extraídos para capturar o timbre e o estilo do falante.
  3. Geração Autorregressiva: Um modelo autorregressivo gera a sequência de tokens de mel condicionada pelo texto e pelos embeddings de voz.
  4. Refinamento por Difusão: Um modelo de difusão refina os espectrogramas mel gerados, adicionando detalhes e naturalidade.
  5. Síntese de Forma de Onda: Um vocoder converte os espectrogramas mel refinados em dados de forma de onda de áudio.
  6. Pós-processamento de Áudio: O áudio final pode passar por normalização de volume, filtragem ou outros ajustes.

Gerenciamento e Otimização de Memória

A classe SpeechSynthesizer implementa estratégias inteligentes para a gestão de memória:

  1. Carregamento de Modelo Sob Demanda: Modelos opcionais, como o CLVP, são carregados apenas quando estritamente necessários.
  2. Consciência do Dispositivo: O sistema identifica e seleciona automaticamente o dispositivo de computação mais adequado (CUDA, MPS ou CPU).
  3. Otimização de Processamento em Lotes: O tamanho dos lotes é ajustado dinamicamente para maximizar a utilização da memória da GPU.
  4. Gerenciamento de Contexto do Modelo: Utiliza-se um gerenciador de contexto temporário (e.g., para CUDA) para otimizar o uso da memória do dispositivo durante a troca de modelos.

Recursos Avançados

Clonagem e Personalização de Voz

Através do método extract_speaker_embeddings, a classe SpeechSynthesizer suporta a clonagem de voz de alta qualidade:

import torch
from tortoise_tts_lib import SpeechSynthesizer, load_audio_sample # Assumindo estas são as importações corretas

# Carregar clipes de referência de áudio
ref_audios = [
    load_audio_sample("amostra_voz_a.wav", 22050), 
    load_audio_sample("amostra_voz_b.wav", 22050)
]

# Inicializar o sintetizador
tts_engine = SpeechSynthesizer()

# Extrair embeddings condicionais do falante
speaker_embeddings = tts_engine.extract_speaker_embeddings(ref_audios)

# Sintetizar áudio com a voz clonada
output_waveform = tts_engine.synthesize_audio("Olá mundo, esta é minha voz clonada.", 
                                                precomputed_embeddings=speaker_embeddings)

# Opcional: Salvar ou reproduzir output_waveform (requer função auxiliar)
# save_audio_to_file(output_waveform, "voz_clonada.wav", 22050)

Suporte para Geração em Fluxo Contínuo

A classe SpeechSynthesizer oferece suporte para a geração de áudio em fluxo contínuo, ideal para aplicações em tempo real:

# Exemplo de Geração em Fluxo Contínuo
# Assumindo que tts_engine e ref_audios já estão definidos como no exemplo anterior

# Para textos mais longos ou aplicações em tempo real
for audio_segment in tts_engine.stream_synthesis("Um texto bem longo para ser transmitido em tempo real.", 
                                                speaker_references=ref_audios,
                                                segment_length_seconds=20):
    # Processar ou reproduzir o segmento de áudio em tempo real
    # Por exemplo: play_sound_segment(audio_segment)
    pass # Substitua por sua lógica de processamento

Geração Reprodutível

O controle por semente garante a reprodutibilidade dos resultados gerados:

# Exemplo de Geração Reprodutível
# from tortoise_tts_lib import SpeechSynthesizer
# tts_engine = SpeechSynthesizer() # Se ainda não instanciado

# Obter um estado de semente para síntese determinística
repro_state = tts_engine.get_reproducible_state(seed_value=42)

# Sintetizar o mesmo texto usando o estado
audio_output_1 = tts_engine.synthesize_audio("Olá", yield_state_info=True, **repro_state)
audio_output_2 = tts_engine.synthesize_audio("Olá", yield_state_info=True, **repro_state)

# 'audio_output_1' e 'audio_output_2' conterão exatamente os mesmos dados de áudio.

Configurações de Otimização de Performance

A classe SpeechSynthesizer disponibiliza diversas opções para otimizar a performance:

Técnica de Otimização Configuração de Parâmetro Benefício Cenário Aplicável
Inferência FP16 fp16_enabled=True Reduz o consumo de memória em 50%. Ambientes com restrição de memória.
Cache de Chave-Valor use_key_value_cache=True Acelera a geração autorregressiva. Geração de textos extensos.
Otimização DeepSpeed deepspeed_optimization=True Otimização para inferência distribuída. Configurações com múltiplas GPUs.
Otimização de Lotes batch_size_ar Maximiza a utilização da GPU. Geração em lote (batch).
# Exemplo de Configuração para Alta Performance
# from tortoise_tts_lib import SpeechSynthesizer # Se ainda não importado

optimized_synthesizer = SpeechSynthesizer(
    deepspeed_optimization=True, 
    use_key_value_cache=True, 
    fp16_enabled=True, 
    batch_size_ar=16
)

Tratamento de Erros e Robustez

A classe SpeechSynthesizer integra mecanismos robustos para o tratamento de erros:

  1. Verificação na Carga do Modelo: Realiza automaticamente a validação da integridade dos arquivos do modelo.
  2. Compatibilidade de Hardware: Assegura suporte para diversos backends de computação, incluindo CUDA, MPS e CPU.
  3. Validação de Entradas: Efetua a checagem da qualidade e da quantidade das amostras de voz fornecidas.
  4. Proteção de Memória: Implementa estratégias de fallback automático para prevenir erros de falta de memória (OOM).

Dessa forma, a classe SpeechSynthesizer proporciona aos desenvolvedores uma interface de programação TTS poderosa e adaptável, que atende tanto a invocações simplificadas via predefinições quanto a cenários de uso avançados e altamente personalizáveis.

Obtenção do Espaço Latente Condicional e Processamento de Amostras de Voz

Uma das capacidades centrais do Tortoise TTS é a síntese de fala com timbre e entonação específicos, baseada em amostras de voz de referência. Este processo depende da aquisição do espaço latente condicional, que codifica as características acústicas das amostras de áudio em representações latentes compactas para guiar a geração da fala.

Carregamento e Pré-processamento de Amostras de Áudio

O Tortoise TTS suporta o carregamento e processamento de múltiplos formatos de áudio, principalmente através da função load_audio_sample:

import os
import torch
import torchaudio
import librosa # Assumindo librosa está disponível para mp3

def load_audio_sample(file_path: str, target_sr: int) -> torch.Tensor:
    """
    Carrega um arquivo de áudio e o pré-processa para uso no Tortoise TTS.
    Suporta formatos WAV e MP3, garantindo o resampling e normalização.
    
    Args:
        file_path: Caminho completo para o arquivo de áudio.
        target_sr: Taxa de amostragem desejada para o áudio de saída.
        
    Returns: Um tensor PyTorch contendo os dados de áudio processados.
    
    Raises:
        AssertionError: Se o formato do arquivo de áudio não for suportado.
    """
    _, ext = os.path.splitext(file_path)
    ext = ext.lower()
    
    audio_data = None
    original_sr = None

    if ext == '.wav':
        audio_data, original_sr = torchaudio.load(file_path)
    elif ext == '.mp3':
        # librosa.load retorna numpy array, precisa converter para tensor
        numpy_audio, original_sr = librosa.load(file_path, sr=target_sr)
        audio_data = torch.FloatTensor(numpy_audio).unsqueeze(0) # Adiciona dimensão de canal/batch
    else:
        assert False, f"Formato de áudio não suportado: {ext}"

    # Reduzir para mono, se necessário (seleciona o primeiro canal)
    if audio_data.ndim > 1:
        if audio_data.shape[0] > 1: # Se tiver mais de 1 canal
             audio_data = audio_data[0] # Seleciona o primeiro canal
        audio_data = audio_data.squeeze(0) # Remove a dimensão de canal se for 1

    # Resampling se a taxa de amostragem original for diferente da alvo
    if original_sr != target_sr:
        audio_data = torchaudio.functional.resample(audio_data, original_sr, target_sr)

    # Normalização e clipping dos valores do áudio para o intervalo [-1, 1]
    if torch.any(audio_data > 1.0) or torch.any(audio_data < -1.0):
        print(f"Aviso: Os valores de áudio em {file_path} excedem o intervalo esperado [-1, 1]. "
              f"Max={audio_data.max():.2f}, Min={audio_data.min():.2f}. Cliping será aplicado.")
        audio_data.clip_(-1.0, 1.0)
    
    return audio_data.unsqueeze(0) # Adiciona uma dimensão de batch

Os passos cruciais executados por esta função incluem:

  • Detecção de formato e carregamento (suporte a WAV e MP3).
  • Processamento multicanal (seleção automática do primeiro canal).
  • Reamostragem da taxa (unificação para a taxa alvo).
  • Normalização do intervalo de áudio (truncagem para [-1, 1]).

Preparação Formato do Condicionamento

As amostras de voz requerem um tratamento de formatação antes de serem inseridas nos modelos, garantindo que seu comprimento e formato atendam aos requisitos do modelo:

import torch.nn.functional as F
import random
# Assumindo TorchMelSpectrogram é importado das partes internas do Tortoise TTS

def prepare_audio_for_conditioning(input_clip: torch.Tensor, target_length_samples: int = 132300, 
                                   computation_device: str = "cuda") -> torch.Tensor:
    """
    Prepara um segmento de áudio para ser usado como entrada condicional,
    ajustando seu comprimento e convertendo-o em um espectrograma MEL.
    
    Args:
        input_clip: O tensor de áudio de entrada.
        target_length_samples: O comprimento alvo em amostras para o segmento de áudio.
        computation_device: O dispositivo (e.g., "cuda", "cpu") para onde mover o tensor.
        
    Returns: Um tensor de espectrograma MEL formatado.
    """
    current_length = input_clip.shape[-1]
    length_diff = current_length - target_length_samples
    
    processed_clip = input_clip
    if length_diff < 0:
        # Preencher com zeros se o clipe for muito curto
        processed_clip = F.pad(processed_clip, (0, abs(length_diff)))
    elif length_diff > 0:
        # Recortar aleatoriamente se o clipe for muito longo
        start_offset = random.randint(0, length_diff)
        processed_clip = processed_clip[:, start_offset:start_offset + target_length_samples]
    
    # Converter para espectrograma MEL
    # TorchMelSpectrogram() é uma classe interna do Tortoise TTS, mantendo o nome funcional
    mel_spectrogram = TorchMelSpectrogram()(processed_clip.unsqueeze(0)).squeeze(0)
    
    return mel_spectrogram.unsqueeze(0).to(computation_device)

Este procedimento assegura que todas as amostras de voz tenham um comprimento consistente e sejam convertidas de um sinal no domínio do tempo para uma representação no domínio da frequência através de um espectrograma Mel.

Extração do Espaço Latente Condicional

O método obtain_speaker_embeddings é o cerne da aquisição do espaço latente condicional:

import torch.nn.functional as F
import random
import torchaudio

# Assumindo que TacotronSTFT, TorchMelSpectrogram, pad_or_truncate,
# e wav_to_univnet_mel são classes/funções internas do Tortoise TTS
# e que a classe SpeechSynthesizer tem atributos como ar_model, diffusion_model,
# mel_stft_processor, target_device, ar_conditioning_len, diffusion_conditioning_len.

class SpeechSynthesizer: # Exemplo de como o método se encaixaria na classe
    def __init__(self, target_device="cuda", ar_conditioning_len=132300, diffusion_conditioning_len=102400):
        self.target_device = torch.device(target_device)
        self.ar_model = None # Deve ser carregado com os pesos do modelo AR
        self.diffusion_model = None # Deve ser carregado com os pesos do modelo Diffusion
        self.mel_stft_processor = None # TacotronSTFT instance
        self.ar_conditioning_len = ar_conditioning_len
        self.diffusion_conditioning_len = diffusion_conditioning_len
        # ... outros atributos

    def obtain_speaker_embeddings(self, audio_clips: list[torch.Tensor], include_intermediate_mels: bool = False) -> tuple:
        """
        Deriva embeddings latentes condicionais (para modelos autorregressivo e de difusão)
        a partir de uma lista de clipes de áudio de referência.
        
        Args:
            audio_clips: Uma lista de tensores de áudio de voz.
            include_intermediate_mels: Se verdadeiro, retorna também os espectrogramas MEL intermediários.
            
        Returns: Uma tupla contendo os embeddings latentes. Se 'include_intermediate_mels' for verdadeiro,
                 inclui também os tensores MEL formatados.
        """
        if self.ar_model is None or self.diffusion_model is None:
            raise RuntimeError("Modelos autorregressivo e/ou de difusão não foram carregados.")

        with torch.no_grad():
            processed_clips_on_device = [clip_tensor.to(self.target_device) for clip_tensor in audio_clips]

            # Processamento para o condicionamento autorregressivo
            ar_conditions_list = []
            for current_clip in processed_clips_on_device:
                # Usando a função reescrita 'prepare_audio_for_conditioning'
                ar_conditions_list.append(prepare_audio_for_conditioning(current_clip, 
                                                                       target_length_samples=self.ar_conditioning_len, 
                                                                       computation_device=self.target_device))
            ar_mel_tensor = torch.stack(ar_conditions_list, dim=1)
            
            # Movendo o modelo para o dispositivo e extraindo o embedding
            self.ar_model = self.ar_model.to(self.target_device)
            ar_latent_embedding = self.ar_model.get_conditioning_features(ar_mel_tensor)
            self.ar_model = self.ar_model.cpu() # Descarrega para CPU para economizar VRAM

            # Processamento para o condicionamento de difusão
            if self.mel_stft_processor is None:
                # Inicializa o processador STFT se ainda não estiver pronto
                self.mel_stft_processor = TacotronSTFT(
                    filter_length=1024, hop_length=256, win_length=1024,
                    n_mel_channels=100, sampling_rate=24000, mel_fmin=0, mel_fmax=12000
                ).to(self.target_device)

            diffusion_conditions_list = []
            for current_clip in processed_clips_on_device:
                # Resampling para a taxa de amostragem do modelo de difusão
                resampled_clip = torchaudio.functional.resample(current_clip, 22050, 24000)
                # pad_or_truncate é uma função utilitária interna, vamos assumir sua existência e reescrever chamadas
                truncated_padded_clip = pad_or_truncate(resampled_clip, self.diffusion_conditioning_len)
                
                # wav_to_univnet_mel é outra função interna, assumindo sua existência
                diff_mel = wav_to_univnet_mel(truncated_padded_clip.to(self.target_device), 
                                              do_normalization=False,
                                              device=self.target_device, stft=self.mel_stft_processor)
                diffusion_conditions_list.append(diff_mel)
            
            diffusion_mel_tensor = torch.stack(diffusion_conditions_list, dim=1)

            # Movendo o modelo de difusão para o dispositivo e extraindo o embedding
            self.diffusion_model = self.diffusion_model.to(self.target_device)
            diffusion_latent_embedding = self.diffusion_model.get_speaker_embedding(diffusion_mel_tensor)
            self.diffusion_model = self.diffusion_model.cpu() # Descarrega para CPU

        if include_intermediate_mels:
            return ar_latent_embedding, diffusion_latent_embedding, ar_mel_tensor, diffusion_mel_tensor
        else:
            return ar_latent_embedding, diffusion_latent_embedding

Fluxo de Processamento de Condicionamento Dual

O Tortoise TTS emprega um mecanismo de condicionamento de caminho duplo, onde cada rota é otimizada para servir, respectivamente, o modelo autorregressivo e o modelo de difusão:

  1. Caminho Autorregressivo: As amostras de áudio são formatadas para uma duração específica (por exemplo, 6 segundos a 22050 Hz) e convertidas em espectrogramas Mel. Estes são então usados pelo modelo autorregressivo para gerar um embedding que captura características de voz de alto nível.
  2. Caminho de Difusão: Separadamente, as amostras de áudio são reamostradas para uma taxa diferente (por exemplo, 24000 Hz) e formatadas para outra duração. Um processador STFT as transforma em espectrogramas Mel específicos para o modelo de difusão, que extrai um embedding mais detalhado e de baixa-nível.

Ferramentas de Gerenciamento de Amostras de Voz

O Tortoise TTS fornece um conjunto completo de ferramentas para gerenciar amostras de voz:

import os
import glob
import torch

# Assumindo que BUILTIN_VOICES_DIRECTORY e load_audio_sample são definidos em outro lugar
# from tortoise_tts_lib import BUILTIN_VOICES_DIRECTORY, load_audio_sample

# Um diretório de exemplo para vozes embutidas
BUILTIN_VOICES_DIRECTORY = os.path.join(os.path.dirname(__file__), "voices", "builtin")

def list_available_speakers(additional_voice_folders: list[str] = None) -> dict[str, list[str]]:
    """
    Lista todos os perfis de voz disponíveis, incluindo os em diretórios adicionais.
    
    Args:
        additional_voice_folders: Uma lista de caminhos para diretórios de voz extras.
        
    Returns: Um dicionário onde as chaves são os nomes dos perfis de voz e os valores são
             listas de caminhos para os arquivos de áudio (.wav, .mp3) ou embeddings (.pth) associados.
    """
    if additional_voice_folders is None:
        additional_voice_folders = []
        
    search_dirs = [BUILTIN_VOICES_DIRECTORY] + additional_voice_folders
    speaker_profiles = {}
    
    for folder_path in search_dirs:
        if not os.path.isdir(folder_path):
            continue
        
        for entry in os.listdir(folder_path):
            full_entry_path = os.path.join(folder_path, entry)
            if os.path.isdir(full_entry_path):
                speaker_name = entry
                # Coleta todos os arquivos de áudio e .pth no diretório do speaker
                audio_files = list(glob.glob(f'{full_entry_path}/*.wav')) + \
                              list(glob.glob(f'{full_entry_path}/*.mp3')) + \
                              list(glob.glob(f'{full_entry_path}/*.pth'))
                
                if audio_files:
                    speaker_profiles[speaker_name] = audio_files
                    
    return speaker_profiles

def retrieve_speaker_data(speaker_id: str, extra_search_paths: list[str] = None) -> tuple[list[torch.Tensor] | None, torch.Tensor | None]:
    """
    Carrega as amostras de áudio de referência ou os embeddings latentes pré-calculados
    para um determinado ID de falante.
    
    Args:
        speaker_id: O identificador do falante a ser carregado.
        extra_search_paths: Caminhos adicionais para procurar perfis de voz.
        
    Returns: Uma tupla contendo (lista de amostras de áudio, tensor de embedding latente).
             Um dos elementos da tupla será None, dependendo do que for carregado.
    """
    if speaker_id == 'random_speaker': 
        return None, None

    all_speakers = list_available_speakers(extra_search_paths)
    if speaker_id not in all_speakers:
        raise ValueError(f"Falante '{speaker_id}' não encontrado nos diretórios configurados.")
        
    file_paths = all_speakers[speaker_id]
    
    # Verifica se há um arquivo .pth (embedding pré-calculado)
    embedding_paths = [p for p in file_paths if p.endswith('.pth')]
    if embedding_paths:
        if len(embedding_paths) == 1:
            return None, torch.load(embedding_paths[0])
        else:
             print(f"Aviso: Múltiplos arquivos .pth encontrados para '{speaker_id}'. Carregando o primeiro: {embedding_paths[0]}")
             return None, torch.load(embedding_paths[0])
    
    # Se não houver .pth, carrega as amostras de áudio
    audio_references = []
    for path in file_paths:
        if not path.endswith('.pth'): 
            audio_references.append(load_audio_sample(path, 22050)) 
            
    if not audio_references:
        raise RuntimeError(f"Nenhuma amostra de áudio ou arquivo .pth encontrado para o falante '{speaker_id}'.")

    print(f"Aviso: Não foi encontrado um arquivo .pth para '{speaker_id}'. Retornando as amostras de áudio diretamente. "
          "Para carregamento mais rápido, considere pré-calcular e salvar os embeddings.")
    
    return audio_references, None

Especificações de Parâmetros Técnicos

A tabela a seguir resume os parâmetros chave no processo de condicionamento:

Parâmetro Técnico Valor Descrição
Taxa de Amostragem AR 22050 Hz Taxa de amostragem esperada para a entrada do modelo autorregressivo.
Duração Condicional AR 132300 amostras Corresponde a aproximadamente 6 segundos de áudio para condicionamento autorregressivo.
Taxa de Amostragem Difusão 24000 Hz Taxa de amostragem para a entrada do modelo de difusão.
Duração Condicional Difusão 102400 amostras Equivalente a cerca de 4.27 segundos de áudio para condicionamento de difusão.
Bandas Mel 80/100 Número de bandas Mel utilizadas no espectrograma para o modelo autorregressivo (variável).

Tags: TortoiseTTS SpeechSynthesis Python API VoiceCloning

Publicado em 6-26 23:21