IGTranscript

How do I transcribe an Instagram video on an iPhone?

There is nothing to install and nothing to sign up for: the page is a web page, it runs in Safari like any other, and the video goes in through one file picker — the same picker as any upload form, except that nothing is ever uploaded, because the decoding and the recognition both happen inside the tab. What a phone changes is not the route but the ceiling. A three-minute Reel recorded at 48 kHz in stereo becomes a 69,120,000-byte decoded audio buffer plus an 11,520,000-byte 16,000 Hz mono copy for the model, so 80,640,000 bytes sit in one tab at one moment before a single word comes back — and the first run also fetches a 79.7 MB speech model. Those two numbers, not the length of the Reel, are what decide whether a given iPhone finishes a given video. The dashed box that says “or drop one here” is wired to 4 drag events that a touch screen cannot fire.

InVideo WW

The rest of this page is that answer taken apart in units you can check rather than reassurances you have to trust: the 12 tokens in the file input’s accept list and the 2 of them that are wildcards, the 4 drag listeners that are dead weight on a touch screen, the 384,000 bytes a second that one second of 48 kHz stereo costs against the 64,000 a second the model actually reads, the 278,082,062 bytes the one measured ten-minute run held at its peak, the 0 occurrences of a service worker in either file that would let a second visit skip the 79.7 MB download, and the 0.419 seconds of recognition this machine spent per second of audio — a rate that is this machine’s, not an iPhone’s.

There is no app, and there is no upload either

The whole tool is two files served from one static host: index.html at 17,965 bytes and app.js at 22,349 bytes. Neither is wrapped in a native shell, there is no App Store listing to look for, and the App Store is not where this lives. On an iPhone the page arrives exactly as it does on a laptop, and it talks to 2 hosts and no more: cdn.jsdelivr.net for the recognition library, and huggingface.co for the speech model and for the generation_config.json the language picker is built from. Those are 1 dynamic import and 1 explicit fetch in the 22,349 bytes, plus the weight files the library fetches for itself. Your video is not part of any of them.

The only door on a phone is the file picker

On a laptop there are two ways in. On an iPhone there is one. The control is an <input type="file"> with id="file" that is visually hidden by the .sr class, and the thing you actually tap is a <label for="file"> drawn as the dashed box. A label forwards the tap to its input, so the picker opens; that is the entire interaction, and it is 1 tap before the system sheet appears.

The drop box is 4 listeners a touch screen cannot fire

The dashed box is a drop zone as well as a button, and the code that makes it one is wireDropZone(): 4 event types — dragenter, dragover, dragleave, drop — each with preventDefault() and stopPropagation(), plus a depth counter that exists because dragenter and dragleave also fire for children. All of it is correct, and on an iPhone none of it can run.

What a minute of audio costs the tab

This is the part that decides whether your phone finishes. Web Audio hands back an AudioBuffer of 32-bit floats, so the cost of one second is sample rate × channels × 4 bytes. At the rate a phone camera records — 48 kHz, stereo — that is 384,000 bytes a second. The model does not read that buffer; it reads a second one, rendered down to 16,000 Hz mono at OfflineAudioContext(1, frames, 16000), which is 64,000 bytes a second. The ratio is exactly 6, and both buffers exist at the same time, because toPcm() holds decoded while startRendering() produces the second one.

Memory held by one transcription run at three Reel lengths. Each bar is the decoded 48 kHz stereo buffer in dark grey followed by its 16 kHz mono render in light grey. A 60-second Reel is 26,880,000 bytes, 90 seconds is 40,320,000, and 180 seconds is 80,640,000. A dashed vertical line marks the 79.7 MB speech model, which the three-minute bar passes. Both buffers are live at once Dark: the decoded source. Light: the 16 kHz mono copy the model reads. 60 s 90 s 180 s the 79.7 MB model The model is downloaded once. The bars are allocated again on every run. There is no swap in a browser tab: when the budget runs out the tab is reloaded.
What one run holds, computed from the constants rather than estimated: 48 kHz stereo float32 is 384,000 bytes a second, 16 kHz mono is 64,000, and toPcm() keeps both because decoded is still referenced while startRendering() runs. 60 seconds is 23,040,000 + 3,840,000 = 26,880,000 bytes; 90 seconds is 34,560,000 + 5,760,000 = 40,320,000; 180 seconds is 69,120,000 + 11,520,000 = 80,640,000, which is 940,000 bytes past the 79.7 MB model marked by the dashed line. The 10-minute run recorded on this machine peaked at 278,082,062 bytes once the 9,147,662-byte file is counted alongside its 230,515,200-byte decode and 38,419,200-byte render. The 48 kHz stereo source rate is an assumption about what a phone camera records, not a measurement of your file; a mono 44.1 kHz recording would be 176,400 bytes a second instead of 384,000.

The model is the other thing a phone pays for

The recognition library is loaded from a CDN and told allowLocalModels = false, so the model weights always come over the network rather than from anything bundled with the page. The progress code records what that costs, measured in this browser: the total climbs as the library discovers files, “26.0 MB at the first sample and 79.7 MB by the third”. On a laptop on wifi that is a wait. On a phone on cellular it is also 79.7 MB of somebody’s data allowance, once per fresh cache.

Three Safari behaviours the source settles

Phones raise questions that a laptop never does, and three of them can be answered from the file rather than from a guess about how mobile browsers behave. The pattern in all three is that the code already contains a fallback, and knowing which fallback is on which path is what tells you whether a failure on iOS is a bug or an expected branch.

