Repository navigation
Decide playability from the codecs, not the file extension - #304
Conversation
isPlayableVideo() asked only the extension, so a .mp4 carrying HEVC video or AC-3 audio passed as playable, went to direct play, and died on the device. An .mp4 of HEVC is as unplayable as an MKV; it just fails later and less obviously because the container opens fine. Audio was never checked anywhere, so an AC-3 or DTS track played silently -- a file that looks like it works and does not. Both questions are asked now and they are separate: the container decides whether the player can open the file at all (iOS cannot demux Matroska whatever is inside), and the codecs decide whether it can decode what it finds. Any one playable audio track is enough, since the transcoder maps a single stream. An unprobed file is still judged on its container alone: "unknown" must not become "unplayable", which would transcode the whole library until the probe caught up. The probe is read only when already loaded, because this runs per row on listings; the endpoints that decide playback load it explicitly.
The first version listed VP8, VP9 and Theora as playable video, Opus and Vorbis as playable audio, and .webm/.ogv as playable containers, because a desktop browser plays all of them. The browser is not the client that breaks. AVFoundation opens neither WebM nor Ogg and decodes none of those codecs, so a .webm of VP9 passed both the container and the codec check and went to direct play -- a black rectangle on the phone, which is the precise failure this check exists to prevent. Opus decodes on Apple only inside a CAF container, not the mp4 a library holds, so it would have produced silence exactly as AC-3 did. H.264 only for video, AAC/MP3/FLAC/ALAC for audio, mp4/m4v/mov for containers. Anything else transcodes, which always works. Four new tests cover the cases, each confirmed to fail against the wider lists.
|
Pushed a correction before you review — the first version of this had the bug it was meant to fix. I listed VP8, VP9 and Theora as playable video, Opus and Vorbis as playable audio, and So a Now: H.264 only for video, AAC/MP3/FLAC/ALAC for audio, mp4/m4v/mov for containers. Everything else transcodes, which always works. The cost of being too narrow is some wasted CPU; the cost of being too wide is a file that looks fine here and fails on the device, so the asymmetry argues for narrow. Four tests added for the cases ( This is worth your eye specifically because it is a judgement call dressed as a fact — if you think HEVC should direct-play on Apple clients, that needs per-client capability negotiation rather than one global list, and I would treat it as separate work rather than widening this. |
|
Verified against real files — the "not verified end-to-end" caveat in the description is now closed. I generated four files with ffmpeg and ran the actual
The MKV row is the one worth looking at: Still not verified: that a transcode of each actually plays on an iPhone. That needs the file on a server the phone can reach, so it remains a check for you rather than something I can close here. |
|
Reviewed on a5 — clean. 15 tests pass. Based on current main, no migration, no file ops. This closes the The codec lists are right: Two nuances, both non-blocking:
Nothing blocking. |
From "I need these files to play on all devices". This is the server-side half of that, and it closes a real hole.
The bug
isPlayableVideo()asked only the file extension. A.mp4carrying HEVC video — or one whose only audio track is AC-3 — passed as playable, was sent to direct play, and died on the device while looking perfectly ordinary on the server.An
.mp4of HEVC is as unplayable as an MKV. It just fails later and less obviously, because the container opens fine.Audio was never checked anywhere. An AC-3 or DTS track played silently — a file that appears to work and does not, which is worse than one that plainly fails.
What it does now
Both questions, because they are separate:
Any one playable audio track is enough: the transcoder maps a single stream and the player picks one it can decode, so a rip carrying AC-3 and AAC plays through the AAC rather than transcoding for nothing.
Two deliberate limits
Unprobed files are still judged on the container alone. "Unknown" must not silently become "unplayable" — that would transcode the whole library until the probe caught up.
library:proberuns hourly now, so this shrinks by itself.The probe is read only when already loaded, since this runs per row on listings and a lazy read would be a query each. The three endpoints that decide playback
loadMissing('probe')explicitly.Testing
11 new tests, 372 pass across playback/streaming/media/probe. Both halves confirmed to fail when removed — extension-only judging (4 fail), ignoring audio codecs (2 fail).
Worth noting the container check exists because a test caught its absence: my first version checked codecs only, and H.264-in-MKV reported playable.
For review
The codec lists are a judgement call.
PLAYABLE_VIDEOis deliberately short — h264/vp8/vp9/theora. HEVC plays on recent Apple hardware and almost nowhere else, which makes it exactly the "sometimes" that produces a black rectangle on whichever device somebody is holding. If you'd rather HEVC direct-play on Apple clients specifically, that needs per-client capability negotiation rather than one list, and I'd treat it as separate work.The transcode command itself was already correct — it always re-encodes to H.264/AAC, so anything ffmpeg can read plays anywhere. The gap was never the encoder; it was deciding when to use it.
Not verified end-to-end. No HEVC or AC-3 file on this machine, so the codec paths are proven by fixtures using real probe JSON shapes, not by playing an actual file. Worth one check on a5 against a known HEVC rip.