diff --git a/server/src/transcribe/worker.rs b/server/src/transcribe/worker.rs index e50024a..b40cea4 100644 --- a/server/src/transcribe/worker.rs +++ b/server/src/transcribe/worker.rs @@ -1,11 +1,14 @@ +use std::path::Path; use std::sync::Arc; use std::time::Duration; use tracing::{error, info, warn}; -use super::{ffmpeg, whisper, TranscribeReceiver}; +use super::{ffmpeg, ollama, whisper, TranscribeReceiver}; use crate::config::Config; +const ONELINER_TIMEOUT: Duration = Duration::from_secs(60); + /// Consume transcription jobs sequentially. Whisper holds the GPU, so parallelism /// here would only cause contention. One job in flight at a time. pub async fn run(mut rx: TranscribeReceiver, config: Arc, client: reqwest::Client) { @@ -48,7 +51,47 @@ pub async fn run(mut rx: TranscribeReceiver, config: Arc, client: reqwes bytes = text.len(), "Transcript written" ); + + if let Some(case_dir) = audio_path.parent() { + ensure_oneliner(case_dir, &text, &client, &config).await; + } } warn!("Transcription worker stopped (channel closed)"); } + +/// Generate `case_dir/oneliner.txt` from the given transcript iff the file +/// does not already exist. Errors are non-fatal: logged and swallowed. +async fn ensure_oneliner( + case_dir: &Path, + transcript: &str, + client: &reqwest::Client, + config: &Config, +) { + let path = case_dir.join("oneliner.txt"); + if path.exists() { + return; + } + + match ollama::generate_oneliner( + client, + &config.ollama_url, + &config.ollama_model, + config.ollama_keep_alive, + transcript, + ONELINER_TIMEOUT, + ) + .await + { + Ok(line) => { + if let Err(e) = tokio::fs::write(&path, &line).await { + error!(path = %path.display(), error = %e, "writing oneliner failed"); + } else { + info!(path = %path.display(), chars = line.chars().count(), "Oneliner written"); + } + } + Err(e) => { + error!(case = %case_dir.display(), error = %e, "oneliner generation failed"); + } + } +}