How long it takes, and why this page will not promise a number

The one full-length run recorded here took 600.3 seconds of audio and 251.5 seconds of recognition, which is 0.419 seconds of work per second of audio on this machine. That number belongs to this machine. The same wasm binary on an iPhone is a different CPU with a different thermal budget, and no run has been measured on one, so the honest form of the answer is the formula rather than a figure: seconds of recognition ≈ seconds of audio × the rate your device achieves, and the rate is the only unknown.

When the tab reloads in the middle

A browser tab has no swap file. When the memory budget runs out the tab is discarded and reloaded, and everything the run was holding goes with it: RESULT is a variable in memory, the transcript panel is a DOM node, and neither is written anywhere until you press a download button. On a phone that reload is not an edge case; it is the most likely way a long video ends.

Is there an Instagram transcription app for iPhone?

Not from this site, and this site does not need one. The tool is 2 files — index.html at 17,965 bytes and app.js at 22,349 bytes — served as a normal web page, so Safari is the whole installation. An app would have to ship the same 79.7 MB of model weights inside a bundle and ask for the same audio buffers; the browser route gets the model over the network once and asks the tab for 26,880,000 bytes per minute of audio, which is a smaller ask than a native app that keeps a model resident.

Does it upload my video from my phone?

No. The file is read with file.arrayBuffer() — 1 call in the 22,349 bytes — and handed straight to decodeAudioData(), which appears 1 time; there is no FormData and no request that carries the file. The 2 network destinations the page has are the recognition library on cdn.jsdelivr.net and the model on huggingface.co, and neither one receives any part of your video. The page’s own header comment states it in one line: the file “is never part of any request”.

Why can’t I drop a video into the box on my phone?

Because a drag gesture needs a pointer that can hold something while it moves, and a finger on a touch screen scrolls the page instead. The drop zone is wired to 4 events — dragenter, dragover, dragleave, drop — and on an iPhone none of the 4 can fire, so the handler that reads e.dataTransfer.files[0] never gets an object to read. The label inside the same box still works: tap it, and the system sheet offers Photos and Files.

Can I record with the camera straight into the page?

No, and that is a deliberate omission rather than a bug. capture appears 0 times on the file input, so tapping it opens the normal picker instead of jumping to the camera; there is also 0 use of getUserMedia anywhere in the 22,349 bytes. The route is: record in the camera app, save to Photos, then tap the box — 3 steps, and the clip is a MOV, which is one of the 10 extensions in the accept list and one of the 4 container formats the code comment records as working.

What is the longest Instagram video an iPhone can transcribe?

There is no fixed number, and any page that gives you one is guessing. The ceiling is the tab’s memory, and the arithmetic is: available bytes − the file − 384,000 per second of 48 kHz stereo source − 64,000 per second for the 16 kHz render. On this desktop browser a valid 20-minute WAV — 76,800,000 bytes as 16 kHz mono — was rejected as “more than the tab holds”, which is the only ceiling that has actually been observed here; no iPhone has been measured, so this page reports the formula and the one refusal it has, not a promise about your phone.

Where does the .srt file go on an iPhone?

The page does not choose. download() creates a blob URL, sets a.download = 'transcript.srt', clicks the anchor and revokes the URL 30,000 ms later; the destination is whatever the operating system does with a download. The filename is fixed for all 4 exits — transcript.txt, transcript.srt, transcript.vtt — and the file is written as text/plain;charset=utf-8 in every case, so a second download of the same kind replaces the first unless the system renames it.

Last checked: 1 November 2026. The source counts were read on this machine from the deployed files: app.js is 22,349 bytes and index.html 17,965, with serviceWorker, capture, multiple, resume(), getUserMedia and setSelectionRange each 0 times, arrayBuffer, decodeAudioData, getChannelData and navigator.clipboard 1 time each, and 4 drag event types wired in wireDropZone(). The accept list is 12 tokens — 2 wildcards, 5 video extensions, 5 audio extensions — counted from the attribute itself. All byte figures are arithmetic on constants in app.js and on the Web Audio specification: a 32-bit float sample, one channel for the render, so 48 kHz stereo is 384,000 bytes a second and 16 kHz mono is 64,000; 60, 90 and 180 seconds were multiplied out and printed here, as were 230,515,200 + 38,419,200 + 9,147,662 = 278,082,062 and 79,700,000 ÷ 384,000 = 207.55. The window counts follow from chunk_length_s: 30 — 480,000 samples, 320,000 apart — and were printed as 4, 9 and 30. The 76,894,612 and 40,844,231 weight sizes were read from Hugging Face for the two q8 checkpoints. The 26.0 MB, 79.7 MB, “44 MB cost 118 MB”, the 20-minute WAV rejection, the “MP4, MOV, WebM and M4A all worked” line and the “two pipelines at once on a phone” sentence are quoted from the comments in app.js, which record what was measured in this browser. The 251.5 seconds and 0.419 per second come from the 600.3-second run recorded on 27 October 2026 on this Windows machine. No part of this page was measured on an iPhone: the iOS behaviour described here is read off the code path and the specification, and is marked as such wherever it appears.

If the file itself is the problem rather than the phone, the five failures page sorts out which of them you have. If the wait is the problem, the long Reel page has the measured 10-minute run in full, and the length limit page covers the 20-minute ceiling quoted above. The SRT and VTT page covers what the 4 exits actually produce, the no-login page covers what the browser needs in order to read a file at all, and the timestamps page covers the 12 characters this tool puts in front of every line.