This is a submission for DEV's Summer Bug Smash: Smash Stories powered by Sentry.
I run snipforge.video, an AI video editing SaaS, solo. One of its core features is share links: process a video, get a URL, send it to someone. A user reported that a shared video showed 0:00 and refused to play on their iPhone. I opened the same link on desktop Chrome and it played perfectly. Classic "works on my machine," except my machine was every desktop and the failure was every iPhone.
This is the worst kind of bug report for a solo founder, because the person hitting it is usually not your user. It is the person your user shared the video with. They do not file a bug. They just conclude your product is broken and close the tab.
Everything about the symptom pointed at the serving path, so that is where I went first. Shared files live on Cloudflare R2 behind the app, and mobile Safari is famously picky about how video is served, so I had a lineup of plausible suspects:
faststart
makes Safari wait for metadata that lives at the end of the fileI checked each one. Range requests: honored, correct 206 responses with proper Content-Range
. Faststart: moov atom at the front, verified. Headers: video/mp4
, correct. Every infrastructure suspect had an alibi. The serving path was completely healthy, which was somehow worse news, because now the file itself was the suspect and the file was "an MP4 that plays fine."
ffprobe
on the shared file settled it in one line. The container was MP4, but the video stream inside it was VP9. Desktop Chrome plays VP9 in an MP4 wrapper without complaint. iPhone Safari does not, and it fails the way Safari loves to fail: no error, no console message, just a player showing 0:00 forever.
The file extension said .mp4, the Content-Type said video/mp4, and both were telling the truth about the container while saying nothing about the codec. Every layer of the stack was technically honest and the sum was a lie.
The fix belonged in the share pipeline's web-optimize step: probe the actual codecs, and if the video is not H.264 or the audio is not AAC, re-encode to the one combination that plays everywhere, instead of trusting the container.
Here is the part I am actually writing this post for.
My first patch probed the streams with ffprobe's CSV output, something shaped like this:
ffprobe -v error -show_entries stream=codec_type,codec_name -of csv=p=0 input.mp4
I wrote the parser assuming each line came back as codec_type,codec_name
, so video,vp9
. Deployed it, re-shared the test video, still 0:00 on the iPhone.
The re-encode condition never fired, because ffprobe prints the fields in its own fixed order, not the order you listed them in -show_entries
. The actual output was vp9,video
. My parser was comparing the codec name against the string "video", the match always failed, the code concluded every file was fine, and the function returned the original untouched file. No exception, no log noise, a clean deploy, and zero effect.
A fix that runs successfully and does nothing is more dangerous than a fix that crashes, because a crash tells you where to look. This one told me nothing, and for a little while I went back to re-suspecting the innocent serving path.
Printing the raw ffprobe output side by side with what my parser thought it saw ended the mystery in about thirty seconds. The lesson was old and evergreen: when parsing tool output, log the raw input next to the parsed result, because your mental model of the format is a hypothesis, not a fact.
With the parser reading fields in the right order, the probe correctly flagged VP9, the pipeline re-encoded to H.264/AAC with faststart, and the same share link played on the same iPhone immediately.
The durable wins:
Not the fix itself, which is twenty lines. It is that the debugging held discipline when the evidence was contradictory: the server was provably healthy AND the file provably did not play. Instead of picking a side and flailing, following the contradiction down one more layer found the third option nobody was accusing, the codec inside a truthful container.
Also, mild pride in having personally shipped, broken, and re-shipped the fix within the same day, which is the full solo founder experience in miniature.