diff --git a/crates/lib/database_queries/src/complex_models/event_responses.rs b/crates/lib/database_queries/src/complex_models/event_responses.rs index a49054696f..4c230e9545 100644 --- a/crates/lib/database_queries/src/complex_models/event_responses.rs +++ b/crates/lib/database_queries/src/complex_models/event_responses.rs @@ -1,4 +1,17 @@ use container_common::anyhow_result::AnyhowResult; +use std::collections::HashMap; + +/// How TTS commands should be prefixed: !voiceName, /voiceName, etc. +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)] +#[serde(rename_all = "snake_case")] +pub enum CommandPrefixType { + /// Prefix voice commands with "!" + Exclamation, + /// Prefix voice commands with "!" or "/" + ExclamationOrSlash, + /// Prefix voice commands with "/" + Slash, +} #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[serde(rename_all = "snake_case")] @@ -16,6 +29,19 @@ pub enum EventResponse { TtsRandomVoice { tts_model_tokens: Vec, }, + + /// Use TTS commands that FakeYou recommends. + TtsCommandPresets { + command_prefix_type: CommandPrefixType, + }, + + /// Use your own TTS commands. + /// The map is from "!command" (without the "/" or "!" prefix) to model token. + /// Command is lower case, alphanum only, and compared case insensitive. + TtsCommandCustom { + command_prefix_type: CommandPrefixType, + command_map: HashMap, + }, } #[cfg(test)] diff --git a/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/validations/validate_event_response.rs b/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/validations/validate_event_response.rs index 8d01fba03a..3356246df4 100644 --- a/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/validations/validate_event_response.rs +++ b/crates/service/storyteller_web/src/http_server/endpoints/twitch/event_rules/validations/validate_event_response.rs @@ -20,6 +20,19 @@ pub fn validate_event_response(event_response: &EventResponse) -> Result<(), Str } } }, + EventResponse::TtsCommandPresets { .. } => { + // Implicitly valid + } + EventResponse::TtsCommandCustom { command_map, .. } => { + for (command, model_token) in command_map.iter() { + if command.trim().is_empty() { + return Err("one or more commands is invalid".to_string()); + } + if model_token.is_empty() { + return Err("one or more model tokens is invalid".to_string()); + } + } + }, } Ok(()) diff --git a/crates/service/storyteller_web/src/tts_inference_job.rs b/crates/service/storyteller_web/src/tts_inference_job.rs index 3183782df9..1d952670b6 100644 --- a/crates/service/storyteller_web/src/tts_inference_job.rs +++ b/crates/service/storyteller_web/src/tts_inference_job.rs @@ -927,6 +927,8 @@ async fn process_job( Some(&inference_result_token) ).await?; + info!("TTS Done. Original text was: {}", &job.raw_inference_text); + inferencer.firehose_publisher.tts_inference_finished( job.maybe_creator_user_token.as_deref(), &model_record.model_token,