Wie man das Plugin verwendet
Das Runtime Text To Speech-Plugin synthetisiert Text in Sprache unter Verwendung herunterladbarer Sprachmodelle. Diese Modelle werden in den Plugin-Einstellungen innerhalb des Editors verwaltet, heruntergeladen und für die Runtime-Nutzung verpackt. Folgen Sie den untenstehenden Schritten, um zu beginnen.
Editor-Seite
Laden Sie die passenden Sprachmodelle für Ihr Projekt herunter, wie hier beschrieben. Sie können mehrere Sprachmodelle gleichzeitig herunterladen.
Runtime-Seite
Erstellen Sie den Synthesizer mit der Funktion CreateRuntimeTextToSpeech
. Stellen Sie sicher, dass Sie eine Referenz darauf behalten (z.B. als separate Variable in Blueprints oder UPROPERTY in C++), um zu verhindern, dass er vom Garbage Collector bereinigt wird.
- 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)
Sprachsynthese
Das Plugin bietet zwei Modi für die Text-zu-Sprache-Synthese:
- Reguläre Text-zu-Sprache-Synthese: Synthetisiert den gesamten Text und gibt das vollständige Audio nach Abschluss zurück
- Streaming Text-zu-Sprache-Synthese: Liefert Audio-Chunks während der Generierung, was eine Echtzeitverarbeitung ermöglicht
Jeder Modus unterstützt zwei Methoden zur Auswahl von Sprachmodellen:
- Nach Name: Wählt ein Sprachmodell anhand seines Namens aus (empfohlen für UE 5.4+)
- Per Objekt: Wählt ein Sprachmodell durch direkte Referenz aus (empfohlen für UE 5.3 und älter)
Reguläre Text-zu-Sprache-Synthese
Nach Name
- Blueprint
- C++
Die Funktion Text To Speech (By Name)
ist in Blueprints ab UE 5.4 komfortabler. Sie ermöglicht die Auswahl von Sprachmodellen aus einer Dropdown-Liste der heruntergeladenen Modelle. In UE-Versionen unter 5.3 erscheint diese Dropdown-Liste nicht, daher müssen Sie bei älteren Versionen manuell über das von GetDownloadedVoiceModels
zurückgegebene Array von Sprachmodellen iterieren, um das gewünschte auszuwählen.
In C++ kann die Auswahl von Sprachmodellen aufgrund des Fehlens einer Dropdown-Liste etwas komplexer sein. Sie können die Funktion GetDownloadedVoiceModelNames
verwenden, um die Namen der heruntergeladenen Sprachmodelle abzurufen und das gewünschte auszuwählen. Anschließend können Sie die Funktion TextToSpeechByName
aufrufen, um Text mit dem ausgewählten Sprachmodellnamen zu synthetisieren.
// 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;
}
Nach Objekt
- Blueprint
- C++
Die Funktion Text To Speech (By Object)
funktioniert in allen Versionen von Unreal Engine, zeigt die Sprachmodelle jedoch als Dropdown-Liste von Asset-Referenzen an, was weniger intuitiv ist. Diese Methode eignet sich für UE 5.3 und ältere Versionen oder wenn Ihr Projekt aus irgendeinem Grund eine direkte Referenz auf ein Sprachmodell-Asset benötigt.
Falls Sie die Modelle heruntergeladen haben, aber nicht sehen können, öffnen Sie das Dropdown-Menü Voice Model, klicken Sie auf die Einstellungen (Zahnrad-Symbol) und aktivieren Sie sowohl Show Plugin Content als auch Show Engine Content, um die Modelle sichtbar zu machen.
In C++ kann die Auswahl der Sprachmodelle aufgrund des fehlenden Dropdown-Menüs etwas komplexer sein. Sie können die Funktion GetDownloadedVoiceModelNames
verwenden, um die Namen der heruntergeladenen Sprachmodelle abzurufen und das gewünschte auszuwählen. Anschließend können Sie mit der Funktion GetVoiceModelFromName
das Sprachmodell-Objekt abrufen und es an die Funktion TextToSpeechByObject
übergeben, um Text zu synthetisieren.
// 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;
}
Streaming Text-to-Speech
Für längere Texte oder wenn Sie Audiodaten in Echtzeit verarbeiten möchten, während sie generiert werden, können Sie die Streaming-Versionen der Text-to-Speech-Funktionen verwenden:
Streaming Text To Speech (By Name)
(StreamingTextToSpeechByName
in C++)Streaming Text To Speech (By Object)
(StreamingTextToSpeechByObject
in C++)
Diese Funktionen liefern Audiodaten in Chunks, während sie generiert werden, was eine sofortige Verarbeitung ermöglicht, ohne auf den Abschluss der gesamten Synthese warten zu müssen. Dies ist nützlich für verschiedene Anwendungen wie Echtzeit-Audiowiedergabe, Live-Visualisierung oder jedes Szenario, in dem Sie Sprachdaten inkrementell verarbeiten müssen.
Streaming By Name
- Blueprint
- C++
Die Funktion Streaming Text To Speech (By Name)
funktioniert ähnlich wie die reguläre Version, liefert jedoch Audio in Chunks über den On Speech Chunk
-Delegate.
// 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 Nach Objekt
- Blueprint
- C++
Die Funktion Streaming Text To Speech (By Object)
bietet dieselbe Streaming-Funktionalität, benötigt jedoch eine Referenz auf ein Voice-Model-Objekt.
// 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);
}
})
);
}
Audio-Wiedergabe
- Reguläre Wiedergabe
- Streaming Playback
Für reguläre (nicht-streaming) Text-to-Speech-Synthese liefert der On Speech Result
-Delegate das synthetisierte Audio als PCM-Daten im Float-Format (als Byte-Array in Blueprints oder TArray<uint8>
in C++), zusammen mit der Sample Rate
und Num Of Channels
.
Für die Wiedergabe wird empfohlen, das Runtime Audio Importer-Plugin zu verwenden, um Roh-Audiodaten in eine abspielbare Soundwelle umzuwandeln.
- Blueprint
- C++
Hier ein Beispiel, wie die Blueprint-Nodes für die Text-Synthese und Audio-Wiedergabe aussehen könnten (Kopierbare Nodes):
Hier ein Beispiel, wie Text synthetisiert und das Audio in C++ wiedergegeben werden kann:
// 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;
}
Für Streaming-Text-to-Speech erhalten Sie Audiodaten in Chunks als PCM-Daten im Float-Format (als Byte-Array in Blueprints oder TArray<uint8>
in C++), zusammen mit der Sample Rate
und Num Of Channels
. Jeder Chunk kann sofort verarbeitet werden, sobald er verfügbar ist.
Für Echtzeit-Wiedergabe wird empfohlen, den Runtime Audio Importer-Plugin's Streaming Sound Wave zu verwenden, der speziell für Streaming-Audio-Wiedergabe oder Echtzeit-Verarbeitung entwickelt wurde.
- Blueprint
- C++
Hier ist ein Beispiel, wie die Blueprint-Nodes für Streaming-Text-to-Speech und Wiedergabe der Audio aussehen könnten (Kopierbare Nodes):
Hier ist ein Beispiel, wie Sie Streaming-Text-to-Speech mit Echtzeit-Wiedergabe in C++ implementieren können:
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);
}
})
);
}
}
Text-to-Speech abbrechen
Sie können eine laufende Text-to-Speech-Syntheseoperation jederzeit abbrechen, indem Sie die Funktion CancelSpeechSynthesis
auf Ihrer Synthesizer-Instanz aufrufen:
- 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"));
}
Wenn eine Synthese abgebrochen wird:
- Der Syntheseprozess wird so schnell wie möglich gestoppt
- Alle laufenden Callbacks werden beendet
- Der Abschluss-Delegate wird mit
bSuccess = false
und einer Fehlermeldung aufgerufen, die anzeigt, dass die Synthese abgebrochen wurde - Alle für die Synthese zugewiesenen Ressourcen werden ordnungsgemäß bereinigt
Dies ist besonders nützlich für lange Texte oder wenn Sie die Wiedergabe unterbrechen müssen, um eine neue Synthese zu starten.
Sprecherauswahl
Beide Text-To-Speech-Funktionen akzeptieren einen optionalen Sprecher-ID-Parameter, was nützlich ist, wenn Sie mit Sprachmodellen arbeiten, die mehrere Sprecher unterstützen. Sie können die Funktionen GetSpeakerCountFromVoiceModel oder GetSpeakerCountFromModelName verwenden, um zu überprüfen, ob Ihr gewähltes Sprachmodell mehrere Sprecher unterstützt. Falls mehrere Sprecher verfügbar sind, geben Sie einfach die gewünschte Sprecher-ID beim Aufruf der Text-To-Speech-Funktionen an. Einige Sprachmodelle bieten eine große Auswahl – beispielsweise enthält English LibriTTS über 900 verschiedene Sprecher zur Auswahl.
Das Runtime Audio Importer-Plugin bietet zusätzliche Funktionen wie das Exportieren von Audiodaten in eine Datei, das Übergeben an SoundCue, MetaSound und mehr. Weitere Details finden Sie in der Runtime Audio Importer-Dokumentation.