初始提交:短剧库源码(含转码优化 ultrafast)
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const {test} = require('node:test');
|
||||
const createLoader = require('./player-media.js');
|
||||
|
||||
function fixture() {
|
||||
class Video extends EventTarget {
|
||||
src = '';
|
||||
error = null;
|
||||
canPlayType() {return 'probably';}
|
||||
load() {}
|
||||
}
|
||||
const instances = [], failures = [];
|
||||
class Hls {
|
||||
static Events = {ERROR:'error',MEDIA_ATTACHED:'attached'};
|
||||
static ErrorTypes = {NETWORK_ERROR:'network'};
|
||||
static isSupported() {return true;}
|
||||
handlers = new Map();
|
||||
destroyed = 0;
|
||||
constructor(options) {this.options=options;instances.push(this);}
|
||||
on(type,handler) {this.handlers.set(type,handler);}
|
||||
attachMedia(video) {this.video=video;}
|
||||
loadSource(url) {this.url=url;}
|
||||
destroy() {this.destroyed++;}
|
||||
emit(type,data) {this.handlers.get(type)?.(type,data);}
|
||||
}
|
||||
const video=new Video();
|
||||
return {Hls,video,instances,failures,loader:createLoader({Hls},video,error=>failures.push(error))};
|
||||
}
|
||||
|
||||
test('changing the media cancels a pending load and ignores the old HLS callbacks', async () => {
|
||||
const f=fixture(), signal=new AbortController().signal;
|
||||
const first=f.loader.load({player:'hls',url:'/old.m3u8'},false,signal);
|
||||
const canceled=assert.rejects(first,{name:'AbortError'});
|
||||
const old=f.instances[0];
|
||||
const next=f.loader.load({player:'hls',url:'/new.m3u8'},false,signal,7.25);
|
||||
old.emit('error',{fatal:true,type:'network'});
|
||||
old.emit('attached');
|
||||
const current=f.instances[1];
|
||||
current.emit('attached');
|
||||
assert.equal(current.url,'/new.m3u8');
|
||||
assert.equal(current.options.startPosition,7.25);
|
||||
assert.equal(old.url,undefined);
|
||||
f.video.dispatchEvent(new Event('loadedmetadata'));
|
||||
await Promise.all([next,canceled]);
|
||||
assert.equal(old.destroyed,1);
|
||||
assert.deepEqual(f.failures,[]);
|
||||
f.loader.destroy();
|
||||
});
|
||||
|
||||
test('synchronous HLS initialization failures clean up and a later load can succeed', async () => {
|
||||
const f=fixture(), signal=new AbortController().signal;
|
||||
f.Hls.prototype.attachMedia=function(){throw new Error('fixture attach failure');};
|
||||
await assert.rejects(f.loader.load({player:'hls',url:'/failed.m3u8'},false,signal),error=>error.playbackDecode===true);
|
||||
assert.equal(f.instances[0].destroyed,1);
|
||||
const next=f.loader.load({player:'mp4',url:'/ready.mp4',mime:'video/mp4'},false,signal);
|
||||
f.video.dispatchEvent(new Event('loadedmetadata'));
|
||||
await next;
|
||||
assert.equal(f.video.src,'/ready.mp4');
|
||||
f.loader.destroy();
|
||||
});
|
||||
|
||||
test('aborting an in-flight load destroys its HLS session without reporting a playback failure', async () => {
|
||||
const f=fixture(), abort=new AbortController();
|
||||
const pending=f.loader.load({player:'hls',url:'/canceled.m3u8'},false,abort.signal);
|
||||
const rejected=assert.rejects(pending,{name:'AbortError'});
|
||||
abort.abort();
|
||||
await rejected;
|
||||
const old=f.instances[0];
|
||||
old.emit('error',{fatal:true,type:'network'});
|
||||
assert.equal(old.destroyed,1);
|
||||
assert.deepEqual(f.failures,[]);
|
||||
f.loader.destroy();
|
||||
});
|
||||
|
||||
test('fatal HLS errors after metadata retain the network versus decode distinction', async () => {
|
||||
const f=fixture();
|
||||
const pending=f.loader.load({player:'hls',url:'/ready.m3u8'},false,new AbortController().signal);
|
||||
f.video.dispatchEvent(new Event('loadedmetadata'));
|
||||
await pending;
|
||||
f.instances[0].emit('error',{fatal:false,type:'network'});
|
||||
assert.deepEqual(f.failures,[]);
|
||||
f.instances[0].emit('error',{fatal:true,type:'network'});
|
||||
assert.equal(f.failures[0].playbackNetwork,true);
|
||||
assert.equal(f.failures[0].playbackDecode,false);
|
||||
f.loader.destroy();
|
||||
});
|
||||
Reference in New Issue
Block a user