aboutsummaryrefslogtreecommitdiffstats
path: root/src/events
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-09-05 19:35:21 +0200
committersalmonik <salmonik@tuta.io>2026-09-05 19:35:21 +0200
commit8e868894cbcaf421c263f3555af4d29bef653420 (patch)
treea6b6f1de5caeef59367e52a8b7cfa6c2cd9f201d /src/events
parentremove ` from TTS and make events use lang.rs (diff)
downloadsenator-sperma-8e868894cbcaf421c263f3555af4d29bef653420.tar.gz
senator-sperma-8e868894cbcaf421c263f3555af4d29bef653420.zip
feat: piper now not a subprocess, cache system for TTS
Diffstat (limited to '')
-rw-r--r--src/events/mod.rs34
1 files changed, 17 insertions, 17 deletions
diff --git a/src/events/mod.rs b/src/events/mod.rs
index e4f1b22..87333c8 100644
--- a/src/events/mod.rs
+++ b/src/events/mod.rs
@@ -28,15 +28,14 @@ fn format_duration(seconds: f64) -> String {
28} 28}
29 29
30async fn play_tts_in_channel( 30async fn play_tts_in_channel(
31 config: crate::config::Config, 31 tts: std::sync::Arc<crate::tts::TtsState>,
32 http_client: reqwest::Client,
33 voice_manager: crate::voice::VoiceManager, 32 voice_manager: crate::voice::VoiceManager,
34 guild_id: serenity::GuildId, 33 guild_id: serenity::GuildId,
35 channel_id: serenity::ChannelId, 34 channel_id: serenity::ChannelId,
36 text: String, 35 text: String,
37) { 36) {
38 let audio_data = match crate::tts::synthesize(&config, &http_client, &text).await { 37 let audio_data = match tts.synthesize(&text).await {
39 Ok((bytes, _)) => bytes, 38 Ok(bytes) => bytes,
40 Err(e) => { 39 Err(e) => {
41 warn!("Failed to synthesize TTS: {e}"); 40 warn!("Failed to synthesize TTS: {e}");
42 return; 41 return;
@@ -51,13 +50,7 @@ async fn play_tts_in_channel(
51 } 50 }
52 }; 51 };
53 52
54 let input = match crate::voice::decode_audio(&audio_data) { 53 let input = crate::tts::pcm_bytes_to_input(audio_data);
55 Ok(i) => i,
56 Err(e) => {
57 warn!("Failed to decode TTS audio: {e}");
58 return;
59 }
60 };
61 54
62 let mut call_lock = call.lock().await; 55 let mut call_lock = call.lock().await;
63 if call_lock.current_channel().is_some() { 56 if call_lock.current_channel().is_some() {
@@ -97,6 +90,16 @@ pub async fn handle_voice_state_update(
97 .map(|m| m.display_name().to_string()) 90 .map(|m| m.display_name().to_string())
98 .unwrap_or_default(); 91 .unwrap_or_default();
99 92
93 // Pre-generate all 6 event phrases for this user (background, non-blocking).
94 // First event per user pays ~120ms; subsequent events are instant from cache.
95 {
96 let tts = data.tts.clone();
97 let name = display_name.clone();
98 tokio::spawn(async move {
99 tts.pre_generate(&name).await;
100 });
101 }
102
100 let now = current_ts as f64; 103 let now = current_ts as f64;
101 104
102 let user_id_str = user_id.to_string(); 105 let user_id_str = user_id.to_string();
@@ -293,8 +296,7 @@ pub async fn handle_voice_state_update(
293 && let Some(cid) = tts_channel.or(new_channel) 296 && let Some(cid) = tts_channel.or(new_channel)
294 { 297 {
295 tokio::spawn(play_tts_in_channel( 298 tokio::spawn(play_tts_in_channel(
296 data.config.clone(), 299 data.tts.clone(),
297 data.http_client.clone(),
298 data.voice_manager.clone(), 300 data.voice_manager.clone(),
299 gid, 301 gid,
300 cid, 302 cid,
@@ -314,8 +316,7 @@ pub async fn handle_voice_state_update(
314 && let Some(cid) = tts_channel.or(new_channel) 316 && let Some(cid) = tts_channel.or(new_channel)
315 { 317 {
316 tokio::spawn(play_tts_in_channel( 318 tokio::spawn(play_tts_in_channel(
317 data.config.clone(), 319 data.tts.clone(),
318 data.http_client.clone(),
319 data.voice_manager.clone(), 320 data.voice_manager.clone(),
320 gid, 321 gid,
321 cid, 322 cid,
@@ -330,8 +331,7 @@ pub async fn handle_voice_state_update(
330 && let Some(gid) = guild_id 331 && let Some(gid) = guild_id
331 { 332 {
332 tokio::spawn(play_tts_in_channel( 333 tokio::spawn(play_tts_in_channel(
333 data.config.clone(), 334 data.tts.clone(),
334 data.http_client.clone(),
335 data.voice_manager.clone(), 335 data.voice_manager.clone(),
336 gid, 336 gid,
337 cid, 337 cid,