From 573ca01925eba3c5f347a1eff3a9499c2aa25b6e Mon Sep 17 00:00:00 2001 From: 4gray Date: Sun, 23 Nov 2025 21:53:01 +0100 Subject: [PATCH] fix(artplayer): manage Hls instance and centralize player teardown Add a dedicated hls field and a destroyPlayer() helper to ensure Hls instances are properly destroyed when the component is torn down or re-initialized. Replace inline Hls creation with a guarded pattern that destroys any existing hls before creating a new one, preventing leaks or duplicate attachments. Use destroyPlayer() from ngOnDestroy and when the channel input changes to centralize teardown logic and keep lifecycle handling consistent. --- .../lib/art-player/art-player.component.ts | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/libs/ui/components/src/lib/art-player/art-player.component.ts b/libs/ui/components/src/lib/art-player/art-player.component.ts index 890d12ece..4f6580452 100644 --- a/libs/ui/components/src/lib/art-player/art-player.component.ts +++ b/libs/ui/components/src/lib/art-player/art-player.component.ts @@ -38,6 +38,7 @@ export class ArtPlayerComponent implements OnInit, OnDestroy, OnChanges { @Input() showCaptions = false; private player!: Artplayer; + private hls: Hls | null = null; private readonly elementRef = inject(ElementRef); @@ -46,20 +47,26 @@ export class ArtPlayerComponent implements OnInit, OnDestroy, OnChanges { } ngOnDestroy(): void { - if (this.player) { - this.player.destroy(); - } + this.destroyPlayer(); } ngOnChanges(changes: SimpleChanges): void { if (changes['channel'] && !changes['channel'].firstChange) { - if (this.player) { - this.player.destroy(); - } + this.destroyPlayer(); this.initPlayer(); } } + private destroyPlayer(): void { + if (this.hls) { + this.hls.destroy(); + this.hls = null; + } + if (this.player) { + this.player.destroy(); + } + } + private initPlayer(): void { const el = this.elementRef.nativeElement.querySelector( '.artplayer-container' @@ -89,11 +96,14 @@ export class ArtPlayerComponent implements OnInit, OnDestroy, OnChanges { mutex: true, theme: '#ff0000', customType: { - m3u8: function (video: HTMLVideoElement, url: string) { + m3u8: (video: HTMLVideoElement, url: string) => { if (Hls.isSupported()) { - const hls = new Hls(); - hls.loadSource(url); - hls.attachMedia(video); + if (this.hls) { + this.hls.destroy(); + } + this.hls = new Hls(); + this.hls.loadSource(url); + this.hls.attachMedia(video); } else if ( video.canPlayType('application/vnd.apple.mpegurl') ) {