Skip to main content

microclaw_engine/internal/app/
transcribe.rs

1use reqwest::multipart;
2
3pub async fn transcribe_audio(api_key: &str, audio_bytes: &[u8]) -> Result<String, String> {
4    let client = reqwest::Client::new();
5
6    let part = multipart::Part::bytes(audio_bytes.to_vec())
7        .file_name("audio.ogg")
8        .mime_str("audio/ogg")
9        .map_err(|e| e.to_string())?;
10
11    let form = multipart::Form::new()
12        .text("model", "whisper-1")
13        .part("file", part);
14
15    let resp = client
16        .post("https://api.openai.com/v1/audio/transcriptions")
17        .header("Authorization", format!("Bearer {api_key}"))
18        .multipart(form)
19        .send()
20        .await
21        .map_err(|e| format!("Whisper API request failed: {e}"))?;
22
23    if !resp.status().is_success() {
24        let status = resp.status();
25        let body = resp.text().await.unwrap_or_default();
26        return Err(format!("Whisper API error HTTP {status}: {body}"));
27    }
28
29    let body: serde_json::Value = resp
30        .json()
31        .await
32        .map_err(|e| format!("Failed to parse Whisper response: {e}"))?;
33
34    body.get("text")
35        .and_then(|t| t.as_str())
36        .map(|s| s.to_string())
37        .ok_or_else(|| "Whisper response missing 'text' field".into())
38}
39
40#[cfg(test)]
41mod tests {
42    #[test]
43    fn test_transcribe_module_exists() {
44        // Basic smoke test that the module compiles
45    }
46}