pr-player 0.1.9 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PrPlayer.d.ts +34 -25
- package/dist/audioPlayer/audioPlayer.d.ts +4 -1
- package/dist/decoder/Decoder.d.ts +23 -2
- package/dist/decoder/DecoderWorker.d.ts +8 -2
- package/dist/decoder/type.d.ts +14 -1
- package/dist/demuxer/Demuxer.d.ts +1 -1
- package/dist/demuxer/flv264Parser.d.ts +1 -1
- package/dist/demuxer/ts264Parser.d.ts +1 -1
- package/dist/index.js +500 -464
- package/dist/index.umd.cjs +4 -4
- package/dist/render/Render.d.ts +4 -29
- package/dist/render/RenderWorker.d.ts +2 -9
- package/dist/render/type.d.ts +0 -1
- package/dist/tools.d.ts +1 -2
- package/package.json +2 -2
- /package/dist/{cacher → demuxer}/Cacher.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const D = '(function(){"use strict";class P{pendingPayloads=[];payload=new Uint8Array(0);chunks=[];push=t=>{this.pendingPayloads.push(t)};next=(t=0)=>{this.payload=this.payload.slice(t);const s=this.pendingPayloads.shift();if(!s)return!1;const e=new Uint8Array(this.payload.byteLength+s.byteLength);return e.set(this.payload,0),e.set(s,this.payload.byteLength),this.payload=e,new DataView(this.payload.buffer)};pushChunk=t=>{this.chunks.push(t),this.chunks.length>1e3&&this.chunks.shift()};destroy=()=>{this.pendingPayloads=[],this.payload=new Uint8Array(0),this.chunks=[]}}const I=(y,t)=>{const s=new Uint8Array(y),e=new Uint8Array(t),n=new Uint8Array(11+s.length+e.length);let a=0;return n[a++]=1,n[a++]=s[1],n[a++]=s[2],n[a++]=s[3],n[a++]=255,n[a++]=225,n[a++]=s.length>>8&255,n[a++]=s.length&255,n.set(s,a),a+=s.length,n[a++]=1,n[a++]=e.length>>8&255,n[a++]=e.length&255,n.set(e,a),n},T=y=>{let t=0;const s=new DataView(y.buffer),e=s.getUint8(t);if(t=t+1,e!==1)throw new Error("Invalid AVC version");const n=s.getUint8(t)&255;t=t+1;const a=s.getUint8(t)&255;t=t+1;const o=s.getUint8(t)&255;t=t+1;const c=`avc1.${Array.from([n,a,o],U=>U.toString(16).padStart(2,"0")).join("")}`,r=(s.getUint8(t)&3)-1;t=t+1;const g=s.getUint8(t)&31;t=t+1;const p=s.getUint16(t,!1);t=t+2;const h=new Uint8Array(s.buffer.slice(t,t+p));t=t+p;const d=s.getUint8(t)&31;t=t+1;const u=s.getUint16(t,!1);t=t+2;const f=new Uint8Array(s.buffer.slice(t,t+u));return t=t+u,{version:e,codec:c,profile:n,compatibility:a,level:o,lengthSizeMinusOne:r,numOfSequenceParameterSets:g,sequenceParameterSetLength:p,sps:h,numOfPictureParameterSets:d,pictureParameterSetLength:u,pps:f}},M=y=>{const t=new Uint8Array(4+y.length);return new DataView(t.buffer).setUint32(0,y.length,!1),t.set(y,4),t},C=y=>{let t=0;for(const n of y)t+=n.length;const s=new Uint8Array(t);let e=0;for(const n of y){const a=n;s.set(a,e),e+=a.length}return s},D=y=>{let t="unknown";switch(y){case 1:case 2:case 27:case 36:t="video";break;case 3:case 4:case 15:t="audio";break;case 6:t="subtitle";break;case 134:t="ad";break}return t};class x{pat;pmt;audioConfig;videoConfig;payloadMap=new Map;on={};constructor(){}parse=async t=>{let s=0;for(;!(s+188>t.byteLength);){if(t.getInt8(s)!=71){s++;continue}await this.parsePacket(t,s),s+=188}return s};parsePacket=async(t,s)=>{if(s+188>t.byteLength)throw new Error("Invalid TS packet");if(t.getUint8(s)!==71)throw new Error("Invalid TS packet");let e=s;const n=this.parseHeader(t,e);e+=4;const{transport_error_indicator:a,pid:o,payload_unit_start_indicator:l,adaptation_field_control:i}=n;if(a===1||o===void 0)return;let c=184;if(i===2||i===3){const r=t.getUint8(e);e+=1,this.parseAdaptationField(t,e),e+=r,c-=r}if(i===3&&(c-=1),i===1||i===3){const r=new Uint8Array(t.buffer.slice(e,e+c));if(o===0)return this.parsePAT(t,e);{const{programs:h=[]}=this.pat||{};if(h.find(u=>u.pmt_pid===o))return this.parsePMT(t,e)}const{streams:g=[]}=this.pmt||{},p=g.find(h=>h.elementary_pid===o);if(p){if(l===1){const h=this.payloadMap.get(o);if(h){switch(p.kind){case"audio":{const d=await this.parseAudio(h);this.on.chunk&&this.on.chunk(d)}break;case"video":{const d=await this.parseVideo(h);this.on.chunk&&this.on.chunk(d),await new Promise(u=>setTimeout(()=>u(!0),8))}break}this.payloadMap.delete(o)}}{this.payloadMap.has(o)||this.payloadMap.set(o,new Uint8Array);const h=this.payloadMap.get(o),d=new Uint8Array(h.byteLength+r.byteLength);d.set(h,0),d.set(r,h.byteLength),this.payloadMap.set(o,d)}}}};parseHeader=(t,s)=>{let e=s;const n=t.getUint8(e),a=t.getUint8(e+1),o=t.getUint8(e+2),l=t.getUint8(e+3),i=(a&128)>>7;if(i===1)return{sync_byte:n,transport_error_indicator:i};const c=(a&64)>>6,r=(a&32)>>5,g=(a&31)<<8|o,p=(l&192)>>6,h=l>>4&3,d=l&15;return{sync_byte:n,transport_error_indicator:i,payload_unit_start_indicator:c,transport_priority:r,pid:g,transport_scrambling_control:p,adaptation_field_control:h,continuity_counter:d}};parsePAT=(t,s)=>{let e=s,n;{const l=t.getUint8(e);e+=1;const i=t.getUint8(e);if(e+=1,i!==0)throw new Error("Invalid PAT table_id");const c=t.getUint16(e)&4095;e+=2;const r=t.getUint16(e);e+=2;const g=(t.getUint8(e)&62)>>1,p=t.getUint8(e)&1;e+=1;const h=t.getUint8(e);e+=1;const d=t.getUint8(e);e+=1,n={pointer_field:l,table_id:i,section_length:c,transport_stream_id:r,version_number:g,current_next_indicator:p,section_number:h,last_section_number:d}}const a=[];{const l=n.section_length-5-4,i=e+l;for(;e<i;){const c=t.getUint16(e),r=t.getUint16(e+2)&8191;e+=4,c!==0&&r>=32&&r<=8190&&a.push({program_number:c,pmt_pid:r})}}const o=t.getUint32(e);this.pat={header:n,programs:a,crc32:o},this.on.debug&&this.on.debug({pat:this.pat})};parsePMT=(t,s)=>{let e=s,n;{const l=t.getUint8(e);e+=1;const i=t.getUint8(e);if(e+=1,i!==2)throw new Error("Invalid PMT table_id");const c=t.getUint16(e)&4095;e+=2;const r=t.getUint16(e);e+=2;const g=(t.getUint8(e)&62)>>1,p=t.getUint8(e)&1;e+=1;const h=t.getUint8(e);e+=1;const d=t.getUint8(e);e+=1;const u=t.getUint16(e)&8191;e+=2;const f=t.getUint16(e)&4095;e+=2,n={pointer_field:l,table_id:i,section_length:c,transport_stream_id:r,version_number:g,current_next_indicator:p,section_number:h,last_section_number:d,pcr_pid:u,program_info_length:f}}const a=[];{const l=n.section_length-9-4,i=e+l;for(;e<i;){const c=t.getUint8(e),r=D(c),g=t.getUint16(e+1)&8191,p=t.getUint16(e+3)&4095;if(e+=5,g<32||g>8190){console.warn(`Invalid elementary_pid: 0x${g.toString(16)}`);continue}a.push({kind:r,stream_type:c,elementary_pid:g,es_info_length:p})}}const o=t.getUint32(e);this.pmt={header:n,streams:a,crc32:o},this.on.debug&&this.on.debug({pmt:this.pmt})};parseAdaptationField=(t,s)=>{let e=s,n,a,o,l;const i=t.getUint8(e),c=!!(i&128),r=!!(i&64),g=!!(i&32),p=!!(i&16),h=!!(i&8),d=!!(i&4),u=!!(i&2),f=!!(i&1);e+=1;const U=(_,b)=>{let m=BigInt(0);m|=BigInt(_.getUint16(b))<<25n,m|=BigInt(_.getUint16(b+1))<<17n,m|=BigInt(_.getUint16(b+2))<<9n,m|=BigInt(_.getUint16(b+3))<<1n,m|=BigInt(_.getUint16(b+4)>>7);const S=(_.getUint16(b+4)&1)<<8|_.getUint16(b+5);return m=m*300n+BigInt(S),m};if(p&&(n=U(t,e),e+=6),h&&(a=U(t,e),e+=6),d&&(o=t.getInt8(e),e+=1),u){const _=t.getUint8(e);e+=1,l=new Uint8Array(t.buffer,e,_),e+=_}return{discontinuity_indicator:c,random_access_indicator:r,elementary_stream_priority_indicator:g,pcr_flag:p,opcr_flag:h,splicing_point_flag:d,transport_private_data_flag:u,adaptation_field_extension_flag:f,pcr:n,opcr:a,splice_countdown:o,transport_private_data:l}};parseAudio=async t=>{const s=new DataView(t.buffer);let e=0,n,a;{const o=s.getUint8(e)===0&&s.getUint8(e+1)===0&&s.getUint8(e+2)===1;if(e+=3,!o)throw new Error("invalid ts audio payload.");const l=s.getUint8(e);e+=1;const i=s.getUint8(e)<<8|s.getUint8(e+1);e+=2;let c,r,g,p,h;{const f=s.getUint8(e);e+=1,c=f>>4&3,r=(f>>3&1)===1,g=(f>>2&1)===1,p=(f>>1&1)===1,h=(f&1)===1}let d,u;{const f=s.getUint8(e);e+=1;const U=f>>6,_=s.getUint8(e);e+=1,(U&2)===2&&(d=this.parsePtsDts(s,e)),(U&1)===1?u=this.parsePtsDts(s,e+5):u=d,e+=_}n={stream_id:l,pes_packet_length:i,scrambling_control:c,priority:r,data_alignment:g,copyright:p,original_copy:h,pts:d,dts:u}}a=t.slice(e);{if(!this.audioConfig&&s.getUint8(e)===255){const g=s.getUint8(e+2),p=s.getUint8(e+3);let h,d;d=g>>2&15,h=(g&1)<<2|p>>6;const u=`mp4a.40.${h}`,U=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350][d];this.audioConfig={kind:"audio",codec:u,sampleRate:U,numberOfChannels:h},this.on.config&&this.on.config(this.audioConfig)}const{dts:o=0,pts:l=0}=n,i=l-o,c=a.slice(7);return{kind:"audio",type:"key",dts:o,pts:l,cts:i,data:c}}};parseVideo=async t=>{const s=new DataView(t.buffer);let e=0,n,a;{const o=s.getUint8(e)===0&&s.getUint8(e+1)===0&&s.getUint8(e+2)===1;if(e+=3,!o)throw new Error("invalid ts video payload.");const l=s.getUint8(e);e+=1;const i=s.getUint8(e)<<8|s.getUint8(e+1);e+=2;let c,r,g,p,h;{const f=s.getUint8(e);e+=1,c=f>>4&3,r=(f>>3&1)===1,g=(f>>2&1)===1,p=(f>>1&1)===1,h=(f&1)===1}let d,u;{const f=s.getUint8(e);e+=1;const U=f>>6,_=s.getUint8(e);e+=1,(U&2)===2&&(d=this.parsePtsDts(s,e)),(U&1)===1?u=this.parsePtsDts(s,e+5):u=d,e+=_}n={stream_id:l,pes_packet_length:i,scrambling_control:c,priority:r,data_alignment:g,copyright:p,original_copy:h,pts:d,dts:u}}a=t.slice(e);{const o=this.getNalus(a);if(!this.videoConfig){let h,d;if(h=o.find(f=>f.type===7)?.nalu.slice(4),d=o.find(f=>f.type===8)?.nalu.slice(4),h&&d){const u=I(h,d),{codec:f}=T(u);this.videoConfig={kind:"video",codec:f,description:u,sps:h,pps:d},this.on.config&&this.on.config(this.videoConfig)}}const l=[];let i="delta";for(const h of o){const{type:d,nalu:u}=h;switch(d){case 6:case 9:l.push(u);break;case 1:i="delta",l.push(u);break;case 5:i="key",l.push(u);break}}const c=C(l),{dts:r=0,pts:g=0}=n,p=g-r;return{kind:"video",type:i,dts:r,pts:g,cts:p,data:c,nalus:l}}};parsePtsDts(t,s){const e=t.getUint8(s),n=t.getUint8(s+1),a=t.getUint8(s+2),o=t.getUint8(s+3),l=t.getUint8(s+4),i=(BigInt(e)&0b00001110n)<<29n|(BigInt(n)&0b11111111n)<<22n|(BigInt(a)&0b11111110n)<<14n|(BigInt(o)&0b11111111n)<<7n|(BigInt(l)&0b11111110n)>>1n;return Number(i)/90}getNalus=t=>{const s=[];let e=0;for(;!(e+4>t.byteLength);){if(t[e]!==0||t[e+1]!==0||t[e+2]!==1){e+=1;continue}e+=3;let n=e;const a=t[e]&31;for(e+=1;!(e+1>t.byteLength);){if(t[e]!==0||t[e+1]!==0||t[e+2]!==1){e+=1;continue}break}let o=e-n;if(t[e-1]===0&&(o-=1),o!==0){const l=t.slice(n,n+o),i=M(l);s.push({type:a,nalu:i})}}return s}}const k=(y,t)=>y.getUint8(t)<<16|y.getUint8(t+1)<<8|y.getUint8(t+2);class L{audioConfig;videoConfig;header;textDecoder=new TextDecoder("utf-8");on={};constructor(){}parse=async t=>{let s=0;for(this.header||(this.parseHeader(t,s),s+=9);this.isSurplusTag(t,s)!==!1;){const n=this.parseTagHeader(t,s+4),{tagType:a,dataSize:o,timestamp:l}=n;if(a){const i=this.parseTagBody(a,t,s+4+11,o);switch(a){case"script":this.on.info&&this.on.info(i);break;case"audio":{const{accPacketType:c}=i;if(c===0){const{codec:r,sampleRate:g,channelConfiguration:p}=i;this.audioConfig={kind:"audio",codec:r,sampleRate:g,numberOfChannels:p},this.on.config&&this.on.config(this.audioConfig)}else{const{cts:r,data:g}=i,p="key",h=r===void 0?void 0:r+l;this.on.chunk&&this.on.chunk({kind:"audio",type:p,dts:l,pts:h,cts:r,data:g})}}break;case"video":{const{avcPacketType:c}=i;if(c===0){const{codec:r,sps:g,pps:p,data:h}=i;this.videoConfig={kind:"video",codec:r,description:h,sps:g,pps:p},this.on.config&&this.on.config(this.videoConfig)}else{const{frameType:r,cts:g,data:p,nalus:h}=i,d=r===1?"key":"delta",u=g===void 0?void 0:g+l;this.on.chunk&&this.on.chunk({kind:"video",type:d,dts:l,pts:u,cts:g,data:p,nalus:h})}}break}s=s+4+11+o}await new Promise(i=>setTimeout(()=>i(!0),8))}return s};parseHeader=(t,s)=>{let e,n,a,o;e=t.getUint8(s)<<16|t.getUint8(s+1)<<8|t.getUint8(s+2),n=t.getUint8(3);{const i=t.getUint8(0).toString(2).padStart(5,"0").split(""),[,,c,,r]=i;a={audio:r==="1",video:c==="1"}}o=t.getUint32(5),this.header={signature:e,version:n,flags:a,dataOffset:o}};isSurplusTag=(t,s)=>{let e=!0;const n=t.byteLength;if(s+4>n)e=!1;else if(s+4+11>n)e=!1;else{const a=k(t,s+4+1);s+4+11+a>n&&(e=!1)}return e};parseTagHeader=(t,s)=>{let e,n,a,o,l;{const i=t.getUint8(s);let c;switch(i){case 18:c="script";break;case 8:c="audio";break;case 9:c="video";break}e=c}return n=k(t,s+1),a=k(t,s+4),o=t.getUint8(s+7),l=k(t,s+8),{tagType:e,dataSize:n,timestamp:a,timestampExtended:o,streamID:l}};parseTagBody=(t,s,e,n)=>{let a;switch(t){case"script":a=this.parseMetaData(s,e);break;case"audio":a=this.parseAudio(s,e,n);break;case"video":a=this.parseVideo(s,e,n);break}return a};parseMetaData=(t,s)=>{let e=s;{if(t.getUint8(e)!==2)throw new Error("Invalid AMF type for onMetaData (expected 0x02)");e=e+1}const n=t.getUint16(e,!1);e=e+2;{const l=new Int8Array(t.buffer.slice(e,e+n));if((this.textDecoder?.decode(l)||"")!=="onMetaData")throw new Error("Expected \'onMetaData\' string");e=e+n}const a=this.getAmfType(t,e);return e=e+1,this.getAMFValue(t,e,a).value};parseAudio=(t,s,e)=>{let n=s;const a=t.getUint8(n),o=a>>4&15,l=a>>2&3,i=a>>1&1,c=a&1;n=n+1;const r=t.getUint8(n);n=n+1;const g=e,p=new Uint8Array(t.buffer.slice(n,n+g));if(o===10&&r===0){const h=t.getUint8(n),d=t.getUint8(n+1),u=h>>3&31,f=(h&7)<<1|d>>7,U=d>>3&15,_=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],b=`mp4a.40.${u}`,m=_[f];return{soundFormat:o,soundRate:l,soundSize:i,soundType:c,accPacketType:r,data:p,samplingFrequencyIndex:f,channelConfiguration:U,codec:b,sampleRate:m}}return{soundFormat:o,soundRate:l,soundSize:i,soundType:c,accPacketType:r,data:p}};parseVideo=(t,s,e)=>{let n=s;const a=t.getUint8(n),o=a>>4&15,l=a&15;n=n+1;const i=t.getUint8(n);n=n+1;const c=k(t,n);n=n+3;const r=e-5,g=new Uint8Array(t.buffer.slice(n,n+r));switch(l){case 7:if(i===0){const p=T(g);return{frameType:o,codecID:l,avcPacketType:i,cts:c,data:g,...p}}else if(i===1){const p=[],h=n+e-5;for(;!(n+4>h);){const d=t.getUint32(n,!1),u=new Uint8Array(t.buffer.slice(n,n+4+d));n+=4+d,p.push(u)}return{frameType:o,codecID:l,avcPacketType:i,cts:c,data:g,nalus:p}}break;default:throw new Error("Unsupported codecID")}return{frameType:o,codecID:l,avcPacketType:i,cts:c,data:g}};getAmfType=(t,s)=>t.getUint8(s);getAMFName=(t,s,e)=>{const n=new Uint8Array(t.buffer.slice(s,s+e));return this.textDecoder?.decode(n)||""};getAMFValue=(t,s,e)=>{let n=s,a,o=0;switch(e){case 0:a=t.getFloat64(n,!1),o=8;break;case 1:a=!!t.getUint8(n),o=1;break;case 2:{a="";const i=t.getUint16(n,!1);n=n+2;const c=new Int8Array(t.buffer,n,i).filter(g=>g!==0);a=(this.textDecoder?.decode(c)||"").trim(),o=2+i}break;case 3:for(a={};n<t.byteLength;){const i=t.getUint16(n,!1);if(i===0)break;n=n+2;const c=this.getAMFName(t,n,i);n=n+i;const r=this.getAmfType(t,n);if(r===6)break;n=n+1;const g=this.getAMFValue(t,n,r);n=n+g.length,a[c]=g.value,o=2+i+1+g.length}break;case 8:{a={};const i=t.getUint32(n,!1);n=n+4;for(let c=0;c<i;c++){const r=t.getUint16(n,!1);n=n+2;const g=this.getAMFName(t,n,r);n=n+r;const p=this.getAmfType(t,n);n=n+1;const h=this.getAMFValue(t,n,p);n=n+h.length,a[g]=h.value,o=2+r+1+h.length}}break;case 10:{a=[];const i=t.getUint32(n,!1);n=n+4;for(let c=0;c<i;c++){const r=this.getAmfType(t,n);n=n+1;const g=this.getAMFValue(t,n,r);n=n+g.length,a.push(g.value),o=1+g.length}}break}return{amfType:e,length:o,value:a}}}class O{pattern;cacher=new P;isParseing=!1;offset=0;on={};parser;constructor(){}init=t=>{switch(this.destroy(),this.pattern=t,this.pattern){case"flv":this.parser=new L;break;case"hls":this.parser=new x;break;default:throw new Error("is error pattern.")}this.parser.on.debug=s=>this.on.debug&&this.on.debug(s),this.parser.on.info=s=>this.on.info&&this.on.info(s),this.parser.on.config=s=>this.on.config&&this.on.config(s),this.parser.on.chunk=s=>{this.cacher.pushChunk(s),this.on.chunk&&this.on.chunk(s)}};push=t=>{this.cacher.push(t),this.isParseing===!1&&this.parse()};destroy=()=>{this.cacher.destroy(),this.isParseing=!1,this.offset=0};parse=async()=>{try{if(this.isParseing=!0,!this.pattern)throw new Error("You need to set the pattern.");if(!this.parser)throw new Error("You need to init parser.");for(;;){const t=this.cacher.next(this.offset);if(this.offset=0,!t)break;this.offset=await this.parser.parse(t)}this.isParseing=!1}catch{this.destroy()}}}const A=new O;A.on.debug=y=>postMessage({action:"onDebug",data:y}),A.on.info=y=>postMessage({action:"onInfo",data:y}),A.on.config=y=>postMessage({action:"onConfig",data:y}),A.on.chunk=y=>postMessage({action:"onChunk",data:y}),onmessage=y=>{const{action:t,data:s}=y.data,e=A[t];e&&e(s)}})();\n', v = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", D], { type: "text/javascript;charset=utf-8" });
|
|
2
|
-
function
|
|
1
|
+
const D = '(function(){"use strict";class P{pendingPayloads=[];payload=new Uint8Array(0);chunks=[];push=t=>{this.pendingPayloads.push(t)};next=(t=0)=>{this.payload=this.payload.slice(t);const s=this.pendingPayloads.shift();if(!s)return!1;const e=new Uint8Array(this.payload.byteLength+s.byteLength);return e.set(this.payload,0),e.set(s,this.payload.byteLength),this.payload=e,new DataView(this.payload.buffer)};pushChunk=t=>{this.chunks.push(t),this.chunks.length>1e3&&this.chunks.shift()};destroy=()=>{this.pendingPayloads=[],this.payload=new Uint8Array(0),this.chunks=[]}}const I=(y,t)=>{const s=new Uint8Array(y),e=new Uint8Array(t),n=new Uint8Array(11+s.length+e.length);let a=0;return n[a++]=1,n[a++]=s[1],n[a++]=s[2],n[a++]=s[3],n[a++]=255,n[a++]=225,n[a++]=s.length>>8&255,n[a++]=s.length&255,n.set(s,a),a+=s.length,n[a++]=1,n[a++]=e.length>>8&255,n[a++]=e.length&255,n.set(e,a),n},T=y=>{let t=0;const s=new DataView(y.buffer),e=s.getUint8(t);if(t=t+1,e!==1)throw new Error("Invalid AVC version");const n=s.getUint8(t)&255;t=t+1;const a=s.getUint8(t)&255;t=t+1;const o=s.getUint8(t)&255;t=t+1;const c=`avc1.${Array.from([n,a,o],U=>U.toString(16).padStart(2,"0")).join("")}`,r=(s.getUint8(t)&3)-1;t=t+1;const g=s.getUint8(t)&31;t=t+1;const p=s.getUint16(t,!1);t=t+2;const h=new Uint8Array(s.buffer.slice(t,t+p));t=t+p;const d=s.getUint8(t)&31;t=t+1;const u=s.getUint16(t,!1);t=t+2;const f=new Uint8Array(s.buffer.slice(t,t+u));return t=t+u,{version:e,codec:c,profile:n,compatibility:a,level:o,lengthSizeMinusOne:r,numOfSequenceParameterSets:g,sequenceParameterSetLength:p,sps:h,numOfPictureParameterSets:d,pictureParameterSetLength:u,pps:f}},M=y=>{const t=new Uint8Array(4+y.length);return new DataView(t.buffer).setUint32(0,y.length,!1),t.set(y,4),t},C=y=>{let t=0;for(const n of y)t+=n.length;const s=new Uint8Array(t);let e=0;for(const n of y){const a=n;s.set(a,e),e+=a.length}return s},D=y=>{let t="unknown";switch(y){case 1:case 2:case 27:case 36:t="video";break;case 3:case 4:case 15:t="audio";break;case 6:t="subtitle";break;case 134:t="ad";break}return t};class x{pat;pmt;audioConfig;videoConfig;payloadMap=new Map;on={};constructor(){}parse=async t=>{let s=0;for(;!(s+188>t.byteLength);){if(t.getInt8(s)!=71){s++;continue}await this.parsePacket(t,s),s+=188}return s};parsePacket=async(t,s)=>{if(s+188>t.byteLength)throw new Error("Invalid TS packet");if(t.getUint8(s)!==71)throw new Error("Invalid TS packet");let e=s;const n=this.parseHeader(t,e);e+=4;const{transport_error_indicator:a,pid:o,payload_unit_start_indicator:l,adaptation_field_control:i}=n;if(a===1||o===void 0)return;let c=184;if(i===2||i===3){const r=t.getUint8(e);e+=1,this.parseAdaptationField(t,e),e+=r,c-=r}if(i===3&&(c-=1),i===1||i===3){const r=new Uint8Array(t.buffer.slice(e,e+c));if(o===0)return this.parsePAT(t,e);{const{programs:h=[]}=this.pat||{};if(h.find(u=>u.pmt_pid===o))return this.parsePMT(t,e)}const{streams:g=[]}=this.pmt||{},p=g.find(h=>h.elementary_pid===o);if(p){if(l===1){const h=this.payloadMap.get(o);if(h){switch(p.kind){case"audio":{const d=await this.parseAudio(h);this.on.chunk&&this.on.chunk(d)}break;case"video":{const d=await this.parseVideo(h);this.on.chunk&&this.on.chunk(d),await new Promise(u=>setTimeout(()=>u(!0),0))}break}this.payloadMap.delete(o)}}{this.payloadMap.has(o)||this.payloadMap.set(o,new Uint8Array);const h=this.payloadMap.get(o),d=new Uint8Array(h.byteLength+r.byteLength);d.set(h,0),d.set(r,h.byteLength),this.payloadMap.set(o,d)}}}};parseHeader=(t,s)=>{let e=s;const n=t.getUint8(e),a=t.getUint8(e+1),o=t.getUint8(e+2),l=t.getUint8(e+3),i=(a&128)>>7;if(i===1)return{sync_byte:n,transport_error_indicator:i};const c=(a&64)>>6,r=(a&32)>>5,g=(a&31)<<8|o,p=(l&192)>>6,h=l>>4&3,d=l&15;return{sync_byte:n,transport_error_indicator:i,payload_unit_start_indicator:c,transport_priority:r,pid:g,transport_scrambling_control:p,adaptation_field_control:h,continuity_counter:d}};parsePAT=(t,s)=>{let e=s,n;{const l=t.getUint8(e);e+=1;const i=t.getUint8(e);if(e+=1,i!==0)throw new Error("Invalid PAT table_id");const c=t.getUint16(e)&4095;e+=2;const r=t.getUint16(e);e+=2;const g=(t.getUint8(e)&62)>>1,p=t.getUint8(e)&1;e+=1;const h=t.getUint8(e);e+=1;const d=t.getUint8(e);e+=1,n={pointer_field:l,table_id:i,section_length:c,transport_stream_id:r,version_number:g,current_next_indicator:p,section_number:h,last_section_number:d}}const a=[];{const l=n.section_length-5-4,i=e+l;for(;e<i;){const c=t.getUint16(e),r=t.getUint16(e+2)&8191;e+=4,c!==0&&r>=32&&r<=8190&&a.push({program_number:c,pmt_pid:r})}}const o=t.getUint32(e);this.pat={header:n,programs:a,crc32:o},this.on.debug&&this.on.debug({pat:this.pat})};parsePMT=(t,s)=>{let e=s,n;{const l=t.getUint8(e);e+=1;const i=t.getUint8(e);if(e+=1,i!==2)throw new Error("Invalid PMT table_id");const c=t.getUint16(e)&4095;e+=2;const r=t.getUint16(e);e+=2;const g=(t.getUint8(e)&62)>>1,p=t.getUint8(e)&1;e+=1;const h=t.getUint8(e);e+=1;const d=t.getUint8(e);e+=1;const u=t.getUint16(e)&8191;e+=2;const f=t.getUint16(e)&4095;e+=2,n={pointer_field:l,table_id:i,section_length:c,transport_stream_id:r,version_number:g,current_next_indicator:p,section_number:h,last_section_number:d,pcr_pid:u,program_info_length:f}}const a=[];{const l=n.section_length-9-4,i=e+l;for(;e<i;){const c=t.getUint8(e),r=D(c),g=t.getUint16(e+1)&8191,p=t.getUint16(e+3)&4095;if(e+=5,g<32||g>8190){console.warn(`Invalid elementary_pid: 0x${g.toString(16)}`);continue}a.push({kind:r,stream_type:c,elementary_pid:g,es_info_length:p})}}const o=t.getUint32(e);this.pmt={header:n,streams:a,crc32:o},this.on.debug&&this.on.debug({pmt:this.pmt})};parseAdaptationField=(t,s)=>{let e=s,n,a,o,l;const i=t.getUint8(e),c=!!(i&128),r=!!(i&64),g=!!(i&32),p=!!(i&16),h=!!(i&8),d=!!(i&4),u=!!(i&2),f=!!(i&1);e+=1;const U=(_,b)=>{let m=BigInt(0);m|=BigInt(_.getUint16(b))<<25n,m|=BigInt(_.getUint16(b+1))<<17n,m|=BigInt(_.getUint16(b+2))<<9n,m|=BigInt(_.getUint16(b+3))<<1n,m|=BigInt(_.getUint16(b+4)>>7);const S=(_.getUint16(b+4)&1)<<8|_.getUint16(b+5);return m=m*300n+BigInt(S),m};if(p&&(n=U(t,e),e+=6),h&&(a=U(t,e),e+=6),d&&(o=t.getInt8(e),e+=1),u){const _=t.getUint8(e);e+=1,l=new Uint8Array(t.buffer,e,_),e+=_}return{discontinuity_indicator:c,random_access_indicator:r,elementary_stream_priority_indicator:g,pcr_flag:p,opcr_flag:h,splicing_point_flag:d,transport_private_data_flag:u,adaptation_field_extension_flag:f,pcr:n,opcr:a,splice_countdown:o,transport_private_data:l}};parseAudio=async t=>{const s=new DataView(t.buffer);let e=0,n,a;{const o=s.getUint8(e)===0&&s.getUint8(e+1)===0&&s.getUint8(e+2)===1;if(e+=3,!o)throw new Error("invalid ts audio payload.");const l=s.getUint8(e);e+=1;const i=s.getUint8(e)<<8|s.getUint8(e+1);e+=2;let c,r,g,p,h;{const f=s.getUint8(e);e+=1,c=f>>4&3,r=(f>>3&1)===1,g=(f>>2&1)===1,p=(f>>1&1)===1,h=(f&1)===1}let d,u;{const f=s.getUint8(e);e+=1;const U=f>>6,_=s.getUint8(e);e+=1,(U&2)===2&&(d=this.parsePtsDts(s,e)),(U&1)===1?u=this.parsePtsDts(s,e+5):u=d,e+=_}n={stream_id:l,pes_packet_length:i,scrambling_control:c,priority:r,data_alignment:g,copyright:p,original_copy:h,pts:d,dts:u}}a=t.slice(e);{if(!this.audioConfig&&s.getUint8(e)===255){const g=s.getUint8(e+2),p=s.getUint8(e+3);let h,d;d=g>>2&15,h=(g&1)<<2|p>>6;const u=`mp4a.40.${h}`,U=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350][d];this.audioConfig={kind:"audio",codec:u,sampleRate:U,numberOfChannels:h},this.on.config&&this.on.config(this.audioConfig)}const{dts:o=0,pts:l=0}=n,i=l-o,c=a.slice(7);return{kind:"audio",type:"key",dts:o,pts:l,cts:i,data:c}}};parseVideo=async t=>{const s=new DataView(t.buffer);let e=0,n,a;{const o=s.getUint8(e)===0&&s.getUint8(e+1)===0&&s.getUint8(e+2)===1;if(e+=3,!o)throw new Error("invalid ts video payload.");const l=s.getUint8(e);e+=1;const i=s.getUint8(e)<<8|s.getUint8(e+1);e+=2;let c,r,g,p,h;{const f=s.getUint8(e);e+=1,c=f>>4&3,r=(f>>3&1)===1,g=(f>>2&1)===1,p=(f>>1&1)===1,h=(f&1)===1}let d,u;{const f=s.getUint8(e);e+=1;const U=f>>6,_=s.getUint8(e);e+=1,(U&2)===2&&(d=this.parsePtsDts(s,e)),(U&1)===1?u=this.parsePtsDts(s,e+5):u=d,e+=_}n={stream_id:l,pes_packet_length:i,scrambling_control:c,priority:r,data_alignment:g,copyright:p,original_copy:h,pts:d,dts:u}}a=t.slice(e);{const o=this.getNalus(a);if(!this.videoConfig){let h,d;if(h=o.find(f=>f.type===7)?.nalu.slice(4),d=o.find(f=>f.type===8)?.nalu.slice(4),h&&d){const u=I(h,d),{codec:f}=T(u);this.videoConfig={kind:"video",codec:f,description:u,sps:h,pps:d},this.on.config&&this.on.config(this.videoConfig)}}const l=[];let i="delta";for(const h of o){const{type:d,nalu:u}=h;switch(d){case 6:case 9:l.push(u);break;case 1:i="delta",l.push(u);break;case 5:i="key",l.push(u);break}}const c=C(l),{dts:r=0,pts:g=0}=n,p=g-r;return{kind:"video",type:i,dts:r,pts:g,cts:p,data:c,nalus:l}}};parsePtsDts(t,s){const e=t.getUint8(s),n=t.getUint8(s+1),a=t.getUint8(s+2),o=t.getUint8(s+3),l=t.getUint8(s+4),i=(BigInt(e)&0b00001110n)<<29n|(BigInt(n)&0b11111111n)<<22n|(BigInt(a)&0b11111110n)<<14n|(BigInt(o)&0b11111111n)<<7n|(BigInt(l)&0b11111110n)>>1n;return Number(i)/90}getNalus=t=>{const s=[];let e=0;for(;!(e+4>t.byteLength);){if(t[e]!==0||t[e+1]!==0||t[e+2]!==1){e+=1;continue}e+=3;let n=e;const a=t[e]&31;for(e+=1;!(e+1>t.byteLength);){if(t[e]!==0||t[e+1]!==0||t[e+2]!==1){e+=1;continue}break}let o=e-n;if(t[e-1]===0&&(o-=1),o!==0){const l=t.slice(n,n+o),i=M(l);s.push({type:a,nalu:i})}}return s}}const k=(y,t)=>y.getUint8(t)<<16|y.getUint8(t+1)<<8|y.getUint8(t+2);class L{audioConfig;videoConfig;header;textDecoder=new TextDecoder("utf-8");on={};constructor(){}parse=async t=>{let s=0;for(this.header||(this.parseHeader(t,s),s+=9);this.isSurplusTag(t,s)!==!1;){const n=this.parseTagHeader(t,s+4),{tagType:a,dataSize:o,timestamp:l}=n;if(a){const i=this.parseTagBody(a,t,s+4+11,o);switch(a){case"script":this.on.info&&this.on.info(i);break;case"audio":{const{accPacketType:c}=i;if(c===0){const{codec:r,sampleRate:g,channelConfiguration:p}=i;this.audioConfig={kind:"audio",codec:r,sampleRate:g,numberOfChannels:p},this.on.config&&this.on.config(this.audioConfig)}else{const{cts:r,data:g}=i,p="key",h=r===void 0?void 0:r+l;this.on.chunk&&this.on.chunk({kind:"audio",type:p,dts:l,pts:h,cts:r,data:g})}}break;case"video":{const{avcPacketType:c}=i;if(c===0){const{codec:r,sps:g,pps:p,data:h}=i;this.videoConfig={kind:"video",codec:r,description:h,sps:g,pps:p},this.on.config&&this.on.config(this.videoConfig)}else{const{frameType:r,cts:g,data:p,nalus:h}=i,d=r===1?"key":"delta",u=g===void 0?void 0:g+l;this.on.chunk&&this.on.chunk({kind:"video",type:d,dts:l,pts:u,cts:g,data:p,nalus:h})}}break}s=s+4+11+o}await new Promise(i=>setTimeout(()=>i(!0),8))}return s};parseHeader=(t,s)=>{let e,n,a,o;e=t.getUint8(s)<<16|t.getUint8(s+1)<<8|t.getUint8(s+2),n=t.getUint8(3);{const i=t.getUint8(0).toString(2).padStart(5,"0").split(""),[,,c,,r]=i;a={audio:r==="1",video:c==="1"}}o=t.getUint32(5),this.header={signature:e,version:n,flags:a,dataOffset:o}};isSurplusTag=(t,s)=>{let e=!0;const n=t.byteLength;if(s+4>n)e=!1;else if(s+4+11>n)e=!1;else{const a=k(t,s+4+1);s+4+11+a>n&&(e=!1)}return e};parseTagHeader=(t,s)=>{let e,n,a,o,l;{const i=t.getUint8(s);let c;switch(i){case 18:c="script";break;case 8:c="audio";break;case 9:c="video";break}e=c}return n=k(t,s+1),a=k(t,s+4),o=t.getUint8(s+7),l=k(t,s+8),{tagType:e,dataSize:n,timestamp:a,timestampExtended:o,streamID:l}};parseTagBody=(t,s,e,n)=>{let a;switch(t){case"script":a=this.parseMetaData(s,e);break;case"audio":a=this.parseAudio(s,e,n);break;case"video":a=this.parseVideo(s,e,n);break}return a};parseMetaData=(t,s)=>{let e=s;{if(t.getUint8(e)!==2)throw new Error("Invalid AMF type for onMetaData (expected 0x02)");e=e+1}const n=t.getUint16(e,!1);e=e+2;{const l=new Int8Array(t.buffer.slice(e,e+n));if((this.textDecoder?.decode(l)||"")!=="onMetaData")throw new Error("Expected \'onMetaData\' string");e=e+n}const a=this.getAmfType(t,e);return e=e+1,this.getAMFValue(t,e,a).value};parseAudio=(t,s,e)=>{let n=s;const a=t.getUint8(n),o=a>>4&15,l=a>>2&3,i=a>>1&1,c=a&1;n=n+1;const r=t.getUint8(n);n=n+1;const g=e,p=new Uint8Array(t.buffer.slice(n,n+g));if(o===10&&r===0){const h=t.getUint8(n),d=t.getUint8(n+1),u=h>>3&31,f=(h&7)<<1|d>>7,U=d>>3&15,_=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],b=`mp4a.40.${u}`,m=_[f];return{soundFormat:o,soundRate:l,soundSize:i,soundType:c,accPacketType:r,data:p,samplingFrequencyIndex:f,channelConfiguration:U,codec:b,sampleRate:m}}return{soundFormat:o,soundRate:l,soundSize:i,soundType:c,accPacketType:r,data:p}};parseVideo=(t,s,e)=>{let n=s;const a=t.getUint8(n),o=a>>4&15,l=a&15;n=n+1;const i=t.getUint8(n);n=n+1;const c=k(t,n);n=n+3;const r=e-5,g=new Uint8Array(t.buffer.slice(n,n+r));switch(l){case 7:if(i===0){const p=T(g);return{frameType:o,codecID:l,avcPacketType:i,cts:c,data:g,...p}}else if(i===1){const p=[],h=n+e-5;for(;!(n+4>h);){const d=t.getUint32(n,!1),u=new Uint8Array(t.buffer.slice(n,n+4+d));n+=4+d,p.push(u)}return{frameType:o,codecID:l,avcPacketType:i,cts:c,data:g,nalus:p}}break;default:throw new Error("Unsupported codecID")}return{frameType:o,codecID:l,avcPacketType:i,cts:c,data:g}};getAmfType=(t,s)=>t.getUint8(s);getAMFName=(t,s,e)=>{const n=new Uint8Array(t.buffer.slice(s,s+e));return this.textDecoder?.decode(n)||""};getAMFValue=(t,s,e)=>{let n=s,a,o=0;switch(e){case 0:a=t.getFloat64(n,!1),o=8;break;case 1:a=!!t.getUint8(n),o=1;break;case 2:{a="";const i=t.getUint16(n,!1);n=n+2;const c=new Int8Array(t.buffer,n,i).filter(g=>g!==0);a=(this.textDecoder?.decode(c)||"").trim(),o=2+i}break;case 3:for(a={};n<t.byteLength;){const i=t.getUint16(n,!1);if(i===0)break;n=n+2;const c=this.getAMFName(t,n,i);n=n+i;const r=this.getAmfType(t,n);if(r===6)break;n=n+1;const g=this.getAMFValue(t,n,r);n=n+g.length,a[c]=g.value,o=2+i+1+g.length}break;case 8:{a={};const i=t.getUint32(n,!1);n=n+4;for(let c=0;c<i;c++){const r=t.getUint16(n,!1);n=n+2;const g=this.getAMFName(t,n,r);n=n+r;const p=this.getAmfType(t,n);n=n+1;const h=this.getAMFValue(t,n,p);n=n+h.length,a[g]=h.value,o=2+r+1+h.length}}break;case 10:{a=[];const i=t.getUint32(n,!1);n=n+4;for(let c=0;c<i;c++){const r=this.getAmfType(t,n);n=n+1;const g=this.getAMFValue(t,n,r);n=n+g.length,a.push(g.value),o=1+g.length}}break}return{amfType:e,length:o,value:a}}}class O{pattern;cacher=new P;isParseing=!1;offset=0;on={};parser;constructor(){}init=t=>{switch(this.destroy(),this.pattern=t,this.pattern){case"flv":this.parser=new L;break;case"hls":this.parser=new x;break;default:throw new Error("is error pattern.")}this.parser.on.debug=s=>this.on.debug&&this.on.debug(s),this.parser.on.info=s=>this.on.info&&this.on.info(s),this.parser.on.config=s=>this.on.config&&this.on.config(s),this.parser.on.chunk=s=>{this.cacher.pushChunk(s),this.on.chunk&&this.on.chunk(s)}};push=t=>{this.cacher.push(t),this.isParseing===!1&&this.parse()};destroy=()=>{this.cacher.destroy(),this.isParseing=!1,this.offset=0};parse=async()=>{try{if(this.isParseing=!0,!this.pattern)throw new Error("You need to set the pattern.");if(!this.parser)throw new Error("You need to init parser.");for(;;){const t=this.cacher.next(this.offset);if(this.offset=0,!t)break;this.offset=await this.parser.parse(t)}this.isParseing=!1}catch{this.destroy()}}}const A=new O;A.on.debug=y=>postMessage({action:"onDebug",data:y}),A.on.info=y=>postMessage({action:"onInfo",data:y}),A.on.config=y=>postMessage({action:"onConfig",data:y}),A.on.chunk=y=>postMessage({action:"onChunk",data:y}),onmessage=y=>{const{action:t,data:s}=y.data,e=A[t];e&&e(s)}})();\n', T = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", D], { type: "text/javascript;charset=utf-8" });
|
|
2
|
+
function L(l) {
|
|
3
3
|
let t;
|
|
4
4
|
try {
|
|
5
|
-
if (t =
|
|
5
|
+
if (t = T && (self.URL || self.webkitURL).createObjectURL(T), !t) throw "";
|
|
6
6
|
const s = new Worker(t, {
|
|
7
7
|
name: l?.name
|
|
8
8
|
});
|
|
@@ -18,8 +18,8 @@ function B(l) {
|
|
|
18
18
|
);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
class
|
|
22
|
-
worker = new
|
|
21
|
+
class N {
|
|
22
|
+
worker = new L();
|
|
23
23
|
on = {};
|
|
24
24
|
constructor() {
|
|
25
25
|
this.worker.onmessage = (t) => {
|
|
@@ -46,12 +46,12 @@ class L {
|
|
|
46
46
|
this.worker.postMessage({ action: "destroy", data: {} }), this.worker.terminate();
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
|
-
const
|
|
50
|
-
`,
|
|
49
|
+
const S = `(function(){"use strict";class n{audioDecoderConfig;audioDecoder;videoDecoderConfig;videoDecoder;hasKeyFrame=!1;baseTime=0;pendingChunks=[];isProcessing=!1;decodeTimer=0;frameTrack=!1;minFrameTrackCacheNum=20;decodingSpeed=40;decodingSpeedRatio=1;maxDecodingSpeedRatio=2;nextRenderTime;on={audio:{},video:{}};constructor(){this.baseTime=new Date().getTime()-performance.now(),this.initDecodeInterval()}init=e=>{const{decodingSpeed:i,frameTrack:d,minFrameTrackCacheNum:o}=e;i!==void 0&&(this.decodingSpeed=i),d!==void 0&&(this.frameTrack=d),o!==void 0&&(this.minFrameTrackCacheNum=o)};setFrameTrack=e=>{this.frameTrack=e,this.frameTrack===!1&&(this.decodingSpeedRatio=1)};initDecodeInterval=()=>{let e=this.decodingSpeed/this.decodingSpeedRatio;const i=this.baseTime+performance.now();if(this.nextRenderTime){const d=i-this.nextRenderTime;e-=d}this.nextRenderTime=i+e,this.decodeTimer=setTimeout(()=>{this.decode(),this.initDecodeInterval()},e)};decode=()=>{if(this.isProcessing!==!0){for(this.isProcessing=!0;;){const e=this.pendingChunks.shift();if(this.frameTrack){const o=this.pendingChunks.length;if(o>=this.minFrameTrackCacheNum){const r=Math.min(1+(o-this.minFrameTrackCacheNum)/100,this.maxDecodingSpeedRatio);this.decodingSpeedRatio=Number(r.toFixed(1))}else this.decodingSpeedRatio=1}if(!e)break;const{type:i,init:d}=e;switch(i){case"audio":this.decodeAudio(d);break;case"video":this.decodeVideo(d);break}if(i==="video")break}this.isProcessing=!1}};decodeAudio=e=>{if(!this.audioDecoder)return;const i=new EncodedAudioChunk(e);this.audioDecoder.decode(i)};decodeVideo=e=>{if(this.videoDecoder&&(e.type==="key"&&(this.hasKeyFrame=!0),this.hasKeyFrame)){const i=new EncodedVideoChunk(e);this.videoDecoder.decode(i)}};destroy=()=>{this.audio.destroy(),this.video.destroy(),clearInterval(this.decodeTimer)};audio={init:e=>{this.audio.destroy(),this.audioDecoderConfig={...e},this.audioDecoder=new AudioDecoder({output:i=>{const d=this.decodingSpeedRatio;this.on.audio.decode&&this.on.audio.decode({audioData:i,playbackRate:d})},error:i=>{this.on.audio.error&&this.on.audio.error(i)}}),this.audioDecoder.configure(this.audioDecoderConfig)},push:e=>{this.pendingChunks.push({type:"audio",init:e})},flush:()=>{this.audioDecoder?.flush()},destroy:()=>{this.audioDecoderConfig=void 0,this.audioDecoder?.close(),this.audioDecoder=void 0}};video={init:e=>{this.video.destroy(),this.videoDecoderConfig={...e},this.videoDecoder=new VideoDecoder({output:async i=>{const d=i.timestamp+this.baseTime*1e3,o=await createImageBitmap(i);i.close(),o.width>0&&o.height>0?this.on.video.decode&&this.on.video.decode({timestamp:d,bitmap:o}):o.close()},error:i=>{this.on.video.error&&this.on.video.error(i)}}),this.videoDecoder.configure(this.videoDecoderConfig)},push:e=>{this.pendingChunks.push({type:"video",init:e})},flush:()=>{this.videoDecoder?.flush()},destroy:()=>{this.videoDecoderConfig=void 0,this.videoDecoder?.close(),this.videoDecoder=void 0,this.hasKeyFrame=!1}}}const s=new n;s.on.audio.decode=t=>postMessage({type:"audio",action:"onDecode",data:t}),s.on.audio.error=t=>postMessage({type:"audio",action:"onError",data:t}),s.on.video.decode=t=>postMessage({type:"video",action:"onDecode",data:t}),s.on.video.error=t=>postMessage({type:"video",action:"onError",data:t}),onmessage=t=>{const{type:e,action:i,data:d}=t.data;if(e){const o=s[e][i];o&&o(d)}else{const o=s[i];o&&o(d)}}})();
|
|
50
|
+
`, v = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", S], { type: "text/javascript;charset=utf-8" });
|
|
51
51
|
function F(l) {
|
|
52
52
|
let t;
|
|
53
53
|
try {
|
|
54
|
-
if (t =
|
|
54
|
+
if (t = v && (self.URL || self.webkitURL).createObjectURL(v), !t) throw "";
|
|
55
55
|
const s = new Worker(t, {
|
|
56
56
|
name: l?.name
|
|
57
57
|
});
|
|
@@ -60,32 +60,34 @@ function F(l) {
|
|
|
60
60
|
}), s;
|
|
61
61
|
} catch {
|
|
62
62
|
return new Worker(
|
|
63
|
-
"data:text/javascript;charset=utf-8," + encodeURIComponent(
|
|
63
|
+
"data:text/javascript;charset=utf-8," + encodeURIComponent(S),
|
|
64
64
|
{
|
|
65
65
|
name: l?.name
|
|
66
66
|
}
|
|
67
67
|
);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
-
class
|
|
70
|
+
class B {
|
|
71
71
|
worker = new F();
|
|
72
72
|
on = { audio: {}, video: {} };
|
|
73
73
|
constructor() {
|
|
74
74
|
this.worker.onmessage = (t) => {
|
|
75
|
-
const { type: s, action: e, data:
|
|
75
|
+
const { type: s, action: e, data: i } = t.data;
|
|
76
76
|
switch (s) {
|
|
77
77
|
case "audio":
|
|
78
|
-
e === "onDecode" && this.on.audio.decode && this.on.audio.decode(
|
|
78
|
+
e === "onDecode" && this.on.audio.decode && this.on.audio.decode(i), e === "onError" && this.on.audio.error && this.on.audio.error(i);
|
|
79
79
|
break;
|
|
80
80
|
case "video":
|
|
81
|
-
e === "onDecode" && this.on.video.decode && this.on.video.decode(
|
|
81
|
+
e === "onDecode" && this.on.video.decode && this.on.video.decode(i), e === "onError" && this.on.video.error && this.on.video.error(i);
|
|
82
82
|
break;
|
|
83
83
|
}
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
|
+
init = (t) => this.worker.postMessage({ action: "init", data: t });
|
|
87
|
+
setFrameTrack = (t) => this.worker.postMessage({ action: "setFrameTrack", data: t });
|
|
86
88
|
audio = {
|
|
87
89
|
init: (t) => this.worker.postMessage({ type: "audio", action: "init", data: t }),
|
|
88
|
-
|
|
90
|
+
push: (t) => this.worker.postMessage({ type: "audio", action: "push", data: t }),
|
|
89
91
|
flush: () => this.worker.postMessage({ type: "audio", action: "flush" }),
|
|
90
92
|
destroy: () => {
|
|
91
93
|
this.worker.postMessage({ type: "audio", action: "destroy" });
|
|
@@ -93,14 +95,14 @@ class N {
|
|
|
93
95
|
};
|
|
94
96
|
video = {
|
|
95
97
|
init: (t) => this.worker.postMessage({ type: "video", action: "init", data: t }),
|
|
96
|
-
|
|
98
|
+
push: (t) => this.worker.postMessage({ type: "video", action: "push", data: t }),
|
|
97
99
|
flush: () => this.worker.postMessage({ type: "video", action: "flush" }),
|
|
98
100
|
destroy: () => {
|
|
99
101
|
this.worker.postMessage({ type: "video", action: "destroy", data: {} });
|
|
100
102
|
}
|
|
101
103
|
};
|
|
102
104
|
destroy = () => {
|
|
103
|
-
this.worker.postMessage({
|
|
105
|
+
this.worker.postMessage({ action: "destroy" }), this.worker.terminate();
|
|
104
106
|
};
|
|
105
107
|
}
|
|
106
108
|
var E = Object.defineProperty, G = (l, t, s) => t in l ? E(l, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : l[t] = s, y = (l, t, s) => G(l, typeof t != "symbol" ? t + "" : t, s);
|
|
@@ -109,8 +111,8 @@ class O {
|
|
|
109
111
|
y(this, "inputStream", new MediaStream()), y(this, "outputStream", new MediaStream()), y(this, "inputGain", 1), y(this, "enhanceGain", 1), y(this, "bgsGain", 1), y(this, "bgmGain", 1), y(this, "outputGain", 1), y(this, "mixAudioMap", /* @__PURE__ */ new Map()), y(this, "audioContext", new AudioContext()), y(this, "sourceNode"), y(this, "inputGainNode"), y(this, "enhanceGainNode"), y(this, "bgsGainNode"), y(this, "bgmGainNode"), y(this, "analyserNode"), y(this, "analyserArrayData"), y(this, "outputGainNode"), y(this, "destinationNode"), y(this, "filterStream", (e) => e), y(this, "stop", () => {
|
|
110
112
|
{
|
|
111
113
|
const e = this.inputStream.getTracks();
|
|
112
|
-
for (const
|
|
113
|
-
|
|
114
|
+
for (const i of e)
|
|
115
|
+
i.stop(), this.inputStream.removeTrack(i);
|
|
114
116
|
}
|
|
115
117
|
}), y(this, "getStream", () => this.filterStream(this.outputStream)), y(this, "setMute", (e = !0) => {
|
|
116
118
|
e ? this.analyserNode.disconnect(this.outputGainNode) : this.analyserNode.connect(this.outputGainNode);
|
|
@@ -125,63 +127,63 @@ class O {
|
|
|
125
127
|
}), y(this, "setOutputGain", (e) => {
|
|
126
128
|
this.outputGain = e, this.outputGainNode.gain.setValueAtTime(this.outputGain, this.audioContext.currentTime);
|
|
127
129
|
}), y(this, "getVolume", () => {
|
|
128
|
-
const { analyserNode: e, analyserArrayData:
|
|
129
|
-
e.getByteFrequencyData(
|
|
130
|
-
let
|
|
131
|
-
for (let r = 0; r <
|
|
132
|
-
|
|
133
|
-
return Math.ceil(
|
|
134
|
-
}), y(this, "mixAudio", (e,
|
|
130
|
+
const { analyserNode: e, analyserArrayData: i } = this;
|
|
131
|
+
e.getByteFrequencyData(i);
|
|
132
|
+
let n = 0;
|
|
133
|
+
for (let r = 0; r < i.length; r++)
|
|
134
|
+
n += i[r];
|
|
135
|
+
return Math.ceil(n / i.length);
|
|
136
|
+
}), y(this, "mixAudio", (e, i = "bgm") => new Promise(async (n, r) => {
|
|
135
137
|
try {
|
|
136
138
|
{
|
|
137
|
-
const d = this.mixAudioMap.get(
|
|
139
|
+
const d = this.mixAudioMap.get(i);
|
|
138
140
|
d && d.stop();
|
|
139
141
|
}
|
|
140
|
-
const
|
|
141
|
-
this.mixAudioMap.set(
|
|
142
|
-
o.disconnect(
|
|
142
|
+
const a = i === "bgs" ? this.bgsGainNode : this.bgmGainNode, o = this.audioContext.createBufferSource();
|
|
143
|
+
this.mixAudioMap.set(i, o), o.buffer = e, o.connect(a), o.onended = () => {
|
|
144
|
+
o.disconnect(a), this.mixAudioMap.delete(i), n(!0);
|
|
143
145
|
}, o.start(0);
|
|
144
|
-
} catch (
|
|
145
|
-
r(
|
|
146
|
+
} catch (a) {
|
|
147
|
+
r(a);
|
|
146
148
|
}
|
|
147
149
|
})), y(this, "mixAudioStop", (e) => {
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
}), y(this, "changeMix", (e,
|
|
151
|
-
const
|
|
152
|
-
|
|
150
|
+
const i = this.mixAudioMap.get(e);
|
|
151
|
+
i?.stop();
|
|
152
|
+
}), y(this, "changeMix", (e, i) => {
|
|
153
|
+
const n = e === "bgs" ? this.bgsGainNode : this.bgmGainNode;
|
|
154
|
+
i ? n.connect(this.destinationNode) : n.disconnect(this.destinationNode);
|
|
153
155
|
}), s && (this.audioContext = s), this.inputStream = t, this.sourceNode = this.audioContext.createMediaStreamSource(this.inputStream), this.inputGainNode = this.audioContext.createGain(), this.inputGainNode.gain.setValueAtTime(this.inputGain, this.audioContext.currentTime), this.enhanceGainNode = this.audioContext.createGain(), this.enhanceGainNode.gain.setValueAtTime(this.enhanceGain, this.audioContext.currentTime), this.bgsGainNode = this.audioContext.createGain(), this.bgsGainNode.gain.setValueAtTime(this.bgsGain, this.audioContext.currentTime), this.bgmGainNode = this.audioContext.createGain(), this.bgmGainNode.gain.setValueAtTime(this.bgmGain, this.audioContext.currentTime), this.analyserNode = this.audioContext.createAnalyser(), this.analyserNode.fftSize = 512, this.analyserArrayData = new Uint8Array(this.analyserNode.frequencyBinCount), this.outputGainNode = this.audioContext.createGain(), this.outputGainNode.gain.setValueAtTime(this.outputGain, this.audioContext.currentTime), this.destinationNode = this.audioContext.createMediaStreamDestination(), this.outputStream = this.destinationNode.stream;
|
|
154
156
|
{
|
|
155
|
-
const { sourceNode: e, inputGainNode:
|
|
156
|
-
e.connect(
|
|
157
|
+
const { sourceNode: e, inputGainNode: i, enhanceGainNode: n, bgsGainNode: r, bgmGainNode: a, analyserNode: o, outputGainNode: d, destinationNode: c } = this;
|
|
158
|
+
e.connect(i), i.connect(n), n.connect(o), r.connect(o), a.connect(o), n.connect(c), r.connect(c), a.connect(c), o.connect(d), d.connect(this.audioContext.destination);
|
|
157
159
|
}
|
|
158
160
|
this.setMute(!0), this.audioContext.resume();
|
|
159
161
|
}
|
|
160
162
|
}
|
|
161
|
-
const
|
|
163
|
+
const V = async (l, t) => {
|
|
162
164
|
try {
|
|
163
|
-
const { format: s, numberOfChannels: e, numberOfFrames:
|
|
164
|
-
for (let
|
|
165
|
-
const o = t.allocationSize({ planeIndex:
|
|
166
|
-
t.copyTo(d, { planeIndex:
|
|
167
|
-
const
|
|
168
|
-
for (let p = 0; p <
|
|
165
|
+
const { format: s, numberOfChannels: e, numberOfFrames: i, sampleRate: n } = t, r = l.createBuffer(e, i, n);
|
|
166
|
+
for (let a = 0; a < e; a++) {
|
|
167
|
+
const o = t.allocationSize({ planeIndex: a }), d = new Uint8Array(o);
|
|
168
|
+
t.copyTo(d, { planeIndex: a });
|
|
169
|
+
const c = new DataView(d.buffer), h = r.getChannelData(a);
|
|
170
|
+
for (let p = 0; p < i; p++) {
|
|
169
171
|
let u;
|
|
170
172
|
switch (s) {
|
|
171
173
|
case "s16":
|
|
172
174
|
// 16-bit signed PCM (范围: -32768 ~ 32767)
|
|
173
175
|
case "s16-planar":
|
|
174
|
-
u =
|
|
176
|
+
u = c.getInt16(p * 2, !0) / 32768;
|
|
175
177
|
break;
|
|
176
178
|
case "f32":
|
|
177
179
|
// 32-bit float (范围: -1.0 ~ 1.0)
|
|
178
180
|
case "f32-planar":
|
|
179
|
-
u =
|
|
181
|
+
u = c.getFloat32(p * 4, !0);
|
|
180
182
|
break;
|
|
181
183
|
case "u8":
|
|
182
184
|
// 8-bit unsigned (范围: 0 ~ 255)
|
|
183
185
|
case "u8-planar":
|
|
184
|
-
u = (
|
|
186
|
+
u = (c.getUint8(p) - 128) / 128;
|
|
185
187
|
break;
|
|
186
188
|
default:
|
|
187
189
|
throw new Error(`Unsupported audio format: ${s}`);
|
|
@@ -194,7 +196,7 @@ const W = async (l, t) => {
|
|
|
194
196
|
throw console.error("Failed to convert AudioData to AudioBuffer:", s), s;
|
|
195
197
|
}
|
|
196
198
|
};
|
|
197
|
-
class
|
|
199
|
+
class W {
|
|
198
200
|
prAudioStream;
|
|
199
201
|
audioContext;
|
|
200
202
|
destination;
|
|
@@ -207,18 +209,19 @@ class V {
|
|
|
207
209
|
t || (t = new (window.AudioContext || window.webkitAudioContext)()), this.audioContext = t, this.destination = this.audioContext.createMediaStreamDestination(), this.stream = new MediaStream(), this.stream.addTrack(this.destination.stream.getAudioTracks()[0]), this.prAudioStream = new O(this.stream, this.audioContext), this.nextStartTime = 0, this.pendingSources = [];
|
|
208
210
|
};
|
|
209
211
|
async push(t) {
|
|
212
|
+
const { audioData: s, playbackRate: e = 1 } = t;
|
|
210
213
|
try {
|
|
211
214
|
if (!this.audioContext || !this.destination) return;
|
|
212
|
-
const
|
|
213
|
-
if (!
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
const
|
|
217
|
-
this.nextStartTime =
|
|
218
|
-
this.pendingSources = this.pendingSources.filter((
|
|
215
|
+
const i = await V(this.audioContext, s);
|
|
216
|
+
if (!i) return;
|
|
217
|
+
const n = this.audioContext.createBufferSource();
|
|
218
|
+
n.buffer = i, n.playbackRate.value = e, n.connect(this.destination);
|
|
219
|
+
const r = Math.max(this.nextStartTime, this.audioContext.currentTime), a = i.duration / e;
|
|
220
|
+
this.nextStartTime = r + a, n.start(r), this.pendingSources.push(n), n.onended = () => {
|
|
221
|
+
this.pendingSources = this.pendingSources.filter((o) => o !== n);
|
|
219
222
|
}, this.audioContext.state === "suspended" && await this.audioContext.resume();
|
|
220
223
|
} finally {
|
|
221
|
-
|
|
224
|
+
s.close();
|
|
222
225
|
}
|
|
223
226
|
}
|
|
224
227
|
getStream = () => this.prAudioStream?.getStream();
|
|
@@ -226,9 +229,9 @@ class V {
|
|
|
226
229
|
this.audioContext?.close(), this.audioContext = void 0, this.destination = void 0, this.nextStartTime = 0, this.prAudioStream?.stop(), this.pendingSources.forEach((t) => t.stop()), this.pendingSources = [];
|
|
227
230
|
}
|
|
228
231
|
}
|
|
229
|
-
const
|
|
230
|
-
`, x = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);",
|
|
231
|
-
function
|
|
232
|
+
const M = `(function(){"use strict";class o{writable;writer;cutOption;pause=!1;constructor(){}init=({writable:t})=>{this.destroy(),this.writable=t,this.writer=this.writable.getWriter()};push=async t=>{if(this.pause)return;const{timestamp:s}=t;let{bitmap:i}=t;if(this.cutOption){const{sx:n=0,sy:c=0,sw:h=i.width,sh:u=i.height}=this.cutOption;i=await createImageBitmap(i,n,c,h,u)}const r=new VideoFrame(i,{timestamp:s});this.cutOption&&i.close(),this.writer.write(r),r.close()};setCut=t=>{this.cutOption=t};setPause=t=>{this.pause=t};destroy=()=>{this.writable=void 0,this.writer=void 0,this.cutOption=void 0}}const a=new o;onmessage=e=>{const{action:t,data:s}=e.data,i=a[t];i&&i(s)}})();
|
|
233
|
+
`, x = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", M], { type: "text/javascript;charset=utf-8" });
|
|
234
|
+
function j(l) {
|
|
232
235
|
let t;
|
|
233
236
|
try {
|
|
234
237
|
if (t = x && (self.URL || self.webkitURL).createObjectURL(x), !t) throw "";
|
|
@@ -240,21 +243,18 @@ function z(l) {
|
|
|
240
243
|
}), s;
|
|
241
244
|
} catch {
|
|
242
245
|
return new Worker(
|
|
243
|
-
"data:text/javascript;charset=utf-8," + encodeURIComponent(
|
|
246
|
+
"data:text/javascript;charset=utf-8," + encodeURIComponent(M),
|
|
244
247
|
{
|
|
245
248
|
name: l?.name
|
|
246
249
|
}
|
|
247
250
|
);
|
|
248
251
|
}
|
|
249
252
|
}
|
|
250
|
-
class
|
|
251
|
-
worker = new
|
|
253
|
+
class z {
|
|
254
|
+
worker = new j();
|
|
252
255
|
constructor() {
|
|
253
256
|
}
|
|
254
|
-
init = ({
|
|
255
|
-
setShader = (t) => this.worker.postMessage({ action: "setShader", data: t });
|
|
256
|
-
setBaseTime = (t) => this.worker.postMessage({ action: "setBaseTime", data: t });
|
|
257
|
-
setSize = ({ width: t, height: s }) => this.worker.postMessage({ action: "setSize", data: { width: t, height: s } });
|
|
257
|
+
init = ({ writable: t }) => this.worker.postMessage({ action: "init", data: { writable: t } }, [t]);
|
|
258
258
|
push = (t) => this.worker.postMessage({ action: "push", data: t });
|
|
259
259
|
setCut = async (t) => this.worker.postMessage({ action: "setCut", data: t });
|
|
260
260
|
setPause = (t) => this.worker.postMessage({ action: "setPause", data: t });
|
|
@@ -262,20 +262,20 @@ class j {
|
|
|
262
262
|
this.worker.postMessage({ action: "destroy", data: {} }), this.worker.terminate();
|
|
263
263
|
};
|
|
264
264
|
}
|
|
265
|
-
const
|
|
265
|
+
const q = (l) => {
|
|
266
266
|
const t = l.toLowerCase();
|
|
267
267
|
return t.includes(".m3u8") || t.includes("hls") || t.includes("master.m3u8") || t.match(/index\d*\.m3u8/) ? "hls" : t.includes(".mpd") || t.includes("dash") ? "dash" : t.startsWith("rtmp://") || t.startsWith("rtmps://") ? "rtmp" : t.includes(".flv") || t.includes("flv") && !t.includes("flash") ? "flv" : "unknown";
|
|
268
268
|
}, P = (l) => {
|
|
269
269
|
const t = l?.getTracks() || [];
|
|
270
270
|
for (const s of t)
|
|
271
271
|
s.stop();
|
|
272
|
-
},
|
|
273
|
-
const l = new
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
272
|
+
}, A = () => {
|
|
273
|
+
const l = new MediaStreamTrackGenerator({ kind: "video" }), t = new MediaStream([l]), s = new z();
|
|
274
|
+
return s.init({ writable: l.writable }), { worker: s, stream: t, destroy: () => {
|
|
275
|
+
s.destroy(), P(t);
|
|
276
|
+
} };
|
|
277
277
|
};
|
|
278
|
-
class
|
|
278
|
+
class $ {
|
|
279
279
|
resolvesMap = /* @__PURE__ */ new Map();
|
|
280
280
|
index = 0;
|
|
281
281
|
constructor() {
|
|
@@ -287,44 +287,44 @@ class H {
|
|
|
287
287
|
* @param timeout 超时时间 ms
|
|
288
288
|
* @returns
|
|
289
289
|
*/
|
|
290
|
-
add = (t, s = () => !1, e = 0) => new Promise((
|
|
291
|
-
if (s()) return
|
|
290
|
+
add = (t, s = () => !1, e = 0) => new Promise((i) => {
|
|
291
|
+
if (s()) return i(!0);
|
|
292
292
|
this.resolvesMap.has(t) || this.resolvesMap.set(t, /* @__PURE__ */ new Map()), this.index++;
|
|
293
|
-
const
|
|
293
|
+
const a = `${this.index}`;
|
|
294
294
|
if (e = Math.max(0, e), e === 0) {
|
|
295
|
-
this.resolvesMap.get(t)?.set(
|
|
295
|
+
this.resolvesMap.get(t)?.set(a, { resolve: i, timer: 0 });
|
|
296
296
|
return;
|
|
297
297
|
}
|
|
298
298
|
const o = window.setTimeout(() => {
|
|
299
299
|
this.emit(t);
|
|
300
300
|
}, e);
|
|
301
|
-
this.resolvesMap.get(t)?.set(
|
|
301
|
+
this.resolvesMap.get(t)?.set(a, { resolve: i, timer: o });
|
|
302
302
|
});
|
|
303
303
|
emit = async (t) => {
|
|
304
304
|
const s = this.resolvesMap.get(t);
|
|
305
305
|
if (!s) return;
|
|
306
306
|
const e = [...s.keys()];
|
|
307
|
-
for (const
|
|
308
|
-
const
|
|
309
|
-
|
|
307
|
+
for (const i of e) {
|
|
308
|
+
const n = s.get(i);
|
|
309
|
+
n && (clearTimeout(n.timer), n.resolve(), s.delete(i));
|
|
310
310
|
}
|
|
311
311
|
};
|
|
312
312
|
}
|
|
313
|
-
const
|
|
314
|
-
const s = new Uint8Array(l), e = new Uint8Array(t),
|
|
315
|
-
let
|
|
316
|
-
return n
|
|
317
|
-
},
|
|
313
|
+
const H = (l, t) => {
|
|
314
|
+
const s = new Uint8Array(l), e = new Uint8Array(t), i = new Uint8Array(11 + s.length + e.length);
|
|
315
|
+
let n = 0;
|
|
316
|
+
return i[n++] = 1, i[n++] = s[1], i[n++] = s[2], i[n++] = s[3], i[n++] = 255, i[n++] = 225, i[n++] = s.length >> 8 & 255, i[n++] = s.length & 255, i.set(s, n), n += s.length, i[n++] = 1, i[n++] = e.length >> 8 & 255, i[n++] = e.length & 255, i.set(e, n), i;
|
|
317
|
+
}, R = (l) => {
|
|
318
318
|
let t = 0;
|
|
319
319
|
const s = new DataView(l.buffer), e = s.getUint8(t);
|
|
320
320
|
if (t = t + 1, e !== 1) throw new Error("Invalid AVC version");
|
|
321
|
-
const n = s.getUint8(t) & 255;
|
|
322
|
-
t = t + 1;
|
|
323
321
|
const i = s.getUint8(t) & 255;
|
|
324
322
|
t = t + 1;
|
|
323
|
+
const n = s.getUint8(t) & 255;
|
|
324
|
+
t = t + 1;
|
|
325
325
|
const r = s.getUint8(t) & 255;
|
|
326
326
|
t = t + 1;
|
|
327
|
-
const d = `avc1.${Array.from([
|
|
327
|
+
const d = `avc1.${Array.from([i, n, r], (b) => b.toString(16).padStart(2, "0")).join("")}`, c = (s.getUint8(t) & 3) - 1;
|
|
328
328
|
t = t + 1;
|
|
329
329
|
const h = s.getUint8(t) & 31;
|
|
330
330
|
t = t + 1;
|
|
@@ -337,36 +337,36 @@ const q = (l, t) => {
|
|
|
337
337
|
const f = s.getUint16(t, !1);
|
|
338
338
|
t = t + 2;
|
|
339
339
|
const m = new Uint8Array(s.buffer.slice(t, t + f));
|
|
340
|
-
return t = t + f, { version: e, codec: d, profile:
|
|
340
|
+
return t = t + f, { version: e, codec: d, profile: i, compatibility: n, level: r, lengthSizeMinusOne: c, numOfSequenceParameterSets: h, sequenceParameterSetLength: p, sps: u, numOfPictureParameterSets: g, pictureParameterSetLength: f, pps: m };
|
|
341
341
|
}, K = (l) => {
|
|
342
342
|
const t = new Uint8Array(4 + l.length);
|
|
343
343
|
return new DataView(t.buffer).setUint32(0, l.length, !1), t.set(l, 4), t;
|
|
344
344
|
}, X = (l) => {
|
|
345
345
|
let t = 0;
|
|
346
|
-
for (const
|
|
347
|
-
t +=
|
|
346
|
+
for (const i of l)
|
|
347
|
+
t += i.length;
|
|
348
348
|
const s = new Uint8Array(t);
|
|
349
349
|
let e = 0;
|
|
350
|
-
for (const
|
|
351
|
-
const
|
|
352
|
-
s.set(
|
|
350
|
+
for (const i of l) {
|
|
351
|
+
const n = i;
|
|
352
|
+
s.set(n, e), e += n.length;
|
|
353
353
|
}
|
|
354
354
|
return s;
|
|
355
355
|
}, Y = (l) => {
|
|
356
356
|
const t = new DataView(l.buffer);
|
|
357
|
-
let s = 0, e,
|
|
357
|
+
let s = 0, e, i, n;
|
|
358
358
|
e = t.getUint32(s, !1), s += 4;
|
|
359
359
|
{
|
|
360
|
-
const r = t.getUint8(s),
|
|
361
|
-
|
|
360
|
+
const r = t.getUint8(s), a = r >> 7 & 1, o = r >> 5 & 3, d = r & 31;
|
|
361
|
+
i = { forbidden_zero_bit: a, nal_ref_idc: o, nal_unit_type: d }, s += 1;
|
|
362
362
|
}
|
|
363
363
|
{
|
|
364
364
|
const r = e - 1;
|
|
365
|
-
|
|
365
|
+
n = new Uint8Array(t.buffer.slice(s, s + r));
|
|
366
366
|
}
|
|
367
|
-
return { size: e, header:
|
|
367
|
+
return { size: e, header: i, data: n };
|
|
368
368
|
};
|
|
369
|
-
class
|
|
369
|
+
class C {
|
|
370
370
|
#e = {
|
|
371
371
|
timeout: 5 * 1e3,
|
|
372
372
|
check: !1
|
|
@@ -380,31 +380,31 @@ class A {
|
|
|
380
380
|
* @param input string | URL | Request
|
|
381
381
|
* @param init RequestInit
|
|
382
382
|
*/
|
|
383
|
-
check = (t, s) => new Promise(async (e,
|
|
383
|
+
check = (t, s) => new Promise(async (e, i) => {
|
|
384
384
|
this.stop(), this.#t = new AbortController();
|
|
385
|
-
const
|
|
386
|
-
this.#t?.abort("Timeout."),
|
|
385
|
+
const n = window.setTimeout(() => {
|
|
386
|
+
this.#t?.abort("Timeout."), i({ status: "timeout", reason: "" });
|
|
387
387
|
}, this.#e.timeout);
|
|
388
388
|
try {
|
|
389
389
|
const r = await fetch(t, { ...s, method: "HEAD", signal: this.#t?.signal });
|
|
390
|
-
r.status === 200 ? e({ status: "successed", reason: "" }) :
|
|
390
|
+
r.status === 200 ? e({ status: "successed", reason: "" }) : i({ status: "failed", reason: `${r.status}` });
|
|
391
391
|
} catch (r) {
|
|
392
|
-
|
|
392
|
+
i({ status: "error", reason: r.message });
|
|
393
393
|
}
|
|
394
|
-
clearTimeout(
|
|
394
|
+
clearTimeout(n);
|
|
395
395
|
});
|
|
396
396
|
/**
|
|
397
397
|
*
|
|
398
398
|
* @param input string | URL | Request
|
|
399
399
|
* @param init RequestInit
|
|
400
400
|
*/
|
|
401
|
-
request = async (t, s) => new Promise(async (e,
|
|
401
|
+
request = async (t, s) => new Promise(async (e, i) => {
|
|
402
402
|
try {
|
|
403
403
|
this.#e.check && await this.check(t, s), this.#t = new AbortController();
|
|
404
|
-
const
|
|
405
|
-
e(
|
|
406
|
-
} catch (
|
|
407
|
-
this.stop(), n
|
|
404
|
+
const n = await fetch(t, { ...s, signal: this.#t?.signal });
|
|
405
|
+
e(n);
|
|
406
|
+
} catch (n) {
|
|
407
|
+
this.stop(), i(n);
|
|
408
408
|
}
|
|
409
409
|
});
|
|
410
410
|
/**
|
|
@@ -416,18 +416,17 @@ class A {
|
|
|
416
416
|
}
|
|
417
417
|
class et {
|
|
418
418
|
option = {
|
|
419
|
-
debug: !1
|
|
419
|
+
debug: !1,
|
|
420
|
+
frameTrack: !1
|
|
420
421
|
};
|
|
421
|
-
prFetch = new
|
|
422
|
-
prResolves = new
|
|
422
|
+
prFetch = new C();
|
|
423
|
+
prResolves = new $();
|
|
423
424
|
url = "";
|
|
424
425
|
demuxerWorker;
|
|
425
426
|
decoderWorker;
|
|
426
427
|
audioPlayer;
|
|
427
428
|
renderWorker;
|
|
428
|
-
renderBaseTime;
|
|
429
429
|
stream;
|
|
430
|
-
canvas;
|
|
431
430
|
on = { demuxer: {}, decoder: {} };
|
|
432
431
|
cutRenders = /* @__PURE__ */ new Map();
|
|
433
432
|
// @ts-ignore
|
|
@@ -440,7 +439,7 @@ class et {
|
|
|
440
439
|
* 初始化
|
|
441
440
|
*/
|
|
442
441
|
init = () => {
|
|
443
|
-
this.initDecoder(), this.audioPlayer = new
|
|
442
|
+
this.initDecoder(), this.initRender(), this.audioPlayer = new W(), this.audioPlayer.init();
|
|
444
443
|
};
|
|
445
444
|
/**
|
|
446
445
|
* 开始播放
|
|
@@ -448,7 +447,7 @@ class et {
|
|
|
448
447
|
*/
|
|
449
448
|
start = async (t) => {
|
|
450
449
|
this.stop(), this.url = t, this.init();
|
|
451
|
-
const s =
|
|
450
|
+
const s = q(t);
|
|
452
451
|
if (s === "unknown") throw new Error("This address cannot be parsed.");
|
|
453
452
|
switch (this.initDemuxer(s), s) {
|
|
454
453
|
case "flv":
|
|
@@ -465,31 +464,34 @@ class et {
|
|
|
465
464
|
stop = async () => {
|
|
466
465
|
try {
|
|
467
466
|
clearInterval(this.hls.getSegmentsTimer), this.prFetch.stop();
|
|
468
|
-
} catch (
|
|
469
|
-
console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: error",
|
|
467
|
+
} catch (t) {
|
|
468
|
+
console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: error", t);
|
|
470
469
|
}
|
|
471
|
-
this.demuxerWorker?.destroy(), this.decoderWorker?.destroy(), this.renderWorker?.destroy(), P(this.stream);
|
|
472
|
-
const t = [...this.cutRenders.keys()];
|
|
473
|
-
for (const s of t)
|
|
474
|
-
this.cut.remove(s);
|
|
475
|
-
this.audioPlayer?.destroy(), this.renderBaseTime = void 0, this.canvas = void 0;
|
|
470
|
+
this.demuxerWorker?.destroy(), this.decoderWorker?.destroy(), this.renderWorker?.destroy(), P(this.stream), this.audioPlayer?.destroy();
|
|
476
471
|
};
|
|
477
|
-
|
|
472
|
+
/**
|
|
473
|
+
* 获取媒体流
|
|
474
|
+
*/
|
|
478
475
|
getStream = () => this.stream;
|
|
479
|
-
setPause = (t) => {
|
|
480
|
-
this.renderWorker?.setPause(t);
|
|
481
|
-
};
|
|
482
476
|
/**
|
|
483
|
-
*
|
|
477
|
+
* 设置暂停
|
|
478
|
+
* @param pause: boolean
|
|
484
479
|
*/
|
|
485
|
-
|
|
486
|
-
this.renderWorker?.
|
|
480
|
+
setPause = (t) => {
|
|
481
|
+
this.renderWorker?.setPause(t);
|
|
487
482
|
};
|
|
488
483
|
/**
|
|
489
484
|
* 是否静音 默认为true
|
|
490
485
|
* @param state?: boolean
|
|
491
486
|
*/
|
|
492
487
|
setMute = (t) => this.audioPlayer?.prAudioStream?.setMute(t);
|
|
488
|
+
/**
|
|
489
|
+
* 是否开启追帧
|
|
490
|
+
* @param frameTrack?: boolean
|
|
491
|
+
*/
|
|
492
|
+
setFrameTrack = (t) => {
|
|
493
|
+
this.decoderWorker?.setFrameTrack(t);
|
|
494
|
+
};
|
|
493
495
|
/**
|
|
494
496
|
* 是否已准备好
|
|
495
497
|
*/
|
|
@@ -497,54 +499,30 @@ class et {
|
|
|
497
499
|
const t = () => this.stream?.active === !0;
|
|
498
500
|
return this.prResolves.add("isReady", t);
|
|
499
501
|
};
|
|
500
|
-
cut = {
|
|
501
|
-
/**
|
|
502
|
-
* 创建剪切
|
|
503
|
-
*/
|
|
504
|
-
create: (t, s) => {
|
|
505
|
-
let e = this.cutRenders.get(t);
|
|
506
|
-
return e ? (e.worker.setCut(s), e.worker.setPause(!1), e) : (e = C(), e.worker.setBaseTime(this.renderBaseTime || 0), e.worker.setCut(s), this.cutRenders.set(t, e), e);
|
|
507
|
-
},
|
|
508
|
-
getCanvas: (t) => this.cutRenders.get(t)?.canvas,
|
|
509
|
-
getStream: (t) => this.cutRenders.get(t)?.stream,
|
|
510
|
-
setPause: (t, s) => {
|
|
511
|
-
this.cutRenders.get(t)?.worker.setPause(s);
|
|
512
|
-
},
|
|
513
|
-
/**
|
|
514
|
-
* 设置渲染模式
|
|
515
|
-
*/
|
|
516
|
-
setShader: (t, s) => {
|
|
517
|
-
this.cutRenders.get(t)?.worker.setShader(s);
|
|
518
|
-
},
|
|
519
|
-
/**
|
|
520
|
-
* 移除剪切
|
|
521
|
-
*/
|
|
522
|
-
remove: (t) => {
|
|
523
|
-
this.cutRenders.get(t)?.destroy(), this.cutRenders.delete(t);
|
|
524
|
-
}
|
|
525
|
-
};
|
|
526
502
|
/**
|
|
527
503
|
* 初始化解复器
|
|
528
504
|
*/
|
|
529
505
|
initDemuxer = (t) => {
|
|
530
|
-
this.demuxerWorker = new
|
|
506
|
+
this.demuxerWorker = new N(), this.demuxerWorker.init(t), this.demuxerWorker.on.debug = (s) => {
|
|
531
507
|
this.option.debug && console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: debug", s);
|
|
532
508
|
}, this.demuxerWorker.on.info = (s) => {
|
|
533
|
-
this.option.debug && console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: info", s)
|
|
509
|
+
this.option.debug && console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: info", s);
|
|
510
|
+
const { framerate: e = 25 } = s, i = 1e3 / e;
|
|
511
|
+
this.decoderWorker?.init({ decodingSpeed: i }), this.on.demuxer.info && this.on.demuxer.info(s);
|
|
534
512
|
}, this.demuxerWorker.on.config = (s) => {
|
|
535
513
|
this.option.debug && console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: config", s), this.on.demuxer.config && this.on.demuxer.config(s);
|
|
536
514
|
const { kind: e } = s;
|
|
537
515
|
switch (e) {
|
|
538
516
|
case "audio":
|
|
539
517
|
{
|
|
540
|
-
const { codec:
|
|
541
|
-
this.decoderWorker?.audio.init({ codec:
|
|
518
|
+
const { codec: i, sampleRate: n, numberOfChannels: r } = s;
|
|
519
|
+
this.decoderWorker?.audio.init({ codec: i, sampleRate: n, numberOfChannels: r });
|
|
542
520
|
}
|
|
543
521
|
break;
|
|
544
522
|
case "video":
|
|
545
523
|
{
|
|
546
|
-
const { codec:
|
|
547
|
-
this.decoderWorker?.video.init({ codec:
|
|
524
|
+
const { codec: i, description: n } = s;
|
|
525
|
+
this.decoderWorker?.video.init({ codec: i, description: n });
|
|
548
526
|
}
|
|
549
527
|
break;
|
|
550
528
|
}
|
|
@@ -554,22 +532,17 @@ class et {
|
|
|
554
532
|
switch (e) {
|
|
555
533
|
case "audio":
|
|
556
534
|
{
|
|
557
|
-
const { type:
|
|
558
|
-
this.decoderWorker.audio.
|
|
535
|
+
const { type: i, dts: n, data: r } = s, a = n * 1;
|
|
536
|
+
this.decoderWorker.audio.push({ type: i, timestamp: a, data: r });
|
|
559
537
|
}
|
|
560
538
|
break;
|
|
561
539
|
case "video":
|
|
562
540
|
{
|
|
563
|
-
const { type:
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
this.renderBaseTime = d - i, this.renderWorker?.setBaseTime(this.renderBaseTime);
|
|
567
|
-
}
|
|
568
|
-
const o = i * 1e3;
|
|
569
|
-
this.decoderWorker.video.decode({ type: n, timestamp: o, data: r });
|
|
570
|
-
for (const d of c) {
|
|
541
|
+
const { type: i, dts: n, data: r, nalus: a = [] } = s, o = n * 1e3;
|
|
542
|
+
this.decoderWorker.video.push({ type: i, timestamp: o, data: r });
|
|
543
|
+
for (const d of a) {
|
|
571
544
|
if (d.byteLength <= 4) continue;
|
|
572
|
-
const { header:
|
|
545
|
+
const { header: c, data: h } = Y(d), { nal_unit_type: p } = c;
|
|
573
546
|
p === 6 && this.on.demuxer.sei && this.on.demuxer.sei(h);
|
|
574
547
|
}
|
|
575
548
|
}
|
|
@@ -581,7 +554,7 @@ class et {
|
|
|
581
554
|
* 初始化解码器
|
|
582
555
|
*/
|
|
583
556
|
initDecoder = () => {
|
|
584
|
-
this.decoderWorker = new
|
|
557
|
+
this.decoderWorker = new B(), this.decoderWorker.on.audio.decode = (t) => {
|
|
585
558
|
this.audioPlayer?.push(t), this.on.decoder.audio && this.on.decoder.audio(t);
|
|
586
559
|
}, this.decoderWorker.on.audio.error = (t) => {
|
|
587
560
|
this.option.debug && console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: audio.error ", t), this.on.error && this.on.error(t);
|
|
@@ -599,20 +572,49 @@ class et {
|
|
|
599
572
|
* 初始化渲染器
|
|
600
573
|
*/
|
|
601
574
|
initRender = () => {
|
|
602
|
-
const { worker: t,
|
|
603
|
-
this.renderWorker = t, this.
|
|
575
|
+
const { worker: t, stream: s } = A();
|
|
576
|
+
this.renderWorker = t, this.stream = s, this.renderWorker.setPause(!1);
|
|
577
|
+
};
|
|
578
|
+
cut = {
|
|
579
|
+
/**
|
|
580
|
+
* 创建剪切
|
|
581
|
+
*/
|
|
582
|
+
create: (t, s) => {
|
|
583
|
+
let e = this.cutRenders.get(t);
|
|
584
|
+
return e ? (e.worker.setCut(s), e.worker.setPause(!1), e) : (e = A(), e.worker.setCut(s), this.cutRenders.set(t, e), e);
|
|
585
|
+
},
|
|
586
|
+
/**
|
|
587
|
+
* 获取媒体流
|
|
588
|
+
*/
|
|
589
|
+
getStream: (t) => this.cutRenders.get(t)?.stream,
|
|
590
|
+
/**
|
|
591
|
+
* 设置暂停
|
|
592
|
+
* @param pause: boolean
|
|
593
|
+
*/
|
|
594
|
+
setPause: (t, s) => {
|
|
595
|
+
this.cutRenders.get(t)?.worker.setPause(s);
|
|
596
|
+
},
|
|
597
|
+
/**
|
|
598
|
+
* 移除剪切
|
|
599
|
+
*/
|
|
600
|
+
remove: (t) => {
|
|
601
|
+
this.cutRenders.get(t)?.destroy(), this.cutRenders.delete(t);
|
|
602
|
+
}
|
|
604
603
|
};
|
|
605
604
|
flv = {
|
|
606
605
|
start: async () => {
|
|
607
606
|
try {
|
|
608
|
-
|
|
607
|
+
let t = await this.prFetch.request(this.url);
|
|
608
|
+
if (t.status !== 200 && (await new Promise((e) => setTimeout(() => e(!0), 500)), t = await this.prFetch.request(this.url)), t.status !== 200 && (await new Promise((e) => setTimeout(() => e(!0), 500)), t = await this.prFetch.request(this.url)), t.status !== 200) throw new Error("request is error.");
|
|
609
|
+
const s = t.body?.getReader();
|
|
609
610
|
if (!s) throw new Error("reader is error.");
|
|
610
611
|
for (; ; ) {
|
|
611
|
-
const { done: e, value:
|
|
612
|
-
if (
|
|
612
|
+
const { done: e, value: i } = await s.read();
|
|
613
|
+
if (i && this.demuxerWorker?.push(i), e) break;
|
|
613
614
|
}
|
|
614
615
|
} catch (t) {
|
|
615
616
|
if (t?.name !== "AbortError") throw Error(t);
|
|
617
|
+
this.on.error && this.on.error(t);
|
|
616
618
|
}
|
|
617
619
|
}
|
|
618
620
|
};
|
|
@@ -622,49 +624,54 @@ class et {
|
|
|
622
624
|
url: "",
|
|
623
625
|
getSegmentsTimer: 0,
|
|
624
626
|
parse: async (t) => {
|
|
625
|
-
const
|
|
626
|
-
`).map((
|
|
627
|
-
let r = 4,
|
|
627
|
+
const i = new TextDecoder("utf-8").decode(t).split(`
|
|
628
|
+
`).map((c) => c.replace("\r", "")), n = this.url.substring(0, this.url.lastIndexOf("/") + 1);
|
|
629
|
+
let r = 4, a = 0, o = !1;
|
|
628
630
|
const d = [];
|
|
629
|
-
for (const
|
|
630
|
-
|
|
631
|
-
url:
|
|
631
|
+
for (const c of i)
|
|
632
|
+
c.startsWith("#EXTINF:") ? r = parseFloat(c.split(":")[1].split(",")[0]) : c.startsWith("#EXT-X-TARGETDURATION:") ? a = parseInt(c.split(":")[1]) : c.startsWith("#EXT-X-ENDLIST") ? o = !1 : c.startsWith("#EXT-X-MEDIA-SEQUENCE:") ? o = !0 : c.includes(".ts") && !c.startsWith("#") && d.push({
|
|
633
|
+
url: c.startsWith("http") ? c : n + c,
|
|
632
634
|
duration: r,
|
|
633
635
|
isLive: o
|
|
634
636
|
});
|
|
635
|
-
return { baseUrl:
|
|
637
|
+
return { baseUrl: n, targetDuration: a, isLive: o, segments: d };
|
|
636
638
|
},
|
|
637
639
|
getSegments: async () => {
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
640
|
+
try {
|
|
641
|
+
const t = new C();
|
|
642
|
+
let s = await t.request(this.url);
|
|
643
|
+
if (s.status !== 200 && (await new Promise((i) => setTimeout(() => i(!0), 500)), s = await t.request(this.url)), s.status !== 200 && (await new Promise((i) => setTimeout(() => i(!0), 500)), s = await t.request(this.url)), s.status !== 200) throw new Error("request is error.");
|
|
644
|
+
const e = s.body?.getReader();
|
|
645
|
+
if (!e) throw new Error("reader is error.");
|
|
646
|
+
for (; ; ) {
|
|
647
|
+
const { done: i, value: n } = await e.read();
|
|
648
|
+
if (n) {
|
|
649
|
+
const r = await this.hls.parse(n), { segments: a = [], isLive: o = !1 } = r;
|
|
650
|
+
this.hls.isLive = o, o === !1 && (this.option.frameTrack = !1);
|
|
651
|
+
let d = Array.from(a, (h) => h.url);
|
|
652
|
+
const c = d.findIndex((h) => h === this.hls.url);
|
|
653
|
+
c !== -1 && (d = d.slice(c + 1)), this.hls.urls = d;
|
|
654
|
+
}
|
|
655
|
+
if (i) break;
|
|
648
656
|
}
|
|
649
|
-
|
|
657
|
+
} catch (t) {
|
|
658
|
+
this.on.error && this.on.error(t);
|
|
650
659
|
}
|
|
651
660
|
},
|
|
652
|
-
getData: async () => {
|
|
653
|
-
},
|
|
654
661
|
start: async () => {
|
|
655
662
|
try {
|
|
656
|
-
for (await this.hls.getSegments(), this.hls.getSegmentsTimer = window.setInterval(this.hls.getSegments,
|
|
663
|
+
for (await this.hls.getSegments(), this.hls.getSegmentsTimer = window.setInterval(this.hls.getSegments, 500), this.hls.isLive === !1 && (clearInterval(this.hls.getSegmentsTimer), this.decoderWorker?.setFrameTrack(!1)); ; ) {
|
|
657
664
|
const t = this.hls.urls.shift();
|
|
658
665
|
if (t) {
|
|
659
666
|
this.hls.url = t;
|
|
660
667
|
const e = (await this.prFetch.request(t)).body?.getReader();
|
|
661
668
|
if (!e) throw new Error("segment reader is error.");
|
|
662
669
|
for (; ; ) {
|
|
663
|
-
const { done:
|
|
664
|
-
if (
|
|
670
|
+
const { done: i, value: n } = await e.read();
|
|
671
|
+
if (n && this.demuxerWorker?.push(n), i) break;
|
|
665
672
|
}
|
|
666
|
-
}
|
|
667
|
-
|
|
673
|
+
} else
|
|
674
|
+
await new Promise((s) => setTimeout(() => s(!0), 300));
|
|
668
675
|
}
|
|
669
676
|
} catch (t) {
|
|
670
677
|
if (t?.name !== "AbortError") throw Error(t);
|
|
@@ -745,17 +752,17 @@ class Z {
|
|
|
745
752
|
if (t.getUint8(s) !== 71)
|
|
746
753
|
throw new Error("Invalid TS packet");
|
|
747
754
|
let e = s;
|
|
748
|
-
const
|
|
755
|
+
const i = this.parseHeader(t, e);
|
|
749
756
|
e += 4;
|
|
750
|
-
const { transport_error_indicator:
|
|
751
|
-
if (
|
|
757
|
+
const { transport_error_indicator: n, pid: r, payload_unit_start_indicator: a, adaptation_field_control: o } = i;
|
|
758
|
+
if (n === 1 || r === void 0) return;
|
|
752
759
|
let d = 184;
|
|
753
760
|
if (o === 2 || o === 3) {
|
|
754
|
-
const
|
|
755
|
-
e += 1, this.parseAdaptationField(t, e), e +=
|
|
761
|
+
const c = t.getUint8(e);
|
|
762
|
+
e += 1, this.parseAdaptationField(t, e), e += c, d -= c;
|
|
756
763
|
}
|
|
757
764
|
if (o === 3 && (d -= 1), o === 1 || o === 3) {
|
|
758
|
-
const
|
|
765
|
+
const c = new Uint8Array(t.buffer.slice(e, e + d));
|
|
759
766
|
if (r === 0) return this.parsePAT(t, e);
|
|
760
767
|
{
|
|
761
768
|
const { programs: u = [] } = this.pat || {};
|
|
@@ -763,7 +770,7 @@ class Z {
|
|
|
763
770
|
}
|
|
764
771
|
const { streams: h = [] } = this.pmt || {}, p = h.find((u) => u.elementary_pid === r);
|
|
765
772
|
if (p) {
|
|
766
|
-
if (
|
|
773
|
+
if (a === 1) {
|
|
767
774
|
const u = this.payloadMap.get(r);
|
|
768
775
|
if (u) {
|
|
769
776
|
switch (p.kind) {
|
|
@@ -776,7 +783,7 @@ class Z {
|
|
|
776
783
|
case "video":
|
|
777
784
|
{
|
|
778
785
|
const g = await this.parseVideo(u);
|
|
779
|
-
this.on.chunk && this.on.chunk(g), await new Promise((f) => setTimeout(() => f(!0),
|
|
786
|
+
this.on.chunk && this.on.chunk(g), await new Promise((f) => setTimeout(() => f(!0), 0));
|
|
780
787
|
}
|
|
781
788
|
break;
|
|
782
789
|
}
|
|
@@ -785,8 +792,8 @@ class Z {
|
|
|
785
792
|
}
|
|
786
793
|
{
|
|
787
794
|
this.payloadMap.has(r) || this.payloadMap.set(r, new Uint8Array());
|
|
788
|
-
const u = this.payloadMap.get(r), g = new Uint8Array(u.byteLength +
|
|
789
|
-
g.set(u, 0), g.set(
|
|
795
|
+
const u = this.payloadMap.get(r), g = new Uint8Array(u.byteLength + c.byteLength);
|
|
796
|
+
g.set(u, 0), g.set(c, u.byteLength), this.payloadMap.set(r, g);
|
|
790
797
|
}
|
|
791
798
|
}
|
|
792
799
|
}
|
|
@@ -794,52 +801,52 @@ class Z {
|
|
|
794
801
|
// Header
|
|
795
802
|
parseHeader = (t, s) => {
|
|
796
803
|
let e = s;
|
|
797
|
-
const
|
|
798
|
-
if (o === 1) return { sync_byte:
|
|
799
|
-
const d = (
|
|
800
|
-
return { sync_byte:
|
|
804
|
+
const i = t.getUint8(e), n = t.getUint8(e + 1), r = t.getUint8(e + 2), a = t.getUint8(e + 3), o = (n & 128) >> 7;
|
|
805
|
+
if (o === 1) return { sync_byte: i, transport_error_indicator: o };
|
|
806
|
+
const d = (n & 64) >> 6, c = (n & 32) >> 5, h = (n & 31) << 8 | r, p = (a & 192) >> 6, u = a >> 4 & 3, g = a & 15;
|
|
807
|
+
return { sync_byte: i, transport_error_indicator: o, payload_unit_start_indicator: d, transport_priority: c, pid: h, transport_scrambling_control: p, adaptation_field_control: u, continuity_counter: g };
|
|
801
808
|
};
|
|
802
809
|
// PAT表
|
|
803
810
|
parsePAT = (t, s) => {
|
|
804
|
-
let e = s,
|
|
811
|
+
let e = s, i;
|
|
805
812
|
{
|
|
806
|
-
const
|
|
813
|
+
const a = t.getUint8(e);
|
|
807
814
|
e += 1;
|
|
808
815
|
const o = t.getUint8(e);
|
|
809
816
|
if (e += 1, o !== 0) throw new Error("Invalid PAT table_id");
|
|
810
817
|
const d = t.getUint16(e) & 4095;
|
|
811
818
|
e += 2;
|
|
812
|
-
const
|
|
819
|
+
const c = t.getUint16(e);
|
|
813
820
|
e += 2;
|
|
814
821
|
const h = (t.getUint8(e) & 62) >> 1, p = t.getUint8(e) & 1;
|
|
815
822
|
e += 1;
|
|
816
823
|
const u = t.getUint8(e);
|
|
817
824
|
e += 1;
|
|
818
825
|
const g = t.getUint8(e);
|
|
819
|
-
e += 1,
|
|
826
|
+
e += 1, i = { pointer_field: a, table_id: o, section_length: d, transport_stream_id: c, version_number: h, current_next_indicator: p, section_number: u, last_section_number: g };
|
|
820
827
|
}
|
|
821
|
-
const
|
|
828
|
+
const n = [];
|
|
822
829
|
{
|
|
823
|
-
const
|
|
830
|
+
const a = i.section_length - 5 - 4, o = e + a;
|
|
824
831
|
for (; e < o; ) {
|
|
825
|
-
const d = t.getUint16(e),
|
|
826
|
-
e += 4, d !== 0 &&
|
|
832
|
+
const d = t.getUint16(e), c = t.getUint16(e + 2) & 8191;
|
|
833
|
+
e += 4, d !== 0 && c >= 32 && c <= 8190 && n.push({ program_number: d, pmt_pid: c });
|
|
827
834
|
}
|
|
828
835
|
}
|
|
829
836
|
const r = t.getUint32(e);
|
|
830
|
-
this.pat = { header:
|
|
837
|
+
this.pat = { header: i, programs: n, crc32: r }, this.on.debug && this.on.debug({ pat: this.pat });
|
|
831
838
|
};
|
|
832
839
|
// PMT表
|
|
833
840
|
parsePMT = (t, s) => {
|
|
834
|
-
let e = s,
|
|
841
|
+
let e = s, i;
|
|
835
842
|
{
|
|
836
|
-
const
|
|
843
|
+
const a = t.getUint8(e);
|
|
837
844
|
e += 1;
|
|
838
845
|
const o = t.getUint8(e);
|
|
839
846
|
if (e += 1, o !== 2) throw new Error("Invalid PMT table_id");
|
|
840
847
|
const d = t.getUint16(e) & 4095;
|
|
841
848
|
e += 2;
|
|
842
|
-
const
|
|
849
|
+
const c = t.getUint16(e);
|
|
843
850
|
e += 2;
|
|
844
851
|
const h = (t.getUint8(e) & 62) >> 1, p = t.getUint8(e) & 1;
|
|
845
852
|
e += 1;
|
|
@@ -850,114 +857,114 @@ class Z {
|
|
|
850
857
|
const f = t.getUint16(e) & 8191;
|
|
851
858
|
e += 2;
|
|
852
859
|
const m = t.getUint16(e) & 4095;
|
|
853
|
-
e += 2,
|
|
860
|
+
e += 2, i = { pointer_field: a, table_id: o, section_length: d, transport_stream_id: c, version_number: h, current_next_indicator: p, section_number: u, last_section_number: g, pcr_pid: f, program_info_length: m };
|
|
854
861
|
}
|
|
855
|
-
const
|
|
862
|
+
const n = [];
|
|
856
863
|
{
|
|
857
|
-
const
|
|
864
|
+
const a = i.section_length - 9 - 4, o = e + a;
|
|
858
865
|
for (; e < o; ) {
|
|
859
|
-
const d = t.getUint8(e),
|
|
866
|
+
const d = t.getUint8(e), c = J(d), h = t.getUint16(e + 1) & 8191, p = t.getUint16(e + 3) & 4095;
|
|
860
867
|
if (e += 5, h < 32 || h > 8190) {
|
|
861
868
|
console.warn(`Invalid elementary_pid: 0x${h.toString(16)}`);
|
|
862
869
|
continue;
|
|
863
870
|
}
|
|
864
|
-
|
|
871
|
+
n.push({ kind: c, stream_type: d, elementary_pid: h, es_info_length: p });
|
|
865
872
|
}
|
|
866
873
|
}
|
|
867
874
|
const r = t.getUint32(e);
|
|
868
|
-
this.pmt = { header:
|
|
875
|
+
this.pmt = { header: i, streams: n, crc32: r }, this.on.debug && this.on.debug({ pmt: this.pmt });
|
|
869
876
|
};
|
|
870
877
|
// AdaptationField
|
|
871
878
|
parseAdaptationField = (t, s) => {
|
|
872
|
-
let e = s,
|
|
873
|
-
const o = t.getUint8(e), d = !!(o & 128),
|
|
879
|
+
let e = s, i, n, r, a;
|
|
880
|
+
const o = t.getUint8(e), d = !!(o & 128), c = !!(o & 64), h = !!(o & 32), p = !!(o & 16), u = !!(o & 8), g = !!(o & 4), f = !!(o & 2), m = !!(o & 1);
|
|
874
881
|
e += 1;
|
|
875
|
-
const
|
|
882
|
+
const b = (k, w) => {
|
|
876
883
|
let U = BigInt(0);
|
|
877
|
-
U |= BigInt(
|
|
878
|
-
const
|
|
879
|
-
return U = U * 300n + BigInt(
|
|
884
|
+
U |= BigInt(k.getUint16(w)) << 25n, U |= BigInt(k.getUint16(w + 1)) << 17n, U |= BigInt(k.getUint16(w + 2)) << 9n, U |= BigInt(k.getUint16(w + 3)) << 1n, U |= BigInt(k.getUint16(w + 4) >> 7);
|
|
885
|
+
const I = (k.getUint16(w + 4) & 1) << 8 | k.getUint16(w + 5);
|
|
886
|
+
return U = U * 300n + BigInt(I), U;
|
|
880
887
|
};
|
|
881
|
-
if (p && (
|
|
882
|
-
const
|
|
883
|
-
e += 1,
|
|
888
|
+
if (p && (i = b(t, e), e += 6), u && (n = b(t, e), e += 6), g && (r = t.getInt8(e), e += 1), f) {
|
|
889
|
+
const k = t.getUint8(e);
|
|
890
|
+
e += 1, a = new Uint8Array(t.buffer, e, k), e += k;
|
|
884
891
|
}
|
|
885
|
-
return { discontinuity_indicator: d, random_access_indicator:
|
|
892
|
+
return { discontinuity_indicator: d, random_access_indicator: c, elementary_stream_priority_indicator: h, pcr_flag: p, opcr_flag: u, splicing_point_flag: g, transport_private_data_flag: f, adaptation_field_extension_flag: m, pcr: i, opcr: n, splice_countdown: r, transport_private_data: a };
|
|
886
893
|
};
|
|
887
894
|
parseAudio = async (t) => {
|
|
888
895
|
const s = new DataView(t.buffer);
|
|
889
|
-
let e = 0,
|
|
896
|
+
let e = 0, i, n;
|
|
890
897
|
{
|
|
891
898
|
const r = s.getUint8(e) === 0 && s.getUint8(e + 1) === 0 && s.getUint8(e + 2) === 1;
|
|
892
899
|
if (e += 3, !r)
|
|
893
900
|
throw new Error("invalid ts audio payload.");
|
|
894
|
-
const
|
|
901
|
+
const a = s.getUint8(e);
|
|
895
902
|
e += 1;
|
|
896
903
|
const o = s.getUint8(e) << 8 | s.getUint8(e + 1);
|
|
897
904
|
e += 2;
|
|
898
|
-
let d,
|
|
905
|
+
let d, c, h, p, u;
|
|
899
906
|
{
|
|
900
907
|
const m = s.getUint8(e);
|
|
901
|
-
e += 1, d = m >> 4 & 3,
|
|
908
|
+
e += 1, d = m >> 4 & 3, c = (m >> 3 & 1) === 1, h = (m >> 2 & 1) === 1, p = (m >> 1 & 1) === 1, u = (m & 1) === 1;
|
|
902
909
|
}
|
|
903
910
|
let g, f;
|
|
904
911
|
{
|
|
905
912
|
const m = s.getUint8(e);
|
|
906
913
|
e += 1;
|
|
907
|
-
const
|
|
908
|
-
e += 1, (
|
|
914
|
+
const b = m >> 6, k = s.getUint8(e);
|
|
915
|
+
e += 1, (b & 2) === 2 && (g = this.parsePtsDts(s, e)), (b & 1) === 1 ? f = this.parsePtsDts(s, e + 5) : f = g, e += k;
|
|
909
916
|
}
|
|
910
|
-
|
|
917
|
+
i = { stream_id: a, pes_packet_length: o, scrambling_control: d, priority: c, data_alignment: h, copyright: p, original_copy: u, pts: g, dts: f };
|
|
911
918
|
}
|
|
912
|
-
|
|
919
|
+
n = t.slice(e);
|
|
913
920
|
{
|
|
914
921
|
if (!this.audioConfig && s.getUint8(e) === 255) {
|
|
915
922
|
const h = s.getUint8(e + 2), p = s.getUint8(e + 3);
|
|
916
923
|
let u, g;
|
|
917
924
|
g = h >> 2 & 15, u = (h & 1) << 2 | p >> 6;
|
|
918
|
-
const f = `mp4a.40.${u}`,
|
|
919
|
-
this.audioConfig = { kind: "audio", codec: f, sampleRate:
|
|
925
|
+
const f = `mp4a.40.${u}`, b = [96e3, 88200, 64e3, 48e3, 44100, 32e3, 24e3, 22050, 16e3, 12e3, 11025, 8e3, 7350][g];
|
|
926
|
+
this.audioConfig = { kind: "audio", codec: f, sampleRate: b, numberOfChannels: u }, this.on.config && this.on.config(this.audioConfig);
|
|
920
927
|
}
|
|
921
|
-
const { dts: r = 0, pts:
|
|
922
|
-
return { kind: "audio", type: "key", dts: r, pts:
|
|
928
|
+
const { dts: r = 0, pts: a = 0 } = i, o = a - r, d = n.slice(7);
|
|
929
|
+
return { kind: "audio", type: "key", dts: r, pts: a, cts: o, data: d };
|
|
923
930
|
}
|
|
924
931
|
};
|
|
925
932
|
parseVideo = async (t) => {
|
|
926
933
|
const s = new DataView(t.buffer);
|
|
927
|
-
let e = 0,
|
|
934
|
+
let e = 0, i, n;
|
|
928
935
|
{
|
|
929
936
|
const r = s.getUint8(e) === 0 && s.getUint8(e + 1) === 0 && s.getUint8(e + 2) === 1;
|
|
930
937
|
if (e += 3, !r)
|
|
931
938
|
throw new Error("invalid ts video payload.");
|
|
932
|
-
const
|
|
939
|
+
const a = s.getUint8(e);
|
|
933
940
|
e += 1;
|
|
934
941
|
const o = s.getUint8(e) << 8 | s.getUint8(e + 1);
|
|
935
942
|
e += 2;
|
|
936
|
-
let d,
|
|
943
|
+
let d, c, h, p, u;
|
|
937
944
|
{
|
|
938
945
|
const m = s.getUint8(e);
|
|
939
|
-
e += 1, d = m >> 4 & 3,
|
|
946
|
+
e += 1, d = m >> 4 & 3, c = (m >> 3 & 1) === 1, h = (m >> 2 & 1) === 1, p = (m >> 1 & 1) === 1, u = (m & 1) === 1;
|
|
940
947
|
}
|
|
941
948
|
let g, f;
|
|
942
949
|
{
|
|
943
950
|
const m = s.getUint8(e);
|
|
944
951
|
e += 1;
|
|
945
|
-
const
|
|
946
|
-
e += 1, (
|
|
952
|
+
const b = m >> 6, k = s.getUint8(e);
|
|
953
|
+
e += 1, (b & 2) === 2 && (g = this.parsePtsDts(s, e)), (b & 1) === 1 ? f = this.parsePtsDts(s, e + 5) : f = g, e += k;
|
|
947
954
|
}
|
|
948
|
-
|
|
955
|
+
i = { stream_id: a, pes_packet_length: o, scrambling_control: d, priority: c, data_alignment: h, copyright: p, original_copy: u, pts: g, dts: f };
|
|
949
956
|
}
|
|
950
|
-
|
|
957
|
+
n = t.slice(e);
|
|
951
958
|
{
|
|
952
|
-
const r = this.getNalus(
|
|
959
|
+
const r = this.getNalus(n);
|
|
953
960
|
if (!this.videoConfig) {
|
|
954
961
|
let u, g;
|
|
955
962
|
if (u = r.find((m) => m.type === 7)?.nalu.slice(4), g = r.find((m) => m.type === 8)?.nalu.slice(4), u && g) {
|
|
956
|
-
const f =
|
|
963
|
+
const f = H(u, g), { codec: m } = R(f);
|
|
957
964
|
this.videoConfig = { kind: "video", codec: m, description: f, sps: u, pps: g }, this.on.config && this.on.config(this.videoConfig);
|
|
958
965
|
}
|
|
959
966
|
}
|
|
960
|
-
const
|
|
967
|
+
const a = [];
|
|
961
968
|
let o = "delta";
|
|
962
969
|
for (const u of r) {
|
|
963
970
|
const { type: g, nalu: f } = u;
|
|
@@ -965,25 +972,25 @@ class Z {
|
|
|
965
972
|
case 6:
|
|
966
973
|
// sei
|
|
967
974
|
case 9:
|
|
968
|
-
|
|
975
|
+
a.push(f);
|
|
969
976
|
break;
|
|
970
977
|
case 1:
|
|
971
|
-
o = "delta",
|
|
978
|
+
o = "delta", a.push(f);
|
|
972
979
|
break;
|
|
973
980
|
case 5:
|
|
974
|
-
o = "key",
|
|
981
|
+
o = "key", a.push(f);
|
|
975
982
|
break;
|
|
976
983
|
}
|
|
977
984
|
}
|
|
978
|
-
const d = X(
|
|
979
|
-
return { kind: "video", type: o, dts:
|
|
985
|
+
const d = X(a), { dts: c = 0, pts: h = 0 } = i, p = h - c;
|
|
986
|
+
return { kind: "video", type: o, dts: c, pts: h, cts: p, data: d, nalus: a };
|
|
980
987
|
}
|
|
981
988
|
};
|
|
982
989
|
/**
|
|
983
990
|
* 解析 PTS/DTS 时间戳(33-bit,单位:90kHz)
|
|
984
991
|
*/
|
|
985
992
|
parsePtsDts(t, s) {
|
|
986
|
-
const e = t.getUint8(s),
|
|
993
|
+
const e = t.getUint8(s), i = t.getUint8(s + 1), n = t.getUint8(s + 2), r = t.getUint8(s + 3), a = t.getUint8(s + 4), o = (BigInt(e) & 0b00001110n) << 29n | (BigInt(i) & 0b11111111n) << 22n | (BigInt(n) & 0b11111110n) << 14n | (BigInt(r) & 0b11111111n) << 7n | (BigInt(a) & 0b11111110n) >> 1n;
|
|
987
994
|
return Number(o) / 90;
|
|
988
995
|
}
|
|
989
996
|
getNalus = (t) => {
|
|
@@ -995,8 +1002,8 @@ class Z {
|
|
|
995
1002
|
continue;
|
|
996
1003
|
}
|
|
997
1004
|
e += 3;
|
|
998
|
-
let
|
|
999
|
-
const
|
|
1005
|
+
let i = e;
|
|
1006
|
+
const n = t[e] & 31;
|
|
1000
1007
|
for (e += 1; !(e + 1 > t.byteLength); ) {
|
|
1001
1008
|
if (t[e] !== 0 || t[e + 1] !== 0 || t[e + 2] !== 1) {
|
|
1002
1009
|
e += 1;
|
|
@@ -1004,10 +1011,10 @@ class Z {
|
|
|
1004
1011
|
}
|
|
1005
1012
|
break;
|
|
1006
1013
|
}
|
|
1007
|
-
let r = e -
|
|
1014
|
+
let r = e - i;
|
|
1008
1015
|
if (t[e - 1] === 0 && (r -= 1), r !== 0) {
|
|
1009
|
-
const
|
|
1010
|
-
s.push({ type:
|
|
1016
|
+
const a = t.slice(i, i + r), o = K(a);
|
|
1017
|
+
s.push({ type: n, nalu: o });
|
|
1011
1018
|
}
|
|
1012
1019
|
}
|
|
1013
1020
|
return s;
|
|
@@ -1026,10 +1033,10 @@ class tt {
|
|
|
1026
1033
|
parse = async (t) => {
|
|
1027
1034
|
let s = 0;
|
|
1028
1035
|
for (this.header || (this.parseHeader(t, s), s += 9); this.isSurplusTag(t, s) !== !1; ) {
|
|
1029
|
-
const
|
|
1030
|
-
if (
|
|
1031
|
-
const o = this.parseTagBody(
|
|
1032
|
-
switch (
|
|
1036
|
+
const i = this.parseTagHeader(t, s + 4), { tagType: n, dataSize: r, timestamp: a } = i;
|
|
1037
|
+
if (n) {
|
|
1038
|
+
const o = this.parseTagBody(n, t, s + 4 + 11, r);
|
|
1039
|
+
switch (n) {
|
|
1033
1040
|
case "script":
|
|
1034
1041
|
this.on.info && this.on.info(o);
|
|
1035
1042
|
break;
|
|
@@ -1037,11 +1044,11 @@ class tt {
|
|
|
1037
1044
|
{
|
|
1038
1045
|
const { accPacketType: d } = o;
|
|
1039
1046
|
if (d === 0) {
|
|
1040
|
-
const { codec:
|
|
1041
|
-
this.audioConfig = { kind: "audio", codec:
|
|
1047
|
+
const { codec: c, sampleRate: h, channelConfiguration: p } = o;
|
|
1048
|
+
this.audioConfig = { kind: "audio", codec: c, sampleRate: h, numberOfChannels: p }, this.on.config && this.on.config(this.audioConfig);
|
|
1042
1049
|
} else {
|
|
1043
|
-
const { cts:
|
|
1044
|
-
this.on.chunk && this.on.chunk({ kind: "audio", type: p, dts:
|
|
1050
|
+
const { cts: c, data: h } = o, p = "key", u = c === void 0 ? void 0 : c + a;
|
|
1051
|
+
this.on.chunk && this.on.chunk({ kind: "audio", type: p, dts: a, pts: u, cts: c, data: h });
|
|
1045
1052
|
}
|
|
1046
1053
|
}
|
|
1047
1054
|
break;
|
|
@@ -1049,11 +1056,11 @@ class tt {
|
|
|
1049
1056
|
{
|
|
1050
1057
|
const { avcPacketType: d } = o;
|
|
1051
1058
|
if (d === 0) {
|
|
1052
|
-
const { codec:
|
|
1053
|
-
this.videoConfig = { kind: "video", codec:
|
|
1059
|
+
const { codec: c, sps: h, pps: p, data: u } = o;
|
|
1060
|
+
this.videoConfig = { kind: "video", codec: c, description: u, sps: h, pps: p }, this.on.config && this.on.config(this.videoConfig);
|
|
1054
1061
|
} else {
|
|
1055
|
-
const { frameType:
|
|
1056
|
-
this.on.chunk && this.on.chunk({ kind: "video", type: g, dts:
|
|
1062
|
+
const { frameType: c, cts: h, data: p, nalus: u } = o, g = c === 1 ? "key" : "delta", f = h === void 0 ? void 0 : h + a;
|
|
1063
|
+
this.on.chunk && this.on.chunk({ kind: "video", type: g, dts: a, pts: f, cts: h, data: p, nalus: u });
|
|
1057
1064
|
}
|
|
1058
1065
|
}
|
|
1059
1066
|
break;
|
|
@@ -1066,30 +1073,30 @@ class tt {
|
|
|
1066
1073
|
};
|
|
1067
1074
|
// Header
|
|
1068
1075
|
parseHeader = (t, s) => {
|
|
1069
|
-
let e,
|
|
1070
|
-
e = t.getUint8(s) << 16 | t.getUint8(s + 1) << 8 | t.getUint8(s + 2),
|
|
1076
|
+
let e, i, n, r;
|
|
1077
|
+
e = t.getUint8(s) << 16 | t.getUint8(s + 1) << 8 | t.getUint8(s + 2), i = t.getUint8(3);
|
|
1071
1078
|
{
|
|
1072
|
-
const o = t.getUint8(0).toString(2).padStart(5, "0").split(""), [, , d, ,
|
|
1073
|
-
|
|
1079
|
+
const o = t.getUint8(0).toString(2).padStart(5, "0").split(""), [, , d, , c] = o;
|
|
1080
|
+
n = { audio: c === "1", video: d === "1" };
|
|
1074
1081
|
}
|
|
1075
|
-
r = t.getUint32(5), this.header = { signature: e, version:
|
|
1082
|
+
r = t.getUint32(5), this.header = { signature: e, version: i, flags: n, dataOffset: r };
|
|
1076
1083
|
};
|
|
1077
1084
|
// 是否是完整tag
|
|
1078
1085
|
isSurplusTag = (t, s) => {
|
|
1079
1086
|
let e = !0;
|
|
1080
|
-
const
|
|
1081
|
-
if (s + 4 >
|
|
1087
|
+
const i = t.byteLength;
|
|
1088
|
+
if (s + 4 > i)
|
|
1082
1089
|
e = !1;
|
|
1083
|
-
else if (s + 4 + 11 >
|
|
1090
|
+
else if (s + 4 + 11 > i)
|
|
1084
1091
|
e = !1;
|
|
1085
1092
|
else {
|
|
1086
|
-
const
|
|
1087
|
-
s + 4 + 11 +
|
|
1093
|
+
const n = _(t, s + 4 + 1);
|
|
1094
|
+
s + 4 + 11 + n > i && (e = !1);
|
|
1088
1095
|
}
|
|
1089
1096
|
return e;
|
|
1090
1097
|
};
|
|
1091
1098
|
parseTagHeader = (t, s) => {
|
|
1092
|
-
let e,
|
|
1099
|
+
let e, i, n, r, a;
|
|
1093
1100
|
{
|
|
1094
1101
|
const o = t.getUint8(s);
|
|
1095
1102
|
let d;
|
|
@@ -1106,22 +1113,22 @@ class tt {
|
|
|
1106
1113
|
}
|
|
1107
1114
|
e = d;
|
|
1108
1115
|
}
|
|
1109
|
-
return
|
|
1116
|
+
return i = _(t, s + 1), n = _(t, s + 4), r = t.getUint8(s + 7), a = _(t, s + 8), { tagType: e, dataSize: i, timestamp: n, timestampExtended: r, streamID: a };
|
|
1110
1117
|
};
|
|
1111
|
-
parseTagBody = (t, s, e,
|
|
1112
|
-
let
|
|
1118
|
+
parseTagBody = (t, s, e, i) => {
|
|
1119
|
+
let n;
|
|
1113
1120
|
switch (t) {
|
|
1114
1121
|
case "script":
|
|
1115
|
-
|
|
1122
|
+
n = this.parseMetaData(s, e);
|
|
1116
1123
|
break;
|
|
1117
1124
|
case "audio":
|
|
1118
|
-
|
|
1125
|
+
n = this.parseAudio(s, e, i);
|
|
1119
1126
|
break;
|
|
1120
1127
|
case "video":
|
|
1121
|
-
|
|
1128
|
+
n = this.parseVideo(s, e, i);
|
|
1122
1129
|
break;
|
|
1123
1130
|
}
|
|
1124
|
-
return
|
|
1131
|
+
return n;
|
|
1125
1132
|
};
|
|
1126
1133
|
parseMetaData = (t, s) => {
|
|
1127
1134
|
let e = s;
|
|
@@ -1129,126 +1136,126 @@ class tt {
|
|
|
1129
1136
|
if (t.getUint8(e) !== 2) throw new Error("Invalid AMF type for onMetaData (expected 0x02)");
|
|
1130
1137
|
e = e + 1;
|
|
1131
1138
|
}
|
|
1132
|
-
const
|
|
1139
|
+
const i = t.getUint16(e, !1);
|
|
1133
1140
|
e = e + 2;
|
|
1134
1141
|
{
|
|
1135
|
-
const
|
|
1136
|
-
if ((this.textDecoder?.decode(
|
|
1137
|
-
e = e +
|
|
1142
|
+
const a = new Int8Array(t.buffer.slice(e, e + i));
|
|
1143
|
+
if ((this.textDecoder?.decode(a) || "") !== "onMetaData") throw new Error("Expected 'onMetaData' string");
|
|
1144
|
+
e = e + i;
|
|
1138
1145
|
}
|
|
1139
|
-
const
|
|
1140
|
-
return e = e + 1, this.getAMFValue(t, e,
|
|
1146
|
+
const n = this.getAmfType(t, e);
|
|
1147
|
+
return e = e + 1, this.getAMFValue(t, e, n).value;
|
|
1141
1148
|
};
|
|
1142
1149
|
parseAudio = (t, s, e) => {
|
|
1143
|
-
let
|
|
1144
|
-
const
|
|
1145
|
-
|
|
1146
|
-
const
|
|
1147
|
-
|
|
1148
|
-
const h = e, p = new Uint8Array(t.buffer.slice(
|
|
1149
|
-
if (r === 10 &&
|
|
1150
|
-
const u = t.getUint8(
|
|
1151
|
-
return { soundFormat: r, soundRate:
|
|
1150
|
+
let i = s;
|
|
1151
|
+
const n = t.getUint8(i), r = n >> 4 & 15, a = n >> 2 & 3, o = n >> 1 & 1, d = n & 1;
|
|
1152
|
+
i = i + 1;
|
|
1153
|
+
const c = t.getUint8(i);
|
|
1154
|
+
i = i + 1;
|
|
1155
|
+
const h = e, p = new Uint8Array(t.buffer.slice(i, i + h));
|
|
1156
|
+
if (r === 10 && c === 0) {
|
|
1157
|
+
const u = t.getUint8(i), g = t.getUint8(i + 1), f = u >> 3 & 31, m = (u & 7) << 1 | g >> 7, b = g >> 3 & 15, k = [96e3, 88200, 64e3, 48e3, 44100, 32e3, 24e3, 22050, 16e3, 12e3, 11025, 8e3, 7350], w = `mp4a.40.${f}`, U = k[m];
|
|
1158
|
+
return { soundFormat: r, soundRate: a, soundSize: o, soundType: d, accPacketType: c, data: p, samplingFrequencyIndex: m, channelConfiguration: b, codec: w, sampleRate: U };
|
|
1152
1159
|
}
|
|
1153
|
-
return { soundFormat: r, soundRate:
|
|
1160
|
+
return { soundFormat: r, soundRate: a, soundSize: o, soundType: d, accPacketType: c, data: p };
|
|
1154
1161
|
};
|
|
1155
1162
|
parseVideo = (t, s, e) => {
|
|
1156
|
-
let
|
|
1157
|
-
const
|
|
1158
|
-
|
|
1159
|
-
const o = t.getUint8(
|
|
1160
|
-
|
|
1161
|
-
const d = _(t,
|
|
1162
|
-
|
|
1163
|
-
const
|
|
1164
|
-
switch (
|
|
1163
|
+
let i = s;
|
|
1164
|
+
const n = t.getUint8(i), r = n >> 4 & 15, a = n & 15;
|
|
1165
|
+
i = i + 1;
|
|
1166
|
+
const o = t.getUint8(i);
|
|
1167
|
+
i = i + 1;
|
|
1168
|
+
const d = _(t, i);
|
|
1169
|
+
i = i + 3;
|
|
1170
|
+
const c = e - 5, h = new Uint8Array(t.buffer.slice(i, i + c));
|
|
1171
|
+
switch (a) {
|
|
1165
1172
|
case 7:
|
|
1166
1173
|
if (o === 0) {
|
|
1167
|
-
const p =
|
|
1168
|
-
return { frameType: r, codecID:
|
|
1174
|
+
const p = R(h);
|
|
1175
|
+
return { frameType: r, codecID: a, avcPacketType: o, cts: d, data: h, ...p };
|
|
1169
1176
|
} else if (o === 1) {
|
|
1170
|
-
const p = [], u =
|
|
1171
|
-
for (; !(
|
|
1172
|
-
const g = t.getUint32(
|
|
1173
|
-
|
|
1177
|
+
const p = [], u = i + e - 5;
|
|
1178
|
+
for (; !(i + 4 > u); ) {
|
|
1179
|
+
const g = t.getUint32(i, !1), f = new Uint8Array(t.buffer.slice(i, i + 4 + g));
|
|
1180
|
+
i += 4 + g, p.push(f);
|
|
1174
1181
|
}
|
|
1175
|
-
return { frameType: r, codecID:
|
|
1182
|
+
return { frameType: r, codecID: a, avcPacketType: o, cts: d, data: h, nalus: p };
|
|
1176
1183
|
}
|
|
1177
1184
|
break;
|
|
1178
1185
|
default:
|
|
1179
1186
|
throw new Error("Unsupported codecID");
|
|
1180
1187
|
}
|
|
1181
|
-
return { frameType: r, codecID:
|
|
1188
|
+
return { frameType: r, codecID: a, avcPacketType: o, cts: d, data: h };
|
|
1182
1189
|
};
|
|
1183
1190
|
getAmfType = (t, s) => t.getUint8(s);
|
|
1184
1191
|
getAMFName = (t, s, e) => {
|
|
1185
|
-
const
|
|
1186
|
-
return this.textDecoder?.decode(
|
|
1192
|
+
const i = new Uint8Array(t.buffer.slice(s, s + e));
|
|
1193
|
+
return this.textDecoder?.decode(i) || "";
|
|
1187
1194
|
};
|
|
1188
1195
|
getAMFValue = (t, s, e) => {
|
|
1189
|
-
let
|
|
1196
|
+
let i = s, n, r = 0;
|
|
1190
1197
|
switch (e) {
|
|
1191
1198
|
case 0:
|
|
1192
|
-
|
|
1199
|
+
n = t.getFloat64(i, !1), r = 8;
|
|
1193
1200
|
break;
|
|
1194
1201
|
case 1:
|
|
1195
|
-
|
|
1202
|
+
n = !!t.getUint8(i), r = 1;
|
|
1196
1203
|
break;
|
|
1197
1204
|
case 2:
|
|
1198
1205
|
{
|
|
1199
|
-
|
|
1200
|
-
const o = t.getUint16(
|
|
1201
|
-
|
|
1202
|
-
const d = new Int8Array(t.buffer,
|
|
1203
|
-
|
|
1206
|
+
n = "";
|
|
1207
|
+
const o = t.getUint16(i, !1);
|
|
1208
|
+
i = i + 2;
|
|
1209
|
+
const d = new Int8Array(t.buffer, i, o).filter((h) => h !== 0);
|
|
1210
|
+
n = (this.textDecoder?.decode(d) || "").trim(), r = 2 + o;
|
|
1204
1211
|
}
|
|
1205
1212
|
break;
|
|
1206
1213
|
case 3:
|
|
1207
|
-
for (
|
|
1208
|
-
const o = t.getUint16(
|
|
1214
|
+
for (n = {}; i < t.byteLength; ) {
|
|
1215
|
+
const o = t.getUint16(i, !1);
|
|
1209
1216
|
if (o === 0) break;
|
|
1210
|
-
|
|
1211
|
-
const d = this.getAMFName(t,
|
|
1212
|
-
|
|
1213
|
-
const
|
|
1214
|
-
if (
|
|
1215
|
-
|
|
1216
|
-
const h = this.getAMFValue(t,
|
|
1217
|
-
|
|
1217
|
+
i = i + 2;
|
|
1218
|
+
const d = this.getAMFName(t, i, o);
|
|
1219
|
+
i = i + o;
|
|
1220
|
+
const c = this.getAmfType(t, i);
|
|
1221
|
+
if (c === 6) break;
|
|
1222
|
+
i = i + 1;
|
|
1223
|
+
const h = this.getAMFValue(t, i, c);
|
|
1224
|
+
i = i + h.length, n[d] = h.value, r = 2 + o + 1 + h.length;
|
|
1218
1225
|
}
|
|
1219
1226
|
break;
|
|
1220
1227
|
case 8:
|
|
1221
1228
|
{
|
|
1222
|
-
|
|
1223
|
-
const o = t.getUint32(
|
|
1224
|
-
|
|
1229
|
+
n = {};
|
|
1230
|
+
const o = t.getUint32(i, !1);
|
|
1231
|
+
i = i + 4;
|
|
1225
1232
|
for (let d = 0; d < o; d++) {
|
|
1226
|
-
const
|
|
1227
|
-
|
|
1228
|
-
const h = this.getAMFName(t,
|
|
1229
|
-
|
|
1230
|
-
const p = this.getAmfType(t,
|
|
1231
|
-
|
|
1232
|
-
const u = this.getAMFValue(t,
|
|
1233
|
-
|
|
1233
|
+
const c = t.getUint16(i, !1);
|
|
1234
|
+
i = i + 2;
|
|
1235
|
+
const h = this.getAMFName(t, i, c);
|
|
1236
|
+
i = i + c;
|
|
1237
|
+
const p = this.getAmfType(t, i);
|
|
1238
|
+
i = i + 1;
|
|
1239
|
+
const u = this.getAMFValue(t, i, p);
|
|
1240
|
+
i = i + u.length, n[h] = u.value, r = 2 + c + 1 + u.length;
|
|
1234
1241
|
}
|
|
1235
1242
|
}
|
|
1236
1243
|
break;
|
|
1237
1244
|
case 10:
|
|
1238
1245
|
{
|
|
1239
|
-
|
|
1240
|
-
const o = t.getUint32(
|
|
1241
|
-
|
|
1246
|
+
n = [];
|
|
1247
|
+
const o = t.getUint32(i, !1);
|
|
1248
|
+
i = i + 4;
|
|
1242
1249
|
for (let d = 0; d < o; d++) {
|
|
1243
|
-
const
|
|
1244
|
-
|
|
1245
|
-
const h = this.getAMFValue(t,
|
|
1246
|
-
|
|
1250
|
+
const c = this.getAmfType(t, i);
|
|
1251
|
+
i = i + 1;
|
|
1252
|
+
const h = this.getAMFValue(t, i, c);
|
|
1253
|
+
i = i + h.length, n.push(h.value), r = 1 + h.length;
|
|
1247
1254
|
}
|
|
1248
1255
|
}
|
|
1249
1256
|
break;
|
|
1250
1257
|
}
|
|
1251
|
-
return { amfType: e, length: r, value:
|
|
1258
|
+
return { amfType: e, length: r, value: n };
|
|
1252
1259
|
};
|
|
1253
1260
|
}
|
|
1254
1261
|
class st {
|
|
@@ -1298,30 +1305,105 @@ class st {
|
|
|
1298
1305
|
}
|
|
1299
1306
|
};
|
|
1300
1307
|
}
|
|
1301
|
-
class
|
|
1308
|
+
class it {
|
|
1302
1309
|
audioDecoderConfig;
|
|
1303
1310
|
audioDecoder;
|
|
1304
1311
|
videoDecoderConfig;
|
|
1305
1312
|
videoDecoder;
|
|
1306
1313
|
hasKeyFrame = !1;
|
|
1314
|
+
baseTime = 0;
|
|
1315
|
+
// ms
|
|
1316
|
+
pendingChunks = [];
|
|
1317
|
+
isProcessing = !1;
|
|
1318
|
+
decodeTimer = 0;
|
|
1319
|
+
// 解码定时器
|
|
1320
|
+
frameTrack = !1;
|
|
1321
|
+
// 追帧
|
|
1322
|
+
minFrameTrackCacheNum = 20;
|
|
1323
|
+
// 最小追帧缓存数 (开启追帧才有效)
|
|
1324
|
+
decodingSpeed = 40;
|
|
1325
|
+
// ms
|
|
1326
|
+
decodingSpeedRatio = 1;
|
|
1327
|
+
maxDecodingSpeedRatio = 2;
|
|
1328
|
+
nextRenderTime;
|
|
1329
|
+
// 下一次渲染的时间
|
|
1307
1330
|
on = { audio: {}, video: {} };
|
|
1308
1331
|
constructor() {
|
|
1332
|
+
this.baseTime = (/* @__PURE__ */ new Date()).getTime() - performance.now(), this.initDecodeInterval();
|
|
1309
1333
|
}
|
|
1334
|
+
init = (t) => {
|
|
1335
|
+
const { decodingSpeed: s, frameTrack: e, minFrameTrackCacheNum: i } = t;
|
|
1336
|
+
s !== void 0 && (this.decodingSpeed = s), e !== void 0 && (this.frameTrack = e), i !== void 0 && (this.minFrameTrackCacheNum = i);
|
|
1337
|
+
};
|
|
1338
|
+
setFrameTrack = (t) => {
|
|
1339
|
+
this.frameTrack = t, this.frameTrack === !1 && (this.decodingSpeedRatio = 1);
|
|
1340
|
+
};
|
|
1341
|
+
initDecodeInterval = () => {
|
|
1342
|
+
let t = this.decodingSpeed / this.decodingSpeedRatio;
|
|
1343
|
+
const s = this.baseTime + performance.now();
|
|
1344
|
+
if (this.nextRenderTime) {
|
|
1345
|
+
const e = s - this.nextRenderTime;
|
|
1346
|
+
t -= e;
|
|
1347
|
+
}
|
|
1348
|
+
this.nextRenderTime = s + t, this.decodeTimer = setTimeout(() => {
|
|
1349
|
+
this.decode(), this.initDecodeInterval();
|
|
1350
|
+
}, t);
|
|
1351
|
+
};
|
|
1352
|
+
decode = () => {
|
|
1353
|
+
if (this.isProcessing !== !0) {
|
|
1354
|
+
for (this.isProcessing = !0; ; ) {
|
|
1355
|
+
const t = this.pendingChunks.shift();
|
|
1356
|
+
if (this.frameTrack) {
|
|
1357
|
+
const i = this.pendingChunks.length;
|
|
1358
|
+
if (i >= this.minFrameTrackCacheNum) {
|
|
1359
|
+
const n = Math.min(1 + (i - this.minFrameTrackCacheNum) / 100, this.maxDecodingSpeedRatio);
|
|
1360
|
+
this.decodingSpeedRatio = Number(n.toFixed(1));
|
|
1361
|
+
} else
|
|
1362
|
+
this.decodingSpeedRatio = 1;
|
|
1363
|
+
}
|
|
1364
|
+
if (!t) break;
|
|
1365
|
+
const { type: s, init: e } = t;
|
|
1366
|
+
switch (s) {
|
|
1367
|
+
case "audio":
|
|
1368
|
+
this.decodeAudio(e);
|
|
1369
|
+
break;
|
|
1370
|
+
case "video":
|
|
1371
|
+
this.decodeVideo(e);
|
|
1372
|
+
break;
|
|
1373
|
+
}
|
|
1374
|
+
if (s === "video") break;
|
|
1375
|
+
}
|
|
1376
|
+
this.isProcessing = !1;
|
|
1377
|
+
}
|
|
1378
|
+
};
|
|
1379
|
+
decodeAudio = (t) => {
|
|
1380
|
+
if (!this.audioDecoder) return;
|
|
1381
|
+
const s = new EncodedAudioChunk(t);
|
|
1382
|
+
this.audioDecoder.decode(s);
|
|
1383
|
+
};
|
|
1384
|
+
decodeVideo = (t) => {
|
|
1385
|
+
if (this.videoDecoder && (t.type === "key" && (this.hasKeyFrame = !0), this.hasKeyFrame)) {
|
|
1386
|
+
const s = new EncodedVideoChunk(t);
|
|
1387
|
+
this.videoDecoder.decode(s);
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1390
|
+
destroy = () => {
|
|
1391
|
+
this.audio.destroy(), this.video.destroy(), clearInterval(this.decodeTimer);
|
|
1392
|
+
};
|
|
1310
1393
|
audio = {
|
|
1311
1394
|
init: (t) => {
|
|
1312
1395
|
this.audio.destroy(), this.audioDecoderConfig = { ...t }, this.audioDecoder = new AudioDecoder({
|
|
1313
1396
|
output: (s) => {
|
|
1314
|
-
|
|
1397
|
+
const e = this.decodingSpeedRatio;
|
|
1398
|
+
this.on.audio.decode && this.on.audio.decode({ audioData: s, playbackRate: e });
|
|
1315
1399
|
},
|
|
1316
1400
|
error: (s) => {
|
|
1317
1401
|
this.on.audio.error && this.on.audio.error(s);
|
|
1318
1402
|
}
|
|
1319
1403
|
}), this.audioDecoder.configure(this.audioDecoderConfig);
|
|
1320
1404
|
},
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
const s = new EncodedAudioChunk(t);
|
|
1324
|
-
this.audioDecoder.decode(s);
|
|
1405
|
+
push: (t) => {
|
|
1406
|
+
this.pendingChunks.push({ type: "audio", init: t });
|
|
1325
1407
|
},
|
|
1326
1408
|
flush: () => {
|
|
1327
1409
|
this.audioDecoder?.flush();
|
|
@@ -1334,19 +1416,16 @@ class nt {
|
|
|
1334
1416
|
init: (t) => {
|
|
1335
1417
|
this.video.destroy(), this.videoDecoderConfig = { ...t }, this.videoDecoder = new VideoDecoder({
|
|
1336
1418
|
output: async (s) => {
|
|
1337
|
-
const e =
|
|
1338
|
-
s.close(),
|
|
1419
|
+
const e = s.timestamp + this.baseTime * 1e3, i = await createImageBitmap(s);
|
|
1420
|
+
s.close(), i.width > 0 && i.height > 0 ? this.on.video.decode && this.on.video.decode({ timestamp: e, bitmap: i }) : i.close();
|
|
1339
1421
|
},
|
|
1340
1422
|
error: (s) => {
|
|
1341
|
-
|
|
1423
|
+
this.on.video.error && this.on.video.error(s);
|
|
1342
1424
|
}
|
|
1343
1425
|
}), this.videoDecoder.configure(this.videoDecoderConfig);
|
|
1344
1426
|
},
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
const s = new EncodedVideoChunk(t);
|
|
1348
|
-
this.videoDecoder.decode(s);
|
|
1349
|
-
}
|
|
1427
|
+
push: (t) => {
|
|
1428
|
+
this.pendingChunks.push({ type: "video", init: t });
|
|
1350
1429
|
},
|
|
1351
1430
|
flush: () => {
|
|
1352
1431
|
this.videoDecoder?.flush();
|
|
@@ -1356,45 +1435,26 @@ class nt {
|
|
|
1356
1435
|
}
|
|
1357
1436
|
};
|
|
1358
1437
|
}
|
|
1359
|
-
class
|
|
1360
|
-
isRendering = !1;
|
|
1361
|
-
pendingFrames = [];
|
|
1362
|
-
offscreenCanvas;
|
|
1438
|
+
class nt {
|
|
1363
1439
|
writable;
|
|
1364
1440
|
writer;
|
|
1365
|
-
ctx;
|
|
1366
1441
|
cutOption;
|
|
1367
|
-
baseTime = 0;
|
|
1368
1442
|
pause = !1;
|
|
1369
|
-
shader = ["stream"];
|
|
1370
1443
|
constructor() {
|
|
1371
1444
|
}
|
|
1372
|
-
init = ({
|
|
1373
|
-
this.destroy(), this.
|
|
1374
|
-
};
|
|
1375
|
-
/**
|
|
1376
|
-
* 设置渲染基准时间
|
|
1377
|
-
*/
|
|
1378
|
-
setBaseTime = (t) => {
|
|
1379
|
-
this.baseTime = t;
|
|
1380
|
-
};
|
|
1381
|
-
/**
|
|
1382
|
-
* 设置渲染模式
|
|
1383
|
-
*/
|
|
1384
|
-
setShader = (t) => {
|
|
1385
|
-
this.shader = t;
|
|
1386
|
-
};
|
|
1387
|
-
/**
|
|
1388
|
-
* 设置尺寸
|
|
1389
|
-
*/
|
|
1390
|
-
setSize = ({ width: t, height: s }) => {
|
|
1391
|
-
this.offscreenCanvas && (this.offscreenCanvas.width = t, this.offscreenCanvas.height = s);
|
|
1392
|
-
};
|
|
1393
|
-
destroy = () => {
|
|
1394
|
-
this.isRendering = !1, this.pendingFrames = [], this.offscreenCanvas = void 0, this.ctx = void 0, this.baseTime = 0;
|
|
1445
|
+
init = ({ writable: t }) => {
|
|
1446
|
+
this.destroy(), this.writable = t, this.writer = this.writable.getWriter();
|
|
1395
1447
|
};
|
|
1396
|
-
push = (t) => {
|
|
1397
|
-
|
|
1448
|
+
push = async (t) => {
|
|
1449
|
+
if (this.pause) return;
|
|
1450
|
+
const { timestamp: s } = t;
|
|
1451
|
+
let { bitmap: e } = t;
|
|
1452
|
+
if (this.cutOption) {
|
|
1453
|
+
const { sx: n = 0, sy: r = 0, sw: a = e.width, sh: o = e.height } = this.cutOption;
|
|
1454
|
+
e = await createImageBitmap(e, n, r, a, o);
|
|
1455
|
+
}
|
|
1456
|
+
const i = new VideoFrame(e, { timestamp: s });
|
|
1457
|
+
this.cutOption && e.close(), this.writer.write(i), i.close();
|
|
1398
1458
|
};
|
|
1399
1459
|
/**
|
|
1400
1460
|
* 设置剪切
|
|
@@ -1406,42 +1466,18 @@ class it {
|
|
|
1406
1466
|
* 设置暂停
|
|
1407
1467
|
*/
|
|
1408
1468
|
setPause = (t) => {
|
|
1409
|
-
this.pause = t
|
|
1410
|
-
};
|
|
1411
|
-
calculateTimeUntilNextFrame = (t) => {
|
|
1412
|
-
const s = performance.timeOrigin + performance.now(), n = this.baseTime + t / 1e3 - s;
|
|
1413
|
-
return Math.max(0, n);
|
|
1414
|
-
};
|
|
1415
|
-
renderFrame = async () => {
|
|
1416
|
-
for (this.isRendering = !0; ; ) {
|
|
1417
|
-
const t = this.pendingFrames.shift();
|
|
1418
|
-
if (!t) break;
|
|
1419
|
-
let { timestamp: s, bitmap: e } = t;
|
|
1420
|
-
if (this.cutOption) {
|
|
1421
|
-
const { sx: i = 0, sy: r = 0, sw: c = e.width, sh: o = e.height } = this.cutOption;
|
|
1422
|
-
e = await createImageBitmap(e, i, r, c, o);
|
|
1423
|
-
}
|
|
1424
|
-
const n = this.calculateTimeUntilNextFrame(s);
|
|
1425
|
-
await new Promise((i) => setTimeout(() => i(!0), n)), this.drawImage({ timestamp: s, bitmap: e }), this.cutOption && e.close();
|
|
1426
|
-
}
|
|
1427
|
-
this.isRendering = !1;
|
|
1469
|
+
this.pause = t;
|
|
1428
1470
|
};
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
if (this.shader.includes("stream")) {
|
|
1432
|
-
const s = new VideoFrame(t.bitmap, { timestamp: t.timestamp });
|
|
1433
|
-
this.writer.write(s), s.close();
|
|
1434
|
-
}
|
|
1435
|
-
this.shader.includes("canvas") && this.ctx && this.offscreenCanvas && this.ctx.drawImage(t.bitmap, 0, 0, this.offscreenCanvas.width, this.offscreenCanvas.height);
|
|
1436
|
-
}
|
|
1471
|
+
destroy = () => {
|
|
1472
|
+
this.writable = void 0, this.writer = void 0, this.cutOption = void 0;
|
|
1437
1473
|
};
|
|
1438
1474
|
}
|
|
1439
1475
|
export {
|
|
1440
|
-
|
|
1441
|
-
|
|
1476
|
+
it as Decoder,
|
|
1477
|
+
B as DecoderWorker,
|
|
1442
1478
|
st as Demuxer,
|
|
1443
|
-
|
|
1479
|
+
N as DemuxerWorker,
|
|
1444
1480
|
et as PrPlayer,
|
|
1445
|
-
|
|
1446
|
-
|
|
1481
|
+
nt as Render,
|
|
1482
|
+
z as RenderWorker
|
|
1447
1483
|
};
|