tonhowtf/omniget · error

Edge TTS nao devolveu audio (o servico pode ter mudado o…

Error message

Edge TTS nao devolveu audio (o servico pode ter mudado o token; tente de novo mais tarde)

What it means

After streaming the TTS request over the WebSocket, synth_chunk expects at least one audio message. If the socket closed (or all messages were parsed) without any audio payload, this error fires, hinting that Microsoft may have changed its DRM token so the service silently returns nothing.

Solutions

  1. Retry later — the message itself suggests the token/service may be temporarily mismatched
  2. Update the edge-tts library to a version with a current Sec-MS-GEC token generator
  3. Verify the requested voice id exists (see list_voices)
  4. Log raw WebSocket messages to confirm whether the server sends an error frame instead of audio

Example fix

// before
let out = edge_tts::synthesize(&opts, &path, progress).await?;
// after
let out = edge_tts::synthesize(&opts, &path, progress).await
    .map_err(|e| if e.to_string().contains("nao devolveu audio") {
        anyhow!("TTS upstream empty; check library version / retry later: {e}")
    } else { e })?;
Defensive patterns

Strategy: retry

Validate before calling

// verify the voice exists first so the service isn't silently rejecting the request
let voices = edge_tts::list_voices().await?;
if !voices.iter().any(|v| v.short_name == opts.voice) { return Err(anyhow!("voz desconhecida")); }

Try / catch

match edge_tts::synthesize(&opts, &path, progress).await {
    Ok(r) => r,
    Err(e) if e.to_string().contains("nao devolveu audio") => {
        tokio::time::sleep(Duration::from_secs(5)).await;
        edge_tts::synthesize(&opts, &path, progress).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Calling synthesize() when the Edge TTS service accepts the WebSocket but never sends audio: expired/invalid Sec-MS-GEC token, Microsoft service-side contract change, or the request being silently rejected (e.g. bad voice id causing immediate close).

Common situations: Microsoft rotating the DRM token algorithm after a browser update; using an outdated library whose token generator is stale; requesting an invalid/deprecated voice name; service-side outage returning empty streams.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/ca36e279c4ff79bd. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/edge_tts.rs:317

                    continue;
                }
                let header_len = u16::from_be_bytes([b[0], b[1]]) as usize;
                if b.len() < header_len + 2 {
                    continue;
                }
                let header = String::from_utf8_lossy(&b[2..2 + header_len]);
                if header.contains("Path:audio") {
                    audio.extend_from_slice(&b[2 + header_len..]);
                    got_audio = true;
                }
            }
            Message::Close(_) => break,
            _ => {}
        }
    }
    let _ = ws.close(None).await;
    if !got_audio {
        return Err(anyhow!("Edge TTS nao devolveu audio (o servico pode ter mudado o token; tente de novo mais tarde)"));
    }
    Ok(ChunkOut { audio, words })
}

/// Agrupa palavras em legendas curtas (até 8 palavras, corta em pausas).
pub fn words_to_cues(words: &[WordBoundary]) -> Vec<Cue> {
    let mut cues = Vec::new();
    let mut buf: Vec<&WordBoundary> = Vec::new();
    let flush = |buf: &mut Vec<&WordBoundary>, cues: &mut Vec<Cue>| {
        if buf.is_empty() {
            return;
        }
        let start = buf[0].start_ms;
        let last = buf[buf.len() - 1];
        let end = last.start_ms + last.duration_ms.max(200);
        let text = buf
            .iter()
            .map(|w| w.text.as_str())

View on GitHub (pinned to 8600b91f42)