mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
fix(playback): keep Video.js controls on the live MPEG-TS path (#1385)
Video.js was constructed without the controls option — the component relied on a [controls] template binding on the original <video> element instead. player.reset(), which every raw MPEG-TS/live source change goes through, replaces the tech <video> element; the binding's target is disposed, so live playback ended up with no native controls and a vjs-controls-disabled control bar: no visible controls at all. Enable controls through the Video.js constructor options in legacy mode and drop the template binding. The Video.js control bar is a player-level child that survives loadTech_, so it stays across resets — and the quality selector and aspect-ratio panel buttons it hosts become reachable again. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f58460380f
commit
c95f826739
5 files changed
+39
-3
No files matched your search
@@ -19,9 +19,29 @@ describe('Video.js player setup', () => {
|
||||
expect(createVjsPlayerOptions(options, false, false)).toEqual({
|
||||
...options,
|
||||
autoplay: true,
|
||||
controls: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps Video.js controls enabled on the raw MPEG-TS legacy path', () => {
|
||||
// player.reset() replaces the tech <video>, so the control bar must
|
||||
// come from the constructor option — a template binding on the
|
||||
// original element cannot survive the swap.
|
||||
expect(
|
||||
createVjsPlayerOptions(
|
||||
{ sources: [{ src: 'https://example.test/live.ts' }] },
|
||||
true,
|
||||
false
|
||||
)
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
sources: [],
|
||||
autoplay: false,
|
||||
controls: true,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('removes duplicate Video.js interaction ownership for shared controls', () => {
|
||||
expect(
|
||||
createVjsPlayerOptions(
|
||||
|
||||
@@ -13,7 +13,12 @@ export function createVjsPlayerOptions(
|
||||
? { ...options, sources: [], autoplay: false }
|
||||
: { ...options, autoplay: true };
|
||||
if (!sharedControls) {
|
||||
return baseOptions;
|
||||
// Controls must be enabled through the constructor, not a `[controls]`
|
||||
// template binding: `player.reset()` (raw MPEG-TS/live path) replaces
|
||||
// the tech <video> element, and a binding to the original element can
|
||||
// never reach the replacement — Video.js's own control bar lives
|
||||
// outside the tech element and survives the swap.
|
||||
return { ...baseOptions, controls: true };
|
||||
}
|
||||
return {
|
||||
...baseOptions,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<video
|
||||
#target
|
||||
class="video-js"
|
||||
[controls]="!sharedControls"
|
||||
muted
|
||||
playsinline
|
||||
preload="none"
|
||||
|
||||
@@ -78,13 +78,16 @@ describe('VjsPlayerComponent', () => {
|
||||
expect.any(Element),
|
||||
expect.objectContaining({
|
||||
autoplay: true,
|
||||
controls: true,
|
||||
userActions: { hotkeys: true },
|
||||
spatialNavigation: { enabled: true },
|
||||
}),
|
||||
expect.any(Function)
|
||||
);
|
||||
// Native controls stay off: Video.js owns the control bar, and the
|
||||
// bar has to survive the tech-element swap in player.reset().
|
||||
expect(fixture.nativeElement.querySelector('video').controls).toBe(
|
||||
true
|
||||
false
|
||||
);
|
||||
expect(
|
||||
fixture.nativeElement.querySelector('app-player-controls')
|
||||
|
||||
Reference in new issue
Block a user