Check probe.has_audio before captions to avoid caption_no_speech
A silent clip fails Sume speech captions with caption_no_speech. Run video_inspect with frames false, read probe.has_audio, then pick STT captions or text cues.

Before you caption a batch of holiday clips, read probe.has_audio from video_inspect with frames: false. The Sume captions docs say speech captions work only when the clip has audible speech, and a silent clip fails with caption_no_speech and next_action: use_overlay_captions. The inspect docs name the same check: a frames: false inspect is enough to read probe.has_audio. If it is false, send text cues instead.
Decision table
Branch on the probe result.
| probe.has_audio | Caption input | Result |
|---|---|---|
| true | No text, or script_text for alignment | STT transcribes and burns |
| true | words or cues | Your text burns; STT does not run |
| false | cues or segments | Your text burns at your times |
| false | none | caption_no_speech error |
Steps
- Import the clip with
POST /v1/media-imports, since inspect takes media.sume.com URLs. - Call
POST /v1/video-inspectwithframes: falseand anIdempotency-Key. The default mode waits up to 30 seconds and returns 200, or 202 if it takes longer. - Read
probe.has_audioin the result (GET /v1/video-inspect/:idif you got a 202). - Route silent clips to a
cuescaption job, and clips with speech to a speech caption job. - Do not request a transcript for silent clips: the docs return
inspect_source_has_no_audio.
The inspect call has its own cost, billed by compute, and I did not find a fixed price in the docs. The caption price is $0.20 per job for up to 60 seconds.
Batch pattern
For a folder of 60 clips, loop in two passes. In the first pass, run inspect with frames: false on every clip and write the has_audio flag next to the URL. In the second pass, send speech caption jobs for the true ones and cue caption jobs for the false ones, taking the cue text from a spreadsheet keyed by clip.
This keeps the paid caption calls from failing on silent clips and keeps the cue copy under review. Use a stable Idempotency-Key per clip and per pass so a restart does not double-submit.
If a clip has a music-only audio track, has_audio may be true while there is no speech. In that case the speech route can still fail with caption_no_speech, so handle that error by falling back to cues.
Budget and detail
Treat the probe result as a gate in your own code. A small function that takes the inspect result and returns either "speech" or "cues" keeps the decision in one place, and you can log it per clip. When the inspect request itself fails, for example with a source that is not on the Sume host, stop and fix the import rather than guessing which route to take.
What Sume does not do
Sume does not auto-switch from speech to cue captions, and the error does not tell you what text to burn. Whether a failed caption job is billed is not stated on the pages I read, so check the job's result and your balance.
Sources
Related posts
More in Developers
- Check Sume webhook signatures in Python with hmac.compare_digest
A Python verifier for the sume-v1 header: raw bytes, constant-time compare, 300 s replay window, empty-secret refusal, and a Flask route that dedupes on job_id.
- Claude Code hook: exit 2 or a JSON deny for a paid Sume call?
Exit code 2 blocks and cannot be overridden by JSON; exit 0 with permissionDecision deny carries a reason. A runnable Python guard for Sume's paid tools.
- Hook matcher rules: when mcp__sume__ names are exact, not regex
Claude Code reads a matcher of letters, digits, underscores and pipes as exact names, and other characters as regex. How to write it for Sume tools.
- Claude Code http hook: send paid Sume call records to an audit log
An http hook POSTs hook input to a URL, with headers from allowed environment variables only. Log Sume tool names and idempotency keys with a tiny receiver.
Written by Sume