Compare commits

...

2 Commits

Author SHA1 Message Date
frostyripper1 faabeebb9a Tts added 2026-06-17 14:19:43 +02:00
frostyripper1 37601b386b Commit first stage of AI voice 2026-06-17 14:19:11 +02:00
3 changed files with 41 additions and 13 deletions
+4 -12
View File
@@ -2,8 +2,7 @@ use anyhow::{anyhow, Context, Result};
use rodio::{Decoder, OutputStream, Sink};
use std::io::Cursor;
use std::process::{Child, Command};
use std::sync::Arc;
use tokio::sync::Mutex;
use std::sync::{Arc, Mutex};
pub struct TtsEngine {
process: Arc<Mutex<Option<Child>>>,
@@ -17,7 +16,6 @@ impl TtsEngine {
let server_url = format!("http://127.0.0.1:{}", port);
let client = reqwest::Client::new();
// Check if server is already running
let already_running = client
.get(&format!("{}/", server_url))
.send()
@@ -82,7 +80,6 @@ impl TtsEngine {
let wav_bytes = response.bytes().await?;
// Play audio in a blocking thread (rodio requires sync)
let bytes = wav_bytes.to_vec();
std::thread::spawn(move || {
if let Ok((_stream, stream_handle)) = OutputStream::try_default() {
@@ -98,8 +95,8 @@ impl TtsEngine {
Ok(())
}
pub async fn stop(&self) {
if let Ok(mut guard) = self.process.lock().await {
pub fn stop(&self) {
if let Ok(mut guard) = self.process.lock() {
if let Some(ref mut child) = *guard {
let _ = child.kill();
let _ = child.wait();
@@ -118,11 +115,6 @@ impl TtsEngine {
impl Drop for TtsEngine {
fn drop(&mut self) {
if let Ok(mut guard) = self.process.lock() {
if let Some(ref mut child) = *guard {
let _ = child.kill();
let _ = child.wait();
}
}
self.stop();
}
}
+36
View File
@@ -1115,7 +1115,43 @@ async fn handle_chat_clear(State(state): State<AppState>) -> Json<serde_json::Va
Json(serde_json::json!({"success": true}))
}
#[derive(Deserialize)]
struct TtsSpeakRequest {
text: String,
speaker: Option<String>,
}
async fn handle_tts_speak(
State(state): State<AppState>,
Json(req): Json<TtsSpeakRequest>,
) -> Json<serde_json::Value> {
let tts = match &state.tts {
Some(t) => t.clone(),
None => {
return Json(serde_json::json!({"success": false, "error": "TTS not available"}))
}
};
let speaker = req.speaker.unwrap_or_else(|| "rick".to_string());
match tts.speak(&req.text, &speaker).await {
Ok(()) => Json(serde_json::json!({"success": true})),
Err(e) => Json(serde_json::json!({"success": false, "error": e.to_string()})),
}
}
async fn handle_tts_status(
State(state): State<AppState>,
) -> Json<serde_json::Value> {
let available = match &state.tts {
Some(t) => t.is_available().await,
None => false,
};
Json(serde_json::json!({"available": available}))
}
async fn handle_shutdown(State(state): State<AppState>) -> Json<serde_json::Value> {
if let Some(tts) = &state.tts {
tts.stop();
}
state.shutdown.notify_one();
Json(serde_json::json!({"success": true, "message": "Server shutting down..."}))
}
+1 -1
View File
@@ -1 +1 @@
{"rustc_fingerprint":8393308305887522202,"outputs":{"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___.exe\nlib___.rlib\n___.dll\n___.dll\n___.lib\n___.dll\nC:\\Users\\USER-PC\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\npacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"cmpxchg16b\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"sse3\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"pc\"\nwindows\n","stderr":""},"12004014463585500860":{"success":true,"status":"","code":0,"stdout":"___.exe\nlib___.rlib\n___.dll\n___.dll\n___.lib\n___.dll\nC:\\Users\\USER-PC\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\npacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"cmpxchg16b\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"sse3\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"pc\"\nwindows\n","stderr":""},"4774525245087777997":{"success":true,"status":"","code":0,"stdout":"rustc 1.96.0 (ac68faa20 2026-05-25)\nbinary: rustc\ncommit-hash: ac68faa20c58cbccd01ee7208bf3b6e93a7d7f96\ncommit-date: 2026-05-25\nhost: x86_64-pc-windows-msvc\nrelease: 1.96.0\nLLVM version: 22.1.2\n","stderr":""}},"successes":{}}
{"rustc_fingerprint":2822674519504102369,"outputs":{"4774525245087777997":{"success":true,"status":"","code":0,"stdout":"rustc 1.96.0 (ac68faa20 2026-05-25)\nbinary: rustc\ncommit-hash: ac68faa20c58cbccd01ee7208bf3b6e93a7d7f96\ncommit-date: 2026-05-25\nhost: x86_64-pc-windows-msvc\nrelease: 1.96.0\nLLVM version: 22.1.2\n","stderr":""},"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___.exe\nlib___.rlib\n___.dll\n___.dll\n___.lib\n___.dll\nC:\\Users\\USER-PC\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\npacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"cmpxchg16b\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"sse3\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"pc\"\nwindows\n","stderr":""}},"successes":{}}