diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp index b2499c9..83101ae 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp @@ -96,6 +96,42 @@ namespace HyperTwistContractLibraryInternal return Profile; } + FHyperTwistNarrationOrchestrationProfile MakeLocalNarrationOrchestrationProfile() + { + FHyperTwistNarrationOrchestrationProfile Profile; + Profile.OrchestrationProfileId = TEXT("local-basic-narration-v1"); + Profile.ServiceLaneId = TEXT("voice/local-sidecar"); + Profile.ModelBindingId = TEXT("voice-model/local-offline-medium-v1"); + Profile.VocoderBindingId = TEXT("vocoder/default-mono-v1"); + Profile.DefaultSpeakerProfileId = TEXT("speaker/default"); + Profile.bEnableSpeakerSelection = false; + Profile.bEnableLanguageRouting = false; + Profile.bEnableSentenceSplitting = false; + Profile.bEnableSpeakerReferenceConditioning = false; + Profile.bSupportsMultiSpeaker = false; + Profile.bSupportsMultiLingual = false; + Profile.bPreferGpu = false; + return Profile; + } + + FHyperTwistNarrationOrchestrationProfile MakeAdvancedNarrationOrchestrationProfile() + { + FHyperTwistNarrationOrchestrationProfile Profile; + Profile.OrchestrationProfileId = TEXT("python-multispeaker-narration-v1"); + Profile.ServiceLaneId = TEXT("voice/python-service"); + Profile.ModelBindingId = TEXT("voice-model/multilingual-premium-v1"); + Profile.VocoderBindingId = TEXT("vocoder/high-fidelity-v1"); + Profile.DefaultSpeakerProfileId = TEXT("speaker/companion-guide"); + Profile.bEnableSpeakerSelection = true; + Profile.bEnableLanguageRouting = true; + Profile.bEnableSentenceSplitting = true; + Profile.bEnableSpeakerReferenceConditioning = true; + Profile.bSupportsMultiSpeaker = true; + Profile.bSupportsMultiLingual = true; + Profile.bPreferGpu = true; + return Profile; + } + FHyperTwistTrainingSourceAttribution MakeMethodDrillCleanRoomAttribution() { FHyperTwistTrainingSourceAttribution Attribution; @@ -826,6 +862,18 @@ TArray UHyperTwistContractLibrary::MakeSampleVoi 1, TEXT("de/de_DE/thorsten/medium/MODEL_CARD"), {TEXT("de-de-thorsten")} + ), + HyperTwistContractLibraryInternal::MakeVoiceProfile( + TEXT("multilingual-guide-premium"), + TEXT("Companion Guide"), + TEXT("mul"), + TEXT("mul"), + TEXT("INTL"), + TEXT("Multilingual"), + TEXT("premium"), + 32, + TEXT("mul/intl/companion-guide/premium/MODEL_CARD"), + {TEXT("xtts-guide"), TEXT("companion-guide")} ) }; } @@ -839,18 +887,46 @@ FHyperTwistNarrationSynthesisRequest UHyperTwistContractLibrary::MakeSampleNarra Request.OutputRouteId = TEXT("companion/narration/local"); Request.VoiceProfileId = TEXT("en_US-lessac-medium"); Request.LanguageCode = TEXT("en_US"); + Request.OrchestrationProfile = HyperTwistContractLibraryInternal::MakeLocalNarrationOrchestrationProfile(); Request.ScriptText = TEXT("Good work. Keep your eyes on the next pair."); Request.SubtitleSeedText = Request.ScriptText; Request.SpeakerId = 0; + Request.SpeakerProfileId = TEXT("speaker/default"); Request.LengthScale = 1.0f; Request.NoiseScale = 0.667f; Request.NoiseW = 0.8f; Request.SentenceSilenceSeconds = 0.2f; + Request.bSplitSentences = false; Request.bPreferCuda = false; Request.AudioEncodingHint = TEXT("wav-pcm16-mono"); return Request; } +FHyperTwistNarrationSynthesisRequest UHyperTwistContractLibrary::MakeSampleAdvancedNarrationSynthesisRequest() +{ + FHyperTwistNarrationSynthesisRequest Request; + Request.RequestId = TEXT("narration_advanced_01"); + Request.NarrationContractId = TEXT("embodied-companion-narration"); + Request.ServiceLaneId = TEXT("voice/python-service"); + Request.OutputRouteId = TEXT("companion/narration/local"); + Request.VoiceProfileId = TEXT("multilingual-guide-premium"); + Request.LanguageCode = TEXT("fr_FR"); + Request.OrchestrationProfile = HyperTwistContractLibraryInternal::MakeAdvancedNarrationOrchestrationProfile(); + Request.ScriptText = TEXT("Bien joue. Garde les coins alignes pour le prochain exercice."); + Request.SubtitleSeedText = Request.ScriptText; + Request.SpeakerId = 7; + Request.SpeakerProfileId = TEXT("speaker/companion-guide"); + Request.ReferenceVoiceSampleRef = TEXT("mock://voice/companion-guide/reference"); + Request.LengthScale = 0.95f; + Request.NoiseScale = 0.5f; + Request.NoiseW = 0.7f; + Request.SentenceSilenceSeconds = 0.12f; + Request.bSplitSentences = true; + Request.bPreferCuda = true; + Request.AudioEncodingHint = TEXT("wav-pcm16-mono"); + return Request; +} + FHyperTwistNarrationSynthesisResult UHyperTwistContractLibrary::MakeMockNarrationSynthesisResult() { const FHyperTwistNarrationSynthesisRequest Request = MakeSampleNarrationSynthesisRequest(); @@ -862,6 +938,12 @@ FHyperTwistNarrationSynthesisResult UHyperTwistContractLibrary::MakeMockNarratio Result.OutputRouteId = Request.OutputRouteId; Result.VoiceProfileId = Request.VoiceProfileId; Result.LanguageCode = Request.LanguageCode; + Result.OrchestrationProfileId = Request.OrchestrationProfile.OrchestrationProfileId; + Result.ModelBindingId = Request.OrchestrationProfile.ModelBindingId; + Result.VocoderBindingId = Request.OrchestrationProfile.VocoderBindingId; + Result.SpeakerProfileId = Request.SpeakerProfileId.IsEmpty() + ? Request.OrchestrationProfile.DefaultSpeakerProfileId + : Request.SpeakerProfileId; Result.SubtitleText = Request.SubtitleSeedText; Result.AudioEncoding = TEXT("wav-pcm16-mono"); Result.SampleRateHz = 16000; @@ -871,6 +953,11 @@ FHyperTwistNarrationSynthesisResult UHyperTwistContractLibrary::MakeMockNarratio Result.AppliedNoiseScale = Request.NoiseScale; Result.AppliedNoiseW = Request.NoiseW; Result.AppliedSentenceSilenceSeconds = Request.SentenceSilenceSeconds; + Result.bUsedSentenceSplitting = Request.bSplitSentences || Request.OrchestrationProfile.bEnableSentenceSplitting; + Result.bUsedSpeakerSelection = + Request.OrchestrationProfile.bEnableSpeakerSelection && !Result.SpeakerProfileId.IsEmpty(); + Result.bUsedSpeakerReferenceConditioning = + Request.OrchestrationProfile.bEnableSpeakerReferenceConditioning && !Request.ReferenceVoiceSampleRef.IsEmpty(); Result.AudioBytes = HyperTwistContractLibraryInternal::MakeSilentMonoPcm16Wav( Result.SampleRateHz, Result.DurationMs @@ -889,7 +976,13 @@ FHyperTwistVoiceServiceHealth UHyperTwistContractLibrary::MakeMockVoiceServiceHe TEXT("offlineNarration"), TEXT("wavOutput"), TEXT("subtitleSeed"), - TEXT("localProfileCatalog") + TEXT("localProfileCatalog"), + TEXT("multiSpeakerNarration"), + TEXT("multiLingualNarration"), + TEXT("speakerReferenceConditioning"), + TEXT("sentenceSplitNarration"), + TEXT("modelBindingSelection"), + TEXT("vocoderBindingSelection") }; for (const FHyperTwistVoiceProfileSummary& Profile : MakeSampleVoiceProfiles()) @@ -897,6 +990,19 @@ FHyperTwistVoiceServiceHealth UHyperTwistContractLibrary::MakeMockVoiceServiceHe Health.SupportedVoiceProfileIds.Add(Profile.VoiceProfileId); } + Health.SupportedOrchestrationProfiles = { + TEXT("local-basic-narration-v1"), + TEXT("python-multispeaker-narration-v1") + }; + Health.SupportedModelBindingIds = { + TEXT("voice-model/local-offline-medium-v1"), + TEXT("voice-model/multilingual-premium-v1") + }; + Health.SupportedVocoderBindingIds = { + TEXT("vocoder/default-mono-v1"), + TEXT("vocoder/high-fidelity-v1") + }; + Health.bReady = true; return Health; } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistRecognition/HyperTwistHttpVoiceClient.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistRecognition/HyperTwistHttpVoiceClient.cpp index a2d6057..0475c35 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistRecognition/HyperTwistHttpVoiceClient.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistRecognition/HyperTwistHttpVoiceClient.cpp @@ -309,12 +309,23 @@ FHyperTwistNarrationSynthesisResult UHyperTwistHttpVoiceClient::SynthesizeNarrat Result.OutputRouteId = Request.OutputRouteId; Result.VoiceProfileId = Request.VoiceProfileId; Result.LanguageCode = Request.LanguageCode; + Result.OrchestrationProfileId = Request.OrchestrationProfile.OrchestrationProfileId; + Result.ModelBindingId = Request.OrchestrationProfile.ModelBindingId; + Result.VocoderBindingId = Request.OrchestrationProfile.VocoderBindingId; + Result.SpeakerProfileId = Request.SpeakerProfileId.IsEmpty() + ? Request.OrchestrationProfile.DefaultSpeakerProfileId + : Request.SpeakerProfileId; Result.SubtitleText = Request.SubtitleSeedText.IsEmpty() ? Request.ScriptText : Request.SubtitleSeedText; Result.AudioEncoding = TEXT("wav-pcm16-mono"); Result.AppliedLengthScale = Request.LengthScale; Result.AppliedNoiseScale = Request.NoiseScale; Result.AppliedNoiseW = Request.NoiseW; Result.AppliedSentenceSilenceSeconds = Request.SentenceSilenceSeconds; + Result.bUsedSentenceSplitting = Request.bSplitSentences || Request.OrchestrationProfile.bEnableSentenceSplitting; + Result.bUsedSpeakerSelection = + Request.OrchestrationProfile.bEnableSpeakerSelection && !Result.SpeakerProfileId.IsEmpty(); + Result.bUsedSpeakerReferenceConditioning = + Request.OrchestrationProfile.bEnableSpeakerReferenceConditioning && !Request.ReferenceVoiceSampleRef.IsEmpty(); if (!Request.IsStructurallyValid()) { @@ -379,7 +390,13 @@ FHyperTwistVoiceServiceHealth UHyperTwistHttpVoiceClient::GetVoiceServiceHealth( TEXT("voiceCatalog"), TEXT("offlineNarration"), TEXT("wavOutput"), - TEXT("subtitleSeed") + TEXT("subtitleSeed"), + TEXT("multiSpeakerNarration"), + TEXT("multiLingualNarration"), + TEXT("speakerReferenceConditioning"), + TEXT("sentenceSplitNarration"), + TEXT("modelBindingSelection"), + TEXT("vocoderBindingSelection") }; Health.bReady = false; @@ -412,7 +429,25 @@ FHyperTwistVoiceServiceHealth UHyperTwistHttpVoiceClient::GetVoiceServiceHealth( TEXT("voiceCatalog"), TEXT("offlineNarration"), TEXT("wavOutput"), - TEXT("subtitleSeed") + TEXT("subtitleSeed"), + TEXT("multiSpeakerNarration"), + TEXT("multiLingualNarration"), + TEXT("speakerReferenceConditioning"), + TEXT("sentenceSplitNarration"), + TEXT("modelBindingSelection"), + TEXT("vocoderBindingSelection") + }; + Health.SupportedOrchestrationProfiles = { + TEXT("local-basic-narration-v1"), + TEXT("python-multispeaker-narration-v1") + }; + Health.SupportedModelBindingIds = { + TEXT("voice-model/local-offline-medium-v1"), + TEXT("voice-model/multilingual-premium-v1") + }; + Health.SupportedVocoderBindingIds = { + TEXT("vocoder/default-mono-v1"), + TEXT("vocoder/high-fidelity-v1") }; Health.bReady = false; Health.LastError = LastTransportError; @@ -434,6 +469,18 @@ FHyperTwistVoiceServiceHealth UHyperTwistHttpVoiceClient::GetVoiceServiceHealth( Health.Capabilities.AddUnique(TEXT("offlineNarration")); Health.Capabilities.AddUnique(TEXT("wavOutput")); Health.Capabilities.AddUnique(TEXT("subtitleSeed")); + Health.Capabilities.AddUnique(TEXT("multiSpeakerNarration")); + Health.Capabilities.AddUnique(TEXT("multiLingualNarration")); + Health.Capabilities.AddUnique(TEXT("speakerReferenceConditioning")); + Health.Capabilities.AddUnique(TEXT("sentenceSplitNarration")); + Health.Capabilities.AddUnique(TEXT("modelBindingSelection")); + Health.Capabilities.AddUnique(TEXT("vocoderBindingSelection")); + Health.SupportedOrchestrationProfiles.AddUnique(TEXT("local-basic-narration-v1")); + Health.SupportedOrchestrationProfiles.AddUnique(TEXT("python-multispeaker-narration-v1")); + Health.SupportedModelBindingIds.AddUnique(TEXT("voice-model/local-offline-medium-v1")); + Health.SupportedModelBindingIds.AddUnique(TEXT("voice-model/multilingual-premium-v1")); + Health.SupportedVocoderBindingIds.AddUnique(TEXT("vocoder/default-mono-v1")); + Health.SupportedVocoderBindingIds.AddUnique(TEXT("vocoder/high-fidelity-v1")); LastTransportError.Reset(); Health.LastError.Reset(); return Health; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistRecognition/HyperTwistMockVoiceClient.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistRecognition/HyperTwistMockVoiceClient.cpp index 1bbbbda..b5f437c 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistRecognition/HyperTwistMockVoiceClient.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistRecognition/HyperTwistMockVoiceClient.cpp @@ -18,11 +18,22 @@ FHyperTwistNarrationSynthesisResult UHyperTwistMockVoiceClient::SynthesizeNarrat Result.OutputRouteId = Request.OutputRouteId; Result.VoiceProfileId = Request.VoiceProfileId; Result.LanguageCode = Request.LanguageCode; + Result.OrchestrationProfileId = Request.OrchestrationProfile.OrchestrationProfileId; + Result.ModelBindingId = Request.OrchestrationProfile.ModelBindingId; + Result.VocoderBindingId = Request.OrchestrationProfile.VocoderBindingId; + Result.SpeakerProfileId = Request.SpeakerProfileId.IsEmpty() + ? Request.OrchestrationProfile.DefaultSpeakerProfileId + : Request.SpeakerProfileId; Result.SubtitleText = Request.SubtitleSeedText.IsEmpty() ? Request.ScriptText : Request.SubtitleSeedText; Result.AppliedLengthScale = Request.LengthScale; Result.AppliedNoiseScale = Request.NoiseScale; Result.AppliedNoiseW = Request.NoiseW; Result.AppliedSentenceSilenceSeconds = Request.SentenceSilenceSeconds; + Result.bUsedSentenceSplitting = Request.bSplitSentences || Request.OrchestrationProfile.bEnableSentenceSplitting; + Result.bUsedSpeakerSelection = + Request.OrchestrationProfile.bEnableSpeakerSelection && !Result.SpeakerProfileId.IsEmpty(); + Result.bUsedSpeakerReferenceConditioning = + Request.OrchestrationProfile.bEnableSpeakerReferenceConditioning && !Request.ReferenceVoiceSampleRef.IsEmpty(); if (!Request.IsStructurallyValid()) { @@ -33,6 +44,12 @@ FHyperTwistNarrationSynthesisResult UHyperTwistMockVoiceClient::SynthesizeNarrat Result.OutputRouteId = Request.OutputRouteId; Result.VoiceProfileId = Request.VoiceProfileId; Result.LanguageCode = Request.LanguageCode; + Result.OrchestrationProfileId = Request.OrchestrationProfile.OrchestrationProfileId; + Result.ModelBindingId = Request.OrchestrationProfile.ModelBindingId; + Result.VocoderBindingId = Request.OrchestrationProfile.VocoderBindingId; + Result.SpeakerProfileId = Request.SpeakerProfileId.IsEmpty() + ? Request.OrchestrationProfile.DefaultSpeakerProfileId + : Request.SpeakerProfileId; Result.Warnings.Add(TEXT("narration-request-invalid")); return Result; } @@ -64,5 +81,13 @@ FHyperTwistVoiceServiceHealth UHyperTwistMockVoiceClient::GetVoiceServiceHealth( Health.Capabilities.AddUnique(TEXT("voiceCatalog")); Health.Capabilities.AddUnique(TEXT("wavOutput")); Health.Capabilities.AddUnique(TEXT("subtitleSeed")); + Health.Capabilities.AddUnique(TEXT("multiSpeakerNarration")); + Health.Capabilities.AddUnique(TEXT("multiLingualNarration")); + Health.Capabilities.AddUnique(TEXT("speakerReferenceConditioning")); + Health.Capabilities.AddUnique(TEXT("sentenceSplitNarration")); + Health.Capabilities.AddUnique(TEXT("modelBindingSelection")); + Health.Capabilities.AddUnique(TEXT("vocoderBindingSelection")); + Health.SupportedOrchestrationProfiles.AddUnique(TEXT("local-basic-narration-v1")); + Health.SupportedOrchestrationProfiles.AddUnique(TEXT("python-multispeaker-narration-v1")); return Health; } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h index 29e6f1f..ccfe882 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h @@ -72,6 +72,9 @@ public: UFUNCTION(BlueprintPure, Category = "HyperTwist|Recognition") static FHyperTwistNarrationSynthesisRequest MakeSampleNarrationSynthesisRequest(); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Recognition") + static FHyperTwistNarrationSynthesisRequest MakeSampleAdvancedNarrationSynthesisRequest(); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Recognition") static FHyperTwistNarrationSynthesisResult MakeMockNarrationSynthesisResult(); diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistRecognition/HyperTwistRecognitionTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistRecognition/HyperTwistRecognitionTypes.h index bd4bd31..e39e187 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistRecognition/HyperTwistRecognitionTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistRecognition/HyperTwistRecognitionTypes.h @@ -1006,6 +1006,57 @@ struct FHyperTwistVoiceProfileCatalog } }; +USTRUCT(BlueprintType) +struct FHyperTwistNarrationOrchestrationProfile +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString OrchestrationProfileId = TEXT("local-basic-narration-v1"); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ServiceLaneId = TEXT("voice/local-sidecar"); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ModelBindingId = TEXT("voice-model/local-offline-medium-v1"); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString VocoderBindingId = TEXT("vocoder/default-mono-v1"); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DefaultSpeakerProfileId = TEXT("speaker/default"); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bEnableSpeakerSelection = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bEnableLanguageRouting = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bEnableSentenceSplitting = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bEnableSpeakerReferenceConditioning = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSupportsMultiSpeaker = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSupportsMultiLingual = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPreferGpu = false; + + bool IsStructurallyValid() const + { + return !OrchestrationProfileId.IsEmpty() + && !ServiceLaneId.IsEmpty() + && !ModelBindingId.IsEmpty() + && !VocoderBindingId.IsEmpty() + && !DefaultSpeakerProfileId.IsEmpty(); + } +}; + USTRUCT(BlueprintType) struct FHyperTwistNarrationSynthesisRequest { @@ -1029,6 +1080,9 @@ struct FHyperTwistNarrationSynthesisRequest UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FString LanguageCode = TEXT("en_US"); + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FHyperTwistNarrationOrchestrationProfile OrchestrationProfile; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FString ScriptText; @@ -1038,6 +1092,12 @@ struct FHyperTwistNarrationSynthesisRequest UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") int32 SpeakerId = 0; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SpeakerProfileId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ReferenceVoiceSampleRef; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") float LengthScale = 1.0f; @@ -1050,6 +1110,9 @@ struct FHyperTwistNarrationSynthesisRequest UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") float SentenceSilenceSeconds = 0.2f; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSplitSentences = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") bool bPreferCuda = false; @@ -1064,6 +1127,8 @@ struct FHyperTwistNarrationSynthesisRequest && !OutputRouteId.IsEmpty() && !VoiceProfileId.IsEmpty() && !LanguageCode.IsEmpty() + && OrchestrationProfile.IsStructurallyValid() + && ServiceLaneId.Equals(OrchestrationProfile.ServiceLaneId, ESearchCase::CaseSensitive) && !ScriptText.IsEmpty() && !AudioEncodingHint.IsEmpty() && LengthScale > 0.0f @@ -1096,6 +1161,18 @@ struct FHyperTwistNarrationSynthesisResult UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FString LanguageCode = TEXT("en_US"); + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString OrchestrationProfileId = TEXT("local-basic-narration-v1"); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ModelBindingId = TEXT("voice-model/local-offline-medium-v1"); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString VocoderBindingId = TEXT("vocoder/default-mono-v1"); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SpeakerProfileId = TEXT("speaker/default"); + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FString SubtitleText; @@ -1123,6 +1200,15 @@ struct FHyperTwistNarrationSynthesisResult UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") float AppliedSentenceSilenceSeconds = 0.2f; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bUsedSentenceSplitting = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bUsedSpeakerSelection = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bUsedSpeakerReferenceConditioning = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") TArray AudioBytes; @@ -1137,6 +1223,9 @@ struct FHyperTwistNarrationSynthesisResult && !OutputRouteId.IsEmpty() && !VoiceProfileId.IsEmpty() && !LanguageCode.IsEmpty() + && !OrchestrationProfileId.IsEmpty() + && !ModelBindingId.IsEmpty() + && !VocoderBindingId.IsEmpty() && !SubtitleText.IsEmpty() && !AudioEncoding.IsEmpty() && SampleRateHz > 0 @@ -1170,6 +1259,15 @@ struct FHyperTwistVoiceServiceHealth UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") TArray SupportedVoiceProfileIds; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray SupportedOrchestrationProfiles; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray SupportedModelBindingIds; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray SupportedVocoderBindingIds; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FString LastError; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistCoquiPhase6RHAdvancedNarrationContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistCoquiPhase6RHAdvancedNarrationContractTest.cpp new file mode 100644 index 0000000..fd7e8e4 --- /dev/null +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistCoquiPhase6RHAdvancedNarrationContractTest.cpp @@ -0,0 +1,189 @@ +// Copyright HyperTwist, Inc. All Rights Reserved. + +#include "Misc/AutomationTest.h" + +#include "HyperTwistBootstrap/HyperTwistContractLibrary.h" +#include "HyperTwistRecognition/HyperTwistVoiceClient.h" +#include "HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h" + +#if WITH_AUTOMATION_TESTS + +namespace HyperTwistCoquiPhase6RHTestInternal +{ + UHyperTwistMockVoiceClient* MakeMockVoiceClient() + { + return NewObject(GetTransientPackage()); + } +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistCoquiPhase6RHAdvancedNarrationRequestTest, + "HyperTwist.Permissive.Coqui.Phase6R.H.AdvancedNarrationRequest", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistCoquiPhase6RHAdvancedNarrationRequestTest::RunTest(const FString& Parameters) +{ + FHyperTwistTrainingCompanionNarrationContract NarrationContract; + TestTrue( + TEXT("The bundled embodied companion narration contract must stay available for Phase 6R-H."), + UHyperTwistTrainingRuntimeLibrary::TryGetBundledEmbodiedCompanionNarrationContract( + TEXT("embodied-companion-narration"), + NarrationContract + ) + ); + TestTrue(TEXT("The bundled narration contract must remain structurally valid."), NarrationContract.IsStructurallyValid()); + + UHyperTwistMockVoiceClient* VoiceClient = HyperTwistCoquiPhase6RHTestInternal::MakeMockVoiceClient(); + TestNotNull(TEXT("The mock voice client must be constructed for Phase 6R-H."), VoiceClient); + if (VoiceClient == nullptr) + { + return false; + } + + const TArray Profiles = VoiceClient->ListVoiceProfiles(); + TestTrue(TEXT("The retained advanced narration slice must expose a multilingual guide profile."), Profiles.ContainsByPredicate( + [](const FHyperTwistVoiceProfileSummary& Profile) + { + return Profile.VoiceProfileId == TEXT("multilingual-guide-premium") + && Profile.NumSpeakers >= 2; + } + )); + + const FHyperTwistNarrationSynthesisRequest Request = + UHyperTwistContractLibrary::MakeSampleAdvancedNarrationSynthesisRequest(); + TestTrue(TEXT("The advanced narration request must be structurally valid."), Request.IsStructurallyValid()); + TestEqual( + TEXT("The advanced request must stay on the embodied companion narration contract."), + Request.NarrationContractId, + TEXT("embodied-companion-narration") + ); + TestEqual( + TEXT("The advanced request must move to the Python voice service lane."), + Request.ServiceLaneId, + TEXT("voice/python-service") + ); + TestEqual( + TEXT("The advanced orchestration profile must be bounded to the retained multispeaker narration slice."), + Request.OrchestrationProfile.OrchestrationProfileId, + TEXT("python-multispeaker-narration-v1") + ); + TestEqual( + TEXT("The advanced request must carry the normalized narration model binding."), + Request.OrchestrationProfile.ModelBindingId, + TEXT("voice-model/multilingual-premium-v1") + ); + TestEqual( + TEXT("The advanced request must carry the normalized vocoder binding."), + Request.OrchestrationProfile.VocoderBindingId, + TEXT("vocoder/high-fidelity-v1") + ); + TestTrue(TEXT("The advanced request must enable speaker selection."), Request.OrchestrationProfile.bEnableSpeakerSelection); + TestTrue(TEXT("The advanced request must enable language routing."), Request.OrchestrationProfile.bEnableLanguageRouting); + TestTrue(TEXT("The advanced request must enable sentence splitting."), Request.bSplitSentences); + TestTrue( + TEXT("The advanced request must retain a reference-voice sample ref without making voice assets part of the packet."), + !Request.ReferenceVoiceSampleRef.IsEmpty() + ); + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistCoquiPhase6RHAdvancedNarrationResultTest, + "HyperTwist.Permissive.Coqui.Phase6R.H.AdvancedNarrationResult", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistCoquiPhase6RHAdvancedNarrationResultTest::RunTest(const FString& Parameters) +{ + UHyperTwistMockVoiceClient* VoiceClient = HyperTwistCoquiPhase6RHTestInternal::MakeMockVoiceClient(); + TestNotNull(TEXT("The mock voice client must be constructed for Phase 6R-H."), VoiceClient); + if (VoiceClient == nullptr) + { + return false; + } + + const FHyperTwistNarrationSynthesisRequest Request = + UHyperTwistContractLibrary::MakeSampleAdvancedNarrationSynthesisRequest(); + const FHyperTwistNarrationSynthesisResult Result = VoiceClient->SynthesizeNarration(Request); + + TestTrue(TEXT("The advanced narration synthesis result must stay structurally valid."), Result.IsStructurallyValid()); + TestEqual(TEXT("The advanced result must preserve the request id."), Result.RequestId, Request.RequestId); + TestEqual( + TEXT("The advanced result must preserve the advanced orchestration profile id."), + Result.OrchestrationProfileId, + Request.OrchestrationProfile.OrchestrationProfileId + ); + TestEqual(TEXT("The advanced result must stay on the Python voice service lane."), Result.ServiceLaneId, TEXT("voice/python-service")); + TestEqual( + TEXT("The advanced result must preserve the normalized narration model binding."), + Result.ModelBindingId, + Request.OrchestrationProfile.ModelBindingId + ); + TestEqual( + TEXT("The advanced result must preserve the normalized vocoder binding."), + Result.VocoderBindingId, + Request.OrchestrationProfile.VocoderBindingId + ); + TestEqual( + TEXT("The advanced result must preserve the selected speaker profile."), + Result.SpeakerProfileId, + Request.SpeakerProfileId + ); + TestTrue(TEXT("The advanced result must report sentence splitting usage."), Result.bUsedSentenceSplitting); + TestTrue(TEXT("The advanced result must report speaker selection usage."), Result.bUsedSpeakerSelection); + TestTrue( + TEXT("The advanced result must report reference-voice conditioning usage."), + Result.bUsedSpeakerReferenceConditioning + ); + TestEqual( + TEXT("The advanced result must preserve subtitle text."), + Result.SubtitleText, + Request.SubtitleSeedText + ); + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistCoquiPhase6RHServiceHealthTest, + "HyperTwist.Permissive.Coqui.Phase6R.H.ServiceHealth", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistCoquiPhase6RHServiceHealthTest::RunTest(const FString& Parameters) +{ + UHyperTwistMockVoiceClient* VoiceClient = HyperTwistCoquiPhase6RHTestInternal::MakeMockVoiceClient(); + TestNotNull(TEXT("The mock voice client must be constructed for Phase 6R-H."), VoiceClient); + if (VoiceClient == nullptr) + { + return false; + } + + const FHyperTwistVoiceServiceHealth Health = VoiceClient->GetVoiceServiceHealth(); + TestTrue(TEXT("The advanced voice service health must be structurally valid."), Health.IsStructurallyValid()); + TestTrue(TEXT("The advanced voice service health must report ready."), Health.bReady); + TestTrue(TEXT("The advanced voice service must expose multispeaker narration capability."), Health.Capabilities.Contains(TEXT("multiSpeakerNarration"))); + TestTrue(TEXT("The advanced voice service must expose multilingual narration capability."), Health.Capabilities.Contains(TEXT("multiLingualNarration"))); + TestTrue( + TEXT("The advanced voice service must expose speaker-reference conditioning capability."), + Health.Capabilities.Contains(TEXT("speakerReferenceConditioning")) + ); + TestTrue(TEXT("The advanced voice service must expose sentence-split narration capability."), Health.Capabilities.Contains(TEXT("sentenceSplitNarration"))); + TestTrue(TEXT("The advanced voice service must expose model-binding selection capability."), Health.Capabilities.Contains(TEXT("modelBindingSelection"))); + TestTrue(TEXT("The advanced voice service must expose vocoder-binding selection capability."), Health.Capabilities.Contains(TEXT("vocoderBindingSelection"))); + TestTrue( + TEXT("The advanced voice service must advertise the retained advanced orchestration profile."), + Health.SupportedOrchestrationProfiles.Contains(TEXT("python-multispeaker-narration-v1")) + ); + TestTrue( + TEXT("The advanced voice service must advertise the normalized premium narration model binding."), + Health.SupportedModelBindingIds.Contains(TEXT("voice-model/multilingual-premium-v1")) + ); + TestTrue( + TEXT("The advanced voice service must advertise the normalized high-fidelity vocoder binding."), + Health.SupportedVocoderBindingIds.Contains(TEXT("vocoder/high-fidelity-v1")) + ); + return true; +} + +#endif diff --git a/docs/REPO_LICENSE_TRACKING.md b/docs/REPO_LICENSE_TRACKING.md index 4583355..9d2463a 100644 --- a/docs/REPO_LICENSE_TRACKING.md +++ b/docs/REPO_LICENSE_TRACKING.md @@ -1312,6 +1312,7 @@ Decision date: - `2026-04-24` - refreshed on `2026-05-13` +- refreshed on `2026-05-22` Current licensing judgment: @@ -1343,6 +1344,15 @@ Approved working posture: - do not collapse code and model-weight licensing into one bucket - track each chosen voice model or downloadable payload separately at implementation time - prefer a bounded speech sidecar or service seam so the product can swap or isolate model choices later without entangling the core coaching logic +- the first bounded advanced narration slice is now landed: + - advanced narration orchestration profile + - normalized model/vocoder binding metadata + - multilingual routing and speaker-selection flags + - reference-speaker conditioning flag + - bounded mock and HTTP voice-client seam support for the richer narration profile + - advanced voice service-health capability exposure +- `coqui-ai/TTS` remains a bounded donor, not the broad voice-platform owner +- keep downloadable voice/model review separate from the code-license judgment ### `rhasspy/piper` diff --git a/docs/arch/HYPERTWIST_PHASE6R_H_COQUI_TTS_ADVANCED_NARRATION_IMPLEMENTATION_PACKET_2026-05-22.md b/docs/arch/HYPERTWIST_PHASE6R_H_COQUI_TTS_ADVANCED_NARRATION_IMPLEMENTATION_PACKET_2026-05-22.md new file mode 100644 index 0000000..f460575 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE6R_H_COQUI_TTS_ADVANCED_NARRATION_IMPLEMENTATION_PACKET_2026-05-22.md @@ -0,0 +1,144 @@ +# HyperTwist Phase 6R-H coqui-ai/TTS advanced narration implementation packet + +Created on `2026-05-22` + +## Status + +- first-party HyperTwist packet +- bounded permissive `Phase 6R-H` implementation slice + +## Purpose + +This packet lands the first narrower bounded slice from the retained `coqui-ai/TTS` voice-output +row. + +The landed slice is: + +- first-party advanced narration orchestration profile above the existing embodied companion + narration lane + +It is not: + +- a broad TTS platform packet +- a downloadable voice-asset or model-shipping packet +- a provider-profile or BYOK packet +- a voice-conversion packet +- a viseme / gesture runtime packet + +## Current authority basis + +This implementation packet stands on: + +- `docs/HYPERTWIST_PHASE_0R_PACKET_0R_A_EVALUATION_2026-05-12.md` +- `docs/HYPERTWIST_PHASE_2R_PACKET_2R_A_OWNERSHIP_AND_ACCEPTANCE_CONTRACT_2026-05-13.md` +- `docs/REPO_LICENSE_TRACKING.md` +- `docs/ops/HYPERTWIST_PROVIDER_NEUTRALITY_AND_BYOK_DOCTRINE_2026-05-21.md` +- `docs/arch/HYPERTWIST_PHASE6R_H_COQUI_TTS_ADVANCED_NARRATION_PREPARATION_PACKET_2026-05-22.md` + +The retained owner remains: + +- `coqui-ai/TTS` + +The top-level provider and companion contract owner does not change here: + +- first-party HyperTwist remains the provider-neutral and companion-contract owner +- this packet keeps `coqui-ai/TTS` bounded to the narrower `A1 / R2 / F2` advanced narration + orchestration slice + +## Landed scope + +The current code now owns a retained advanced narration orchestration contract through: + +- retained recognition contract types for: + - narration orchestration profile + - advanced narration request metadata + - advanced narration result metadata + - advanced voice service health metadata +- sample voice profiles, basic and advanced narration request shaping, narration result shaping, and + voice service health outputs in: + - `UHyperTwistContractLibrary` +- bounded voice client seam support in: + - `UHyperTwistMockVoiceClient` + - `UHyperTwistHttpVoiceClient` +- focused automation coverage in: + - `HyperTwistCoquiPhase6RHAdvancedNarrationContractTest.cpp` + +## Why this is still intentionally bounded + +This packet lands a richer voice-output donor seam, but it does not widen into the neighboring +retained families. + +Still deferred: + +- downloadable voice/model review +- bundled voice asset shipping +- voice conversion +- broad playback runtime ownership +- viseme / gesture runtime integration +- provider-profile and BYOK custody +- broad assistant-platform scope + +## Validation + +Build validation: + +- `Build.bat UnrealHyperTwistEditor Win64 Development -Project='C:\HyperTwist\UnrealHyperTwist\UnrealHyperTwist.uproject' -WaitMutex -NoHotReloadFromIDE` + +Focused automation validation: + +- `Automation RunTests HyperTwist.Permissive.Coqui.Phase6R.H` + +Regression automation validation: + +- `Automation RunTests HyperTwist.Permissive.Piper.Phase6R.G` +- `Automation RunTests HyperTwist.Permissive.FasterWhisper.Phase6R.F` +- `Automation RunTests HyperTwist.Permissive.WhisperCpp.Phase6R.E` +- `Automation RunTests HyperTwist.CleanRoom.CubeDesk` + +Expected covered tests: + +- `AdvancedNarrationRequest` +- `AdvancedNarrationResult` +- `ServiceHealth` +- `NarrationRequest` +- `SynthesisResult` +- `SessionConfig` +- `TranscriptMetadata` +- `TranscriptResult` +- existing `CubeDesk` clean-room regression suite + +## Queue effect + +This packet consumes the current `Phase 6R-H` implementation slice. + +`coqui-ai/TTS` remains only partially incorporated: + +- landed now: + - advanced narration orchestration profile + - normalized model/vocoder binding metadata + - multilingual routing and speaker-selection flags + - reference-speaker conditioning flag + - bounded mock and HTTP voice-client seam support for the richer narration profile + - advanced voice service-health capability exposure +- still deferred: + - downloadable voice/model review + - bundled voice asset shipping + - voice conversion + - broad playback runtime ownership + - viseme / gesture runtime integration + - broad assistant-platform scope + +The next clean move is: + +- source-backed `Phase 6R-I` `roice3/Magic120Cell` preparation/control pass + +Keep the future sequencing guards visible: + +- speech-input / voice sidecar set + - keep code-license judgments separate from model, voice, and payload-license review +- `coqui-ai/TTS` + - keep the landed slice bounded to orchestration metadata rather than broad voice-platform + ownership +- `roice3/Magic120Cell` + - keep the next widening slice bounded to one retained hyper-engine family rather than treating + the row as a generic non-Euclidean platform by default diff --git a/docs/arch/HYPERTWIST_PHASE6R_H_COQUI_TTS_ADVANCED_NARRATION_PREPARATION_PACKET_2026-05-22.md b/docs/arch/HYPERTWIST_PHASE6R_H_COQUI_TTS_ADVANCED_NARRATION_PREPARATION_PACKET_2026-05-22.md new file mode 100644 index 0000000..c528f9f --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE6R_H_COQUI_TTS_ADVANCED_NARRATION_PREPARATION_PACKET_2026-05-22.md @@ -0,0 +1,79 @@ +# HyperTwist Phase 6R-H coqui-ai/TTS advanced narration preparation packet + +Created on `2026-05-22` + +## Status + +- first-party HyperTwist packet +- source-backed permissive `Phase 6R-H` preparation/control slice + +## Purpose + +This packet narrows the retained `coqui-ai/TTS` row before implementation. + +The retained first slice is: + +- advanced narration orchestration profile above the already landed embodied companion narration lane + +It is not: + +- a broad TTS platform packet +- a downloadable voice-asset or model-shipping packet +- a provider-profile or BYOK packet +- a voice-conversion packet +- a viseme, gesture, or avatar-runtime widening packet + +## Source-backed basis + +Primary donor surfaces inspected: + +- `README.md` +- `docs/source/inference.md` +- `TTS/server/README.md` +- `TTS/api.py` + +## Narrowing decision + +The strongest bounded donor seam is not raw audio output by itself. That lighter local sidecar lane +already landed through `rhasspy/piper`. + +The smallest stronger `coqui-ai/TTS` seam is: + +- richer narration orchestration metadata +- normalized model/vocoder binding selection +- speaker-selection and multilingual routing flags +- optional speaker-reference conditioning +- sentence-splitting policy above the same first-party narration contract + +The first bounded implementation packet should therefore land only: + +- first-party advanced narration orchestration profile types +- bounded request/result metadata for model/vocoder/speaker/reference selection +- mock and HTTP voice-client seam support for the bounded advanced narration profile +- focused automation around the advanced narration request/result/health contract + +## Explicit deferrals + +Still deferred after this control pass: + +- downloadable voice/model review +- bundled voice asset shipping +- voice conversion +- broad playback runtime ownership +- viseme / gesture runtime integration +- provider-profile and BYOK custody +- broad assistant-platform scope + +## Queue effect + +This preparation packet authorizes one bounded permissive implementation packet: + +- `Phase 6R-H` advanced narration orchestration profile + +After that packet, move the queue head to: + +- source-backed `Phase 6R-I` `roice3/Magic120Cell` preparation/control pass + +Keep the legal guard visible: + +- `coqui-ai/TTS` code-license judgment stays separate from model, voice, and payload review diff --git a/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md b/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md index 537a2e8..62276e3 100644 --- a/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md +++ b/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md @@ -80,10 +80,10 @@ Use these as the current governing docs: The next bounded move is now: -1. source-backed `Phase 6R-H` `coqui-ai/TTS` preparation/control pass -2. keep it behind the landed `whisper.cpp`, `faster-whisper`, and `piper` bounded slices -3. narrow the first widening slice to one richer bounded voice-output seam -4. keep voice-asset and payload review separate from the code-license judgment +1. source-backed `Phase 6R-I` `roice3/Magic120Cell` preparation/control pass +2. keep it after the landed `whisper.cpp`, `faster-whisper`, `piper`, and `coqui-ai/TTS` bounded slices +3. narrow the first widening slice to one bounded hyper-engine topology/runtime-anchor seam +4. keep later non-Euclidean shell widening separate from the code-license judgment and retained row ownership ## Memory-specific sequencing rule diff --git a/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md b/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md index c833aa5..685fb4c 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md @@ -183,6 +183,7 @@ repo. | Provider-backed speech session health and transcript envelopes | Implemented now | first-party speech client surfaces | Current first-party speech seam. | | Python transcription-service orchestration profile | Implemented now | landed `faster-whisper` packet | Current bounded Python STT orchestration truth above the existing speech session boundary. | | Local narration sidecar seam | Implemented now | landed `piper` packet | Current bounded offline narration contract, voice catalog, and local sidecar truth. | +| Advanced narration orchestration profile | Implemented now | landed `coqui-ai/TTS` packet | Current bounded richer narration profile above the existing companion narration contract. | | Broad voice output / narration sidecars | Deep-source grounded retained | `piper`, `coqui-ai/TTS` retained remainder | Keep downloadable voice/model review separate from the code-license judgment. | | Broad live microphone shell and downloadable payload shipping | Deep-source grounded retained | speech stack retained remainder | Explicitly deferred. | diff --git a/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md b/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md index 0603dfa..7124489 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md @@ -78,8 +78,13 @@ Canonical discovery surfaces for roadmap interpretation: in current code - `rhasspy/piper` remains partially incorporated; downloadable voice/model review, bundled voice asset shipping, and broad voice-platform ownership stay deferred -- the current next bounded move is a source-backed `Phase 6R-H` `coqui-ai/TTS` - preparation/control pass for a richer bounded voice-output seam +- the generic source-backed `Phase 6R-H` `coqui-ai/TTS` control pass is now consumed +- the bounded permissive `Phase 6R-H` `coqui-ai/TTS` advanced narration orchestration packet is now + landed in current code +- `coqui-ai/TTS` remains partially incorporated; downloadable voice/model review, bundled voice + asset shipping, voice conversion, and broad voice-platform ownership stay deferred +- the current next bounded move is a source-backed `Phase 6R-I` `roice3/Magic120Cell` + preparation/control pass for one bounded hyper-engine widening slice - the repo-row implementation queue is now live from that `Phase 6R-A` entry point rather than waiting on another first-party packet @@ -141,8 +146,8 @@ Current routing truth: - active non-live implementation-board rows: `35` - retained benchmark, oracle, or clean-room-later rows outside the active implementation board: `9` -The next bounded move is a source-backed `Phase 6R-H` -`coqui-ai/TTS` preparation/control pass. +The next bounded move is a source-backed `Phase 6R-I` +`roice3/Magic120Cell` preparation/control pass. Queue interpretation after that packet: @@ -225,13 +230,32 @@ Queue interpretation after that packet: - rich playback runtime ownership - viseme / gesture runtime integration - broad assistant-platform scope +- `coqui-ai/TTS` is now landed as a partially incorporated row rather than a generic future + placeholder: + - landed: + - advanced narration orchestration profile + - normalized model/vocoder binding metadata + - multilingual routing and speaker-selection flags + - reference-speaker conditioning flag + - bounded mock and HTTP voice-client seam support for the richer narration profile + - advanced voice service-health capability exposure + - still deferred: + - downloadable voice/model review + - bundled voice asset shipping + - voice conversion + - broad playback runtime ownership + - viseme / gesture runtime integration + - broad assistant-platform scope - the next queue shape is now: - - `coqui-ai/TTS` + - `roice3/Magic120Cell` - keep the speech-input / voice sidecar legal sequencing guard visible: - keep code-license judgments separate from model, voice, and payload-license review - keep the provider-neutral speech-lane guard visible: - first-party HyperTwist owns the top-level provider/session contract - `whisper.cpp` and `faster-whisper` may win narrower donor slices without inheriting that lane +- keep the voice-output guard visible: + - `coqui-ai/TTS` stays bounded to advanced narration orchestration metadata rather than broad + voice-platform ownership - keep the optional `Phase 3R-G` browser comparison lane deferred unless the landed primary browser spatial stack exposes a real gap