fix(playback): route non-HLS containers to the native source path (#1510)

The HTML5 player chose its engine by exclusion: anything that was not
mpd/ts/mp4 went to hls.js, so .mkv (the default Xtream series/VOD
container), .webm, .avi, .mov and .m4v were fed to hls.js as manifests.
hls.js raised a manifest error and the player showed the network/provider
diagnostic over media Chromium plays natively.

Add resolvePlaybackUrlSourceKind() to @iptvnator/playback/util as the one
URL-to-engine rule (mpd -> dash, m3u8/m3u -> hls, ts/m2ts/extension-less
-> mpegts, everything else -> native) and read it from both the HTML5
player and ArtPlayer's getArtPlayerVideoType(), so the two engines agree.
ArtPlayer serves every native container through a single
ART_PLAYER_NATIVE_SOURCE_TYPE custom type, keeping the source session the
owner of teardown and controls binding. The HTML5 native <source> carries
the video/mp4 hint only for MP4-family files: a hint the browser's
canPlayType() rejects makes it skip the source, and Chromium demuxes
containers it does not advertise there.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Fable 5.1 authored and GitHub committed 2026-09-03 09:43:33 +02:00
1 parent 0a2f6121f8
commit 5e51c1ea5d
15 files changed
+257 -35

No files matched your search

+17 -4
View File
@@ -635,12 +635,25 @@ video.
URL extension metadata is filtered before diagnostics and player selection use it. Web script extensions such as `.php` are not shown as stream containers; explicit media query metadata such as `extension=ts` or `format=m3u8` is preferred when present.
The HTML5 player and ArtPlayer choose their source engine from one URL rule,
`resolvePlaybackUrlSourceKind()` in `@iptvnator/playback/util`, which maps the
normalized media extension to `dash` (`mpd`), `hls` (`m3u8`/`m3u`), `mpegts`
(`ts`, `m2ts`, and extension-less proxy/script URLs) or `native` (every other
container: `mkv`, `webm`, `mp4`, `avi`, `mov`, `m4v`, audio files). hls.js
therefore only ever receives HLS manifests; it used to be handed every
unlisted container and raised a manifest error over media Chromium plays by
itself. ArtPlayer serves the `native` kind through a single
`ART_PLAYER_NATIVE_SOURCE_TYPE` custom type so `ArtPlayerSourceSession` keeps
owning engine teardown and controls binding; the HTML5 player appends one
`<source>` whose `video/mp4` MIME hint is set only for MP4-family files, since
a hint the browser's `canPlayType()` rejects makes it skip the source
(`resolveNativeSourceMimeType()`).
MKV sources are attempted through Chromium's native Matroska path. Video.js
receives `video/matroska` for `.mkv` URLs and explicit query metadata such as
`extension=mkv` or `container=mkv`; ArtPlayer and HTML5 continue to use their
native video paths. This is container support rather than a universal codec
guarantee: native source or decode failures still produce a diagnostic whose
ranked actions may include MPV/VLC.
`extension=mkv` or `container=mkv`. This is container support rather than a
universal codec guarantee: native source or decode failures still produce a
diagnostic whose ranked actions may include MPV/VLC.
Portal VOD and episode payloads with `contentInfo` are treated as non-live by the inline players unless `isLive` is explicitly set. If Chromium leaves the underlying MediaSource duration at `Infinity` for a finite TS VOD, the Video.js wrapper normalizes its UI duration from the finite `seekable` or `buffered` range. Embedded MPV uses the same live decision rule and shows an unknown duration placeholder for VOD/episode snapshots until MPV reports a finite duration. This removes the misleading `LIVE` control state without changing stream decoding, diagnostics, or external fallback behavior.
+3 -2
View File
@@ -1037,8 +1037,9 @@ player in settings.
because those players never receive its keys.
Channels with `drm.supported === false` emit a `DrmOrEncryption` diagnostic
with a fixed safe detail string and without starting an engine.
- HTML5 player: `extension === 'mpd'` branch in `playChannel()`. ArtPlayer:
`customType.mpd` in `ArtPlayerSourceSession`. Shared-controls bridge:
- HTML5 player: the `dash` branch of `playChannel()` (source kind from the
shared `resolvePlaybackUrlSourceKind()`). ArtPlayer: `customType.mpd` in
`ArtPlayerSourceSession`. Shared-controls bridge:
`WebVideoControlsSource` kind `'shaka'` + `WebVideoShakaControls`
(audio/text tracks via the Shaka 5 API — selecting a text track shows it,
`selectTextTrack(null)` hides).