diff --git a/src/openhuman/voice/cloud_transcribe.rs b/src/openhuman/voice/cloud_transcribe.rs index a88591c26..f7f121d5c 100644 --- a/src/openhuman/voice/cloud_transcribe.rs +++ b/src/openhuman/voice/cloud_transcribe.rs @@ -22,6 +22,10 @@ use crate::rpc::RpcOutcome; const LOG_PREFIX: &str = "[voice_cloud_stt]"; +/// Maximum base64 audio input length (~25MB base64 → ~18MB decoded audio). +/// Prevents OOM on unreasonably large payloads (multi-hour recordings). +const MAX_AUDIO_BASE64_LEN: usize = 33_554_432; + /// Default model id sent to the backend. The backend's controller currently /// resolves this to whichever provider it has configured for audio /// transcription (today: GMI Whisper). Callers can override. @@ -56,6 +60,12 @@ pub async fn transcribe_cloud( if trimmed.is_empty() { return Err("audio_base64 is required".to_string()); } + if trimmed.len() > MAX_AUDIO_BASE64_LEN { + return Err(format!( + "audio_base64 exceeds maximum size ({}MB)", + MAX_AUDIO_BASE64_LEN / 1_048_576 + )); + } let audio_bytes = BASE64 .decode(trimmed) .map_err(|e| format!("invalid base64 audio: {e}"))?;