@ -82,7 +82,7 @@ const playM3u8 =
hls . loadSource ( url ) ;
hls . loadSource ( url ) ;
hls . attachMedia ( video ) ;
hls . attachMedia ( video ) ;
art . hls = hls ;
art . hls = hls ;
art. on ( "destroy" , ( ) = > hls . destroy ( ) ) ;
hookMediaDestroy( art , "hls" ) ;
} else if ( video . canPlayType ( "application/vnd.apple.mpegurl" ) ) {
} else if ( video . canPlayType ( "application/vnd.apple.mpegurl" ) ) {
video . src = url ;
video . src = url ;
} else {
} else {
@ -106,12 +106,35 @@ const playFlv = (video: HTMLVideoElement, url: string, art: Artplayer) => {
flv . attachMediaElement ( video ) ;
flv . attachMediaElement ( video ) ;
flv . load ( ) ;
flv . load ( ) ;
art . flv = flv ;
art . flv = flv ;
art. on ( "destroy" , ( ) = > flv . destroy ( ) ) ;
hookMediaDestroy( art , "flv" ) ;
} else {
} else {
art . notice . show = "Unsupported playback format: flv" ;
art . notice . show = "Unsupported playback format: flv" ;
}
}
} ;
} ;
// Registers a single destroy hook per media type. switchUrl() re-invokes the
// customType handler and would otherwise stack one handler per player —
// destroying a stale, already-destroyed instance (mpegts null-derefs, #3139).
const hookedPlayers = new WeakMap < Artplayer , Set < string > > ( ) ;
const hookMediaDestroy = ( art : Artplayer , key : "hls" | "flv" ) = > {
let flags = hookedPlayers . get ( art ) ;
if ( ! flags ) {
flags = new Set ( ) ;
hookedPlayers . set ( art , flags ) ;
}
if ( flags . has ( key ) ) {
return ;
}
flags . add ( key ) ;
art . on ( "destroy" , ( ) = > {
try {
art [ key ] ? . destroy ( ) ;
} catch ( e ) {
console . warn ( ` Failed to destroy ${ key } player: ` , e ) ;
}
} ) ;
} ;
export default function Player ( {
export default function Player ( {
option ,
option ,
chapters ,
chapters ,