My Instagram video has no captions — can I still get a transcript?
Yes, and the caption track has nothing to do with it. Nothing in the tool ever looks for one: the string “caption” appears 0 times in the 22,349 bytes of app.js, together with 0 uses of TextTrack, 0 of textTracks and 0 of VTTCue, because the only input it accepts is decoded audio. One call to decodeAudioData, one resample to 16,000 Hz mono, one recognition run — that is the entire path from file to words. What does come back empty is something else: a file with no audio track at all, and a file whose audio has no speech in it.
The rest of this page is the evidence for that — the four places in app.js where a caption track would have had to be read, the three failures the browser reports with one identical error, what rebuilding the words costs in bytes when a caption track would have cost a few hundred, what the three pages that outrank this one say across 38,642 characters of their own Instagram copy, and how to tell which of the two empty cases you are looking at before you upload a 26,880,000-byte minute of audio.
The caption track was never part of the path
The file enters at toPcm(), and toPcm() does two things with it: file.arrayBuffer(), then AudioContext.decodeAudioData(). That function appears 1 time in the 22,349 bytes of app.js and it is the only door in. A caption track is not a stream the audio decoder can see — it is a separate text track attached to the container — and reading one takes an API this file never calls.
- 0 calls to the text-track API. TextTrack, textTracks, addTextTrack, VTTCue and getTrackById each appear 0 times across the 22,349 bytes. The word “track” appears 4 times, and all 4 are “audio track”: three inside the error comment at lines 213, 220 and 223, and one in the progress message at line 267.
- One channel is read, and it is channel 0. The render target is built as
OfflineAudioContext(1, frames, 16000)— one channel — so a stereo track is folded down by the browser beforegetChannelData(0)is called, and getChannelData appears exactly 1 time in the file. There is no getChannelData(1) anywhere, and no branch that would produce one. - The length comes from the audio, not from the container.
framesisMath.ceil(decoded.duration × 16000), anddecodedis the audio buffer. A 60-second clip is 960,000 frames, which at 4 bytes a sample is 3,840,000 bytes of mono float32 — the exact array handed to the model, with no text track consulted at any point before it.
The two files that do come back empty
Neither of them is about captions. The first is a file with a picture and no audio track; the second is a file with an audio track and no speech in it. The first is recorded in app.js’s own error comment, measured in this browser: “a WebM with a picture and no audio track, which the video element itself plays happily” rejects exactly like a damaged file — EncodingError, “Unable to decode audio data”, code 0.
- A silent screen recording looks like a damaged file. The comment at line 213 of the 22,349-byte file lists three causes that arrive wearing the same face — a 77-byte text file named .mp4, a valid 20-minute WAV, and a WebM with a picture and no audio track — and states that nothing in the error object separates them. That is why the message names all three instead of guessing, and why the page cannot tell you which one you have.
- A music bed with no speech is stripped to nothing. Before any word is counted, a 20-character regex —
\[[^\]]*\]|\([^)]*\)— removes both annotation styles. Measured on a video carrying a music bed and no speech, the model returned “(smooth music)”, which the old count read as 2 words above an otherwise empty transcript; after the strip it is 0 words and the panel says “No speech found”. - A visually captioned Reel with no voice returns nothing, even though you can read it. Burned-in captions are pixels, and there are 0 uses of canvas, 0 of getImageData and 0 of OCR in the 22,349 bytes. The tool is not reading your caption track and it is not reading your caption text either; it is reading the waveform, and a waveform with no speech in it is silence.
decodeAudioData, and the box after it is fixed: one channel at 16,000 Hz. A 60-second clip comes out of that box as 960,000 frames and 3,840,000 bytes. The bottom row is the case that fails — a picture with no audio track, which a video element plays happily and which the audio decoder refuses with the same EncodingError, code 0, that a damaged file produces. The red cross on the caption row is the whole answer to the question: the path was never built to carry text in, only audio.What rebuilding the words costs, when a caption track would have been free
A caption track for a one-minute clip is a few kilobytes at most; the signal those words have to be recovered from is 3,840,000 bytes. The rate is fixed by the Web Audio spec rather than chosen here: an AudioBuffer sample is a 32-bit float, so 16,000 samples a second, one channel, 4 bytes each, is 64,000 bytes a second, and nothing in the tool can lower that without lowering the sample rate the model was trained on.
- A one-minute clip peaks at 26,880,000 bytes in the tab. The decoded source at 48 kHz stereo is 23,040,000 bytes and the 16 kHz mono render is 3,840,000, and both exist at the same moment because the render reads from the source. Twenty minutes — the ceiling Instagram states for a Reel — is 20 × 26,880,000 = 537,600,000 bytes.
- The model is worth about twenty minutes of speech. 79.7 MB is 1,245.3125 seconds of 16 kHz mono, or 20.75 minutes; the smaller checkpoint at 43.6 MB is 681.25 seconds, or 11.35 minutes. Past that point the one-time download is smaller than the audio it has already processed, and below it you paid more for the model than for the clip.
- For scale, one minute of audio is 1,067 times the size of a 100-cue subtitle file. A WebVTT cue with a 12-character stamp at each end costs 36 bytes of scaffolding on average when the text is one character, and 100 of them come out of
buildVtt()as 3,599 bytes. 3,840,000 ÷ 3,599 = 1,067, so the signal a minute of speech has to be recovered from is more than a thousand times the file that describes it. - And the download is charged twice if you switch models mid-run. app.js records the measurement: choosing the other model after a load has started leaves both downloads running, “a run that should have cost 44 MB cost 118 MB” — 2.68 times the intended figure. That is why the model is fetched at the first file rather than on page load, and why a video with no audio in it never triggers a download at all.
What the three pages that outrank this one say about it
Across the 6 Instagram pages the three sites publish — 38,642 characters of body text once the heading lists and the scraper’s metadata are stripped, because those are not sentences a reader sees — the word “caption” appears 10 times on wayin.ai, 7 times on speakapp.com and 2 times on getthescript.app. Only one of the three answers the question.
- wayin.ai answers it directly. Its FAQ entry “Can I transcribe an Instagram video if it has no captions?” is the only direct answer in the 38,642 characters: “Yes. WayinVideo processes the actual audio track of the video, not the on-screen text. Even if the creator didn’t add native captions or text stickers, you will receive a highly accurate text output.” Its feature block says the same thing under the heading “Works Without Native Captions”: “Our AI extracts text directly from the audio track.”
- speakapp.com never explains it, in 7 uses. One is a customer testimonial — “I generate transcripts for client posts that were uploaded without captions, and the language detection just works” — and the others describe what you can do with the output, as in “use it as a starting point for captions, subtitles, or written content”. 0 of the 7 says how a file without captions is handled.
- getthescript.app uses the word twice, both times in the same line. “Turn Reels into carousel copy, captions, and newsletters without retyping a word.” That is a use for the output, not a claim about the input; across its 6,702 characters of Instagram copy there is no mention of a video arriving without captions.
- 0 of the three describes the case that actually fails. None of the 38,642 characters covers a picture that plays with no sound in it — the one input that returns nothing here — and none mentions what a music-only Reel produces. The question is answered once, in a two-sentence FAQ, and the harder half of it is not answered at all.
How to tell which case you have, before you upload
Three checks, each under a minute, and they separate the outcomes cleanly: it works, it decodes to nothing, or it decodes to silence. All three are cheaper than the 79.7 MB model download that a run with no speech in it would otherwise trigger.
- Play it with the sound on. If you hear speech, the caption track is irrelevant and the words will come back — the path is decode, resample to 16,000 Hz, recognise, and captions are not a step in it. If the video plays and you hear nothing at all, you have either no audio track or an audio track with nothing in it, and the second of those returns 0 words rather than an error.
- Try a shorter cut of the same source. The error message ends with two things worth trying, and the second is “if a shorter clip works, the file itself was fine” — which separates a file too long or too large for the tab from one with no audio in it. A 20-minute WAV is 76,800,000 bytes at 16 kHz mono and was rejected on this machine for size; the same audio cut short decodes.
- If the words are burned into the picture, this is the wrong route for them. A Reel that shows its text on screen with no voice returns nothing here, because 0 of the 22,349 bytes touch pixels. That is on-screen text rather than speech, and it needs a different approach from the one this page takes.
decodeAudioData and all three come back as the same object: EncodingError, “Unable to decode audio data”, code 0. The comment at line 213 of the 22,349-byte app.js lists exactly those three and states that nothing in the error separates them, so the message names all three instead of guessing. The checks that do separate them are on your side of the upload: play it with the sound on, and try a shorter cut of the same source.Do I need to add captions before transcribing?
No, and adding them changes nothing about the output. The transcript is produced from the audio by the model, and the string “caption” appears 0 times in the 22,349 bytes of app.js — there is no code that would read a caption track even if the file carried one. A Reel with captions and a Reel without them take exactly the same path: decode, resample to 16,000 Hz mono, recognise.
Will the transcript match the captions already on the video?
Only where the captions were right. The tool never sees them, so a typo in the caption track is not reproduced and a word someone corrected by hand is not carried over; every word comes from the model’s own decoding of the waveform at 16,000 samples a second. For a 60-second clip that is 960,000 samples and 3,840,000 bytes, decoded once, with no second source to compare against.
Why did I get “No speech found” on a video that clearly has sound?
Two reasons, and both are on the page rather than in the file. The sound may be music rather than speech — measured, a music bed came back as “(smooth music)”, which strips to 0 words — or the language picker may be set to a language other than the one being spoken, in which case the words come back wrong or not at all. Neither is caused by a missing caption track, and adding captions would not change either.
Does a file with no audio track fail the same way as a silent one?
No, it fails earlier. A file with no audio track stops at decodeAudioData with EncodingError and code 0, before the model is loaded, so it costs 0 bytes of download. A silent track decodes normally and fails later at the word count, after the 79.7 MB model has been fetched — which is why the decode runs first in run() and the model is loaded only once there is something to transcribe.
Is a caption track that is burned into the picture read as text?
No. There are 0 uses of canvas, 0 of getImageData and 0 of OCR across the 22,349 bytes, so no frame is ever sampled and no pixel is ever examined. Words painted onto the picture are invisible to this tool; only the audio track is read, and a Reel whose message is entirely on screen with no voice over it produces an empty transcript here.
Last checked: 25 October 2026. The source counts were read from the deployed files on this machine: app.js is 22,349 bytes, with “caption” 0 times, TextTrack, textTracks, addTextTrack, VTTCue and getTrackById 0 times each, “track” 4 times (all “audio track”, at lines 213, 220, 223 and 267), canvas, getImageData and OCR 0 times, decodeAudioData 1 time and getChannelData 1 time. The byte figures are arithmetic on the constants in app.js and on the Web Audio spec: RATE = 16000, one channel, a 32-bit float sample, so 64,000 bytes a second — 60 seconds is 960,000 samples and 3,840,000 bytes, 20 minutes is 76,800,000 bytes at 16 kHz mono, and a one-minute clip held as a 48 kHz stereo source plus its 16 kHz mono render is 23,040,000 + 3,840,000 = 26,880,000 bytes. The 3,599 bytes for 100 cues, and the 1,067 that follows from it, were produced by running this site’s own buildVtt() logic on this machine; the 3,500 bytes written here on 25 October counted the cue blocks but not the 99 newlines that join them, and were corrected on 26 October. 79.7 MB ÷ 64,000 = 1,245.3125 seconds was printed and re-checked here before it was written down. The 48 kHz stereo source rate is an assumption about what a phone camera records, not a measurement of your file. The EncodingError text and the three causes are quoted from the comment in app.js at lines 207–219, which records what was measured in this browser; the “(smooth music)” result and the 2-word count are from the same measurement record at line 405. The competitor figures cover 6 Instagram pages and 38,642 characters of body text in files held in this site’s benchmark directory, measured after the heading lists were stripped; the quoted sentences from wayin.ai, speakapp.com and getthescript.app are reproduced exactly as they appear there.
If the captions are what you are trying to obtain rather than replace, how to get captions on an Instagram Reel covers Instagram’s own feature and why it does not hand you a file. If the words are burned into the picture, extracting text from an Instagram video works out why that is a different problem from speech. The timestamps page covers the 12 characters this tool puts in front of every line, the no-login page covers what the browser needs in order to read a file at all, and the length limit page covers the 20-minute ceiling whose 537,600,000 bytes are quoted above.