Comment utiliser le plugin
Le plugin Runtime Text To Speech synthétise du texte en parole en utilisant des modèles vocaux téléchargeables. Ces modèles sont gérés dans les paramètres du plugin dans l'éditeur, téléchargés et empaquetés pour une utilisation à l'exécution. Suivez les étapes ci-dessous pour commencer.
Côté éditeur
Téléchargez les modèles vocaux appropriés pour votre projet comme décrit ici. Vous pouvez télécharger plusieurs modèles vocaux simultanément.
Côté runtime
Créez le synthétiseur en utilisant la fonction CreateRuntimeTextToSpeech
. Assurez-vous de maintenir une référence à celui-ci (par exemple comme une variable séparée dans Blueprints ou une UPROPERTY en C++) pour éviter qu'il ne soit collecté par le garbage collector.
- Blueprint
- C++
// Create the Runtime Text To Speech synthesizer in C++
URuntimeTextToSpeech* Synthesizer = URuntimeTextToSpeech::CreateRuntimeTextToSpeech();
// Ensure the synthesizer is referenced correctly to prevent garbage collection (e.g. as a UPROPERTY)
Synthèse de la parole
Le plugin propose deux modes de synthèse vocale :
- Synthèse vocale standard : Synthétise l'intégralité du texte et renvoie l'audio complet une fois terminé
- Synthèse vocale en streaming : Fournit des segments audio au fur et à mesure de leur génération, permettant un traitement en temps réel
Chaque mode prend en charge deux méthodes pour sélectionner les modèles vocaux :
- Par nom : Sélectionne un modèle vocal par son nom (recommandé pour UE 5.4+)
- Par objet : Sélectionne un modèle vocal par référence directe (recommandé pour UE 5.3 et versions antérieures)
Synthèse vocale standard
Par nom
- Blueprint
- C++
La fonction Text To Speech (By Name)
est plus pratique dans les Blueprints à partir de UE 5.4. Elle permet de sélectionner les modèles vocaux dans une liste déroulante des modèles téléchargés. Dans les versions UE inférieures à 5.3, cette liste déroulante n'apparaît pas, donc si vous utilisez une version plus ancienne, vous devrez parcourir manuellement le tableau des modèles vocaux renvoyé par GetDownloadedVoiceModels
pour sélectionner celui dont vous avez besoin.
En C++, la sélection des modèles vocaux peut être légèrement plus complexe en raison de l'absence de liste déroulante. Vous pouvez utiliser la fonction GetDownloadedVoiceModelNames
pour récupérer les noms des modèles vocaux téléchargés et sélectionner celui dont vous avez besoin. Ensuite, vous pouvez appeler la fonction TextToSpeechByName
pour synthétiser du texte en utilisant le nom du modèle vocal sélectionné.
// Assuming "Synthesizer" is a valid and referenced URuntimeTextToSpeech object (ensure it is not eligible for garbage collection during the callback)
TArray<FName> DownloadedVoiceNames = URuntimeTTSLibrary::GetDownloadedVoiceModelNames();
// If there are downloaded voice models, use the first one to synthesize text, just as an example
if (DownloadedVoiceNames.Num() > 0)
{
const FName& VoiceName = DownloadedVoiceNames[0]; // Select the first available voice model
Synthesizer->TextToSpeechByName(VoiceName, 0, TEXT("Text example 123"), FOnTTSResultDelegateFast::CreateLambda([](URuntimeTextToSpeech* TextToSpeechInstance, bool bSuccess, const TArray<uint8>& AudioData, int32 SampleRate, int32 NumChannels)
{
UE_LOG(LogTemp, Log, TEXT("TextToSpeech result: %s, AudioData size: %d, SampleRate: %d, NumChannels: %d"), bSuccess ? TEXT("Success") : TEXT("Failed"), AudioData.Num(), SampleRate, NumChannels);
}));
return;
}
Par Objet
- Blueprint
- C++
La fonction Text To Speech (By Object)
fonctionne sur toutes les versions d'Unreal Engine mais présente les modèles vocaux sous forme de liste déroulante de références d'assets, ce qui est moins intuitif. Cette méthode est adaptée pour UE 5.3 et versions antérieures, ou si votre projet nécessite une référence directe à un asset de modèle vocal pour une raison quelconque.
Si vous avez téléchargé les modèles mais ne les voyez pas, ouvrez le menu déroulant Voice Model, cliquez sur les paramètres (icône d'engrenage), et activez à la fois Show Plugin Content et Show Engine Content pour rendre les modèles visibles.
En C++, la sélection des modèles vocaux peut être légèrement plus complexe en raison de l'absence de liste déroulante. Vous pouvez utiliser la fonction GetDownloadedVoiceModelNames
pour récupérer les noms des modèles vocaux téléchargés et sélectionner celui dont vous avez besoin. Ensuite, vous pouvez appeler la fonction GetVoiceModelFromName
pour obtenir l'objet du modèle vocal et le passer à la fonction TextToSpeechByObject
pour synthétiser le texte.
// Assuming "Synthesizer" is a valid and referenced URuntimeTextToSpeech object (ensure it is not eligible for garbage collection during the callback)
TArray<FName> DownloadedVoiceNames = URuntimeTTSLibrary::GetDownloadedVoiceModelNames();
// If there are downloaded voice models, use the first one to synthesize text, for example
if (DownloadedVoiceNames.Num() > 0)
{
const FName& VoiceName = DownloadedVoiceNames[0]; // Select the first available voice model
TSoftObjectPtr<URuntimeTTSModel> VoiceModel;
if (!URuntimeTTSLibrary::GetVoiceModelFromName(VoiceName, VoiceModel))
{
UE_LOG(LogTemp, Error, TEXT("Failed to get voice model from name: %s"), *VoiceName.ToString());
return;
}
Synthesizer->TextToSpeechByObject(VoiceModel, 0, TEXT("Text example 123"), FOnTTSResultDelegateFast::CreateLambda([](URuntimeTextToSpeech* TextToSpeechInstance, bool bSuccess, const TArray<uint8>& AudioData, int32 SampleRate, int32 NumChannels)
{
UE_LOG(LogTemp, Log, TEXT("TextToSpeech result: %s, AudioData size: %d, SampleRate: %d, NumChannels: %d"), bSuccess ? TEXT("Success") : TEXT("Failed"), AudioData.Num(), SampleRate, NumChannels);
}));
return;
}
Synthèse vocale en streaming
Pour les textes longs ou lorsque vous souhaitez traiter les données audio en temps réel au fur et à mesure de leur génération, vous pouvez utiliser les versions streaming des fonctions de synthèse vocale :
Streaming Text To Speech (By Name)
(StreamingTextToSpeechByName
en C++)Streaming Text To Speech (By Object)
(StreamingTextToSpeechByObject
en C++)
Ces fonctions fournissent les données audio par morceaux au fur et à mesure de leur génération, permettant un traitement immédiat sans attendre la fin complète de la synthèse. Ceci est utile pour diverses applications comme la lecture audio en temps réel, la visualisation live, ou tout scénario nécessitant un traitement incrémental des données vocales.
Streaming par nom
- Blueprint
- C++
La fonction Streaming Text To Speech (By Name)
fonctionne de manière similaire à la version standard mais fournit l'audio par morceaux via le délégué On Speech Chunk
.
// Assuming "Synthesizer" is a valid and referenced URuntimeTextToSpeech object
TArray<FName> DownloadedVoiceNames = URuntimeTTSLibrary::GetDownloadedVoiceModelNames();
if (DownloadedVoiceNames.Num() > 0)
{
const FName& VoiceName = DownloadedVoiceNames[0]; // Select the first available voice model
Synthesizer->StreamingTextToSpeechByName(
VoiceName,
0,
TEXT("This is a long text that will be synthesized in chunks."),
FOnTTSStreamingChunkDelegateFast::CreateLambda([](URuntimeTextToSpeech* TextToSpeechInstance, const TArray<uint8>& ChunkAudioData, int32 SampleRate, int32 NumOfChannels, bool bIsFinalChunk)
{
// Process each chunk of audio data as it becomes available
UE_LOG(LogTemp, Log, TEXT("Received chunk %d with %d bytes of audio data. Sample rate: %d, Channels: %d, Is Final: %s"),
ChunkIndex, ChunkAudioData.Num(), SampleRate, NumOfChannels, bIsFinalChunk ? TEXT("Yes") : TEXT("No"));
// You can start processing/playing this chunk immediately
}),
FOnTTSStreamingCompleteDelegateFast::CreateLambda([](URuntimeTextToSpeech* TextToSpeechInstance, bool bSuccess, const FString& ErrorMessage)
{
// Called when the entire synthesis is complete or if it fails
if (bSuccess)
{
UE_LOG(LogTemp, Log, TEXT("Streaming synthesis completed successfully"));
}
else
{
UE_LOG(LogTemp, Error, TEXT("Streaming synthesis failed: %s"), *ErrorMessage);
}
})
);
}
Streaming Par Objet
- Blueprint
- C++
La fonction Streaming Text To Speech (By Object)
offre les mêmes capacités de streaming mais prend une référence d'objet de modèle vocal.
// Assuming "Synthesizer" is a valid and referenced URuntimeTextToSpeech object
TArray<FName> DownloadedVoiceNames = URuntimeTTSLibrary::GetDownloadedVoiceModelNames();
if (DownloadedVoiceNames.Num() > 0)
{
const FName& VoiceName = DownloadedVoiceNames[0]; // Select the first available voice model
TSoftObjectPtr<URuntimeTTSModel> VoiceModel;
if (!URuntimeTTSLibrary::GetVoiceModelFromName(VoiceName, VoiceModel))
{
UE_LOG(LogTemp, Error, TEXT("Failed to get voice model from name: %s"), *VoiceName.ToString());
return;
}
Synthesizer->StreamingTextToSpeechByObject(
VoiceModel,
0,
TEXT("This is a long text that will be synthesized in chunks."),
FOnTTSStreamingChunkDelegateFast::CreateLambda([](URuntimeTextToSpeech* TextToSpeechInstance, const TArray<uint8>& ChunkAudioData, int32 SampleRate, int32 NumOfChannels, bool bIsFinalChunk)
{
// Process each chunk of audio data as it becomes available
UE_LOG(LogTemp, Log, TEXT("Received chunk %d with %d bytes of audio data. Sample rate: %d, Channels: %d, Is Final: %s"),
ChunkIndex, ChunkAudioData.Num(), SampleRate, NumOfChannels, bIsFinalChunk ? TEXT("Yes") : TEXT("No"));
// You can start processing/playing this chunk immediately
}),
FOnTTSStreamingCompleteDelegateFast::CreateLambda([](URuntimeTextToSpeech* TextToSpeechInstance, bool bSuccess, const FString& ErrorMessage)
{
// Called when the entire synthesis is complete or if it fails
if (bSuccess)
{
UE_LOG(LogTemp, Log, TEXT("Streaming synthesis completed successfully"));
}
else
{
UE_LOG(LogTemp, Error, TEXT("Streaming synthesis failed: %s"), *ErrorMessage);
}
})
);
}
Lecture audio
- Lecture standard
- Streaming Playback
Pour la synthèse vocale standard (non-streaming), le délégué On Speech Result
fournit l'audio synthétisé sous forme de données PCM en format float (sous forme de tableau d'octets dans Blueprints ou TArray<uint8>
en C++), ainsi que le Sample Rate
et Num Of Channels
.
Pour la lecture, il est recommandé d'utiliser le plugin Runtime Audio Importer pour convertir les données audio brutes en une onde sonore jouable.
- Blueprint
- C++
Voici un exemple de ce à quoi pourraient ressembler les nœuds Blueprint pour synthétiser du texte et lire l'audio (Nœuds copiables) :
Voici un exemple de comment synthétiser du texte et lire l'audio en C++ :
// Assuming "Synthesizer" is a valid and referenced URuntimeTextToSpeech object (ensure it is not eligible for garbage collection during the callback)
// Ensure "this" is a valid and referenced UObject (must not be eligible for garbage collection during the callback)
TArray<FName> DownloadedVoiceNames = URuntimeTTSLibrary::GetDownloadedVoiceModelNames();
// If there are downloaded voice models, use the first one to synthesize text, for example
if (DownloadedVoiceNames.Num() > 0)
{
const FName& VoiceName = DownloadedVoiceNames[0]; // Select the first available voice model
Synthesizer->TextToSpeechByName(VoiceName, 0, TEXT("Text example 123"), FOnTTSResultDelegateFast::CreateLambda([this](URuntimeTextToSpeech* TextToSpeechInstance, bool bSuccess, const TArray<uint8>& AudioData, int32 SampleRate, int32 NumOfChannels)
{
if (!bSuccess)
{
UE_LOG(LogTemp, Error, TEXT("TextToSpeech failed"));
return;
}
// Create the Runtime Audio Importer to process the audio data
URuntimeAudioImporterLibrary* RuntimeAudioImporter = URuntimeAudioImporterLibrary::CreateRuntimeAudioImporter();
// Prevent the RuntimeAudioImporter from being garbage collected by adding it to the root (you can also use a UPROPERTY, TStrongObjectPtr, etc.)
RuntimeAudioImporter->AddToRoot();
RuntimeAudioImporter->OnResultNative.AddWeakLambda(RuntimeAudioImporter, [this](URuntimeAudioImporterLibrary* Importer, UImportedSoundWave* ImportedSoundWave, ERuntimeImportStatus Status)
{
// Once done, remove it from the root to allow garbage collection
Importer->RemoveFromRoot();
if (Status != ERuntimeImportStatus::SuccessfulImport)
{
UE_LOG(LogTemp, Error, TEXT("Failed to import audio, status: %s"), *UEnum::GetValueAsString(Status));
return;
}
// Play the imported sound wave (ensure a reference is kept to prevent garbage collection)
UGameplayStatics::PlaySound2D(GetWorld(), ImportedSoundWave);
});
RuntimeAudioImporter->ImportAudioFromRAWBuffer(AudioData, ERuntimeRAWAudioFormat::Float32, SampleRate, NumOfChannels);
}));
return;
}
Pour la synthèse vocale en streaming, vous recevrez les données audio par morceaux sous forme de données PCM au format float (sous forme de tableau d'octets dans Blueprints ou TArray<uint8>
en C++), accompagnées du Sample Rate
et du Num Of Channels
. Chaque morceau peut être traité immédiatement dès qu'il est disponible.
Pour une lecture en temps réel, il est recommandé d'utiliser le plugin Runtime Audio Importer avec son Streaming Sound Wave, spécialement conçu pour la lecture audio en streaming ou le traitement en temps réel.
- Blueprint
- C++
Voici un exemple de ce à quoi pourraient ressembler les nœuds Blueprint pour la synthèse vocale en streaming et la lecture audio (Nœuds copiables):
Voici un exemple de mise en œuvre de la synthèse vocale en streaming avec lecture en temps réel en C++:
UPROPERTY()
URuntimeTextToSpeech* Synthesizer;
UPROPERTY()
UStreamingSoundWave* StreamingSoundWave;
UPROPERTY()
bool bIsPlaying = false;
void StartStreamingTTS()
{
// Create synthesizer if not already created
if (!Synthesizer)
{
Synthesizer = URuntimeTextToSpeech::CreateRuntimeTextToSpeech();
}
// Create a sound wave for streaming if not already created
if (!StreamingSoundWave)
{
StreamingSoundWave = UStreamingSoundWave::CreateStreamingSoundWave();
StreamingSoundWave->OnPopulateAudioStateNative.AddWeakLambda(this, [this]()
{
if (!bIsPlaying)
{
bIsPlaying = true;
UGameplayStatics::PlaySound2D(GetWorld(), StreamingSoundWave);
}
});
}
TArray<FName> DownloadedVoiceNames = URuntimeTTSLibrary::GetDownloadedVoiceModelNames();
// If there are downloaded voice models, use the first one to synthesize text, for example
if (DownloadedVoiceNames.Num() > 0)
{
const FName& VoiceName = DownloadedVoiceNames[0]; // Select the first available voice model
Synthesizer->StreamingTextToSpeechByName(
VoiceName,
0,
TEXT("Streaming synthesis output begins with a steady flow of data. This data is processed in real-time to ensure consistency. As the process continues, information is streamed without interruption. The output adapts seamlessly to changing inputs. Each piece of data is instantly integrated into the stream. Real-time processing allows for immediate adjustments. This constant flow ensures that the synthesis output is dynamic. As new data comes in, the output evolves accordingly. The system is designed to maintain a continuous output stream. This uninterrupted flow is what drives the efficiency of streaming synthesis."),
FOnTTSStreamingChunkDelegateFast::CreateWeakLambda(this, [this](URuntimeTextToSpeech* TextToSpeechInstance, const TArray<uint8>& ChunkAudioData, int32 SampleRate, int32 NumOfChannels, bool bIsFinalChunk)
{
StreamingSoundWave->AppendAudioDataFromRAW(ChunkAudioData, ERuntimeRAWAudioFormat::Float32, SampleRate, NumOfChannels);
}),
FOnTTSStreamingCompleteDelegateFast::CreateWeakLambda(this, [this](URuntimeTextToSpeech* TextToSpeechInstance, bool bSuccess, const FString& ErrorMessage)
{
if (bSuccess)
{
UE_LOG(LogTemp, Log, TEXT("Streaming text-to-speech synthesis is complete"));
}
else
{
UE_LOG(LogTemp, Error, TEXT("Streaming synthesis failed: %s"), *ErrorMessage);
}
})
);
}
}
Annulation de la synthèse vocale
Vous pouvez annuler une opération de synthèse vocale en cours à tout moment en appelant la fonction CancelSpeechSynthesis
sur votre instance de synthétiseur :
- Blueprint
- C++
// Assuming "Synthesizer" is a valid URuntimeTextToSpeech instance
// Start a long synthesis operation
Synthesizer->TextToSpeechByName(VoiceName, 0, TEXT("Very long text..."), ...);
// Later, if you need to cancel it:
bool bWasCancelled = Synthesizer->CancelSpeechSynthesis();
if (bWasCancelled)
{
UE_LOG(LogTemp, Log, TEXT("Successfully cancelled ongoing synthesis"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("No synthesis was in progress to cancel"));
}
Lorsqu'une synthèse est annulée :
- Le processus de synthèse s'arrêtera dès que possible
- Tous les callbacks en cours seront interrompus
- Le délégué de complétion sera appelé avec
bSuccess = false
et un message d'erreur indiquant que la synthèse a été annulée - Toutes les ressources allouées pour la synthèse seront correctement nettoyées
Ceci est particulièrement utile pour les textes longs ou lorsque vous devez interrompre la lecture pour démarrer une nouvelle synthèse.
Sélection du Speaker
Les deux fonctions Text To Speech acceptent un paramètre optionnel d'ID de speaker, ce qui est utile lorsque vous travaillez avec des modèles vocaux prenant en charge plusieurs speakers. Vous pouvez utiliser les fonctions GetSpeakerCountFromVoiceModel ou GetSpeakerCountFromModelName pour vérifier si plusieurs speakers sont supportés par votre modèle vocal choisi. Si plusieurs speakers sont disponibles, spécifiez simplement l'ID du speaker souhaité lors de l'appel des fonctions Text To Speech. Certains modèles vocaux offrent une grande variété - par exemple, English LibriTTS inclut plus de 900 speakers différents parmi lesquels choisir.
Le plugin Runtime Audio Importer propose également des fonctionnalités supplémentaires comme l'export des données audio vers un fichier, leur passage à SoundCue, MetaSound, et plus encore. Pour plus de détails, consultez la documentation Runtime Audio Importer.