pr-player 0.3.5 → 0.3.7

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/index.js CHANGED
@@ -1,1710 +1,1805 @@
1
- const x = '(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>100&&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;parser;on={};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.info=y=>postMessage({action:"on.info",data:y}),A.on.config=y=>postMessage({action:"on.config",data:y}),A.on.chunk=y=>postMessage({action:"on.chunk",data:y}),A.on.debug=y=>postMessage({action:"on.debug",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);", x], { type: "text/javascript;charset=utf-8" });
2
- function R(g) {
3
- let t;
4
- try {
5
- if (t = T && (self.URL || self.webkitURL).createObjectURL(T), !t) throw "";
6
- const s = new Worker(t, {
7
- name: g?.name
8
- });
9
- return s.addEventListener("error", () => {
10
- (self.URL || self.webkitURL).revokeObjectURL(t);
11
- }), s;
12
- } catch {
13
- return new Worker(
14
- "data:text/javascript;charset=utf-8," + encodeURIComponent(x),
15
- {
16
- name: g?.name
17
- }
18
- );
19
- }
1
+ //#region src/demuxer/demuxer.worker.ts?worker&inline
2
+ var e = "(function(){var e=class{pendingPayloads=[];payload=new Uint8Array;chunks=[];push=e=>{this.pendingPayloads.push(e)};next=(e=0)=>{this.payload=this.payload.slice(e);let t=this.pendingPayloads.shift();if(!t)return!1;let n=new Uint8Array(this.payload.byteLength+t.byteLength);return n.set(this.payload,0),n.set(t,this.payload.byteLength),this.payload=n,new DataView(this.payload.buffer)};pushChunk=e=>{this.chunks.push(e),this.chunks.length>100&&this.chunks.shift()};destroy=()=>{this.pendingPayloads=[],this.payload=new Uint8Array,this.chunks=[]}};let t=(e,t)=>{let n=new Uint8Array(e),r=new Uint8Array(t),i=new Uint8Array(11+n.length+r.length),a=0;return i[a++]=1,i[a++]=n[1],i[a++]=n[2],i[a++]=n[3],i[a++]=255,i[a++]=225,i[a++]=n.length>>8&255,i[a++]=n.length&255,i.set(n,a),a+=n.length,i[a++]=1,i[a++]=r.length>>8&255,i[a++]=r.length&255,i.set(r,a),i},n=e=>{let t=0,n=new DataView(e.buffer),r=n.getUint8(t);if(t+=1,r!==1)throw Error(`Invalid AVC version`);let i=n.getUint8(t)&255;t+=1;let a=n.getUint8(t)&255;t+=1;let o=n.getUint8(t)&255;t+=1;let s=`avc1.${Array.from([i,a,o],e=>e.toString(16).padStart(2,`0`)).join(``)}`,c=(n.getUint8(t)&3)-1;t+=1;let l=n.getUint8(t)&31;t+=1;let u=n.getUint16(t,!1);t+=2;let d=new Uint8Array(n.buffer.slice(t,t+u));t+=u;let f=n.getUint8(t)&31;t+=1;let p=n.getUint16(t,!1);t+=2;let m=new Uint8Array(n.buffer.slice(t,t+p));return t+=p,{version:r,codec:s,profile:i,compatibility:a,level:o,lengthSizeMinusOne:c,numOfSequenceParameterSets:l,sequenceParameterSetLength:u,sps:d,numOfPictureParameterSets:f,pictureParameterSetLength:p,pps:m}},r=e=>{let t=new Uint8Array(4+e.length);return new DataView(t.buffer).setUint32(0,e.length,!1),t.set(e,4),t},i=e=>{let t=0;for(let n of e)t+=n.length;let n=new Uint8Array(t),r=0;for(let t of e){let e=t;n.set(e,r),r+=e.length}return n},a=e=>{let t=`unknown`;switch(e){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};var o=class{pat;pmt;audioConfig;videoConfig;payloadMap=new Map;on={};constructor(){}parse=async e=>{let t=0;for(;!(t+188>e.byteLength);){if(e.getInt8(t)!=71){t++;continue}await this.parsePacket(e,t),t+=188}return t};parsePacket=async(e,t)=>{if(t+188>e.byteLength||e.getUint8(t)!==71)throw Error(`Invalid TS packet`);let n=t,r=this.parseHeader(e,n);n+=4;let{transport_error_indicator:i,pid:a,payload_unit_start_indicator:o,adaptation_field_control:s}=r;if(i===1||a===void 0)return;let c=184;if(s===2||s===3){let t=e.getUint8(n);n+=1,this.parseAdaptationField(e,n),n+=t,c-=t}if(s===3&&--c,s===1||s===3){let t=new Uint8Array(e.buffer.slice(n,n+c));if(a===0)return this.parsePAT(e,n);{let{programs:t=[]}=this.pat||{};if(t.find(e=>e.pmt_pid===a))return this.parsePMT(e,n)}let{streams:r=[]}=this.pmt||{},i=r.find(e=>e.elementary_pid===a);if(i){if(o===1){let e=this.payloadMap.get(a);if(e){switch(i.kind){case`audio`:{let t=await this.parseAudio(e);this.on.chunk&&this.on.chunk(t)}break;case`video`:{let t=await this.parseVideo(e);this.on.chunk&&this.on.chunk(t),await new Promise(e=>setTimeout(()=>e(!0),0))}break}this.payloadMap.delete(a)}}{this.payloadMap.has(a)||this.payloadMap.set(a,new Uint8Array);let e=this.payloadMap.get(a),n=new Uint8Array(e.byteLength+t.byteLength);n.set(e,0),n.set(t,e.byteLength),this.payloadMap.set(a,n)}}}};parseHeader=(e,t)=>{let n=t,r=e.getUint8(n),i=e.getUint8(n+1),a=e.getUint8(n+2),o=e.getUint8(n+3),s=(i&128)>>7;return s===1?{sync_byte:r,transport_error_indicator:s}:{sync_byte:r,transport_error_indicator:s,payload_unit_start_indicator:(i&64)>>6,transport_priority:(i&32)>>5,pid:(i&31)<<8|a,transport_scrambling_control:(o&192)>>6,adaptation_field_control:o>>4&3,continuity_counter:o&15}};parsePAT=(e,t)=>{let n=t,r;{let t=e.getUint8(n);n+=1;let i=e.getUint8(n);if(n+=1,i!==0)throw Error(`Invalid PAT table_id`);let a=e.getUint16(n)&4095;n+=2;let o=e.getUint16(n);n+=2;let s=(e.getUint8(n)&62)>>1,c=e.getUint8(n)&1;n+=1;let l=e.getUint8(n);n+=1;let u=e.getUint8(n);n+=1,r={pointer_field:t,table_id:i,section_length:a,transport_stream_id:o,version_number:s,current_next_indicator:c,section_number:l,last_section_number:u}}let i=[];{let t=r.section_length-5-4,a=n+t;for(;n<a;){let t=e.getUint16(n),r=e.getUint16(n+2)&8191;n+=4,t!==0&&r>=32&&r<=8190&&i.push({program_number:t,pmt_pid:r})}}let a=e.getUint32(n);this.pat={header:r,programs:i,crc32:a},this.on.debug&&this.on.debug({pat:this.pat})};parsePMT=(e,t)=>{let n=t,r;{let t=e.getUint8(n);n+=1;let i=e.getUint8(n);if(n+=1,i!==2)throw Error(`Invalid PMT table_id`);let a=e.getUint16(n)&4095;n+=2;let o=e.getUint16(n);n+=2;let s=(e.getUint8(n)&62)>>1,c=e.getUint8(n)&1;n+=1;let l=e.getUint8(n);n+=1;let u=e.getUint8(n);n+=1;let d=e.getUint16(n)&8191;n+=2;let f=e.getUint16(n)&4095;n+=2,r={pointer_field:t,table_id:i,section_length:a,transport_stream_id:o,version_number:s,current_next_indicator:c,section_number:l,last_section_number:u,pcr_pid:d,program_info_length:f}}let i=[];{let t=r.section_length-9-4,o=n+t;for(;n<o;){let t=e.getUint8(n),r=a(t),o=e.getUint16(n+1)&8191,s=e.getUint16(n+3)&4095;if(n+=5,o<32||o>8190){console.warn(`Invalid elementary_pid: 0x${o.toString(16)}`);continue}i.push({kind:r,stream_type:t,elementary_pid:o,es_info_length:s})}}let o=e.getUint32(n);this.pmt={header:r,streams:i,crc32:o},this.on.debug&&this.on.debug({pmt:this.pmt})};parseAdaptationField=(e,t)=>{let n=t,r,i,a,o,s=e.getUint8(n),c=!!(s&128),l=!!(s&64),u=!!(s&32),d=!!(s&16),f=!!(s&8),p=!!(s&4),m=!!(s&2),h=!!(s&1);n+=1;let g=(e,t)=>{let n=BigInt(0);n|=BigInt(e.getUint16(t))<<25n,n|=BigInt(e.getUint16(t+1))<<17n,n|=BigInt(e.getUint16(t+2))<<9n,n|=BigInt(e.getUint16(t+3))<<1n,n|=BigInt(e.getUint16(t+4)>>7);let r=(e.getUint16(t+4)&1)<<8|e.getUint16(t+5);return n=n*300n+BigInt(r),n};if(d&&(r=g(e,n),n+=6),f&&(i=g(e,n),n+=6),p&&(a=e.getInt8(n),n+=1),m){let t=e.getUint8(n);n+=1,o=new Uint8Array(e.buffer,n,t),n+=t}return{discontinuity_indicator:c,random_access_indicator:l,elementary_stream_priority_indicator:u,pcr_flag:d,opcr_flag:f,splicing_point_flag:p,transport_private_data_flag:m,adaptation_field_extension_flag:h,pcr:r,opcr:i,splice_countdown:a,transport_private_data:o}};parseAudio=async e=>{let t=new DataView(e.buffer),n=0,r,i;{let e=t.getUint8(n)===0&&t.getUint8(n+1)===0&&t.getUint8(n+2)===1;if(n+=3,!e)throw Error(`invalid ts audio payload.`);let i=t.getUint8(n);n+=1;let a=t.getUint8(n)<<8|t.getUint8(n+1);n+=2;let o,s,c,l,u;{let e=t.getUint8(n);n+=1,o=e>>4&3,s=(e>>3&1)==1,c=(e>>2&1)==1,l=(e>>1&1)==1,u=(e&1)==1}let d,f;{let e=t.getUint8(n);n+=1;let r=e>>6,i=t.getUint8(n);n+=1,(r&2)==2&&(d=this.parsePtsDts(t,n)),f=(r&1)==1?this.parsePtsDts(t,n+5):d,n+=i}r={stream_id:i,pes_packet_length:a,scrambling_control:o,priority:s,data_alignment:c,copyright:l,original_copy:u,pts:d,dts:f}}i=e.slice(n);{if(!this.audioConfig&&t.getUint8(n)===255){let e=t.getUint8(n+2),r=t.getUint8(n+3),i,a;a=e>>2&15,i=(e&1)<<2|r>>6,this.audioConfig={kind:`audio`,codec:`mp4a.40.${i}`,sampleRate:[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350][a],numberOfChannels:i},this.on.config&&this.on.config(this.audioConfig)}let{dts:e=0,pts:a=0}=r;return{kind:`audio`,type:`key`,dts:e,pts:a,cts:a-e,data:i.slice(7)}}};parseVideo=async e=>{let r=new DataView(e.buffer),a=0,o,s;{let e=r.getUint8(a)===0&&r.getUint8(a+1)===0&&r.getUint8(a+2)===1;if(a+=3,!e)throw Error(`invalid ts video payload.`);let t=r.getUint8(a);a+=1;let n=r.getUint8(a)<<8|r.getUint8(a+1);a+=2;let i,s,c,l,u;{let e=r.getUint8(a);a+=1,i=e>>4&3,s=(e>>3&1)==1,c=(e>>2&1)==1,l=(e>>1&1)==1,u=(e&1)==1}let d,f;{let e=r.getUint8(a);a+=1;let t=e>>6,n=r.getUint8(a);a+=1,(t&2)==2&&(d=this.parsePtsDts(r,a)),f=(t&1)==1?this.parsePtsDts(r,a+5):d,a+=n}o={stream_id:t,pes_packet_length:n,scrambling_control:i,priority:s,data_alignment:c,copyright:l,original_copy:u,pts:d,dts:f}}s=e.slice(a);{let e=this.getNalus(s);if(!this.videoConfig){let r,i;if(r=e.find(e=>e.type===7)?.nalu.slice(4),i=e.find(e=>e.type===8)?.nalu.slice(4),r&&i){let e=t(r,i),{codec:a}=n(e);this.videoConfig={kind:`video`,codec:a,description:e,sps:r,pps:i},this.on.config&&this.on.config(this.videoConfig)}}let r=[],a=`delta`;for(let t of e){let{type:e,nalu:n}=t;switch(e){case 6:case 9:r.push(n);break;case 1:a=`delta`,r.push(n);break;case 5:a=`key`,r.push(n);break}}let c=i(r),{dts:l=0,pts:u=0}=o,d=u-l;return{kind:`video`,type:a,dts:l,pts:u,cts:d,data:c,nalus:r}}};parsePtsDts(e,t){let n=e.getUint8(t),r=e.getUint8(t+1),i=e.getUint8(t+2),a=e.getUint8(t+3),o=e.getUint8(t+4),s=(BigInt(n)&14n)<<29n|(BigInt(r)&255n)<<22n|(BigInt(i)&254n)<<14n|(BigInt(a)&255n)<<7n|(BigInt(o)&254n)>>1n;return Number(s)/90}getNalus=e=>{let t=[],n=0;for(;!(n+4>e.byteLength);){if(e[n]!==0||e[n+1]!==0||e[n+2]!==1){n+=1;continue}n+=3;let i=n,a=e[n]&31;for(n+=1;!(n+1>e.byteLength);){if(e[n]!==0||e[n+1]!==0||e[n+2]!==1){n+=1;continue}break}let o=n-i;if(e[n-1]===0&&--o,o!==0){let n=r(e.slice(i,i+o));t.push({type:a,nalu:n})}}return t}};let s=(e,t)=>e.getUint8(t)<<16|e.getUint8(t+1)<<8|e.getUint8(t+2);var c=class{audioConfig;videoConfig;header;textDecoder=new TextDecoder(`utf-8`);on={};constructor(){}parse=async e=>{let t=0;for(this.header||(this.parseHeader(e,t),t+=9);this.isSurplusTag(e,t)!==!1;){let{tagType:n,dataSize:r,timestamp:i}=this.parseTagHeader(e,t+4);if(n){let a=this.parseTagBody(n,e,t+4+11,r);switch(n){case`script`:this.on.info&&this.on.info(a);break;case`audio`:{let{accPacketType:e}=a;if(e===0){let{codec:e,sampleRate:t,channelConfiguration:n}=a;this.audioConfig={kind:`audio`,codec:e,sampleRate:t,numberOfChannels:n},this.on.config&&this.on.config(this.audioConfig)}else{let{cts:e,data:t}=a,n=e===void 0?void 0:e+i;this.on.chunk&&this.on.chunk({kind:`audio`,type:`key`,dts:i,pts:n,cts:e,data:t})}}break;case`video`:{let{avcPacketType:e}=a;if(e===0){let{codec:e,sps:t,pps:n,data:r}=a;this.videoConfig={kind:`video`,codec:e,description:r,sps:t,pps:n},this.on.config&&this.on.config(this.videoConfig)}else{let{frameType:e,cts:t,data:n,nalus:r}=a,o=e===1?`key`:`delta`,s=t===void 0?void 0:t+i;this.on.chunk&&this.on.chunk({kind:`video`,type:o,dts:i,pts:s,cts:t,data:n,nalus:r})}}break}t=t+4+11+r}await new Promise(e=>setTimeout(()=>e(!0),8))}return t};parseHeader=(e,t)=>{let n,r,i,a;n=e.getUint8(t)<<16|e.getUint8(t+1)<<8|e.getUint8(t+2),r=e.getUint8(3);{let[,,t,,n]=e.getUint8(0).toString(2).padStart(5,`0`).split(``);i={audio:n===`1`,video:t===`1`}}a=e.getUint32(5),this.header={signature:n,version:r,flags:i,dataOffset:a}};isSurplusTag=(e,t)=>{let n=!0,r=e.byteLength;if(t+4>r)n=!1;else if(t+4+11>r)n=!1;else{let i=s(e,t+4+1);t+4+11+i>r&&(n=!1)}return n};parseTagHeader=(e,t)=>{let n,r,i,a,o;{let r=e.getUint8(t),i;switch(r){case 18:i=`script`;break;case 8:i=`audio`;break;case 9:i=`video`;break}n=i}return r=s(e,t+1),i=s(e,t+4),a=e.getUint8(t+7),o=s(e,t+8),{tagType:n,dataSize:r,timestamp:i,timestampExtended:a,streamID:o}};parseTagBody=(e,t,n,r)=>{let i;switch(e){case`script`:i=this.parseMetaData(t,n);break;case`audio`:i=this.parseAudio(t,n,r);break;case`video`:i=this.parseVideo(t,n,r);break}return i};parseMetaData=(e,t)=>{let n=t;if(e.getUint8(n)!==2)throw Error(`Invalid AMF type for onMetaData (expected 0x02)`);n+=1;let r=e.getUint16(n,!1);n+=2;{let t=new Int8Array(e.buffer.slice(n,n+r));if((this.textDecoder?.decode(t)||``)!==`onMetaData`)throw Error(`Expected 'onMetaData' string`);n+=r}let i=this.getAmfType(e,n);return n+=1,this.getAMFValue(e,n,i).value};parseAudio=(e,t,n)=>{let r=t,i=e.getUint8(r),a=i>>4&15,o=i>>2&3,s=i>>1&1,c=i&1;r+=1;let l=e.getUint8(r);r+=1;let u=n,d=new Uint8Array(e.buffer.slice(r,r+u));if(a===10&&l===0){let t=e.getUint8(r),n=e.getUint8(r+1),i=t>>3&31,u=(t&7)<<1|n>>7;return{soundFormat:a,soundRate:o,soundSize:s,soundType:c,accPacketType:l,data:d,samplingFrequencyIndex:u,channelConfiguration:n>>3&15,codec:`mp4a.40.${i}`,sampleRate:[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350][u]}}return{soundFormat:a,soundRate:o,soundSize:s,soundType:c,accPacketType:l,data:d}};parseVideo=(e,t,r)=>{let i=t,a=e.getUint8(i),o=a>>4&15,c=a&15;i+=1;let l=e.getUint8(i);i+=1;let u=s(e,i);i+=3;let d=r-5,f=new Uint8Array(e.buffer.slice(i,i+d));switch(c){case 7:if(l===0)return{frameType:o,codecID:c,avcPacketType:l,cts:u,data:f,...n(f)};if(l===1){let t=[],n=i+r-5;for(;!(i+4>n);){let n=e.getUint32(i,!1),r=new Uint8Array(e.buffer.slice(i,i+4+n));i+=4+n,t.push(r)}return{frameType:o,codecID:c,avcPacketType:l,cts:u,data:f,nalus:t}}break;default:throw Error(`Unsupported codecID`)}return{frameType:o,codecID:c,avcPacketType:l,cts:u,data:f}};getAmfType=(e,t)=>e.getUint8(t);getAMFName=(e,t,n)=>{let r=new Uint8Array(e.buffer.slice(t,t+n));return this.textDecoder?.decode(r)||``};getAMFValue=(e,t,n)=>{let r=t,i,a=0;switch(n){case 0:i=e.getFloat64(r,!1),a=8;break;case 1:i=!!e.getUint8(r),a=1;break;case 2:{i=``;let t=e.getUint16(r,!1);r+=2;let n=new Int8Array(e.buffer,r,t).filter(e=>e!==0);i=(this.textDecoder?.decode(n)||``).trim(),a=2+t}break;case 3:for(i={};r<e.byteLength;){let t=e.getUint16(r,!1);if(t===0)break;r+=2;let n=this.getAMFName(e,r,t);r+=t;let o=this.getAmfType(e,r);if(o===6)break;r+=1;let s=this.getAMFValue(e,r,o);r+=s.length,i[n]=s.value,a=2+t+1+s.length}break;case 8:{i={};let t=e.getUint32(r,!1);r+=4;for(let n=0;n<t;n++){let t=e.getUint16(r,!1);r+=2;let n=this.getAMFName(e,r,t);r+=t;let o=this.getAmfType(e,r);r+=1;let s=this.getAMFValue(e,r,o);r+=s.length,i[n]=s.value,a=2+t+1+s.length}}break;case 10:{i=[];let t=e.getUint32(r,!1);r+=4;for(let n=0;n<t;n++){let t=this.getAmfType(e,r);r+=1;let n=this.getAMFValue(e,r,t);r+=n.length,i.push(n.value),a=1+n.length}}break}return{amfType:n,length:a,value:i}}};let l=new class{pattern;cacher=new e;isParseing=!1;offset=0;parser;on={};constructor(){}init=e=>{switch(this.destroy(),this.pattern=e,this.pattern){case`flv`:this.parser=new c;break;case`hls`:this.parser=new o;break;default:throw Error(`is error pattern.`)}this.parser.on.debug=e=>this.on.debug&&this.on.debug(e),this.parser.on.info=e=>this.on.info&&this.on.info(e),this.parser.on.config=e=>this.on.config&&this.on.config(e),this.parser.on.chunk=e=>{this.cacher.pushChunk(e),this.on.chunk&&this.on.chunk(e)}};push=e=>{this.cacher.push(e),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 Error(`You need to set the pattern.`);if(!this.parser)throw Error(`You need to init parser.`);for(;;){let e=this.cacher.next(this.offset);if(this.offset=0,!e)break;this.offset=await this.parser.parse(e)}this.isParseing=!1}catch{this.destroy()}}};l.on.info=e=>postMessage({action:`on.info`,data:e}),l.on.config=e=>postMessage({action:`on.config`,data:e}),l.on.chunk=e=>postMessage({action:`on.chunk`,data:e}),l.on.debug=e=>postMessage({action:`on.debug`,data:e}),onmessage=e=>{let{action:t,data:n}=e.data,r=l[t];r&&r(n)}})();", t = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", e], { type: "text/javascript;charset=utf-8" });
3
+ function n(n) {
4
+ let r;
5
+ try {
6
+ if (r = t && (self.URL || self.webkitURL).createObjectURL(t), !r) throw "";
7
+ let e = new Worker(r, { name: n?.name });
8
+ return e.addEventListener("error", () => {
9
+ (self.URL || self.webkitURL).revokeObjectURL(r);
10
+ }), e;
11
+ } catch {
12
+ return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(e), { name: n?.name });
13
+ }
20
14
  }
21
- class P {
22
- worker = new R();
23
- on = {};
24
- constructor() {
25
- this.worker.onmessage = (t) => {
26
- const { action: s, data: e } = t.data;
27
- switch (s) {
28
- case "on.info":
29
- this.on.info && this.on.info(e);
30
- break;
31
- case "on.config":
32
- this.on.config && this.on.config(e);
33
- break;
34
- case "on.chunk":
35
- this.on.chunk && this.on.chunk(e);
36
- break;
37
- case "on.debug":
38
- this.on.debug && this.on.debug(e);
39
- break;
40
- }
41
- };
42
- }
43
- init = (t) => this.worker.postMessage({ action: "init", data: t });
44
- push = (t) => this.worker.postMessage({ action: "push", data: t });
45
- destroy = () => {
46
- this.worker.postMessage({ action: "destroy", data: {} }), this.worker.terminate();
47
- };
15
+ //#endregion
16
+ //#region src/demuxer/DemuxerWorker.ts
17
+ var r = class {
18
+ worker = new n();
19
+ on = {};
20
+ constructor() {
21
+ this.worker.onmessage = (e) => {
22
+ let { action: t, data: n } = e.data;
23
+ switch (t) {
24
+ case "on.info":
25
+ this.on.info && this.on.info(n);
26
+ break;
27
+ case "on.config":
28
+ this.on.config && this.on.config(n);
29
+ break;
30
+ case "on.chunk":
31
+ this.on.chunk && this.on.chunk(n);
32
+ break;
33
+ case "on.debug":
34
+ this.on.debug && this.on.debug(n);
35
+ break;
36
+ }
37
+ };
38
+ }
39
+ init = (e) => this.worker.postMessage({
40
+ action: "init",
41
+ data: e
42
+ });
43
+ push = (e) => this.worker.postMessage({
44
+ action: "push",
45
+ data: e
46
+ });
47
+ destroy = () => {
48
+ this.worker.postMessage({
49
+ action: "destroy",
50
+ data: {}
51
+ }), this.worker.terminate();
52
+ };
53
+ }, i = "(function(){let e=new class{pattern=`flv`;audioDecoderConfig;audioDecoder;videoDecoderConfig;videoDecoder;hasKeyFrame=!1;baseTime=0;pendingChunks=[];currentChunk;isProcessing=!1;decodeTimer=0;frameTrack=!1;isFrameTrack=!1;fameTrackOption={flv:[30,50],hls:[200,300],dash:[50,100],rtmp:[50,100]};decodingSpeedRatio=1;maxDecodingSpeedRatio=2;decodingSpeed=16;fps=0;firstVideoChunkTimestamp;secondVideoChunkTimestamp;frameStartTime;lastRenderTime;nextRenderTime;on={audio:{},video:{}};constructor(){}init=e=>{this.destroy(),this.pattern=e,this.baseTime=new Date().getTime()-performance.now(),this.initDecodeInterval()};initAudio=e=>{this.audio.destroy(),this.audioDecoderConfig={...e},this.audioDecoder=new AudioDecoder({output:e=>{let t=this.decodingSpeedRatio;this.on.audio.decode&&this.on.audio.decode({audioData:e,playbackRate:t})},error:e=>{this.on.audio.error&&this.on.audio.error(e)}}),this.audioDecoder.configure(this.audioDecoderConfig)};initVideo=e=>{this.video.destroy(),this.videoDecoderConfig={...e},this.videoDecoder=new VideoDecoder({output:async e=>{this.frameStartTime||=e.timestamp;try{let t=e.timestamp-this.frameStartTime+this.baseTime*1e3,n=await createImageBitmap(e);if(e.close(),!n.width||!n.height)return n.close();this.on.video.decode&&this.on.video.decode({timestamp:t,bitmap:n}),this.currentChunk&&this.currentChunk.kind===`video`&&this.currentChunk.nalus&&this.on.nalus&&this.on.nalus(this.currentChunk.nalus)}catch{e.close()}},error:e=>{this.on.video.error&&this.on.video.error(e)}}),this.videoDecoder.configure(this.videoDecoderConfig)};setFrameTrack=e=>{this.frameTrack=e,this.frameTrack===!1&&(this.decodingSpeedRatio=1)};push=e=>{this.pendingChunks.push(e)};destroy=()=>{this.audio.destroy(),this.video.destroy(),this.pendingChunks=[],this.firstVideoChunkTimestamp=void 0,this.secondVideoChunkTimestamp=void 0,this.frameStartTime=void 0,this.lastRenderTime=void 0,this.nextRenderTime=void 0,clearInterval(this.decodeTimer)};initDecodeInterval=()=>{let e=this.decodingSpeed/this.decodingSpeedRatio,t=this.baseTime+performance.now();if(this.lastRenderTime||=t,this.fps=Math.round(1e3/(t-this.lastRenderTime)),this.lastRenderTime=t,this.nextRenderTime){let t=this.lastRenderTime-this.nextRenderTime;e-=t}this.nextRenderTime=this.lastRenderTime+e,this.decodeTimer=setTimeout(()=>{this.decode(),this.initDecodeInterval()},e)};decode=()=>{if(this.isProcessing!==!0){for(this.isProcessing=!0;this.currentChunk=this.pendingChunks.shift(),this.currentChunk;){let e=this.pendingChunks.length;if(this.frameTrack){let[t,n]=this.fameTrackOption[this.pattern];if(e<=t&&(this.isFrameTrack=!1),e>=n&&(this.isFrameTrack=!0),this.isFrameTrack){let n=Math.min(1+(e-t)/100,this.maxDecodingSpeedRatio);this.decodingSpeedRatio=Number(n.toFixed(1))}else this.decodingSpeedRatio=1}if(this.on.analysis){let{decodingSpeed:t,decodingSpeedRatio:n,fps:r}=this;this.on.analysis({decodingSpeed:t,decodingSpeedRatio:n,fps:r,cacheLength:e})}let{kind:t,init:n}=this.currentChunk;switch(t){case`audio`:this.decodeAudio(n);break;case`video`:this.decodeVideo(n);break}if(t===`video`)break}this.isProcessing=!1}};decodeAudio=e=>{if(!this.audioDecoder)return;let t=new EncodedAudioChunk(e);this.audioDecoder.decode(t)};decodeVideo=e=>{if(this.videoDecoder&&(e.type===`key`&&(this.hasKeyFrame=!0),this.firstVideoChunkTimestamp?this.secondVideoChunkTimestamp||(this.secondVideoChunkTimestamp=e.timestamp,this.decodingSpeed=(this.secondVideoChunkTimestamp-this.firstVideoChunkTimestamp)/1e3):this.firstVideoChunkTimestamp=e.timestamp,this.hasKeyFrame)){let t=new EncodedVideoChunk(e);this.videoDecoder.decode(t)}};audio={flush:()=>{this.audioDecoder?.flush()},destroy:()=>{this.audioDecoderConfig=void 0,this.audioDecoder?.close(),this.audioDecoder=void 0}};video={flush:()=>{this.videoDecoder?.flush()},destroy:()=>{this.videoDecoderConfig=void 0,this.videoDecoder?.close(),this.videoDecoder=void 0,this.hasKeyFrame=!1}}};e.on.audio.decode=e=>postMessage({action:`on.audio.decode`,data:e},[e.audioData]),e.on.audio.error=e=>postMessage({action:`on.audio.error`,data:e}),e.on.video.decode=e=>postMessage({action:`on.video.decode`,data:e},[e.bitmap]),e.on.video.error=e=>postMessage({action:`on.video.error`,data:e}),e.on.nalus=e=>postMessage({action:`on.nalus`,data:e}),e.on.analysis=e=>postMessage({action:`on.analysis`,data:e}),onmessage=t=>{let{action:n,data:r}=t.data,i=e[n];i&&i(r)}})();", a = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", i], { type: "text/javascript;charset=utf-8" });
54
+ function o(e) {
55
+ let t;
56
+ try {
57
+ if (t = a && (self.URL || self.webkitURL).createObjectURL(a), !t) throw "";
58
+ let n = new Worker(t, { name: e?.name });
59
+ return n.addEventListener("error", () => {
60
+ (self.URL || self.webkitURL).revokeObjectURL(t);
61
+ }), n;
62
+ } catch {
63
+ return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(i), { name: e?.name });
64
+ }
48
65
  }
49
- const A = `(function(){"use strict";class a{pattern="flv";audioDecoderConfig;audioDecoder;videoDecoderConfig;videoDecoder;hasKeyFrame=!1;baseTime=0;pendingChunks=[];currentChunk;isProcessing=!1;decodeTimer=0;frameTrack=!1;isFrameTrack=!1;fameTrackOption={flv:[30,50],hls:[200,300],dash:[50,100],rtmp:[50,100]};decodingSpeedRatio=1;maxDecodingSpeedRatio=2;decodingSpeed=16;fps=0;firstVideoChunkTimestamp;secondVideoChunkTimestamp;frameStartTime;lastRenderTime;nextRenderTime;on={audio:{},video:{}};constructor(){}init=e=>{this.destroy(),this.pattern=e,this.baseTime=new Date().getTime()-performance.now(),this.initDecodeInterval()};initAudio=e=>{this.audio.destroy(),this.audioDecoderConfig={...e},this.audioDecoder=new AudioDecoder({output:i=>{const o=this.decodingSpeedRatio;this.on.audio.decode&&this.on.audio.decode({audioData:i,playbackRate:o})},error:i=>{this.on.audio.error&&this.on.audio.error(i)}}),this.audioDecoder.configure(this.audioDecoderConfig)};initVideo=e=>{this.video.destroy(),this.videoDecoderConfig={...e},this.videoDecoder=new VideoDecoder({output:async i=>{this.frameStartTime||(this.frameStartTime=i.timestamp);try{const o=i.timestamp-this.frameStartTime+this.baseTime*1e3,s=await createImageBitmap(i);if(i.close(),!s.width||!s.height)return s.close();this.on.video.decode&&this.on.video.decode({timestamp:o,bitmap:s}),this.currentChunk&&this.currentChunk.kind==="video"&&this.currentChunk.nalus&&this.on.nalus&&this.on.nalus(this.currentChunk.nalus)}catch{i.close()}},error:i=>{this.on.video.error&&this.on.video.error(i)}}),this.videoDecoder.configure(this.videoDecoderConfig)};setFrameTrack=e=>{this.frameTrack=e,this.frameTrack===!1&&(this.decodingSpeedRatio=1)};push=e=>{this.pendingChunks.push(e)};destroy=()=>{this.audio.destroy(),this.video.destroy(),this.pendingChunks=[],this.firstVideoChunkTimestamp=void 0,this.secondVideoChunkTimestamp=void 0,this.frameStartTime=void 0,this.lastRenderTime=void 0,this.nextRenderTime=void 0,clearInterval(this.decodeTimer)};initDecodeInterval=()=>{let e=this.decodingSpeed/this.decodingSpeedRatio;const i=this.baseTime+performance.now();if(this.lastRenderTime||(this.lastRenderTime=i),this.fps=Math.round(1e3/(i-this.lastRenderTime)),this.lastRenderTime=i,this.nextRenderTime){const o=this.lastRenderTime-this.nextRenderTime;e-=o}this.nextRenderTime=this.lastRenderTime+e,this.decodeTimer=setTimeout(()=>{this.decode(),this.initDecodeInterval()},e)};decode=()=>{if(this.isProcessing!==!0){for(this.isProcessing=!0;this.currentChunk=this.pendingChunks.shift(),!!this.currentChunk;){const e=this.pendingChunks.length;if(this.frameTrack){const[s,n]=this.fameTrackOption[this.pattern];if(e<=s&&(this.isFrameTrack=!1),e>=n&&(this.isFrameTrack=!0),this.isFrameTrack){const r=Math.min(1+(e-s)/100,this.maxDecodingSpeedRatio);this.decodingSpeedRatio=Number(r.toFixed(1))}else this.decodingSpeedRatio=1}if(this.on.analysis){const{decodingSpeed:s,decodingSpeedRatio:n,fps:r}=this;this.on.analysis({decodingSpeed:s,decodingSpeedRatio:n,fps:r,cacheLength:e})}const{kind:i,init:o}=this.currentChunk;switch(i){case"audio":this.decodeAudio(o);break;case"video":this.decodeVideo(o);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.firstVideoChunkTimestamp?this.secondVideoChunkTimestamp||(this.secondVideoChunkTimestamp=e.timestamp,this.decodingSpeed=(this.secondVideoChunkTimestamp-this.firstVideoChunkTimestamp)/1e3):this.firstVideoChunkTimestamp=e.timestamp,this.hasKeyFrame)){const i=new EncodedVideoChunk(e);this.videoDecoder.decode(i)}};audio={flush:()=>{this.audioDecoder?.flush()},destroy:()=>{this.audioDecoderConfig=void 0,this.audioDecoder?.close(),this.audioDecoder=void 0}};video={flush:()=>{this.videoDecoder?.flush()},destroy:()=>{this.videoDecoderConfig=void 0,this.videoDecoder?.close(),this.videoDecoder=void 0,this.hasKeyFrame=!1}}}const d=new a;d.on.audio.decode=t=>postMessage({action:"on.audio.decode",data:t},[t.audioData]),d.on.audio.error=t=>postMessage({action:"on.audio.error",data:t}),d.on.video.decode=t=>postMessage({action:"on.video.decode",data:t},[t.bitmap]),d.on.video.error=t=>postMessage({action:"on.video.error",data:t}),d.on.nalus=t=>postMessage({action:"on.nalus",data:t}),d.on.analysis=t=>postMessage({action:"on.analysis",data:t}),onmessage=t=>{const{action:e,data:i}=t.data,o=d[e];o&&o(i)}})();
50
- `, _ = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", A], { type: "text/javascript;charset=utf-8" });
51
- function I(g) {
52
- let t;
53
- try {
54
- if (t = _ && (self.URL || self.webkitURL).createObjectURL(_), !t) throw "";
55
- const s = new Worker(t, {
56
- name: g?.name
57
- });
58
- return s.addEventListener("error", () => {
59
- (self.URL || self.webkitURL).revokeObjectURL(t);
60
- }), s;
61
- } catch {
62
- return new Worker(
63
- "data:text/javascript;charset=utf-8," + encodeURIComponent(A),
64
- {
65
- name: g?.name
66
- }
67
- );
68
- }
66
+ //#endregion
67
+ //#region src/decoder/DecoderWorker.ts
68
+ var s = class {
69
+ worker = new o();
70
+ on = {
71
+ audio: {},
72
+ video: {}
73
+ };
74
+ constructor() {
75
+ this.worker.onmessage = (e) => {
76
+ let { action: t, data: n } = e.data;
77
+ switch (t) {
78
+ case "on.audio.decode":
79
+ this.on.audio.decode && this.on.audio.decode(n);
80
+ break;
81
+ case "on.audio.error":
82
+ this.on.audio.error && this.on.audio.error(n);
83
+ break;
84
+ case "on.video.decode":
85
+ this.on.video.decode && this.on.video.decode(n);
86
+ break;
87
+ case "on.video.error":
88
+ this.on.video.error && this.on.video.error(n);
89
+ break;
90
+ case "on.nalus":
91
+ this.on.nalus && this.on.nalus(n);
92
+ break;
93
+ case "on.analysis":
94
+ this.on.analysis && this.on.analysis(n);
95
+ break;
96
+ }
97
+ };
98
+ }
99
+ init = (e) => this.worker.postMessage({
100
+ action: "init",
101
+ data: e
102
+ });
103
+ initAudio = (e) => this.worker.postMessage({
104
+ action: "initAudio",
105
+ data: e
106
+ });
107
+ initVideo = (e) => this.worker.postMessage({
108
+ action: "initVideo",
109
+ data: e
110
+ });
111
+ push = (e) => this.worker.postMessage({
112
+ action: "push",
113
+ data: e
114
+ });
115
+ setFrameTrack = (e) => this.worker.postMessage({
116
+ action: "setFrameTrack",
117
+ data: e
118
+ });
119
+ destroy = () => {
120
+ this.worker.postMessage({ action: "destroy" }), this.worker.terminate();
121
+ };
122
+ }, c = "(function(){let e=new class{renderMap=new Map;constructor(){}push=async e=>{let{timestamp:t}=e,{bitmap:n}=e;try{let e=[...this.renderMap.keys()];for(let r of e){let e=this.renderMap.get(r);if(!e)continue;let{pause:i=!1,writer:a,offscreen:o,option:s}=e;if(i===!0)continue;let c=async e=>{if(a){let n=new VideoFrame(e,{timestamp:t});try{await a.write(n)}catch{}n.close()}else o&&(o.width=e.width,o.height=e.height,o?.getContext(`2d`)?.drawImage(e,0,0))};if(r===`default`)await c(n);else if(s){let{sx:e=0,sy:t=0,sw:r=n.width,sh:i=n.height}=s;await c(await createImageBitmap(n,e,t,r,i))}}}catch{}n.close()};addCut=e=>{let{key:t,writable:n,offscreen:r,option:i}={key:`default`,...e};if(n){let e=n.getWriter();this.renderMap.set(t,{writer:e,option:i,pause:!1})}else this.renderMap.set(t,{offscreen:r,option:i,pause:!1})};delCut=e=>{this.renderMap.delete(e)};setCut=e=>{let{key:t,cutOption:n}={key:`default`,...e},r=this.renderMap.get(t);r&&this.renderMap.set(t,{...r,option:n})};setPause=e=>{let{key:t,pause:n}={key:`default`,...e},r=this.renderMap.get(t);r&&this.renderMap.set(t,{...r,pause:n})};destroy=()=>{this.renderMap=new Map}};onmessage=t=>{let{action:n,data:r}=t.data,i=e[n];i&&i(r)}})();", l = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", c], { type: "text/javascript;charset=utf-8" });
123
+ function u(e) {
124
+ let t;
125
+ try {
126
+ if (t = l && (self.URL || self.webkitURL).createObjectURL(l), !t) throw "";
127
+ let n = new Worker(t, { name: e?.name });
128
+ return n.addEventListener("error", () => {
129
+ (self.URL || self.webkitURL).revokeObjectURL(t);
130
+ }), n;
131
+ } catch {
132
+ return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(c), { name: e?.name });
133
+ }
69
134
  }
70
- class N {
71
- worker = new I();
72
- on = { audio: {}, video: {} };
73
- constructor() {
74
- this.worker.onmessage = (t) => {
75
- const { action: s, data: e } = t.data;
76
- switch (s) {
77
- case "on.audio.decode":
78
- this.on.audio.decode && this.on.audio.decode(e);
79
- break;
80
- case "on.audio.error":
81
- this.on.audio.error && this.on.audio.error(e);
82
- break;
83
- case "on.video.decode":
84
- this.on.video.decode && this.on.video.decode(e);
85
- break;
86
- case "on.video.error":
87
- this.on.video.error && this.on.video.error(e);
88
- break;
89
- case "on.nalus":
90
- this.on.nalus && this.on.nalus(e);
91
- break;
92
- case "on.analysis":
93
- this.on.analysis && this.on.analysis(e);
94
- break;
95
- }
96
- };
97
- }
98
- init = (t) => this.worker.postMessage({ action: "init", data: t });
99
- initAudio = (t) => this.worker.postMessage({ action: "initAudio", data: t });
100
- initVideo = (t) => this.worker.postMessage({ action: "initVideo", data: t });
101
- push = (t) => this.worker.postMessage({ action: "push", data: t });
102
- setFrameTrack = (t) => this.worker.postMessage({ action: "setFrameTrack", data: t });
103
- destroy = () => {
104
- this.worker.postMessage({ action: "destroy" }), this.worker.terminate();
105
- };
106
- }
107
- const S = `(function(){"use strict";class l{renderMap=new Map;constructor(){}push=async t=>{const{timestamp:s}=t,{bitmap:e}=t;if(e.height===0||e.width===0)return e.close();try{const n=[...this.renderMap.keys()];for(const i of n){const a=this.renderMap.get(i);if(!a)continue;const{pause:y=!1,writer:h,offscreen:c,option:u}=a;if(y===!0)continue;const f=r=>{if(h){const o=new VideoFrame(r,{timestamp:s});try{o&&h.write(o)}catch{}o.close()}else c&&(c.width=r.width,c.height=r.height,c?.getContext("2d")?.drawImage(r,0,0))};if(i==="default")f(e);else if(u){const{sx:r=0,sy:o=0,sw:p=e.width,sh:g=e.height}=u,M=await createImageBitmap(e,r,o,p,g);f(M)}}}catch{}e.close()};addCut=t=>{const{key:s,writable:e,offscreen:n,option:i}={key:"default",...t};if(e){const a=e.getWriter();this.renderMap.set(s,{writer:a,option:i,pause:!1})}else this.renderMap.set(s,{offscreen:n,option:i,pause:!1})};delCut=t=>{this.renderMap.delete(t)};setCut=t=>{const{key:s,cutOption:e}={key:"default",...t},n=this.renderMap.get(s);n&&this.renderMap.set(s,{...n,option:e})};setPause=t=>{const{key:s,pause:e}={key:"default",...t},n=this.renderMap.get(s);n&&this.renderMap.set(s,{...n,pause:e})};destroy=()=>{this.renderMap=new Map}}const w=new l;onmessage=d=>{const{action:t,data:s}=d.data,e=w[t];e&&e(s)}})();
108
- `, C = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", S], { type: "text/javascript;charset=utf-8" });
109
- function L(g) {
110
- let t;
111
- try {
112
- if (t = C && (self.URL || self.webkitURL).createObjectURL(C), !t) throw "";
113
- const s = new Worker(t, {
114
- name: g?.name
115
- });
116
- return s.addEventListener("error", () => {
117
- (self.URL || self.webkitURL).revokeObjectURL(t);
118
- }), s;
119
- } catch {
120
- return new Worker(
121
- "data:text/javascript;charset=utf-8," + encodeURIComponent(S),
122
- {
123
- name: g?.name
124
- }
125
- );
126
- }
127
- }
128
- class V {
129
- worker = new L();
130
- constructor() {
131
- }
132
- push = (t) => this.worker.postMessage({ action: "push", data: t }, [t.bitmap]);
133
- addCut = (t) => {
134
- const s = [];
135
- t.writable && s.push(t.writable), t.offscreen && s.push(t.offscreen), this.worker.postMessage({ action: "addCut", data: t }, s);
136
- };
137
- delCut = (t) => this.worker.postMessage({ action: "delCut", data: t });
138
- setCut = (t) => this.worker.postMessage({ action: "setCut", data: t });
139
- setPause = (t) => this.worker.postMessage({ action: "setPause", data: t });
140
- destroy = () => {
141
- this.worker.postMessage({ action: "destroy", data: {} }), this.worker.terminate();
142
- };
143
- }
144
- class W {
145
- inputStream = new MediaStream();
146
- // 输入音频流 (原始音频)
147
- outputStream = new MediaStream();
148
- // 输出音频流 (处理后音频)
149
- inputGain = 1;
150
- // 麦克风音量
151
- enhanceGain = 1;
152
- // 麦克风增强音量 1+x
153
- bgsGain = 1;
154
- // 音效音量
155
- bgmGain = 1;
156
- // 音乐音量
157
- outputGain = 1;
158
- // 扬声器音量
159
- mixAudioMap = /* @__PURE__ */ new Map();
160
- // 音频上下文实例
161
- audioContext = new AudioContext();
162
- // 输入节点(处理器的音频)
163
- sourceNode;
164
- // 音量输入控制节点 (麦克风输入)
165
- inputGainNode;
166
- // 音量输入增强节点 (麦克风增强)
167
- enhanceGainNode;
168
- // 音效控制节点 (音效音量)
169
- bgsGainNode;
170
- // 背景音乐控制节点 (背景音乐音量)
171
- bgmGainNode;
172
- // @ts-ignore 噪音过滤节点
173
- rnnoiseNode;
174
- // 音频分析节点
175
- analyserNode;
176
- // 缓冲区 存储分析节点的时域数据
177
- analyserArrayData;
178
- // 音量输出控制节点 (扬声器音量)
179
- outputGainNode;
180
- // 输出节点(处理后的音频)
181
- destinationNode;
182
- // 是否开启降噪
183
- denoise = !1;
184
- // 是否静音
185
- mute = !0;
186
- rnnoiseWorklet;
187
- rnnoiseWorkletNode;
188
- // 过滤流
189
- filterStream = (t) => t;
190
- constructor(t, s) {
191
- this.inputStream = t, s && (this.audioContext = s), 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;
192
- {
193
- const { sourceNode: e, inputGainNode: n, enhanceGainNode: i, bgsGainNode: o, bgmGainNode: a, analyserNode: r, outputGainNode: d, destinationNode: c } = this;
194
- e.connect(n), n.connect(i), i.connect(r), o.connect(r), a.connect(r), i.connect(c), o.connect(c), a.connect(c), d.connect(this.audioContext.destination);
195
- }
196
- this.audioContext.resume();
197
- }
198
- /**
199
- * 使用插件
200
- */
201
- use = ({ rnnoise: t }) => {
202
- this.rnnoiseWorklet = new t.RnnoiseWorklet();
203
- };
204
- _changeSource = () => {
205
- this.sourceNode.disconnect(), this.sourceNode = this.audioContext.createMediaStreamSource(this.inputStream), this.sourceNode.connect(this.inputGainNode);
206
- };
207
- /**
208
- * 替换轨道
209
- * @param track MediaStreamTrack
210
- */
211
- replaceTrack = (t) => {
212
- const s = this.inputStream.getTracks();
213
- for (const e of s)
214
- this.inputStream.removeTrack(e);
215
- this.inputStream.addTrack(t), this._changeSource();
216
- };
217
- /**
218
- * 停止流
219
- */
220
- stop = () => {
221
- {
222
- const t = this.inputStream.getTracks();
223
- for (const s of t)
224
- s.stop(), this.inputStream.removeTrack(s);
225
- }
226
- };
227
- /**
228
- * 暂停
229
- * @param pause
230
- */
231
- pause = async (t) => {
232
- const s = this.inputStream.getTracks();
233
- for (const e of s)
234
- e.enabled = !t;
235
- };
236
- /**
237
- * 获取数据流
238
- */
239
- getStream = () => this.filterStream(this.outputStream);
240
- /**
241
- * 静音
242
- * @param state 是否开启
243
- */
244
- setMute = (t = !0) => {
245
- this.mute = t, this.analyserNode.disconnect(), t === !1 && this.analyserNode.connect(this.outputGainNode);
246
- };
247
- /**
248
- * 降噪
249
- * @param state 是否开启
250
- */
251
- setDenoise = async (t = !0) => {
252
- this.rnnoiseWorklet && (this.inputGainNode.disconnect(), this.rnnoiseWorklet.destroy(), t ? (this.rnnoiseWorkletNode = await this.rnnoiseWorklet.createRnnoiseWorkletNode(this.audioContext), this.inputGainNode.connect(this.rnnoiseWorkletNode), this.rnnoiseWorkletNode.connect(this.enhanceGainNode)) : this.inputGainNode.connect(this.enhanceGainNode), this.denoise = t);
253
- };
254
- /**
255
- * 设置麦克风输入音量
256
- */
257
- setInputGain = (t) => {
258
- this.inputGain = t, this.inputGainNode.gain.setValueAtTime(t, this.audioContext.currentTime);
259
- };
260
- /**
261
- * 设置麦克风增强音量
262
- */
263
- setEnhanceGain = async (t) => {
264
- this.enhanceGain = t + 1, this.enhanceGainNode.gain.setValueAtTime(this.enhanceGain, this.audioContext.currentTime);
265
- };
266
- /**
267
- * 设置音效输入音量
268
- */
269
- setBgsGain = (t) => {
270
- this.bgsGain = t, this.bgsGainNode.gain.setValueAtTime(t, this.audioContext.currentTime);
271
- };
272
- /**
273
- * 设置背景音乐输入音量
274
- */
275
- setBgmGain = (t) => {
276
- this.bgmGain = t, this.bgmGainNode.gain.setValueAtTime(t, this.audioContext.currentTime);
277
- };
278
- /**
279
- * 设置扬声器音量
280
- */
281
- setOutputGain = (t) => {
282
- this.outputGain = t, this.outputGainNode.gain.setValueAtTime(this.outputGain, this.audioContext.currentTime);
283
- };
284
- /**
285
- * 获取输入音量
286
- */
287
- getVolume = () => {
288
- const { analyserNode: t, analyserArrayData: s } = this;
289
- t.getByteFrequencyData(s);
290
- let e = 0;
291
- for (let n = 0; n < s.length; n++)
292
- e += s[n];
293
- return Math.ceil(e / s.length);
294
- };
295
- /**
296
- * 融合音频
297
- */
298
- mixAudio = (t, s = "bgm") => new Promise(async (e, n) => {
299
- try {
300
- {
301
- const a = this.mixAudioMap.get(s);
302
- a && a.stop();
303
- }
304
- const i = s === "bgs" ? this.bgsGainNode : this.bgmGainNode, o = this.audioContext.createBufferSource();
305
- this.mixAudioMap.set(s, o), o.buffer = t, o.connect(i), o.onended = () => {
306
- o.disconnect(i), this.mixAudioMap.delete(s), e(!0);
307
- }, o.start(0);
308
- } catch (i) {
309
- n(i);
310
- }
311
- });
312
- /**
313
- * 停止融合音频
314
- */
315
- mixAudioStop = (t) => {
316
- this.mixAudioMap.get(t)?.stop();
317
- };
318
- /**
319
- * 改变融合状态
320
- */
321
- changeMix = (t, s) => {
322
- const e = t === "bgs" ? this.bgsGainNode : this.bgmGainNode;
323
- s ? e.connect(this.destinationNode) : e.disconnect(this.destinationNode);
324
- };
325
- }
326
- const F = async (g, t) => {
327
- try {
328
- const { format: s, numberOfChannels: e, numberOfFrames: n, sampleRate: i } = t, o = g.createBuffer(e, n, i);
329
- for (let a = 0; a < e; a++) {
330
- const r = t.allocationSize({ planeIndex: a }), d = new Uint8Array(r);
331
- t.copyTo(d, { planeIndex: a });
332
- const c = new DataView(d.buffer), h = o.getChannelData(a);
333
- for (let l = 0; l < n; l++) {
334
- let u;
335
- switch (s) {
336
- case "s16":
337
- // 16-bit signed PCM (范围: -32768 ~ 32767)
338
- case "s16-planar":
339
- u = c.getInt16(l * 2, !0) / 32768;
340
- break;
341
- case "f32":
342
- // 32-bit float (范围: -1.0 ~ 1.0)
343
- case "f32-planar":
344
- u = c.getFloat32(l * 4, !0);
345
- break;
346
- case "u8":
347
- // 8-bit unsigned (范围: 0 ~ 255)
348
- case "u8-planar":
349
- u = (c.getUint8(l) - 128) / 128;
350
- break;
351
- default:
352
- throw new Error(`Unsupported audio format: ${s}`);
353
- }
354
- h[l] = Math.max(-1, Math.min(1, u));
355
- }
356
- }
357
- return o;
358
- } catch (s) {
359
- throw console.error("Failed to convert AudioData to AudioBuffer:", s), s;
360
- }
361
- };
362
- class B {
363
- prAudioStream;
364
- audioContext;
365
- destination;
366
- stream = new MediaStream();
367
- nextStartTime = 0;
368
- pendingSources = [];
369
- constructor() {
370
- }
371
- init = (t) => {
372
- 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 W(this.stream, this.audioContext), this.nextStartTime = 0, this.pendingSources = [];
373
- };
374
- async push(t) {
375
- const { audioData: s, playbackRate: e = 1 } = t;
376
- if (!this.audioContext || !this.destination) return;
377
- let n = await F(this.audioContext, s);
378
- if (s.close(), !n) return;
379
- const i = this.audioContext.createBufferSource();
380
- i.buffer = n, i.playbackRate.value = e;
381
- const o = -1200 * Math.log2(e);
382
- i.detune.value = o, i.connect(this.destination);
383
- const a = Math.max(this.nextStartTime, this.audioContext.currentTime), r = n.duration / e;
384
- this.nextStartTime = a + r, i.start(a), this.pendingSources.push(i), i.onended = () => {
385
- this.pendingSources = this.pendingSources.filter((d) => d !== i);
386
- }, this.audioContext.state === "suspended" && await this.audioContext.resume();
387
- }
388
- getStream = () => this.prAudioStream?.getStream();
389
- destroy() {
390
- 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 = [];
391
- }
392
- }
393
- const G = (g) => {
394
- const t = g.toLowerCase();
395
- 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";
396
- }, E = (g) => {
397
- const t = g?.getTracks() || [];
398
- for (const s of t)
399
- s.stop();
400
- };
401
- class O {
402
- resolvesMap = /* @__PURE__ */ new Map();
403
- index = 0;
404
- constructor() {
405
- }
406
- /**
407
- *
408
- * @param eventKey 唯一key
409
- * @param checkFun 检测函数
410
- * @param timeout 超时时间 ms
411
- * @returns
412
- */
413
- add = (t, s = () => !1, e = 0) => new Promise((n) => {
414
- if (s()) return n(!0);
415
- this.resolvesMap.has(t) || this.resolvesMap.set(t, /* @__PURE__ */ new Map()), this.index++;
416
- const a = `${this.index}`;
417
- if (e = Math.max(0, e), e === 0) {
418
- this.resolvesMap.get(t)?.set(a, { resolve: n, timer: 0 });
419
- return;
420
- }
421
- const r = window.setTimeout(() => {
422
- this.emit(t);
423
- }, e);
424
- this.resolvesMap.get(t)?.set(a, { resolve: n, timer: r });
425
- });
426
- emit = async (t) => {
427
- const s = this.resolvesMap.get(t);
428
- if (!s) return;
429
- const e = [...s.keys()];
430
- for (const n of e) {
431
- const i = s.get(n);
432
- i && (clearTimeout(i.timer), i.resolve(), s.delete(n));
433
- }
434
- };
435
- }
436
- const j = (g, t) => {
437
- const s = new Uint8Array(g), e = new Uint8Array(t), n = new Uint8Array(11 + s.length + e.length);
438
- let i = 0;
439
- return n[i++] = 1, n[i++] = s[1], n[i++] = s[2], n[i++] = s[3], n[i++] = 255, n[i++] = 225, n[i++] = s.length >> 8 & 255, n[i++] = s.length & 255, n.set(s, i), i += s.length, n[i++] = 1, n[i++] = e.length >> 8 & 255, n[i++] = e.length & 255, n.set(e, i), n;
440
- }, M = (g) => {
441
- let t = 0;
442
- const s = new DataView(g.buffer), e = s.getUint8(t);
443
- if (t = t + 1, e !== 1) throw new Error("Invalid AVC version");
444
- const n = s.getUint8(t) & 255;
445
- t = t + 1;
446
- const i = s.getUint8(t) & 255;
447
- t = t + 1;
448
- const o = s.getUint8(t) & 255;
449
- t = t + 1;
450
- const d = `avc1.${Array.from([n, i, o], (k) => k.toString(16).padStart(2, "0")).join("")}`, c = (s.getUint8(t) & 3) - 1;
451
- t = t + 1;
452
- const h = s.getUint8(t) & 31;
453
- t = t + 1;
454
- const l = s.getUint16(t, !1);
455
- t = t + 2;
456
- const u = new Uint8Array(s.buffer.slice(t, t + l));
457
- t = t + l;
458
- const p = s.getUint8(t) & 31;
459
- t = t + 1;
460
- const f = s.getUint16(t, !1);
461
- t = t + 2;
462
- const m = new Uint8Array(s.buffer.slice(t, t + f));
463
- return t = t + f, { version: e, codec: d, profile: n, compatibility: i, level: o, lengthSizeMinusOne: c, numOfSequenceParameterSets: h, sequenceParameterSetLength: l, sps: u, numOfPictureParameterSets: p, pictureParameterSetLength: f, pps: m };
464
- }, z = (g) => {
465
- const t = new Uint8Array(4 + g.length);
466
- return new DataView(t.buffer).setUint32(0, g.length, !1), t.set(g, 4), t;
467
- }, $ = (g) => {
468
- let t = 0;
469
- for (const n of g)
470
- t += n.length;
471
- const s = new Uint8Array(t);
472
- let e = 0;
473
- for (const n of g) {
474
- const i = n;
475
- s.set(i, e), e += i.length;
476
- }
477
- return s;
478
- }, q = (g) => {
479
- const t = new DataView(g.buffer);
480
- let s = 0, e, n, i;
481
- e = t.getUint32(s, !1), s += 4;
482
- {
483
- const o = t.getUint8(s), a = o >> 7 & 1, r = o >> 5 & 3, d = o & 31;
484
- n = { forbidden_zero_bit: a, nal_ref_idc: r, nal_unit_type: d }, s += 1;
485
- }
486
- {
487
- const o = e - 1;
488
- i = new Uint8Array(t.buffer.slice(s, s + o));
489
- }
490
- return { size: e, header: n, data: i };
491
- };
492
- class v {
493
- #e = {
494
- timeout: 5 * 1e3,
495
- check: !1
496
- };
497
- #t = null;
498
- // 实例变量:统一管理当前请求的中止
499
- constructor(t = {}) {
500
- this.#e = { ...this.#e, ...t };
501
- }
502
- /**
503
- * 检查资源可用性(HEAD 请求)—— 用实例变量控制器
504
- */
505
- #s = (t, s) => new Promise(async (e) => {
506
- this.#t = new AbortController();
507
- const { signal: n } = this.#t, i = this.#e.timeout, o = setTimeout(() => {
508
- this.#t?.abort(`Timeout (${i}ms)`);
509
- }, i);
510
- await fetch(t, { cache: "no-store", ...s, method: "HEAD", signal: n }).then((a) => {
511
- clearTimeout(o), e({ status: a.status === 200 ? "successed" : "failed", reason: a.status === 200 ? "" : `HTTP ${a.status}` });
512
- }).catch((a) => {
513
- if (clearTimeout(o), a.name === "AbortError") {
514
- const r = n.reason || "Actively stopped";
515
- e({
516
- status: r.includes("Timeout") ? "timeout" : "stopped",
517
- reason: r
518
- });
519
- } else
520
- e({ status: "error", reason: a.message });
521
- });
522
- });
523
- /**
524
- * 发起数据请求(GET/POST 等)—— 用实例变量控制器
525
- */
526
- request = (t, s) => new Promise(async (e, n) => {
527
- try {
528
- this.stop(), this.#e.check && await this.#s(t), this.#t = new AbortController();
529
- const { signal: i } = this.#t, o = await fetch(t, { cache: "no-store", ...s, signal: i });
530
- e(o);
531
- } catch (i) {
532
- n(i);
533
- }
534
- });
535
- stop = () => {
536
- if (this.#t?.signal.aborted === !1) {
537
- const t = new Error("Actively stopped.");
538
- t.name = "AbortError", this.#t.abort(t);
539
- }
540
- };
541
- }
542
- class Q {
543
- option = {
544
- debug: !1,
545
- frameTrack: !1
546
- };
547
- converter = "MediaStreamTrackGenerator" in window ? "generator" : "canvas";
548
- // 自动检测浏览器 使用哪一种模式转换生产视频流
549
- prFetch = new v();
550
- getSegmentsFetch = new v();
551
- prResolves = new O();
552
- url = "";
553
- start_resolve;
554
- demuxerWorker;
555
- decoderWorker;
556
- audioPlayer;
557
- renderWorker;
558
- stream;
559
- on = { demuxer: {}, decoder: {} };
560
- cutRenders = /* @__PURE__ */ new Map();
561
- // @ts-ignore
562
- trackGenerator;
563
- constructor(t = {}) {
564
- const { debug: s = !1 } = t;
565
- this.option.debug = s;
566
- }
567
- /**
568
- * 开始播放
569
- * @param url : string
570
- */
571
- start = async (t) => {
572
- await this.stop(), this.url = t;
573
- const s = G(t);
574
- if (s === "unknown") throw new Error("This address cannot be parsed.");
575
- switch (this.init(s), s) {
576
- case "flv":
577
- this.flv.start();
578
- break;
579
- case "hls":
580
- this.hls.start();
581
- break;
582
- }
583
- };
584
- /**
585
- * 停止
586
- */
587
- stop = async () => {
588
- try {
589
- this.url = "", clearInterval(this.hls.getSegmentsTimer), this.prFetch.stop(), this.getSegmentsFetch.stop(), this.demuxerWorker?.destroy(), this.decoderWorker?.destroy(), this.renderWorker?.destroy(), this.cutRenders = /* @__PURE__ */ new Map(), E(this.stream), this.audioPlayer?.destroy();
590
- } catch (t) {
591
- console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: error", t);
592
- }
593
- };
594
- /**
595
- * 获取媒体流
596
- */
597
- getStream = () => this.stream;
598
- /**
599
- * 设置暂停
600
- * @param pause: boolean
601
- */
602
- setPause = (t) => {
603
- this.renderWorker?.setPause({ pause: t });
604
- };
605
- /**
606
- * 是否静音 默认为true
607
- * @param state?: boolean
608
- */
609
- setMute = (t) => this.audioPlayer?.prAudioStream?.setMute(t);
610
- /**
611
- * 设置输出音量
612
- * @param gain
613
- */
614
- setOutputGain = (t) => {
615
- this.audioPlayer?.prAudioStream?.setOutputGain(t);
616
- };
617
- /**
618
- * 是否开启追帧
619
- * @param frameTrack?: boolean
620
- */
621
- setFrameTrack = (t) => {
622
- this.option.frameTrack = t, this.decoderWorker?.setFrameTrack(t);
623
- };
624
- /**
625
- * 是否已准备好
626
- */
627
- isReady = () => {
628
- const t = () => this.stream?.active === !0;
629
- return this.prResolves.add("isReady", t);
630
- };
631
- cut = {
632
- /**
633
- * 创建剪切
634
- */
635
- create: (t, s) => {
636
- if (this.converter === "generator") {
637
- const o = new MediaStreamTrackGenerator({ kind: "video" }), a = new MediaStream([o]);
638
- return this.renderWorker?.addCut({ key: t, writable: o.writable, option: s }), this.cutRenders.set(t, { stream: a }), a;
639
- }
640
- const e = document.createElement("canvas"), n = e.captureStream(), i = e.transferControlToOffscreen();
641
- return this.renderWorker?.addCut({ key: t, offscreen: i, option: s }), this.cutRenders.set(t, { stream: n }), n;
642
- },
643
- /**
644
- * 设置剪切
645
- */
646
- setCut: (t, s) => {
647
- this.renderWorker?.setCut({ key: t, cutOption: s });
648
- },
649
- /**
650
- * 获取媒体流
651
- */
652
- getStream: (t) => this.cutRenders.get(t)?.stream,
653
- /**
654
- * 移除剪切
655
- */
656
- remove: (t) => {
657
- this.renderWorker?.delCut(t), this.cutRenders.delete(t);
658
- },
659
- /**
660
- * 设置暂停
661
- * @param pause: boolean
662
- */
663
- setPause: (t, s) => {
664
- this.renderWorker?.setPause({ key: t, pause: s });
665
- }
666
- };
667
- /**
668
- * 初始化
669
- */
670
- init = (t) => {
671
- this.initDecoder(t), this.initRender(), this.initDemuxer(t), this.audioPlayer = new B(), this.audioPlayer.init();
672
- };
673
- /**
674
- * 初始化解复器
675
- */
676
- initDemuxer = (t) => {
677
- this.demuxerWorker = new P(), this.demuxerWorker.init(t), this.demuxerWorker.on.debug = (s) => {
678
- this.option.debug && this.on.debug && this.on.debug(s);
679
- }, this.demuxerWorker.on.info = (s) => {
680
- this.option.debug && console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: info", s), this.on.demuxer.info && this.on.demuxer.info(s);
681
- }, this.demuxerWorker.on.config = (s) => {
682
- 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);
683
- const { kind: e } = s;
684
- switch (e) {
685
- case "audio":
686
- {
687
- const { codec: n, sampleRate: i, numberOfChannels: o } = s;
688
- this.decoderWorker?.initAudio({ codec: n, sampleRate: i, numberOfChannels: o });
689
- }
690
- break;
691
- case "video":
692
- {
693
- const { codec: n, description: i } = s;
694
- this.decoderWorker?.initVideo({ codec: n, description: i });
695
- }
696
- break;
697
- }
698
- }, this.demuxerWorker.on.chunk = (s) => {
699
- if (this.on.demuxer.chunk && this.on.demuxer.chunk(s), !this.decoderWorker) return;
700
- const { kind: e } = s;
701
- switch (e) {
702
- case "audio":
703
- {
704
- const { type: n, dts: i, data: o } = s, a = i * 1e3;
705
- this.decoderWorker.push({ kind: e, init: { type: n, timestamp: a, data: o } });
706
- }
707
- break;
708
- case "video":
709
- {
710
- const { type: n, dts: i, data: o, nalus: a = [] } = s, r = i * 1e3;
711
- this.decoderWorker.push({ kind: e, init: { type: n, timestamp: r, data: o }, nalus: a });
712
- }
713
- break;
714
- }
715
- };
716
- };
717
- /**
718
- * 初始化解码器
719
- */
720
- initDecoder = (t) => {
721
- this.decoderWorker = new N(), this.decoderWorker.init(t);
722
- const { frameTrack: s = !1 } = this.option;
723
- this.decoderWorker.setFrameTrack(s), this.decoderWorker.on.audio.decode = (e) => {
724
- this.audioPlayer?.push(e), this.on.decoder.audio && this.on.decoder.audio(e);
725
- }, this.decoderWorker.on.audio.error = (e) => {
726
- this.option.debug && console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: audio.error ", e), this.on.error && this.on.error(e);
727
- }, this.decoderWorker.on.video.decode = async (e) => {
728
- this.start_resolve && (this.start_resolve(!0), this.start_resolve = void 0), this.renderWorker?.push(e), this.on.decoder.video && this.on.decoder.video(e);
729
- }, this.decoderWorker.on.video.error = (e) => {
730
- this.on.error && this.on.error(e);
731
- }, this.decoderWorker.on.nalus = async (e) => {
732
- for (const n of e) {
733
- if (n.byteLength <= 4) continue;
734
- const { header: i, data: o } = q(n), { nal_unit_type: a } = i;
735
- a === 6 && this.on.decoder.sei && this.on.decoder.sei(o);
736
- }
737
- }, this.decoderWorker.on.analysis = (e) => {
738
- this.on.decoder.analysis && this.on.decoder.analysis(e);
739
- };
740
- };
741
- /**
742
- * 初始化渲染器
743
- */
744
- initRender = () => {
745
- if (this.renderWorker = new V(), this.converter === "generator") {
746
- const t = new MediaStreamTrackGenerator({ kind: "video" }), s = new MediaStream([t]);
747
- this.renderWorker?.addCut({ writable: t.writable }), this.stream = s;
748
- } else {
749
- const t = document.createElement("canvas"), s = t.captureStream(), e = t.transferControlToOffscreen();
750
- this.renderWorker?.addCut({ offscreen: e }), this.stream = s;
751
- }
752
- this.renderWorker?.setPause({ pause: !1 });
753
- };
754
- flv = {
755
- start: () => new Promise(async (t, s) => {
756
- try {
757
- this.start_resolve = t;
758
- let e, n = 0;
759
- for (; ; ) {
760
- n += 1;
761
- try {
762
- e = await this.prFetch.request(this.url);
763
- } catch (o) {
764
- console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->Breathe: error", o);
765
- }
766
- if (e?.status === 200 || n === 3) break;
767
- await new Promise((o) => setTimeout(() => o(!0), 500));
768
- }
769
- if (!e || e.status !== 200) return s("request is error.");
770
- const i = e.body?.getReader();
771
- if (!i) return s("reader is error.");
772
- for (; ; ) {
773
- const { done: o, value: a } = await i.read();
774
- if (a && this.demuxerWorker?.push(a), o || this.url === "") break;
775
- }
776
- } catch (e) {
777
- e.name !== "AbortError" && s(e);
778
- }
779
- })
780
- };
781
- hls = {
782
- isLive: !1,
783
- urls: [],
784
- url: "",
785
- getSegmentsTimer: 0,
786
- parse: async (t) => {
787
- const n = new TextDecoder("utf-8").decode(t).split(`
788
- `).map((c) => c.replace("\r", "")), i = this.url.substring(0, this.url.lastIndexOf("/") + 1);
789
- let o = 4, a = 0, r = !1;
790
- const d = [];
791
- for (const c of n)
792
- c.startsWith("#EXTINF:") ? o = parseFloat(c.split(":")[1].split(",")[0]) : c.startsWith("#EXT-X-TARGETDURATION:") ? a = parseInt(c.split(":")[1]) : c.startsWith("#EXT-X-ENDLIST") ? r = !1 : c.startsWith("#EXT-X-MEDIA-SEQUENCE:") ? r = !0 : c.includes(".ts") && !c.startsWith("#") && d.push({
793
- url: c.startsWith("http") ? c : i + c,
794
- duration: o,
795
- isLive: r
796
- });
797
- return { baseUrl: i, targetDuration: a, isLive: r, segments: d };
798
- },
799
- getSegments: async () => {
800
- try {
801
- let t, s = 0;
802
- for (; ; ) {
803
- s += 1;
804
- try {
805
- t = await this.getSegmentsFetch.request(this.url);
806
- } catch (n) {
807
- console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->Breathe: error", n);
808
- }
809
- if (t?.status === 200 || s === 3) break;
810
- await new Promise((n) => setTimeout(() => n(!0), 500));
811
- }
812
- if (!t || t.status !== 200) throw new Error("request is error.");
813
- const e = t.body?.getReader();
814
- if (!e) throw new Error("reader is error.");
815
- for (; ; ) {
816
- const { done: n, value: i } = await e.read();
817
- if (i) {
818
- const o = await this.hls.parse(i), { segments: a = [], isLive: r = !1 } = o;
819
- this.hls.isLive = r, r === !1 && (this.option.frameTrack = !1);
820
- let d = Array.from(a, (h) => h.url);
821
- const c = d.findIndex((h) => h === this.hls.url);
822
- c !== -1 && (d = d.slice(c + 1)), this.hls.urls = d;
823
- }
824
- if (n || this.url === "") break;
825
- }
826
- } catch (t) {
827
- t.name !== "AbortError" && this.on.error && this.on.error(t);
828
- }
829
- },
830
- start: () => new Promise(async (t, s) => {
831
- try {
832
- for (this.start_resolve = t, this.hls.url = "", this.hls.urls = [], 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)); ; ) {
833
- const e = this.hls.urls.shift();
834
- if (e) {
835
- this.hls.url = e;
836
- const i = (await this.prFetch.request(e)).body?.getReader();
837
- if (!i) throw new Error("segment reader is error.");
838
- for (; ; ) {
839
- const { done: o, value: a } = await i.read();
840
- if (a && this.demuxerWorker?.push(a), o || this.url === "") break;
841
- }
842
- } else
843
- await new Promise((n) => setTimeout(() => n(!0), 300));
844
- }
845
- } catch (e) {
846
- e.name !== "AbortError" && s(e);
847
- }
848
- })
849
- };
850
- }
851
- class H {
852
- pendingPayloads = [];
853
- // 所有原始分段数据
854
- payload = new Uint8Array(0);
855
- // 当前正在复解的原始数据
856
- chunks = [];
857
- // 复解后的数据 用于重播使用
858
- push = (t) => {
859
- this.pendingPayloads.push(t);
860
- };
861
- next = (t = 0) => {
862
- this.payload = this.payload.slice(t);
863
- const s = this.pendingPayloads.shift();
864
- if (!s) return !1;
865
- const e = new Uint8Array(this.payload.byteLength + s.byteLength);
866
- return e.set(this.payload, 0), e.set(s, this.payload.byteLength), this.payload = e, new DataView(this.payload.buffer);
867
- };
868
- pushChunk = (t) => {
869
- this.chunks.push(t), this.chunks.length > 100 && this.chunks.shift();
870
- };
871
- destroy = () => {
872
- this.pendingPayloads = [], this.payload = new Uint8Array(0), this.chunks = [];
873
- };
874
- }
875
- const K = (g) => {
876
- let t = "unknown";
877
- switch (g) {
878
- case 1:
879
- case 2:
880
- case 27:
881
- case 36:
882
- t = "video";
883
- break;
884
- case 3:
885
- case 4:
886
- case 15:
887
- t = "audio";
888
- break;
889
- case 6:
890
- t = "subtitle";
891
- break;
892
- case 134:
893
- t = "ad";
894
- break;
895
- }
896
- return t;
897
- };
898
- class X {
899
- pat;
900
- pmt;
901
- audioConfig;
902
- videoConfig;
903
- payloadMap = /* @__PURE__ */ new Map();
904
- on = {};
905
- constructor() {
906
- }
907
- parse = async (t) => {
908
- let s = 0;
909
- for (; !(s + 188 > t.byteLength); ) {
910
- if (t.getInt8(s) != 71) {
911
- s++;
912
- continue;
913
- }
914
- await this.parsePacket(t, s), s += 188;
915
- }
916
- return s;
917
- };
918
- parsePacket = async (t, s) => {
919
- if (s + 188 > t.byteLength)
920
- throw new Error("Invalid TS packet");
921
- if (t.getUint8(s) !== 71)
922
- throw new Error("Invalid TS packet");
923
- let e = s;
924
- const n = this.parseHeader(t, e);
925
- e += 4;
926
- const { transport_error_indicator: i, pid: o, payload_unit_start_indicator: a, adaptation_field_control: r } = n;
927
- if (i === 1 || o === void 0) return;
928
- let d = 184;
929
- if (r === 2 || r === 3) {
930
- const c = t.getUint8(e);
931
- e += 1, this.parseAdaptationField(t, e), e += c, d -= c;
932
- }
933
- if (r === 3 && (d -= 1), r === 1 || r === 3) {
934
- const c = new Uint8Array(t.buffer.slice(e, e + d));
935
- if (o === 0) return this.parsePAT(t, e);
936
- {
937
- const { programs: u = [] } = this.pat || {};
938
- if (u.find((f) => f.pmt_pid === o)) return this.parsePMT(t, e);
939
- }
940
- const { streams: h = [] } = this.pmt || {}, l = h.find((u) => u.elementary_pid === o);
941
- if (l) {
942
- if (a === 1) {
943
- const u = this.payloadMap.get(o);
944
- if (u) {
945
- switch (l.kind) {
946
- case "audio":
947
- {
948
- const p = await this.parseAudio(u);
949
- this.on.chunk && this.on.chunk(p);
950
- }
951
- break;
952
- case "video":
953
- {
954
- const p = await this.parseVideo(u);
955
- this.on.chunk && this.on.chunk(p), await new Promise((f) => setTimeout(() => f(!0), 0));
956
- }
957
- break;
958
- }
959
- this.payloadMap.delete(o);
960
- }
961
- }
962
- {
963
- this.payloadMap.has(o) || this.payloadMap.set(o, new Uint8Array());
964
- const u = this.payloadMap.get(o), p = new Uint8Array(u.byteLength + c.byteLength);
965
- p.set(u, 0), p.set(c, u.byteLength), this.payloadMap.set(o, p);
966
- }
967
- }
968
- }
969
- };
970
- // Header
971
- parseHeader = (t, s) => {
972
- let e = s;
973
- const n = t.getUint8(e), i = t.getUint8(e + 1), o = t.getUint8(e + 2), a = t.getUint8(e + 3), r = (i & 128) >> 7;
974
- if (r === 1) return { sync_byte: n, transport_error_indicator: r };
975
- const d = (i & 64) >> 6, c = (i & 32) >> 5, h = (i & 31) << 8 | o, l = (a & 192) >> 6, u = a >> 4 & 3, p = a & 15;
976
- return { sync_byte: n, transport_error_indicator: r, payload_unit_start_indicator: d, transport_priority: c, pid: h, transport_scrambling_control: l, adaptation_field_control: u, continuity_counter: p };
977
- };
978
- // PAT表
979
- parsePAT = (t, s) => {
980
- let e = s, n;
981
- {
982
- const a = t.getUint8(e);
983
- e += 1;
984
- const r = t.getUint8(e);
985
- if (e += 1, r !== 0) throw new Error("Invalid PAT table_id");
986
- const d = t.getUint16(e) & 4095;
987
- e += 2;
988
- const c = t.getUint16(e);
989
- e += 2;
990
- const h = (t.getUint8(e) & 62) >> 1, l = t.getUint8(e) & 1;
991
- e += 1;
992
- const u = t.getUint8(e);
993
- e += 1;
994
- const p = t.getUint8(e);
995
- e += 1, n = { pointer_field: a, table_id: r, section_length: d, transport_stream_id: c, version_number: h, current_next_indicator: l, section_number: u, last_section_number: p };
996
- }
997
- const i = [];
998
- {
999
- const a = n.section_length - 5 - 4, r = e + a;
1000
- for (; e < r; ) {
1001
- const d = t.getUint16(e), c = t.getUint16(e + 2) & 8191;
1002
- e += 4, d !== 0 && c >= 32 && c <= 8190 && i.push({ program_number: d, pmt_pid: c });
1003
- }
1004
- }
1005
- const o = t.getUint32(e);
1006
- this.pat = { header: n, programs: i, crc32: o }, this.on.debug && this.on.debug({ pat: this.pat });
1007
- };
1008
- // PMT表
1009
- parsePMT = (t, s) => {
1010
- let e = s, n;
1011
- {
1012
- const a = t.getUint8(e);
1013
- e += 1;
1014
- const r = t.getUint8(e);
1015
- if (e += 1, r !== 2) throw new Error("Invalid PMT table_id");
1016
- const d = t.getUint16(e) & 4095;
1017
- e += 2;
1018
- const c = t.getUint16(e);
1019
- e += 2;
1020
- const h = (t.getUint8(e) & 62) >> 1, l = t.getUint8(e) & 1;
1021
- e += 1;
1022
- const u = t.getUint8(e);
1023
- e += 1;
1024
- const p = t.getUint8(e);
1025
- e += 1;
1026
- const f = t.getUint16(e) & 8191;
1027
- e += 2;
1028
- const m = t.getUint16(e) & 4095;
1029
- e += 2, n = { pointer_field: a, table_id: r, section_length: d, transport_stream_id: c, version_number: h, current_next_indicator: l, section_number: u, last_section_number: p, pcr_pid: f, program_info_length: m };
1030
- }
1031
- const i = [];
1032
- {
1033
- const a = n.section_length - 9 - 4, r = e + a;
1034
- for (; e < r; ) {
1035
- const d = t.getUint8(e), c = K(d), h = t.getUint16(e + 1) & 8191, l = t.getUint16(e + 3) & 4095;
1036
- if (e += 5, h < 32 || h > 8190) {
1037
- console.warn(`Invalid elementary_pid: 0x${h.toString(16)}`);
1038
- continue;
1039
- }
1040
- i.push({ kind: c, stream_type: d, elementary_pid: h, es_info_length: l });
1041
- }
1042
- }
1043
- const o = t.getUint32(e);
1044
- this.pmt = { header: n, streams: i, crc32: o }, this.on.debug && this.on.debug({ pmt: this.pmt });
1045
- };
1046
- // AdaptationField
1047
- parseAdaptationField = (t, s) => {
1048
- let e = s, n, i, o, a;
1049
- const r = t.getUint8(e), d = !!(r & 128), c = !!(r & 64), h = !!(r & 32), l = !!(r & 16), u = !!(r & 8), p = !!(r & 4), f = !!(r & 2), m = !!(r & 1);
1050
- e += 1;
1051
- const k = (y, U) => {
1052
- let b = BigInt(0);
1053
- b |= BigInt(y.getUint16(U)) << 25n, b |= BigInt(y.getUint16(U + 1)) << 17n, b |= BigInt(y.getUint16(U + 2)) << 9n, b |= BigInt(y.getUint16(U + 3)) << 1n, b |= BigInt(y.getUint16(U + 4) >> 7);
1054
- const D = (y.getUint16(U + 4) & 1) << 8 | y.getUint16(U + 5);
1055
- return b = b * 300n + BigInt(D), b;
1056
- };
1057
- if (l && (n = k(t, e), e += 6), u && (i = k(t, e), e += 6), p && (o = t.getInt8(e), e += 1), f) {
1058
- const y = t.getUint8(e);
1059
- e += 1, a = new Uint8Array(t.buffer, e, y), e += y;
1060
- }
1061
- return { discontinuity_indicator: d, random_access_indicator: c, elementary_stream_priority_indicator: h, pcr_flag: l, opcr_flag: u, splicing_point_flag: p, transport_private_data_flag: f, adaptation_field_extension_flag: m, pcr: n, opcr: i, splice_countdown: o, transport_private_data: a };
1062
- };
1063
- parseAudio = async (t) => {
1064
- const s = new DataView(t.buffer);
1065
- let e = 0, n, i;
1066
- {
1067
- const o = s.getUint8(e) === 0 && s.getUint8(e + 1) === 0 && s.getUint8(e + 2) === 1;
1068
- if (e += 3, !o)
1069
- throw new Error("invalid ts audio payload.");
1070
- const a = s.getUint8(e);
1071
- e += 1;
1072
- const r = s.getUint8(e) << 8 | s.getUint8(e + 1);
1073
- e += 2;
1074
- let d, c, h, l, u;
1075
- {
1076
- const m = s.getUint8(e);
1077
- e += 1, d = m >> 4 & 3, c = (m >> 3 & 1) === 1, h = (m >> 2 & 1) === 1, l = (m >> 1 & 1) === 1, u = (m & 1) === 1;
1078
- }
1079
- let p, f;
1080
- {
1081
- const m = s.getUint8(e);
1082
- e += 1;
1083
- const k = m >> 6, y = s.getUint8(e);
1084
- e += 1, (k & 2) === 2 && (p = this.parsePtsDts(s, e)), (k & 1) === 1 ? f = this.parsePtsDts(s, e + 5) : f = p, e += y;
1085
- }
1086
- n = { stream_id: a, pes_packet_length: r, scrambling_control: d, priority: c, data_alignment: h, copyright: l, original_copy: u, pts: p, dts: f };
1087
- }
1088
- i = t.slice(e);
1089
- {
1090
- if (!this.audioConfig && s.getUint8(e) === 255) {
1091
- const h = s.getUint8(e + 2), l = s.getUint8(e + 3);
1092
- let u, p;
1093
- p = h >> 2 & 15, u = (h & 1) << 2 | l >> 6;
1094
- const f = `mp4a.40.${u}`, k = [96e3, 88200, 64e3, 48e3, 44100, 32e3, 24e3, 22050, 16e3, 12e3, 11025, 8e3, 7350][p];
1095
- this.audioConfig = { kind: "audio", codec: f, sampleRate: k, numberOfChannels: u }, this.on.config && this.on.config(this.audioConfig);
1096
- }
1097
- const { dts: o = 0, pts: a = 0 } = n, r = a - o, d = i.slice(7);
1098
- return { kind: "audio", type: "key", dts: o, pts: a, cts: r, data: d };
1099
- }
1100
- };
1101
- parseVideo = async (t) => {
1102
- const s = new DataView(t.buffer);
1103
- let e = 0, n, i;
1104
- {
1105
- const o = s.getUint8(e) === 0 && s.getUint8(e + 1) === 0 && s.getUint8(e + 2) === 1;
1106
- if (e += 3, !o)
1107
- throw new Error("invalid ts video payload.");
1108
- const a = s.getUint8(e);
1109
- e += 1;
1110
- const r = s.getUint8(e) << 8 | s.getUint8(e + 1);
1111
- e += 2;
1112
- let d, c, h, l, u;
1113
- {
1114
- const m = s.getUint8(e);
1115
- e += 1, d = m >> 4 & 3, c = (m >> 3 & 1) === 1, h = (m >> 2 & 1) === 1, l = (m >> 1 & 1) === 1, u = (m & 1) === 1;
1116
- }
1117
- let p, f;
1118
- {
1119
- const m = s.getUint8(e);
1120
- e += 1;
1121
- const k = m >> 6, y = s.getUint8(e);
1122
- e += 1, (k & 2) === 2 && (p = this.parsePtsDts(s, e)), (k & 1) === 1 ? f = this.parsePtsDts(s, e + 5) : f = p, e += y;
1123
- }
1124
- n = { stream_id: a, pes_packet_length: r, scrambling_control: d, priority: c, data_alignment: h, copyright: l, original_copy: u, pts: p, dts: f };
1125
- }
1126
- i = t.slice(e);
1127
- {
1128
- const o = this.getNalus(i);
1129
- if (!this.videoConfig) {
1130
- let u, p;
1131
- if (u = o.find((m) => m.type === 7)?.nalu.slice(4), p = o.find((m) => m.type === 8)?.nalu.slice(4), u && p) {
1132
- const f = j(u, p), { codec: m } = M(f);
1133
- this.videoConfig = { kind: "video", codec: m, description: f, sps: u, pps: p }, this.on.config && this.on.config(this.videoConfig);
1134
- }
1135
- }
1136
- const a = [];
1137
- let r = "delta";
1138
- for (const u of o) {
1139
- const { type: p, nalu: f } = u;
1140
- switch (p) {
1141
- case 6:
1142
- // sei
1143
- case 9:
1144
- a.push(f);
1145
- break;
1146
- case 1:
1147
- r = "delta", a.push(f);
1148
- break;
1149
- case 5:
1150
- r = "key", a.push(f);
1151
- break;
1152
- }
1153
- }
1154
- const d = $(a), { dts: c = 0, pts: h = 0 } = n, l = h - c;
1155
- return { kind: "video", type: r, dts: c, pts: h, cts: l, data: d, nalus: a };
1156
- }
1157
- };
1158
- /**
1159
- * 解析 PTS/DTS 时间戳(33-bit,单位:90kHz)
1160
- */
1161
- parsePtsDts(t, s) {
1162
- const e = t.getUint8(s), n = t.getUint8(s + 1), i = t.getUint8(s + 2), o = t.getUint8(s + 3), a = t.getUint8(s + 4), r = (BigInt(e) & 0b00001110n) << 29n | (BigInt(n) & 0b11111111n) << 22n | (BigInt(i) & 0b11111110n) << 14n | (BigInt(o) & 0b11111111n) << 7n | (BigInt(a) & 0b11111110n) >> 1n;
1163
- return Number(r) / 90;
1164
- }
1165
- getNalus = (t) => {
1166
- const s = [];
1167
- let e = 0;
1168
- for (; !(e + 4 > t.byteLength); ) {
1169
- if (t[e] !== 0 || t[e + 1] !== 0 || t[e + 2] !== 1) {
1170
- e += 1;
1171
- continue;
1172
- }
1173
- e += 3;
1174
- let n = e;
1175
- const i = t[e] & 31;
1176
- for (e += 1; !(e + 1 > t.byteLength); ) {
1177
- if (t[e] !== 0 || t[e + 1] !== 0 || t[e + 2] !== 1) {
1178
- e += 1;
1179
- continue;
1180
- }
1181
- break;
1182
- }
1183
- let o = e - n;
1184
- if (t[e - 1] === 0 && (o -= 1), o !== 0) {
1185
- const a = t.slice(n, n + o), r = z(a);
1186
- s.push({ type: i, nalu: r });
1187
- }
1188
- }
1189
- return s;
1190
- };
1191
- }
1192
- const w = (g, t) => g.getUint8(t) << 16 | g.getUint8(t + 1) << 8 | g.getUint8(t + 2);
1193
- class Y {
1194
- audioConfig;
1195
- videoConfig;
1196
- header;
1197
- textDecoder = new TextDecoder("utf-8");
1198
- // 指定编码格式
1199
- on = {};
1200
- constructor() {
1201
- }
1202
- parse = async (t) => {
1203
- let s = 0;
1204
- for (this.header || (this.parseHeader(t, s), s += 9); this.isSurplusTag(t, s) !== !1; ) {
1205
- const n = this.parseTagHeader(t, s + 4), { tagType: i, dataSize: o, timestamp: a } = n;
1206
- if (i) {
1207
- const r = this.parseTagBody(i, t, s + 4 + 11, o);
1208
- switch (i) {
1209
- case "script":
1210
- this.on.info && this.on.info(r);
1211
- break;
1212
- case "audio":
1213
- {
1214
- const { accPacketType: d } = r;
1215
- if (d === 0) {
1216
- const { codec: c, sampleRate: h, channelConfiguration: l } = r;
1217
- this.audioConfig = { kind: "audio", codec: c, sampleRate: h, numberOfChannels: l }, this.on.config && this.on.config(this.audioConfig);
1218
- } else {
1219
- const { cts: c, data: h } = r, l = "key", u = c === void 0 ? void 0 : c + a;
1220
- this.on.chunk && this.on.chunk({ kind: "audio", type: l, dts: a, pts: u, cts: c, data: h });
1221
- }
1222
- }
1223
- break;
1224
- case "video":
1225
- {
1226
- const { avcPacketType: d } = r;
1227
- if (d === 0) {
1228
- const { codec: c, sps: h, pps: l, data: u } = r;
1229
- this.videoConfig = { kind: "video", codec: c, description: u, sps: h, pps: l }, this.on.config && this.on.config(this.videoConfig);
1230
- } else {
1231
- const { frameType: c, cts: h, data: l, nalus: u } = r, p = c === 1 ? "key" : "delta", f = h === void 0 ? void 0 : h + a;
1232
- this.on.chunk && this.on.chunk({ kind: "video", type: p, dts: a, pts: f, cts: h, data: l, nalus: u });
1233
- }
1234
- }
1235
- break;
1236
- }
1237
- s = s + 4 + 11 + o;
1238
- }
1239
- await new Promise((r) => setTimeout(() => r(!0), 8));
1240
- }
1241
- return s;
1242
- };
1243
- // Header
1244
- parseHeader = (t, s) => {
1245
- let e, n, i, o;
1246
- e = t.getUint8(s) << 16 | t.getUint8(s + 1) << 8 | t.getUint8(s + 2), n = t.getUint8(3);
1247
- {
1248
- const r = t.getUint8(0).toString(2).padStart(5, "0").split(""), [, , d, , c] = r;
1249
- i = { audio: c === "1", video: d === "1" };
1250
- }
1251
- o = t.getUint32(5), this.header = { signature: e, version: n, flags: i, dataOffset: o };
1252
- };
1253
- // 是否是完整tag
1254
- isSurplusTag = (t, s) => {
1255
- let e = !0;
1256
- const n = t.byteLength;
1257
- if (s + 4 > n)
1258
- e = !1;
1259
- else if (s + 4 + 11 > n)
1260
- e = !1;
1261
- else {
1262
- const i = w(t, s + 4 + 1);
1263
- s + 4 + 11 + i > n && (e = !1);
1264
- }
1265
- return e;
1266
- };
1267
- parseTagHeader = (t, s) => {
1268
- let e, n, i, o, a;
1269
- {
1270
- const r = t.getUint8(s);
1271
- let d;
1272
- switch (r) {
1273
- case 18:
1274
- d = "script";
1275
- break;
1276
- case 8:
1277
- d = "audio";
1278
- break;
1279
- case 9:
1280
- d = "video";
1281
- break;
1282
- }
1283
- e = d;
1284
- }
1285
- return n = w(t, s + 1), i = w(t, s + 4), o = t.getUint8(s + 7), a = w(t, s + 8), { tagType: e, dataSize: n, timestamp: i, timestampExtended: o, streamID: a };
1286
- };
1287
- parseTagBody = (t, s, e, n) => {
1288
- let i;
1289
- switch (t) {
1290
- case "script":
1291
- i = this.parseMetaData(s, e);
1292
- break;
1293
- case "audio":
1294
- i = this.parseAudio(s, e, n);
1295
- break;
1296
- case "video":
1297
- i = this.parseVideo(s, e, n);
1298
- break;
1299
- }
1300
- return i;
1301
- };
1302
- parseMetaData = (t, s) => {
1303
- let e = s;
1304
- {
1305
- if (t.getUint8(e) !== 2) throw new Error("Invalid AMF type for onMetaData (expected 0x02)");
1306
- e = e + 1;
1307
- }
1308
- const n = t.getUint16(e, !1);
1309
- e = e + 2;
1310
- {
1311
- const a = new Int8Array(t.buffer.slice(e, e + n));
1312
- if ((this.textDecoder?.decode(a) || "") !== "onMetaData") throw new Error("Expected 'onMetaData' string");
1313
- e = e + n;
1314
- }
1315
- const i = this.getAmfType(t, e);
1316
- return e = e + 1, this.getAMFValue(t, e, i).value;
1317
- };
1318
- parseAudio = (t, s, e) => {
1319
- let n = s;
1320
- const i = t.getUint8(n), o = i >> 4 & 15, a = i >> 2 & 3, r = i >> 1 & 1, d = i & 1;
1321
- n = n + 1;
1322
- const c = t.getUint8(n);
1323
- n = n + 1;
1324
- const h = e, l = new Uint8Array(t.buffer.slice(n, n + h));
1325
- if (o === 10 && c === 0) {
1326
- const u = t.getUint8(n), p = t.getUint8(n + 1), f = u >> 3 & 31, m = (u & 7) << 1 | p >> 7, k = p >> 3 & 15, y = [96e3, 88200, 64e3, 48e3, 44100, 32e3, 24e3, 22050, 16e3, 12e3, 11025, 8e3, 7350], U = `mp4a.40.${f}`, b = y[m];
1327
- return { soundFormat: o, soundRate: a, soundSize: r, soundType: d, accPacketType: c, data: l, samplingFrequencyIndex: m, channelConfiguration: k, codec: U, sampleRate: b };
1328
- }
1329
- return { soundFormat: o, soundRate: a, soundSize: r, soundType: d, accPacketType: c, data: l };
1330
- };
1331
- parseVideo = (t, s, e) => {
1332
- let n = s;
1333
- const i = t.getUint8(n), o = i >> 4 & 15, a = i & 15;
1334
- n = n + 1;
1335
- const r = t.getUint8(n);
1336
- n = n + 1;
1337
- const d = w(t, n);
1338
- n = n + 3;
1339
- const c = e - 5, h = new Uint8Array(t.buffer.slice(n, n + c));
1340
- switch (a) {
1341
- case 7:
1342
- if (r === 0) {
1343
- const l = M(h);
1344
- return { frameType: o, codecID: a, avcPacketType: r, cts: d, data: h, ...l };
1345
- } else if (r === 1) {
1346
- const l = [], u = n + e - 5;
1347
- for (; !(n + 4 > u); ) {
1348
- const p = t.getUint32(n, !1), f = new Uint8Array(t.buffer.slice(n, n + 4 + p));
1349
- n += 4 + p, l.push(f);
1350
- }
1351
- return { frameType: o, codecID: a, avcPacketType: r, cts: d, data: h, nalus: l };
1352
- }
1353
- break;
1354
- default:
1355
- throw new Error("Unsupported codecID");
1356
- }
1357
- return { frameType: o, codecID: a, avcPacketType: r, cts: d, data: h };
1358
- };
1359
- getAmfType = (t, s) => t.getUint8(s);
1360
- getAMFName = (t, s, e) => {
1361
- const n = new Uint8Array(t.buffer.slice(s, s + e));
1362
- return this.textDecoder?.decode(n) || "";
1363
- };
1364
- getAMFValue = (t, s, e) => {
1365
- let n = s, i, o = 0;
1366
- switch (e) {
1367
- case 0:
1368
- i = t.getFloat64(n, !1), o = 8;
1369
- break;
1370
- case 1:
1371
- i = !!t.getUint8(n), o = 1;
1372
- break;
1373
- case 2:
1374
- {
1375
- i = "";
1376
- const r = t.getUint16(n, !1);
1377
- n = n + 2;
1378
- const d = new Int8Array(t.buffer, n, r).filter((h) => h !== 0);
1379
- i = (this.textDecoder?.decode(d) || "").trim(), o = 2 + r;
1380
- }
1381
- break;
1382
- case 3:
1383
- for (i = {}; n < t.byteLength; ) {
1384
- const r = t.getUint16(n, !1);
1385
- if (r === 0) break;
1386
- n = n + 2;
1387
- const d = this.getAMFName(t, n, r);
1388
- n = n + r;
1389
- const c = this.getAmfType(t, n);
1390
- if (c === 6) break;
1391
- n = n + 1;
1392
- const h = this.getAMFValue(t, n, c);
1393
- n = n + h.length, i[d] = h.value, o = 2 + r + 1 + h.length;
1394
- }
1395
- break;
1396
- case 8:
1397
- {
1398
- i = {};
1399
- const r = t.getUint32(n, !1);
1400
- n = n + 4;
1401
- for (let d = 0; d < r; d++) {
1402
- const c = t.getUint16(n, !1);
1403
- n = n + 2;
1404
- const h = this.getAMFName(t, n, c);
1405
- n = n + c;
1406
- const l = this.getAmfType(t, n);
1407
- n = n + 1;
1408
- const u = this.getAMFValue(t, n, l);
1409
- n = n + u.length, i[h] = u.value, o = 2 + c + 1 + u.length;
1410
- }
1411
- }
1412
- break;
1413
- case 10:
1414
- {
1415
- i = [];
1416
- const r = t.getUint32(n, !1);
1417
- n = n + 4;
1418
- for (let d = 0; d < r; d++) {
1419
- const c = this.getAmfType(t, n);
1420
- n = n + 1;
1421
- const h = this.getAMFValue(t, n, c);
1422
- n = n + h.length, i.push(h.value), o = 1 + h.length;
1423
- }
1424
- }
1425
- break;
1426
- }
1427
- return { amfType: e, length: o, value: i };
1428
- };
1429
- }
1430
- class J {
1431
- pattern;
1432
- cacher = new H();
1433
- isParseing = !1;
1434
- offset = 0;
1435
- parser;
1436
- on = {};
1437
- constructor() {
1438
- }
1439
- init = (t) => {
1440
- switch (this.destroy(), this.pattern = t, this.pattern) {
1441
- case "flv":
1442
- this.parser = new Y();
1443
- break;
1444
- case "hls":
1445
- this.parser = new X();
1446
- break;
1447
- default:
1448
- throw new Error("is error pattern.");
1449
- }
1450
- 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) => {
1451
- this.cacher.pushChunk(s), this.on.chunk && this.on.chunk(s);
1452
- };
1453
- };
1454
- push = (t) => {
1455
- this.cacher.push(t), this.isParseing === !1 && this.parse();
1456
- };
1457
- destroy = () => {
1458
- this.cacher.destroy(), this.isParseing = !1, this.offset = 0;
1459
- };
1460
- parse = async () => {
1461
- try {
1462
- if (this.isParseing = !0, !this.pattern)
1463
- throw new Error("You need to set the pattern.");
1464
- if (!this.parser)
1465
- throw new Error("You need to init parser.");
1466
- for (; ; ) {
1467
- const t = this.cacher.next(this.offset);
1468
- if (this.offset = 0, !t) break;
1469
- this.offset = await this.parser.parse(t);
1470
- }
1471
- this.isParseing = !1;
1472
- } catch {
1473
- this.destroy();
1474
- }
1475
- };
1476
- }
1477
- class Z {
1478
- pattern = "flv";
1479
- audioDecoderConfig;
1480
- audioDecoder;
1481
- videoDecoderConfig;
1482
- videoDecoder;
1483
- hasKeyFrame = !1;
1484
- baseTime = 0;
1485
- // ms
1486
- pendingChunks = [];
1487
- currentChunk;
1488
- isProcessing = !1;
1489
- decodeTimer = 0;
1490
- // 解码定时器
1491
- frameTrack = !1;
1492
- // 是否开启自动追帧
1493
- isFrameTrack = !1;
1494
- // 当前是否正在追帧
1495
- fameTrackOption = {
1496
- // [停止追帧, 开启追帧]
1497
- flv: [30, 50],
1498
- hls: [200, 300],
1499
- dash: [50, 100],
1500
- rtmp: [50, 100]
1501
- };
1502
- decodingSpeedRatio = 1;
1503
- // 解码速率
1504
- maxDecodingSpeedRatio = 2;
1505
- // 最大解码速率
1506
- decodingSpeed = 16;
1507
- // ms
1508
- fps = 0;
1509
- // 实时渲染fps
1510
- firstVideoChunkTimestamp;
1511
- // 第一帧时间戳
1512
- secondVideoChunkTimestamp;
1513
- // 第二帧时间戳
1514
- frameStartTime;
1515
- // 帧开始时间 用于校准最终渲染时间
1516
- lastRenderTime;
1517
- // 上一次渲染的时间
1518
- nextRenderTime;
1519
- // 下一次渲染的时间
1520
- on = { audio: {}, video: {} };
1521
- constructor() {
1522
- }
1523
- init = (t) => {
1524
- this.destroy(), this.pattern = t, this.baseTime = (/* @__PURE__ */ new Date()).getTime() - performance.now(), this.initDecodeInterval();
1525
- };
1526
- initAudio = (t) => {
1527
- this.audio.destroy(), this.audioDecoderConfig = { ...t }, this.audioDecoder = new AudioDecoder({
1528
- output: (s) => {
1529
- const e = this.decodingSpeedRatio;
1530
- this.on.audio.decode && this.on.audio.decode({ audioData: s, playbackRate: e });
1531
- },
1532
- error: (s) => {
1533
- this.on.audio.error && this.on.audio.error(s);
1534
- }
1535
- }), this.audioDecoder.configure(this.audioDecoderConfig);
1536
- };
1537
- initVideo = (t) => {
1538
- this.video.destroy(), this.videoDecoderConfig = { ...t }, this.videoDecoder = new VideoDecoder({
1539
- output: async (s) => {
1540
- this.frameStartTime || (this.frameStartTime = s.timestamp);
1541
- try {
1542
- const e = s.timestamp - this.frameStartTime + this.baseTime * 1e3, n = await createImageBitmap(s);
1543
- if (s.close(), !n.width || !n.height) return n.close();
1544
- this.on.video.decode && this.on.video.decode({ timestamp: e, bitmap: n }), this.currentChunk && this.currentChunk.kind === "video" && this.currentChunk.nalus && this.on.nalus && this.on.nalus(this.currentChunk.nalus);
1545
- } catch {
1546
- s.close();
1547
- }
1548
- },
1549
- error: (s) => {
1550
- this.on.video.error && this.on.video.error(s);
1551
- }
1552
- }), this.videoDecoder.configure(this.videoDecoderConfig);
1553
- };
1554
- setFrameTrack = (t) => {
1555
- this.frameTrack = t, this.frameTrack === !1 && (this.decodingSpeedRatio = 1);
1556
- };
1557
- push = (t) => {
1558
- this.pendingChunks.push(t);
1559
- };
1560
- destroy = () => {
1561
- this.audio.destroy(), this.video.destroy(), this.pendingChunks = [], this.firstVideoChunkTimestamp = void 0, this.secondVideoChunkTimestamp = void 0, this.frameStartTime = void 0, this.lastRenderTime = void 0, this.nextRenderTime = void 0, clearInterval(this.decodeTimer);
1562
- };
1563
- initDecodeInterval = () => {
1564
- let t = this.decodingSpeed / this.decodingSpeedRatio;
1565
- const s = this.baseTime + performance.now();
1566
- if (this.lastRenderTime || (this.lastRenderTime = s), this.fps = Math.round(1e3 / (s - this.lastRenderTime)), this.lastRenderTime = s, this.nextRenderTime) {
1567
- const e = this.lastRenderTime - this.nextRenderTime;
1568
- t -= e;
1569
- }
1570
- this.nextRenderTime = this.lastRenderTime + t, this.decodeTimer = setTimeout(() => {
1571
- this.decode(), this.initDecodeInterval();
1572
- }, t);
1573
- };
1574
- decode = () => {
1575
- if (this.isProcessing !== !0) {
1576
- for (this.isProcessing = !0; this.currentChunk = this.pendingChunks.shift(), !!this.currentChunk; ) {
1577
- const t = this.pendingChunks.length;
1578
- if (this.frameTrack) {
1579
- const [n, i] = this.fameTrackOption[this.pattern];
1580
- if (t <= n && (this.isFrameTrack = !1), t >= i && (this.isFrameTrack = !0), this.isFrameTrack) {
1581
- const o = Math.min(1 + (t - n) / 100, this.maxDecodingSpeedRatio);
1582
- this.decodingSpeedRatio = Number(o.toFixed(1));
1583
- } else
1584
- this.decodingSpeedRatio = 1;
1585
- }
1586
- if (this.on.analysis) {
1587
- const { decodingSpeed: n, decodingSpeedRatio: i, fps: o } = this;
1588
- this.on.analysis({ decodingSpeed: n, decodingSpeedRatio: i, fps: o, cacheLength: t });
1589
- }
1590
- const { kind: s, init: e } = this.currentChunk;
1591
- switch (s) {
1592
- case "audio":
1593
- this.decodeAudio(e);
1594
- break;
1595
- case "video":
1596
- this.decodeVideo(e);
1597
- break;
1598
- }
1599
- if (s === "video") break;
1600
- }
1601
- this.isProcessing = !1;
1602
- }
1603
- };
1604
- decodeAudio = (t) => {
1605
- if (!this.audioDecoder) return;
1606
- const s = new EncodedAudioChunk(t);
1607
- this.audioDecoder.decode(s);
1608
- };
1609
- decodeVideo = (t) => {
1610
- if (this.videoDecoder && (t.type === "key" && (this.hasKeyFrame = !0), this.firstVideoChunkTimestamp ? this.secondVideoChunkTimestamp || (this.secondVideoChunkTimestamp = t.timestamp, this.decodingSpeed = (this.secondVideoChunkTimestamp - this.firstVideoChunkTimestamp) / 1e3) : this.firstVideoChunkTimestamp = t.timestamp, this.hasKeyFrame)) {
1611
- const s = new EncodedVideoChunk(t);
1612
- this.videoDecoder.decode(s);
1613
- }
1614
- };
1615
- audio = {
1616
- flush: () => {
1617
- this.audioDecoder?.flush();
1618
- },
1619
- destroy: () => {
1620
- this.audioDecoderConfig = void 0, this.audioDecoder?.close(), this.audioDecoder = void 0;
1621
- }
1622
- };
1623
- video = {
1624
- flush: () => {
1625
- this.videoDecoder?.flush();
1626
- },
1627
- destroy: () => {
1628
- this.videoDecoderConfig = void 0, this.videoDecoder?.close(), this.videoDecoder = void 0, this.hasKeyFrame = !1;
1629
- }
1630
- };
1631
- }
1632
- class tt {
1633
- renderMap = /* @__PURE__ */ new Map();
1634
- constructor() {
1635
- }
1636
- push = async (t) => {
1637
- const { timestamp: s } = t, { bitmap: e } = t;
1638
- if (e.height === 0 || e.width === 0) return e.close();
1639
- try {
1640
- const n = [...this.renderMap.keys()];
1641
- for (const i of n) {
1642
- const o = this.renderMap.get(i);
1643
- if (!o) continue;
1644
- const { pause: a = !1, writer: r, offscreen: d, option: c } = o;
1645
- if (a === !0) continue;
1646
- const h = (l) => {
1647
- if (r) {
1648
- const u = new VideoFrame(l, { timestamp: s });
1649
- try {
1650
- u && r.write(u);
1651
- } catch {
1652
- }
1653
- u.close();
1654
- } else d && (d.width = l.width, d.height = l.height, d?.getContext("2d")?.drawImage(l, 0, 0));
1655
- };
1656
- if (i === "default")
1657
- h(e);
1658
- else if (c) {
1659
- const { sx: l = 0, sy: u = 0, sw: p = e.width, sh: f = e.height } = c, m = await createImageBitmap(e, l, u, p, f);
1660
- h(m);
1661
- }
1662
- }
1663
- } catch {
1664
- }
1665
- e.close();
1666
- };
1667
- /**
1668
- * 增加剪切
1669
- */
1670
- addCut = (t) => {
1671
- const { key: s, writable: e, offscreen: n, option: i } = { key: "default", ...t };
1672
- if (e) {
1673
- const o = e.getWriter();
1674
- this.renderMap.set(s, { writer: o, option: i, pause: !1 });
1675
- } else
1676
- this.renderMap.set(s, { offscreen: n, option: i, pause: !1 });
1677
- };
1678
- /**
1679
- * 删除剪切
1680
- */
1681
- delCut = (t) => {
1682
- this.renderMap.delete(t);
1683
- };
1684
- /**
1685
- * 设置剪切
1686
- */
1687
- setCut = (t) => {
1688
- const { key: s, cutOption: e } = { key: "default", ...t }, n = this.renderMap.get(s);
1689
- n && this.renderMap.set(s, { ...n, option: e });
1690
- };
1691
- /**
1692
- * 设置暂停
1693
- */
1694
- setPause = (t) => {
1695
- const { key: s, pause: e } = { key: "default", ...t }, n = this.renderMap.get(s);
1696
- n && this.renderMap.set(s, { ...n, pause: e });
1697
- };
1698
- destroy = () => {
1699
- this.renderMap = /* @__PURE__ */ new Map();
1700
- };
1701
- }
1702
- export {
1703
- Z as Decoder,
1704
- N as DecoderWorker,
1705
- J as Demuxer,
1706
- P as DemuxerWorker,
1707
- Q as PrPlayer,
1708
- tt as Render,
1709
- V as RenderWorker
135
+ //#endregion
136
+ //#region src/render/RenderWorker.ts
137
+ var d = class {
138
+ worker = new u();
139
+ constructor() {}
140
+ push = (e) => this.worker.postMessage({
141
+ action: "push",
142
+ data: e
143
+ }, [e.bitmap]);
144
+ addCut = (e) => {
145
+ let t = [];
146
+ e.writable && t.push(e.writable), e.offscreen && t.push(e.offscreen), this.worker.postMessage({
147
+ action: "addCut",
148
+ data: e
149
+ }, t);
150
+ };
151
+ delCut = (e) => this.worker.postMessage({
152
+ action: "delCut",
153
+ data: e
154
+ });
155
+ setCut = (e) => this.worker.postMessage({
156
+ action: "setCut",
157
+ data: e
158
+ });
159
+ setPause = (e) => this.worker.postMessage({
160
+ action: "setPause",
161
+ data: e
162
+ });
163
+ destroy = () => {
164
+ this.worker.postMessage({
165
+ action: "destroy",
166
+ data: {}
167
+ }), this.worker.terminate();
168
+ };
169
+ }, f = class {
170
+ inputStream = new MediaStream();
171
+ outputStream = new MediaStream();
172
+ inputGain = 1;
173
+ enhanceGain = 1;
174
+ bgsGain = 1;
175
+ bgmGain = 1;
176
+ outputGain = 1;
177
+ mixAudioMap = /* @__PURE__ */ new Map();
178
+ audioContext = new AudioContext();
179
+ sourceNode;
180
+ inputGainNode;
181
+ enhanceGainNode;
182
+ bgsGainNode;
183
+ bgmGainNode;
184
+ rnnoiseNode;
185
+ analyserNode;
186
+ analyserArrayData;
187
+ outputGainNode;
188
+ destinationNode;
189
+ denoise = !1;
190
+ mute = !0;
191
+ rnnoiseWorklet;
192
+ rnnoiseWorkletNode;
193
+ filterStream = (e) => e;
194
+ constructor(e, t) {
195
+ this.inputStream = e, t && (this.audioContext = 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;
196
+ {
197
+ let { sourceNode: e, inputGainNode: t, enhanceGainNode: n, bgsGainNode: r, bgmGainNode: i, analyserNode: a, outputGainNode: o, destinationNode: s } = this;
198
+ e.connect(t), t.connect(n), n.connect(a), r.connect(a), i.connect(a), n.connect(s), r.connect(s), i.connect(s), o.connect(this.audioContext.destination);
199
+ }
200
+ this.audioContext.resume();
201
+ }
202
+ use = ({ rnnoise: e }) => {
203
+ this.rnnoiseWorklet = new e.RnnoiseWorklet();
204
+ };
205
+ _changeSource = () => {
206
+ this.sourceNode.disconnect(), this.sourceNode = this.audioContext.createMediaStreamSource(this.inputStream), this.sourceNode.connect(this.inputGainNode);
207
+ };
208
+ replaceTrack = (e) => {
209
+ let t = this.inputStream.getTracks();
210
+ for (let e of t) this.inputStream.removeTrack(e);
211
+ this.inputStream.addTrack(e), this._changeSource();
212
+ };
213
+ stop = () => {
214
+ {
215
+ let e = this.inputStream.getTracks();
216
+ for (let t of e) t.stop(), this.inputStream.removeTrack(t);
217
+ }
218
+ };
219
+ pause = async (e) => {
220
+ let t = this.inputStream.getTracks();
221
+ for (let n of t) n.enabled = !e;
222
+ };
223
+ getStream = () => this.filterStream(this.outputStream);
224
+ setMute = (e = !0) => {
225
+ this.mute = e, this.analyserNode.disconnect(), e === !1 && this.analyserNode.connect(this.outputGainNode);
226
+ };
227
+ setDenoise = async (e = !0) => {
228
+ this.rnnoiseWorklet && (this.inputGainNode.disconnect(), this.rnnoiseWorklet.destroy(), e ? (this.rnnoiseWorkletNode = await this.rnnoiseWorklet.createRnnoiseWorkletNode(this.audioContext), this.inputGainNode.connect(this.rnnoiseWorkletNode), this.rnnoiseWorkletNode.connect(this.enhanceGainNode)) : this.inputGainNode.connect(this.enhanceGainNode), this.denoise = e);
229
+ };
230
+ setInputGain = (e) => {
231
+ this.inputGain = e, this.inputGainNode.gain.setValueAtTime(e, this.audioContext.currentTime);
232
+ };
233
+ setEnhanceGain = async (e) => {
234
+ this.enhanceGain = e + 1, this.enhanceGainNode.gain.setValueAtTime(this.enhanceGain, this.audioContext.currentTime);
235
+ };
236
+ setBgsGain = (e) => {
237
+ this.bgsGain = e, this.bgsGainNode.gain.setValueAtTime(e, this.audioContext.currentTime);
238
+ };
239
+ setBgmGain = (e) => {
240
+ this.bgmGain = e, this.bgmGainNode.gain.setValueAtTime(e, this.audioContext.currentTime);
241
+ };
242
+ setOutputGain = (e) => {
243
+ this.outputGain = e, this.outputGainNode.gain.setValueAtTime(this.outputGain, this.audioContext.currentTime);
244
+ };
245
+ getVolume = () => {
246
+ let { analyserNode: e, analyserArrayData: t } = this;
247
+ e.getByteFrequencyData(t);
248
+ let n = 0;
249
+ for (let e = 0; e < t.length; e++) n += t[e];
250
+ return Math.ceil(n / t.length);
251
+ };
252
+ mixAudio = (e, t = "bgm") => new Promise(async (n, r) => {
253
+ try {
254
+ {
255
+ let e = this.mixAudioMap.get(t);
256
+ e && e.stop();
257
+ }
258
+ let r = t === "bgs" ? this.bgsGainNode : this.bgmGainNode, i = this.audioContext.createBufferSource();
259
+ this.mixAudioMap.set(t, i), i.buffer = e, i.connect(r), i.onended = () => {
260
+ i.disconnect(r), this.mixAudioMap.delete(t), n(!0);
261
+ }, i.start(0);
262
+ } catch (e) {
263
+ r(e);
264
+ }
265
+ });
266
+ mixAudioStop = (e) => {
267
+ this.mixAudioMap.get(e)?.stop();
268
+ };
269
+ changeMix = (e, t) => {
270
+ let n = e === "bgs" ? this.bgsGainNode : this.bgmGainNode;
271
+ t ? n.connect(this.destinationNode) : n.disconnect(this.destinationNode);
272
+ };
273
+ }, p = async (e, t) => {
274
+ try {
275
+ let { format: n, numberOfChannels: r, numberOfFrames: i, sampleRate: a } = t, o = e.createBuffer(r, i, a);
276
+ for (let e = 0; e < r; e++) {
277
+ let r = t.allocationSize({ planeIndex: e }), a = new Uint8Array(r);
278
+ t.copyTo(a, { planeIndex: e });
279
+ let s = new DataView(a.buffer), c = o.getChannelData(e);
280
+ for (let e = 0; e < i; e++) {
281
+ let t;
282
+ switch (n) {
283
+ case "s16":
284
+ case "s16-planar":
285
+ t = s.getInt16(e * 2, !0) / 32768;
286
+ break;
287
+ case "f32":
288
+ case "f32-planar":
289
+ t = s.getFloat32(e * 4, !0);
290
+ break;
291
+ case "u8":
292
+ case "u8-planar":
293
+ t = (s.getUint8(e) - 128) / 128;
294
+ break;
295
+ default: throw Error(`Unsupported audio format: ${n}`);
296
+ }
297
+ c[e] = Math.max(-1, Math.min(1, t));
298
+ }
299
+ }
300
+ return o;
301
+ } catch (e) {
302
+ throw console.error("Failed to convert AudioData to AudioBuffer:", e), e;
303
+ }
304
+ }, m = class {
305
+ prAudioStream;
306
+ audioContext;
307
+ destination;
308
+ stream = new MediaStream();
309
+ nextStartTime = 0;
310
+ pendingSources = [];
311
+ constructor() {}
312
+ init = (e) => {
313
+ e ||= new (window.AudioContext || window.webkitAudioContext)(), this.audioContext = e, this.destination = this.audioContext.createMediaStreamDestination(), this.stream = new MediaStream(), this.stream.addTrack(this.destination.stream.getAudioTracks()[0]), this.prAudioStream = new f(this.stream, this.audioContext), this.nextStartTime = 0, this.pendingSources = [];
314
+ };
315
+ async push(e) {
316
+ let { audioData: t, playbackRate: n = 1 } = e;
317
+ if (!this.audioContext || !this.destination) return;
318
+ let r = await p(this.audioContext, t);
319
+ if (t.close(), !r) return;
320
+ let i = this.audioContext.createBufferSource();
321
+ i.buffer = r, i.playbackRate.value = n;
322
+ let a = -1200 * Math.log2(n);
323
+ i.detune.value = a, i.connect(this.destination);
324
+ let o = Math.max(this.nextStartTime, this.audioContext.currentTime);
325
+ this.nextStartTime = o + r.duration / n, i.start(o), this.pendingSources.push(i), i.onended = () => {
326
+ this.pendingSources = this.pendingSources.filter((e) => e !== i);
327
+ }, this.audioContext.state === "suspended" && await this.audioContext.resume();
328
+ }
329
+ getStream = () => this.prAudioStream?.getStream();
330
+ destroy() {
331
+ this.audioContext?.close(), this.audioContext = void 0, this.destination = void 0, this.nextStartTime = 0, this.prAudioStream?.stop(), this.pendingSources.forEach((e) => e.stop()), this.pendingSources = [];
332
+ }
333
+ }, h = (e) => {
334
+ let t = e.toLowerCase();
335
+ 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";
336
+ }, g = (e) => {
337
+ let t = e?.getTracks() || [];
338
+ for (let e of t) e.stop();
339
+ }, _ = class {
340
+ resolvesMap = /* @__PURE__ */ new Map();
341
+ index = 0;
342
+ constructor() {}
343
+ add = (e, t = () => !1, n = 0) => new Promise((r) => {
344
+ if (t()) return r(!0);
345
+ this.resolvesMap.has(e) || this.resolvesMap.set(e, /* @__PURE__ */ new Map()), this.index++;
346
+ let i = `${this.index}`;
347
+ if (n = Math.max(0, n), n === 0) {
348
+ this.resolvesMap.get(e)?.set(i, {
349
+ resolve: r,
350
+ timer: 0
351
+ });
352
+ return;
353
+ }
354
+ let a = window.setTimeout(() => {
355
+ this.emit(e);
356
+ }, n);
357
+ this.resolvesMap.get(e)?.set(i, {
358
+ resolve: r,
359
+ timer: a
360
+ });
361
+ });
362
+ emit = async (e) => {
363
+ let t = this.resolvesMap.get(e);
364
+ if (!t) return;
365
+ let n = [...t.keys()];
366
+ for (let e of n) {
367
+ let n = t.get(e);
368
+ n && (clearTimeout(n.timer), n.resolve(), t.delete(e));
369
+ }
370
+ };
371
+ }, v = (e, t) => {
372
+ let n = new Uint8Array(e), r = new Uint8Array(t), i = new Uint8Array(11 + n.length + r.length), a = 0;
373
+ return i[a++] = 1, i[a++] = n[1], i[a++] = n[2], i[a++] = n[3], i[a++] = 255, i[a++] = 225, i[a++] = n.length >> 8 & 255, i[a++] = n.length & 255, i.set(n, a), a += n.length, i[a++] = 1, i[a++] = r.length >> 8 & 255, i[a++] = r.length & 255, i.set(r, a), i;
374
+ }, y = (e) => {
375
+ let t = 0, n = new DataView(e.buffer), r = n.getUint8(t);
376
+ if (t += 1, r !== 1) throw Error("Invalid AVC version");
377
+ let i = n.getUint8(t) & 255;
378
+ t += 1;
379
+ let a = n.getUint8(t) & 255;
380
+ t += 1;
381
+ let o = n.getUint8(t) & 255;
382
+ t += 1;
383
+ let s = `avc1.${Array.from([
384
+ i,
385
+ a,
386
+ o
387
+ ], (e) => e.toString(16).padStart(2, "0")).join("")}`, c = (n.getUint8(t) & 3) - 1;
388
+ t += 1;
389
+ let l = n.getUint8(t) & 31;
390
+ t += 1;
391
+ let u = n.getUint16(t, !1);
392
+ t += 2;
393
+ let d = new Uint8Array(n.buffer.slice(t, t + u));
394
+ t += u;
395
+ let f = n.getUint8(t) & 31;
396
+ t += 1;
397
+ let p = n.getUint16(t, !1);
398
+ t += 2;
399
+ let m = new Uint8Array(n.buffer.slice(t, t + p));
400
+ return t += p, {
401
+ version: r,
402
+ codec: s,
403
+ profile: i,
404
+ compatibility: a,
405
+ level: o,
406
+ lengthSizeMinusOne: c,
407
+ numOfSequenceParameterSets: l,
408
+ sequenceParameterSetLength: u,
409
+ sps: d,
410
+ numOfPictureParameterSets: f,
411
+ pictureParameterSetLength: p,
412
+ pps: m
413
+ };
414
+ }, b = (e) => {
415
+ let t = new Uint8Array(4 + e.length);
416
+ return new DataView(t.buffer).setUint32(0, e.length, !1), t.set(e, 4), t;
417
+ }, x = (e) => {
418
+ let t = 0;
419
+ for (let n of e) t += n.length;
420
+ let n = new Uint8Array(t), r = 0;
421
+ for (let t of e) {
422
+ let e = t;
423
+ n.set(e, r), r += e.length;
424
+ }
425
+ return n;
426
+ }, S = (e) => {
427
+ let t = new DataView(e.buffer), n = 0, r, i, a;
428
+ r = t.getUint32(n, !1), n += 4;
429
+ {
430
+ let e = t.getUint8(n);
431
+ i = {
432
+ forbidden_zero_bit: e >> 7 & 1,
433
+ nal_ref_idc: e >> 5 & 3,
434
+ nal_unit_type: e & 31
435
+ }, n += 1;
436
+ }
437
+ {
438
+ let e = r - 1;
439
+ a = new Uint8Array(t.buffer.slice(n, n + e));
440
+ }
441
+ return {
442
+ size: r,
443
+ header: i,
444
+ data: a
445
+ };
446
+ }, C = class {
447
+ #e = {
448
+ timeout: 5 * 1e3,
449
+ check: !1
450
+ };
451
+ #t = null;
452
+ constructor(e = {}) {
453
+ this.#e = {
454
+ ...this.#e,
455
+ ...e
456
+ };
457
+ }
458
+ #n = (e, t) => new Promise(async (n) => {
459
+ this.#t = new AbortController();
460
+ let { signal: r } = this.#t, i = this.#e.timeout, a = setTimeout(() => {
461
+ this.#t?.abort(`Timeout (${i}ms)`);
462
+ }, i);
463
+ await fetch(e, {
464
+ cache: "no-store",
465
+ ...t,
466
+ method: "HEAD",
467
+ signal: r
468
+ }).then((e) => {
469
+ clearTimeout(a), n({
470
+ status: e.status === 200 ? "successed" : "failed",
471
+ reason: e.status === 200 ? "" : `HTTP ${e.status}`
472
+ });
473
+ }).catch((e) => {
474
+ if (clearTimeout(a), e.name === "AbortError") {
475
+ let e = r.reason || "Actively stopped";
476
+ n({
477
+ status: e.includes("Timeout") ? "timeout" : "stopped",
478
+ reason: e
479
+ });
480
+ } else n({
481
+ status: "error",
482
+ reason: e.message
483
+ });
484
+ });
485
+ });
486
+ request = (e, t) => new Promise(async (n, r) => {
487
+ try {
488
+ this.stop(), this.#e.check && await this.#n(e), this.#t = new AbortController();
489
+ let { signal: r } = this.#t;
490
+ n(await fetch(e, {
491
+ cache: "no-store",
492
+ ...t,
493
+ signal: r
494
+ }));
495
+ } catch (e) {
496
+ r(e);
497
+ }
498
+ });
499
+ stop = () => {
500
+ if (this.#t?.signal.aborted === !1) {
501
+ let e = /* @__PURE__ */ Error("Actively stopped.");
502
+ e.name = "AbortError", this.#t.abort(e);
503
+ }
504
+ };
505
+ }, w = class {
506
+ option = {
507
+ debug: !1,
508
+ frameTrack: !1
509
+ };
510
+ converter = "MediaStreamTrackGenerator" in window ? "generator" : "canvas";
511
+ prFetch = new C();
512
+ getSegmentsFetch = new C();
513
+ prResolves = new _();
514
+ url = "";
515
+ start_resolve;
516
+ demuxerWorker;
517
+ decoderWorker;
518
+ audioPlayer;
519
+ renderWorker;
520
+ stream;
521
+ on = {
522
+ demuxer: {},
523
+ decoder: {}
524
+ };
525
+ cutRenders = /* @__PURE__ */ new Map();
526
+ trackGenerator;
527
+ constructor(e = {}) {
528
+ let { debug: t = !1 } = e;
529
+ this.option.debug = t;
530
+ }
531
+ start = async (e) => {
532
+ await this.stop(), this.url = e;
533
+ let t = h(e);
534
+ if (t === "unknown") throw Error("This address cannot be parsed.");
535
+ switch (this.init(t), t) {
536
+ case "flv":
537
+ this.flv.start();
538
+ break;
539
+ case "hls":
540
+ this.hls.start();
541
+ break;
542
+ }
543
+ };
544
+ stop = async () => {
545
+ try {
546
+ this.url = "", clearInterval(this.hls.getSegmentsTimer), this.prFetch.stop(), this.getSegmentsFetch.stop(), this.demuxerWorker?.destroy(), this.decoderWorker?.destroy(), this.renderWorker?.destroy(), this.cutRenders = /* @__PURE__ */ new Map(), g(this.stream), this.audioPlayer?.destroy();
547
+ } catch (e) {
548
+ console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: error", e);
549
+ }
550
+ };
551
+ getStream = () => this.stream;
552
+ setPause = (e) => {
553
+ this.renderWorker?.setPause({ pause: e });
554
+ };
555
+ setMute = (e) => this.audioPlayer?.prAudioStream?.setMute(e);
556
+ setOutputGain = (e) => {
557
+ this.audioPlayer?.prAudioStream?.setOutputGain(e);
558
+ };
559
+ setFrameTrack = (e) => {
560
+ this.option.frameTrack = e, this.decoderWorker?.setFrameTrack(e);
561
+ };
562
+ isReady = () => this.prResolves.add("isReady", () => this.stream?.active === !0);
563
+ cut = {
564
+ create: (e, t) => {
565
+ if (this.converter === "generator") {
566
+ let n = new MediaStreamTrackGenerator({ kind: "video" }), r = new MediaStream([n]);
567
+ return this.renderWorker?.addCut({
568
+ key: e,
569
+ writable: n.writable,
570
+ option: t
571
+ }), this.cutRenders.set(e, { stream: r }), r;
572
+ }
573
+ let n = document.createElement("canvas"), r = n.captureStream(), i = n.transferControlToOffscreen();
574
+ return this.renderWorker?.addCut({
575
+ key: e,
576
+ offscreen: i,
577
+ option: t
578
+ }), this.cutRenders.set(e, { stream: r }), r;
579
+ },
580
+ setCut: (e, t) => {
581
+ this.renderWorker?.setCut({
582
+ key: e,
583
+ cutOption: t
584
+ });
585
+ },
586
+ getStream: (e) => this.cutRenders.get(e)?.stream,
587
+ remove: (e) => {
588
+ this.renderWorker?.delCut(e), this.cutRenders.delete(e);
589
+ },
590
+ setPause: (e, t) => {
591
+ this.renderWorker?.setPause({
592
+ key: e,
593
+ pause: t
594
+ });
595
+ }
596
+ };
597
+ init = (e) => {
598
+ this.initRender(), this.initDecoder(e), this.initDemuxer(e), this.audioPlayer = new m(), this.audioPlayer.init();
599
+ };
600
+ initDemuxer = (e) => {
601
+ this.demuxerWorker = new r(), this.demuxerWorker.init(e), this.demuxerWorker.on.debug = (e) => {
602
+ this.option.debug && this.on.debug && this.on.debug(e);
603
+ }, this.demuxerWorker.on.info = (e) => {
604
+ this.option.debug && console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: info", e), this.on.demuxer.info && this.on.demuxer.info(e);
605
+ }, this.demuxerWorker.on.config = (e) => {
606
+ this.option.debug && console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: config", e), this.on.demuxer.config && this.on.demuxer.config(e);
607
+ let { kind: t } = e;
608
+ switch (t) {
609
+ case "audio":
610
+ {
611
+ let { codec: t, sampleRate: n, numberOfChannels: r } = e;
612
+ this.decoderWorker?.initAudio({
613
+ codec: t,
614
+ sampleRate: n,
615
+ numberOfChannels: r
616
+ });
617
+ }
618
+ break;
619
+ case "video":
620
+ {
621
+ let { codec: t, description: n } = e;
622
+ this.decoderWorker?.initVideo({
623
+ codec: t,
624
+ description: n
625
+ });
626
+ }
627
+ break;
628
+ }
629
+ }, this.demuxerWorker.on.chunk = (e) => {
630
+ if (this.on.demuxer.chunk && this.on.demuxer.chunk(e), !this.decoderWorker) return;
631
+ let { kind: t } = e;
632
+ switch (t) {
633
+ case "audio":
634
+ {
635
+ let { type: n, dts: r, data: i } = e, a = r * 1e3;
636
+ this.decoderWorker.push({
637
+ kind: t,
638
+ init: {
639
+ type: n,
640
+ timestamp: a,
641
+ data: i
642
+ }
643
+ });
644
+ }
645
+ break;
646
+ case "video":
647
+ {
648
+ let { type: n, dts: r, data: i, nalus: a = [] } = e, o = r * 1e3;
649
+ this.decoderWorker.push({
650
+ kind: t,
651
+ init: {
652
+ type: n,
653
+ timestamp: o,
654
+ data: i
655
+ },
656
+ nalus: a
657
+ });
658
+ }
659
+ break;
660
+ }
661
+ };
662
+ };
663
+ initDecoder = (e) => {
664
+ this.decoderWorker = new s(), this.decoderWorker.init(e);
665
+ let { frameTrack: t = !1 } = this.option;
666
+ this.decoderWorker.setFrameTrack(t), this.decoderWorker.on.audio.decode = (e) => {
667
+ this.audioPlayer?.push(e), this.on.decoder.audio && this.on.decoder.audio(e);
668
+ }, this.decoderWorker.on.audio.error = (e) => {
669
+ this.option.debug && console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->pr-player: audio.error ", e), this.on.error && this.on.error(e);
670
+ }, this.decoderWorker.on.video.decode = async (e) => {
671
+ this.start_resolve &&= (this.start_resolve(!0), void 0), this.renderWorker?.push(e), this.on.decoder.video && this.on.decoder.video(e);
672
+ }, this.decoderWorker.on.video.error = (e) => {
673
+ this.on.error && this.on.error(e);
674
+ }, this.decoderWorker.on.nalus = async (e) => {
675
+ for (let t of e) {
676
+ if (t.byteLength <= 4) continue;
677
+ let { header: e, data: n } = S(t), { nal_unit_type: r } = e;
678
+ r === 6 && this.on.decoder.sei && this.on.decoder.sei(n);
679
+ }
680
+ }, this.decoderWorker.on.analysis = (e) => {
681
+ this.on.decoder.analysis && this.on.decoder.analysis(e);
682
+ };
683
+ };
684
+ initRender = () => {
685
+ if (this.renderWorker = new d(), this.converter === "generator") {
686
+ let e = new MediaStreamTrackGenerator({ kind: "video" }), t = new MediaStream([e]);
687
+ this.renderWorker?.addCut({ writable: e.writable }), this.stream = t;
688
+ } else {
689
+ let e = document.createElement("canvas"), t = e.captureStream(), n = e.transferControlToOffscreen();
690
+ this.renderWorker?.addCut({ offscreen: n }), this.stream = t;
691
+ }
692
+ this.renderWorker?.setPause({ pause: !1 });
693
+ };
694
+ flv = { start: () => new Promise(async (e, t) => {
695
+ try {
696
+ this.start_resolve = e;
697
+ let n, r = 0;
698
+ for (;;) {
699
+ r += 1;
700
+ try {
701
+ n = await this.prFetch.request(this.url);
702
+ } catch (e) {
703
+ console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->Breathe: error", e);
704
+ }
705
+ if (n?.status === 200 || r === 3) break;
706
+ await new Promise((e) => setTimeout(() => e(!0), 500));
707
+ }
708
+ if (!n || n.status !== 200) return t("request is error.");
709
+ let i = n.body?.getReader();
710
+ if (!i) return t("reader is error.");
711
+ for (;;) {
712
+ let { done: e, value: t } = await i.read();
713
+ if (t && this.demuxerWorker?.push(t), e || this.url === "") break;
714
+ }
715
+ } catch (e) {
716
+ e.name !== "AbortError" && t(e);
717
+ }
718
+ }) };
719
+ hls = {
720
+ isLive: !1,
721
+ urls: [],
722
+ url: "",
723
+ getSegmentsTimer: 0,
724
+ parse: async (e) => {
725
+ let t = new TextDecoder("utf-8").decode(e).split("\n").map((e) => e.replace("\r", "")), n = this.url.substring(0, this.url.lastIndexOf("/") + 1), r = 4, i = 0, a = !1, o = [];
726
+ for (let e of t) e.startsWith("#EXTINF:") ? r = parseFloat(e.split(":")[1].split(",")[0]) : e.startsWith("#EXT-X-TARGETDURATION:") ? i = parseInt(e.split(":")[1]) : e.startsWith("#EXT-X-ENDLIST") ? a = !1 : e.startsWith("#EXT-X-MEDIA-SEQUENCE:") ? a = !0 : e.includes(".ts") && !e.startsWith("#") && o.push({
727
+ url: e.startsWith("http") ? e : n + e,
728
+ duration: r,
729
+ isLive: a
730
+ });
731
+ return {
732
+ baseUrl: n,
733
+ targetDuration: i,
734
+ isLive: a,
735
+ segments: o
736
+ };
737
+ },
738
+ getSegments: async () => {
739
+ try {
740
+ let e, t = 0;
741
+ for (;;) {
742
+ t += 1;
743
+ try {
744
+ e = await this.getSegmentsFetch.request(this.url);
745
+ } catch (e) {
746
+ console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m", "color:#0097ff;", "------->Breathe: error", e);
747
+ }
748
+ if (e?.status === 200 || t === 3) break;
749
+ await new Promise((e) => setTimeout(() => e(!0), 500));
750
+ }
751
+ if (!e || e.status !== 200) throw Error("request is error.");
752
+ let n = e.body?.getReader();
753
+ if (!n) throw Error("reader is error.");
754
+ for (;;) {
755
+ let { done: e, value: t } = await n.read();
756
+ if (t) {
757
+ let { segments: e = [], isLive: n = !1 } = await this.hls.parse(t);
758
+ this.hls.isLive = n, n === !1 && (this.option.frameTrack = !1);
759
+ let r = Array.from(e, (e) => e.url), i = r.findIndex((e) => e === this.hls.url);
760
+ i !== -1 && (r = r.slice(i + 1)), this.hls.urls = r;
761
+ }
762
+ if (e || this.url === "") break;
763
+ }
764
+ } catch (e) {
765
+ e.name !== "AbortError" && this.on.error && this.on.error(e);
766
+ }
767
+ },
768
+ start: () => new Promise(async (e, t) => {
769
+ try {
770
+ for (this.start_resolve = e, this.hls.url = "", this.hls.urls = [], 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));;) {
771
+ let e = this.hls.urls.shift();
772
+ if (e) {
773
+ this.hls.url = e;
774
+ let t = (await this.prFetch.request(e)).body?.getReader();
775
+ if (!t) throw Error("segment reader is error.");
776
+ for (;;) {
777
+ let { done: e, value: n } = await t.read();
778
+ if (n && this.demuxerWorker?.push(n), e || this.url === "") break;
779
+ }
780
+ } else await new Promise((e) => setTimeout(() => e(!0), 300));
781
+ }
782
+ } catch (e) {
783
+ e.name !== "AbortError" && t(e);
784
+ }
785
+ })
786
+ };
787
+ }, T = class {
788
+ pendingPayloads = [];
789
+ payload = new Uint8Array();
790
+ chunks = [];
791
+ push = (e) => {
792
+ this.pendingPayloads.push(e);
793
+ };
794
+ next = (e = 0) => {
795
+ this.payload = this.payload.slice(e);
796
+ let t = this.pendingPayloads.shift();
797
+ if (!t) return !1;
798
+ let n = new Uint8Array(this.payload.byteLength + t.byteLength);
799
+ return n.set(this.payload, 0), n.set(t, this.payload.byteLength), this.payload = n, new DataView(this.payload.buffer);
800
+ };
801
+ pushChunk = (e) => {
802
+ this.chunks.push(e), this.chunks.length > 100 && this.chunks.shift();
803
+ };
804
+ destroy = () => {
805
+ this.pendingPayloads = [], this.payload = new Uint8Array(), this.chunks = [];
806
+ };
807
+ }, E = (e) => {
808
+ let t = "unknown";
809
+ switch (e) {
810
+ case 1:
811
+ case 2:
812
+ case 27:
813
+ case 36:
814
+ t = "video";
815
+ break;
816
+ case 3:
817
+ case 4:
818
+ case 15:
819
+ t = "audio";
820
+ break;
821
+ case 6:
822
+ t = "subtitle";
823
+ break;
824
+ case 134:
825
+ t = "ad";
826
+ break;
827
+ }
828
+ return t;
829
+ }, D = class {
830
+ pat;
831
+ pmt;
832
+ audioConfig;
833
+ videoConfig;
834
+ payloadMap = /* @__PURE__ */ new Map();
835
+ on = {};
836
+ constructor() {}
837
+ parse = async (e) => {
838
+ let t = 0;
839
+ for (; !(t + 188 > e.byteLength);) {
840
+ if (e.getInt8(t) != 71) {
841
+ t++;
842
+ continue;
843
+ }
844
+ await this.parsePacket(e, t), t += 188;
845
+ }
846
+ return t;
847
+ };
848
+ parsePacket = async (e, t) => {
849
+ if (t + 188 > e.byteLength || e.getUint8(t) !== 71) throw Error("Invalid TS packet");
850
+ let n = t, r = this.parseHeader(e, n);
851
+ n += 4;
852
+ let { transport_error_indicator: i, pid: a, payload_unit_start_indicator: o, adaptation_field_control: s } = r;
853
+ if (i === 1 || a === void 0) return;
854
+ let c = 184;
855
+ if (s === 2 || s === 3) {
856
+ let t = e.getUint8(n);
857
+ n += 1, this.parseAdaptationField(e, n), n += t, c -= t;
858
+ }
859
+ if (s === 3 && --c, s === 1 || s === 3) {
860
+ let t = new Uint8Array(e.buffer.slice(n, n + c));
861
+ if (a === 0) return this.parsePAT(e, n);
862
+ {
863
+ let { programs: t = [] } = this.pat || {};
864
+ if (t.find((e) => e.pmt_pid === a)) return this.parsePMT(e, n);
865
+ }
866
+ let { streams: r = [] } = this.pmt || {}, i = r.find((e) => e.elementary_pid === a);
867
+ if (i) {
868
+ if (o === 1) {
869
+ let e = this.payloadMap.get(a);
870
+ if (e) {
871
+ switch (i.kind) {
872
+ case "audio":
873
+ {
874
+ let t = await this.parseAudio(e);
875
+ this.on.chunk && this.on.chunk(t);
876
+ }
877
+ break;
878
+ case "video":
879
+ {
880
+ let t = await this.parseVideo(e);
881
+ this.on.chunk && this.on.chunk(t), await new Promise((e) => setTimeout(() => e(!0), 0));
882
+ }
883
+ break;
884
+ }
885
+ this.payloadMap.delete(a);
886
+ }
887
+ }
888
+ {
889
+ this.payloadMap.has(a) || this.payloadMap.set(a, new Uint8Array());
890
+ let e = this.payloadMap.get(a), n = new Uint8Array(e.byteLength + t.byteLength);
891
+ n.set(e, 0), n.set(t, e.byteLength), this.payloadMap.set(a, n);
892
+ }
893
+ }
894
+ }
895
+ };
896
+ parseHeader = (e, t) => {
897
+ let n = t, r = e.getUint8(n), i = e.getUint8(n + 1), a = e.getUint8(n + 2), o = e.getUint8(n + 3), s = (i & 128) >> 7;
898
+ return s === 1 ? {
899
+ sync_byte: r,
900
+ transport_error_indicator: s
901
+ } : {
902
+ sync_byte: r,
903
+ transport_error_indicator: s,
904
+ payload_unit_start_indicator: (i & 64) >> 6,
905
+ transport_priority: (i & 32) >> 5,
906
+ pid: (i & 31) << 8 | a,
907
+ transport_scrambling_control: (o & 192) >> 6,
908
+ adaptation_field_control: o >> 4 & 3,
909
+ continuity_counter: o & 15
910
+ };
911
+ };
912
+ parsePAT = (e, t) => {
913
+ let n = t, r;
914
+ {
915
+ let t = e.getUint8(n);
916
+ n += 1;
917
+ let i = e.getUint8(n);
918
+ if (n += 1, i !== 0) throw Error("Invalid PAT table_id");
919
+ let a = e.getUint16(n) & 4095;
920
+ n += 2;
921
+ let o = e.getUint16(n);
922
+ n += 2;
923
+ let s = (e.getUint8(n) & 62) >> 1, c = e.getUint8(n) & 1;
924
+ n += 1;
925
+ let l = e.getUint8(n);
926
+ n += 1;
927
+ let u = e.getUint8(n);
928
+ n += 1, r = {
929
+ pointer_field: t,
930
+ table_id: i,
931
+ section_length: a,
932
+ transport_stream_id: o,
933
+ version_number: s,
934
+ current_next_indicator: c,
935
+ section_number: l,
936
+ last_section_number: u
937
+ };
938
+ }
939
+ let i = [];
940
+ {
941
+ let t = r.section_length - 5 - 4, a = n + t;
942
+ for (; n < a;) {
943
+ let t = e.getUint16(n), r = e.getUint16(n + 2) & 8191;
944
+ n += 4, t !== 0 && r >= 32 && r <= 8190 && i.push({
945
+ program_number: t,
946
+ pmt_pid: r
947
+ });
948
+ }
949
+ }
950
+ let a = e.getUint32(n);
951
+ this.pat = {
952
+ header: r,
953
+ programs: i,
954
+ crc32: a
955
+ }, this.on.debug && this.on.debug({ pat: this.pat });
956
+ };
957
+ parsePMT = (e, t) => {
958
+ let n = t, r;
959
+ {
960
+ let t = e.getUint8(n);
961
+ n += 1;
962
+ let i = e.getUint8(n);
963
+ if (n += 1, i !== 2) throw Error("Invalid PMT table_id");
964
+ let a = e.getUint16(n) & 4095;
965
+ n += 2;
966
+ let o = e.getUint16(n);
967
+ n += 2;
968
+ let s = (e.getUint8(n) & 62) >> 1, c = e.getUint8(n) & 1;
969
+ n += 1;
970
+ let l = e.getUint8(n);
971
+ n += 1;
972
+ let u = e.getUint8(n);
973
+ n += 1;
974
+ let d = e.getUint16(n) & 8191;
975
+ n += 2;
976
+ let f = e.getUint16(n) & 4095;
977
+ n += 2, r = {
978
+ pointer_field: t,
979
+ table_id: i,
980
+ section_length: a,
981
+ transport_stream_id: o,
982
+ version_number: s,
983
+ current_next_indicator: c,
984
+ section_number: l,
985
+ last_section_number: u,
986
+ pcr_pid: d,
987
+ program_info_length: f
988
+ };
989
+ }
990
+ let i = [];
991
+ {
992
+ let t = r.section_length - 9 - 4, a = n + t;
993
+ for (; n < a;) {
994
+ let t = e.getUint8(n), r = E(t), a = e.getUint16(n + 1) & 8191, o = e.getUint16(n + 3) & 4095;
995
+ if (n += 5, a < 32 || a > 8190) {
996
+ console.warn(`Invalid elementary_pid: 0x${a.toString(16)}`);
997
+ continue;
998
+ }
999
+ i.push({
1000
+ kind: r,
1001
+ stream_type: t,
1002
+ elementary_pid: a,
1003
+ es_info_length: o
1004
+ });
1005
+ }
1006
+ }
1007
+ let a = e.getUint32(n);
1008
+ this.pmt = {
1009
+ header: r,
1010
+ streams: i,
1011
+ crc32: a
1012
+ }, this.on.debug && this.on.debug({ pmt: this.pmt });
1013
+ };
1014
+ parseAdaptationField = (e, t) => {
1015
+ let n = t, r, i, a, o, s = e.getUint8(n), c = !!(s & 128), l = !!(s & 64), u = !!(s & 32), d = !!(s & 16), f = !!(s & 8), p = !!(s & 4), m = !!(s & 2), h = !!(s & 1);
1016
+ n += 1;
1017
+ let g = (e, t) => {
1018
+ let n = BigInt(0);
1019
+ n |= BigInt(e.getUint16(t)) << 25n, n |= BigInt(e.getUint16(t + 1)) << 17n, n |= BigInt(e.getUint16(t + 2)) << 9n, n |= BigInt(e.getUint16(t + 3)) << 1n, n |= BigInt(e.getUint16(t + 4) >> 7);
1020
+ let r = (e.getUint16(t + 4) & 1) << 8 | e.getUint16(t + 5);
1021
+ return n = n * 300n + BigInt(r), n;
1022
+ };
1023
+ if (d && (r = g(e, n), n += 6), f && (i = g(e, n), n += 6), p && (a = e.getInt8(n), n += 1), m) {
1024
+ let t = e.getUint8(n);
1025
+ n += 1, o = new Uint8Array(e.buffer, n, t), n += t;
1026
+ }
1027
+ return {
1028
+ discontinuity_indicator: c,
1029
+ random_access_indicator: l,
1030
+ elementary_stream_priority_indicator: u,
1031
+ pcr_flag: d,
1032
+ opcr_flag: f,
1033
+ splicing_point_flag: p,
1034
+ transport_private_data_flag: m,
1035
+ adaptation_field_extension_flag: h,
1036
+ pcr: r,
1037
+ opcr: i,
1038
+ splice_countdown: a,
1039
+ transport_private_data: o
1040
+ };
1041
+ };
1042
+ parseAudio = async (e) => {
1043
+ let t = new DataView(e.buffer), n = 0, r, i;
1044
+ {
1045
+ let e = t.getUint8(n) === 0 && t.getUint8(n + 1) === 0 && t.getUint8(n + 2) === 1;
1046
+ if (n += 3, !e) throw Error("invalid ts audio payload.");
1047
+ let i = t.getUint8(n);
1048
+ n += 1;
1049
+ let a = t.getUint8(n) << 8 | t.getUint8(n + 1);
1050
+ n += 2;
1051
+ let o, s, c, l, u;
1052
+ {
1053
+ let e = t.getUint8(n);
1054
+ n += 1, o = e >> 4 & 3, s = (e >> 3 & 1) == 1, c = (e >> 2 & 1) == 1, l = (e >> 1 & 1) == 1, u = (e & 1) == 1;
1055
+ }
1056
+ let d, f;
1057
+ {
1058
+ let e = t.getUint8(n);
1059
+ n += 1;
1060
+ let r = e >> 6, i = t.getUint8(n);
1061
+ n += 1, (r & 2) == 2 && (d = this.parsePtsDts(t, n)), f = (r & 1) == 1 ? this.parsePtsDts(t, n + 5) : d, n += i;
1062
+ }
1063
+ r = {
1064
+ stream_id: i,
1065
+ pes_packet_length: a,
1066
+ scrambling_control: o,
1067
+ priority: s,
1068
+ data_alignment: c,
1069
+ copyright: l,
1070
+ original_copy: u,
1071
+ pts: d,
1072
+ dts: f
1073
+ };
1074
+ }
1075
+ i = e.slice(n);
1076
+ {
1077
+ if (!this.audioConfig && t.getUint8(n) === 255) {
1078
+ let e = t.getUint8(n + 2), r = t.getUint8(n + 3), i, a;
1079
+ a = e >> 2 & 15, i = (e & 1) << 2 | r >> 6, this.audioConfig = {
1080
+ kind: "audio",
1081
+ codec: `mp4a.40.${i}`,
1082
+ sampleRate: [
1083
+ 96e3,
1084
+ 88200,
1085
+ 64e3,
1086
+ 48e3,
1087
+ 44100,
1088
+ 32e3,
1089
+ 24e3,
1090
+ 22050,
1091
+ 16e3,
1092
+ 12e3,
1093
+ 11025,
1094
+ 8e3,
1095
+ 7350
1096
+ ][a],
1097
+ numberOfChannels: i
1098
+ }, this.on.config && this.on.config(this.audioConfig);
1099
+ }
1100
+ let { dts: e = 0, pts: a = 0 } = r;
1101
+ return {
1102
+ kind: "audio",
1103
+ type: "key",
1104
+ dts: e,
1105
+ pts: a,
1106
+ cts: a - e,
1107
+ data: i.slice(7)
1108
+ };
1109
+ }
1110
+ };
1111
+ parseVideo = async (e) => {
1112
+ let t = new DataView(e.buffer), n = 0, r, i;
1113
+ {
1114
+ let e = t.getUint8(n) === 0 && t.getUint8(n + 1) === 0 && t.getUint8(n + 2) === 1;
1115
+ if (n += 3, !e) throw Error("invalid ts video payload.");
1116
+ let i = t.getUint8(n);
1117
+ n += 1;
1118
+ let a = t.getUint8(n) << 8 | t.getUint8(n + 1);
1119
+ n += 2;
1120
+ let o, s, c, l, u;
1121
+ {
1122
+ let e = t.getUint8(n);
1123
+ n += 1, o = e >> 4 & 3, s = (e >> 3 & 1) == 1, c = (e >> 2 & 1) == 1, l = (e >> 1 & 1) == 1, u = (e & 1) == 1;
1124
+ }
1125
+ let d, f;
1126
+ {
1127
+ let e = t.getUint8(n);
1128
+ n += 1;
1129
+ let r = e >> 6, i = t.getUint8(n);
1130
+ n += 1, (r & 2) == 2 && (d = this.parsePtsDts(t, n)), f = (r & 1) == 1 ? this.parsePtsDts(t, n + 5) : d, n += i;
1131
+ }
1132
+ r = {
1133
+ stream_id: i,
1134
+ pes_packet_length: a,
1135
+ scrambling_control: o,
1136
+ priority: s,
1137
+ data_alignment: c,
1138
+ copyright: l,
1139
+ original_copy: u,
1140
+ pts: d,
1141
+ dts: f
1142
+ };
1143
+ }
1144
+ i = e.slice(n);
1145
+ {
1146
+ let e = this.getNalus(i);
1147
+ if (!this.videoConfig) {
1148
+ let t, n;
1149
+ if (t = e.find((e) => e.type === 7)?.nalu.slice(4), n = e.find((e) => e.type === 8)?.nalu.slice(4), t && n) {
1150
+ let e = v(t, n), { codec: r } = y(e);
1151
+ this.videoConfig = {
1152
+ kind: "video",
1153
+ codec: r,
1154
+ description: e,
1155
+ sps: t,
1156
+ pps: n
1157
+ }, this.on.config && this.on.config(this.videoConfig);
1158
+ }
1159
+ }
1160
+ let t = [], n = "delta";
1161
+ for (let r of e) {
1162
+ let { type: e, nalu: i } = r;
1163
+ switch (e) {
1164
+ case 6:
1165
+ case 9:
1166
+ t.push(i);
1167
+ break;
1168
+ case 1:
1169
+ n = "delta", t.push(i);
1170
+ break;
1171
+ case 5:
1172
+ n = "key", t.push(i);
1173
+ break;
1174
+ }
1175
+ }
1176
+ let a = x(t), { dts: o = 0, pts: s = 0 } = r, c = s - o;
1177
+ return {
1178
+ kind: "video",
1179
+ type: n,
1180
+ dts: o,
1181
+ pts: s,
1182
+ cts: c,
1183
+ data: a,
1184
+ nalus: t
1185
+ };
1186
+ }
1187
+ };
1188
+ parsePtsDts(e, t) {
1189
+ let n = e.getUint8(t), r = e.getUint8(t + 1), i = e.getUint8(t + 2), a = e.getUint8(t + 3), o = e.getUint8(t + 4), s = (BigInt(n) & 14n) << 29n | (BigInt(r) & 255n) << 22n | (BigInt(i) & 254n) << 14n | (BigInt(a) & 255n) << 7n | (BigInt(o) & 254n) >> 1n;
1190
+ return Number(s) / 90;
1191
+ }
1192
+ getNalus = (e) => {
1193
+ let t = [], n = 0;
1194
+ for (; !(n + 4 > e.byteLength);) {
1195
+ if (e[n] !== 0 || e[n + 1] !== 0 || e[n + 2] !== 1) {
1196
+ n += 1;
1197
+ continue;
1198
+ }
1199
+ n += 3;
1200
+ let r = n, i = e[n] & 31;
1201
+ for (n += 1; !(n + 1 > e.byteLength);) {
1202
+ if (e[n] !== 0 || e[n + 1] !== 0 || e[n + 2] !== 1) {
1203
+ n += 1;
1204
+ continue;
1205
+ }
1206
+ break;
1207
+ }
1208
+ let a = n - r;
1209
+ if (e[n - 1] === 0 && --a, a !== 0) {
1210
+ let n = b(e.slice(r, r + a));
1211
+ t.push({
1212
+ type: i,
1213
+ nalu: n
1214
+ });
1215
+ }
1216
+ }
1217
+ return t;
1218
+ };
1219
+ }, O = (e, t) => e.getUint8(t) << 16 | e.getUint8(t + 1) << 8 | e.getUint8(t + 2), k = class {
1220
+ audioConfig;
1221
+ videoConfig;
1222
+ header;
1223
+ textDecoder = new TextDecoder("utf-8");
1224
+ on = {};
1225
+ constructor() {}
1226
+ parse = async (e) => {
1227
+ let t = 0;
1228
+ for (this.header || (this.parseHeader(e, t), t += 9); this.isSurplusTag(e, t) !== !1;) {
1229
+ let { tagType: n, dataSize: r, timestamp: i } = this.parseTagHeader(e, t + 4);
1230
+ if (n) {
1231
+ let a = this.parseTagBody(n, e, t + 4 + 11, r);
1232
+ switch (n) {
1233
+ case "script":
1234
+ this.on.info && this.on.info(a);
1235
+ break;
1236
+ case "audio":
1237
+ {
1238
+ let { accPacketType: e } = a;
1239
+ if (e === 0) {
1240
+ let { codec: e, sampleRate: t, channelConfiguration: n } = a;
1241
+ this.audioConfig = {
1242
+ kind: "audio",
1243
+ codec: e,
1244
+ sampleRate: t,
1245
+ numberOfChannels: n
1246
+ }, this.on.config && this.on.config(this.audioConfig);
1247
+ } else {
1248
+ let { cts: e, data: t } = a, n = e === void 0 ? void 0 : e + i;
1249
+ this.on.chunk && this.on.chunk({
1250
+ kind: "audio",
1251
+ type: "key",
1252
+ dts: i,
1253
+ pts: n,
1254
+ cts: e,
1255
+ data: t
1256
+ });
1257
+ }
1258
+ }
1259
+ break;
1260
+ case "video":
1261
+ {
1262
+ let { avcPacketType: e } = a;
1263
+ if (e === 0) {
1264
+ let { codec: e, sps: t, pps: n, data: r } = a;
1265
+ this.videoConfig = {
1266
+ kind: "video",
1267
+ codec: e,
1268
+ description: r,
1269
+ sps: t,
1270
+ pps: n
1271
+ }, this.on.config && this.on.config(this.videoConfig);
1272
+ } else {
1273
+ let { frameType: e, cts: t, data: n, nalus: r } = a, o = e === 1 ? "key" : "delta", s = t === void 0 ? void 0 : t + i;
1274
+ this.on.chunk && this.on.chunk({
1275
+ kind: "video",
1276
+ type: o,
1277
+ dts: i,
1278
+ pts: s,
1279
+ cts: t,
1280
+ data: n,
1281
+ nalus: r
1282
+ });
1283
+ }
1284
+ }
1285
+ break;
1286
+ }
1287
+ t = t + 4 + 11 + r;
1288
+ }
1289
+ await new Promise((e) => setTimeout(() => e(!0), 8));
1290
+ }
1291
+ return t;
1292
+ };
1293
+ parseHeader = (e, t) => {
1294
+ let n, r, i, a;
1295
+ n = e.getUint8(t) << 16 | e.getUint8(t + 1) << 8 | e.getUint8(t + 2), r = e.getUint8(3);
1296
+ {
1297
+ let [, , t, , n] = e.getUint8(0).toString(2).padStart(5, "0").split("");
1298
+ i = {
1299
+ audio: n === "1",
1300
+ video: t === "1"
1301
+ };
1302
+ }
1303
+ a = e.getUint32(5), this.header = {
1304
+ signature: n,
1305
+ version: r,
1306
+ flags: i,
1307
+ dataOffset: a
1308
+ };
1309
+ };
1310
+ isSurplusTag = (e, t) => {
1311
+ let n = !0, r = e.byteLength;
1312
+ if (t + 4 > r) n = !1;
1313
+ else if (t + 4 + 11 > r) n = !1;
1314
+ else {
1315
+ let i = O(e, t + 4 + 1);
1316
+ t + 4 + 11 + i > r && (n = !1);
1317
+ }
1318
+ return n;
1319
+ };
1320
+ parseTagHeader = (e, t) => {
1321
+ let n, r, i, a, o;
1322
+ {
1323
+ let r = e.getUint8(t), i;
1324
+ switch (r) {
1325
+ case 18:
1326
+ i = "script";
1327
+ break;
1328
+ case 8:
1329
+ i = "audio";
1330
+ break;
1331
+ case 9:
1332
+ i = "video";
1333
+ break;
1334
+ }
1335
+ n = i;
1336
+ }
1337
+ return r = O(e, t + 1), i = O(e, t + 4), a = e.getUint8(t + 7), o = O(e, t + 8), {
1338
+ tagType: n,
1339
+ dataSize: r,
1340
+ timestamp: i,
1341
+ timestampExtended: a,
1342
+ streamID: o
1343
+ };
1344
+ };
1345
+ parseTagBody = (e, t, n, r) => {
1346
+ let i;
1347
+ switch (e) {
1348
+ case "script":
1349
+ i = this.parseMetaData(t, n);
1350
+ break;
1351
+ case "audio":
1352
+ i = this.parseAudio(t, n, r);
1353
+ break;
1354
+ case "video":
1355
+ i = this.parseVideo(t, n, r);
1356
+ break;
1357
+ }
1358
+ return i;
1359
+ };
1360
+ parseMetaData = (e, t) => {
1361
+ let n = t;
1362
+ if (e.getUint8(n) !== 2) throw Error("Invalid AMF type for onMetaData (expected 0x02)");
1363
+ n += 1;
1364
+ let r = e.getUint16(n, !1);
1365
+ n += 2;
1366
+ {
1367
+ let t = new Int8Array(e.buffer.slice(n, n + r));
1368
+ if ((this.textDecoder?.decode(t) || "") !== "onMetaData") throw Error("Expected 'onMetaData' string");
1369
+ n += r;
1370
+ }
1371
+ let i = this.getAmfType(e, n);
1372
+ return n += 1, this.getAMFValue(e, n, i).value;
1373
+ };
1374
+ parseAudio = (e, t, n) => {
1375
+ let r = t, i = e.getUint8(r), a = i >> 4 & 15, o = i >> 2 & 3, s = i >> 1 & 1, c = i & 1;
1376
+ r += 1;
1377
+ let l = e.getUint8(r);
1378
+ r += 1;
1379
+ let u = n, d = new Uint8Array(e.buffer.slice(r, r + u));
1380
+ if (a === 10 && l === 0) {
1381
+ let t = e.getUint8(r), n = e.getUint8(r + 1), i = t >> 3 & 31, u = (t & 7) << 1 | n >> 7;
1382
+ return {
1383
+ soundFormat: a,
1384
+ soundRate: o,
1385
+ soundSize: s,
1386
+ soundType: c,
1387
+ accPacketType: l,
1388
+ data: d,
1389
+ samplingFrequencyIndex: u,
1390
+ channelConfiguration: n >> 3 & 15,
1391
+ codec: `mp4a.40.${i}`,
1392
+ sampleRate: [
1393
+ 96e3,
1394
+ 88200,
1395
+ 64e3,
1396
+ 48e3,
1397
+ 44100,
1398
+ 32e3,
1399
+ 24e3,
1400
+ 22050,
1401
+ 16e3,
1402
+ 12e3,
1403
+ 11025,
1404
+ 8e3,
1405
+ 7350
1406
+ ][u]
1407
+ };
1408
+ }
1409
+ return {
1410
+ soundFormat: a,
1411
+ soundRate: o,
1412
+ soundSize: s,
1413
+ soundType: c,
1414
+ accPacketType: l,
1415
+ data: d
1416
+ };
1417
+ };
1418
+ parseVideo = (e, t, n) => {
1419
+ let r = t, i = e.getUint8(r), a = i >> 4 & 15, o = i & 15;
1420
+ r += 1;
1421
+ let s = e.getUint8(r);
1422
+ r += 1;
1423
+ let c = O(e, r);
1424
+ r += 3;
1425
+ let l = n - 5, u = new Uint8Array(e.buffer.slice(r, r + l));
1426
+ switch (o) {
1427
+ case 7:
1428
+ if (s === 0) return {
1429
+ frameType: a,
1430
+ codecID: o,
1431
+ avcPacketType: s,
1432
+ cts: c,
1433
+ data: u,
1434
+ ...y(u)
1435
+ };
1436
+ if (s === 1) {
1437
+ let t = [], i = r + n - 5;
1438
+ for (; !(r + 4 > i);) {
1439
+ let n = e.getUint32(r, !1), i = new Uint8Array(e.buffer.slice(r, r + 4 + n));
1440
+ r += 4 + n, t.push(i);
1441
+ }
1442
+ return {
1443
+ frameType: a,
1444
+ codecID: o,
1445
+ avcPacketType: s,
1446
+ cts: c,
1447
+ data: u,
1448
+ nalus: t
1449
+ };
1450
+ }
1451
+ break;
1452
+ default: throw Error("Unsupported codecID");
1453
+ }
1454
+ return {
1455
+ frameType: a,
1456
+ codecID: o,
1457
+ avcPacketType: s,
1458
+ cts: c,
1459
+ data: u
1460
+ };
1461
+ };
1462
+ getAmfType = (e, t) => e.getUint8(t);
1463
+ getAMFName = (e, t, n) => {
1464
+ let r = new Uint8Array(e.buffer.slice(t, t + n));
1465
+ return this.textDecoder?.decode(r) || "";
1466
+ };
1467
+ getAMFValue = (e, t, n) => {
1468
+ let r = t, i, a = 0;
1469
+ switch (n) {
1470
+ case 0:
1471
+ i = e.getFloat64(r, !1), a = 8;
1472
+ break;
1473
+ case 1:
1474
+ i = !!e.getUint8(r), a = 1;
1475
+ break;
1476
+ case 2:
1477
+ {
1478
+ i = "";
1479
+ let t = e.getUint16(r, !1);
1480
+ r += 2;
1481
+ let n = new Int8Array(e.buffer, r, t).filter((e) => e !== 0);
1482
+ i = (this.textDecoder?.decode(n) || "").trim(), a = 2 + t;
1483
+ }
1484
+ break;
1485
+ case 3:
1486
+ for (i = {}; r < e.byteLength;) {
1487
+ let t = e.getUint16(r, !1);
1488
+ if (t === 0) break;
1489
+ r += 2;
1490
+ let n = this.getAMFName(e, r, t);
1491
+ r += t;
1492
+ let o = this.getAmfType(e, r);
1493
+ if (o === 6) break;
1494
+ r += 1;
1495
+ let s = this.getAMFValue(e, r, o);
1496
+ r += s.length, i[n] = s.value, a = 2 + t + 1 + s.length;
1497
+ }
1498
+ break;
1499
+ case 8:
1500
+ {
1501
+ i = {};
1502
+ let t = e.getUint32(r, !1);
1503
+ r += 4;
1504
+ for (let n = 0; n < t; n++) {
1505
+ let t = e.getUint16(r, !1);
1506
+ r += 2;
1507
+ let n = this.getAMFName(e, r, t);
1508
+ r += t;
1509
+ let o = this.getAmfType(e, r);
1510
+ r += 1;
1511
+ let s = this.getAMFValue(e, r, o);
1512
+ r += s.length, i[n] = s.value, a = 2 + t + 1 + s.length;
1513
+ }
1514
+ }
1515
+ break;
1516
+ case 10:
1517
+ {
1518
+ i = [];
1519
+ let t = e.getUint32(r, !1);
1520
+ r += 4;
1521
+ for (let n = 0; n < t; n++) {
1522
+ let t = this.getAmfType(e, r);
1523
+ r += 1;
1524
+ let n = this.getAMFValue(e, r, t);
1525
+ r += n.length, i.push(n.value), a = 1 + n.length;
1526
+ }
1527
+ }
1528
+ break;
1529
+ }
1530
+ return {
1531
+ amfType: n,
1532
+ length: a,
1533
+ value: i
1534
+ };
1535
+ };
1536
+ }, A = class {
1537
+ pattern;
1538
+ cacher = new T();
1539
+ isParseing = !1;
1540
+ offset = 0;
1541
+ parser;
1542
+ on = {};
1543
+ constructor() {}
1544
+ init = (e) => {
1545
+ switch (this.destroy(), this.pattern = e, this.pattern) {
1546
+ case "flv":
1547
+ this.parser = new k();
1548
+ break;
1549
+ case "hls":
1550
+ this.parser = new D();
1551
+ break;
1552
+ default: throw Error("is error pattern.");
1553
+ }
1554
+ this.parser.on.debug = (e) => this.on.debug && this.on.debug(e), this.parser.on.info = (e) => this.on.info && this.on.info(e), this.parser.on.config = (e) => this.on.config && this.on.config(e), this.parser.on.chunk = (e) => {
1555
+ this.cacher.pushChunk(e), this.on.chunk && this.on.chunk(e);
1556
+ };
1557
+ };
1558
+ push = (e) => {
1559
+ this.cacher.push(e), this.isParseing === !1 && this.parse();
1560
+ };
1561
+ destroy = () => {
1562
+ this.cacher.destroy(), this.isParseing = !1, this.offset = 0;
1563
+ };
1564
+ parse = async () => {
1565
+ try {
1566
+ if (this.isParseing = !0, !this.pattern) throw Error("You need to set the pattern.");
1567
+ if (!this.parser) throw Error("You need to init parser.");
1568
+ for (;;) {
1569
+ let e = this.cacher.next(this.offset);
1570
+ if (this.offset = 0, !e) break;
1571
+ this.offset = await this.parser.parse(e);
1572
+ }
1573
+ this.isParseing = !1;
1574
+ } catch {
1575
+ this.destroy();
1576
+ }
1577
+ };
1578
+ }, j = class {
1579
+ pattern = "flv";
1580
+ audioDecoderConfig;
1581
+ audioDecoder;
1582
+ videoDecoderConfig;
1583
+ videoDecoder;
1584
+ hasKeyFrame = !1;
1585
+ baseTime = 0;
1586
+ pendingChunks = [];
1587
+ currentChunk;
1588
+ isProcessing = !1;
1589
+ decodeTimer = 0;
1590
+ frameTrack = !1;
1591
+ isFrameTrack = !1;
1592
+ fameTrackOption = {
1593
+ flv: [30, 50],
1594
+ hls: [200, 300],
1595
+ dash: [50, 100],
1596
+ rtmp: [50, 100]
1597
+ };
1598
+ decodingSpeedRatio = 1;
1599
+ maxDecodingSpeedRatio = 2;
1600
+ decodingSpeed = 16;
1601
+ fps = 0;
1602
+ firstVideoChunkTimestamp;
1603
+ secondVideoChunkTimestamp;
1604
+ frameStartTime;
1605
+ lastRenderTime;
1606
+ nextRenderTime;
1607
+ on = {
1608
+ audio: {},
1609
+ video: {}
1610
+ };
1611
+ constructor() {}
1612
+ init = (e) => {
1613
+ this.destroy(), this.pattern = e, this.baseTime = (/* @__PURE__ */ new Date()).getTime() - performance.now(), this.initDecodeInterval();
1614
+ };
1615
+ initAudio = (e) => {
1616
+ this.audio.destroy(), this.audioDecoderConfig = { ...e }, this.audioDecoder = new AudioDecoder({
1617
+ output: (e) => {
1618
+ let t = this.decodingSpeedRatio;
1619
+ this.on.audio.decode && this.on.audio.decode({
1620
+ audioData: e,
1621
+ playbackRate: t
1622
+ });
1623
+ },
1624
+ error: (e) => {
1625
+ this.on.audio.error && this.on.audio.error(e);
1626
+ }
1627
+ }), this.audioDecoder.configure(this.audioDecoderConfig);
1628
+ };
1629
+ initVideo = (e) => {
1630
+ this.video.destroy(), this.videoDecoderConfig = { ...e }, this.videoDecoder = new VideoDecoder({
1631
+ output: async (e) => {
1632
+ this.frameStartTime ||= e.timestamp;
1633
+ try {
1634
+ let t = e.timestamp - this.frameStartTime + this.baseTime * 1e3, n = await createImageBitmap(e);
1635
+ if (e.close(), !n.width || !n.height) return n.close();
1636
+ this.on.video.decode && this.on.video.decode({
1637
+ timestamp: t,
1638
+ bitmap: n
1639
+ }), this.currentChunk && this.currentChunk.kind === "video" && this.currentChunk.nalus && this.on.nalus && this.on.nalus(this.currentChunk.nalus);
1640
+ } catch {
1641
+ e.close();
1642
+ }
1643
+ },
1644
+ error: (e) => {
1645
+ this.on.video.error && this.on.video.error(e);
1646
+ }
1647
+ }), this.videoDecoder.configure(this.videoDecoderConfig);
1648
+ };
1649
+ setFrameTrack = (e) => {
1650
+ this.frameTrack = e, this.frameTrack === !1 && (this.decodingSpeedRatio = 1);
1651
+ };
1652
+ push = (e) => {
1653
+ this.pendingChunks.push(e);
1654
+ };
1655
+ destroy = () => {
1656
+ this.audio.destroy(), this.video.destroy(), this.pendingChunks = [], this.firstVideoChunkTimestamp = void 0, this.secondVideoChunkTimestamp = void 0, this.frameStartTime = void 0, this.lastRenderTime = void 0, this.nextRenderTime = void 0, clearInterval(this.decodeTimer);
1657
+ };
1658
+ initDecodeInterval = () => {
1659
+ let e = this.decodingSpeed / this.decodingSpeedRatio, t = this.baseTime + performance.now();
1660
+ if (this.lastRenderTime ||= t, this.fps = Math.round(1e3 / (t - this.lastRenderTime)), this.lastRenderTime = t, this.nextRenderTime) {
1661
+ let t = this.lastRenderTime - this.nextRenderTime;
1662
+ e -= t;
1663
+ }
1664
+ this.nextRenderTime = this.lastRenderTime + e, this.decodeTimer = setTimeout(() => {
1665
+ this.decode(), this.initDecodeInterval();
1666
+ }, e);
1667
+ };
1668
+ decode = () => {
1669
+ if (this.isProcessing !== !0) {
1670
+ for (this.isProcessing = !0; this.currentChunk = this.pendingChunks.shift(), this.currentChunk;) {
1671
+ let e = this.pendingChunks.length;
1672
+ if (this.frameTrack) {
1673
+ let [t, n] = this.fameTrackOption[this.pattern];
1674
+ if (e <= t && (this.isFrameTrack = !1), e >= n && (this.isFrameTrack = !0), this.isFrameTrack) {
1675
+ let n = Math.min(1 + (e - t) / 100, this.maxDecodingSpeedRatio);
1676
+ this.decodingSpeedRatio = Number(n.toFixed(1));
1677
+ } else this.decodingSpeedRatio = 1;
1678
+ }
1679
+ if (this.on.analysis) {
1680
+ let { decodingSpeed: t, decodingSpeedRatio: n, fps: r } = this;
1681
+ this.on.analysis({
1682
+ decodingSpeed: t,
1683
+ decodingSpeedRatio: n,
1684
+ fps: r,
1685
+ cacheLength: e
1686
+ });
1687
+ }
1688
+ let { kind: t, init: n } = this.currentChunk;
1689
+ switch (t) {
1690
+ case "audio":
1691
+ this.decodeAudio(n);
1692
+ break;
1693
+ case "video":
1694
+ this.decodeVideo(n);
1695
+ break;
1696
+ }
1697
+ if (t === "video") break;
1698
+ }
1699
+ this.isProcessing = !1;
1700
+ }
1701
+ };
1702
+ decodeAudio = (e) => {
1703
+ if (!this.audioDecoder) return;
1704
+ let t = new EncodedAudioChunk(e);
1705
+ this.audioDecoder.decode(t);
1706
+ };
1707
+ decodeVideo = (e) => {
1708
+ if (this.videoDecoder && (e.type === "key" && (this.hasKeyFrame = !0), this.firstVideoChunkTimestamp ? this.secondVideoChunkTimestamp || (this.secondVideoChunkTimestamp = e.timestamp, this.decodingSpeed = (this.secondVideoChunkTimestamp - this.firstVideoChunkTimestamp) / 1e3) : this.firstVideoChunkTimestamp = e.timestamp, this.hasKeyFrame)) {
1709
+ let t = new EncodedVideoChunk(e);
1710
+ this.videoDecoder.decode(t);
1711
+ }
1712
+ };
1713
+ audio = {
1714
+ flush: () => {
1715
+ this.audioDecoder?.flush();
1716
+ },
1717
+ destroy: () => {
1718
+ this.audioDecoderConfig = void 0, this.audioDecoder?.close(), this.audioDecoder = void 0;
1719
+ }
1720
+ };
1721
+ video = {
1722
+ flush: () => {
1723
+ this.videoDecoder?.flush();
1724
+ },
1725
+ destroy: () => {
1726
+ this.videoDecoderConfig = void 0, this.videoDecoder?.close(), this.videoDecoder = void 0, this.hasKeyFrame = !1;
1727
+ }
1728
+ };
1729
+ }, M = class {
1730
+ renderMap = /* @__PURE__ */ new Map();
1731
+ constructor() {}
1732
+ push = async (e) => {
1733
+ let { timestamp: t } = e, { bitmap: n } = e;
1734
+ try {
1735
+ let e = [...this.renderMap.keys()];
1736
+ for (let r of e) {
1737
+ let e = this.renderMap.get(r);
1738
+ if (!e) continue;
1739
+ let { pause: i = !1, writer: a, offscreen: o, option: s } = e;
1740
+ if (i === !0) continue;
1741
+ let c = async (e) => {
1742
+ if (a) {
1743
+ let n = new VideoFrame(e, { timestamp: t });
1744
+ try {
1745
+ await a.write(n);
1746
+ } catch {}
1747
+ n.close();
1748
+ } else o && (o.width = e.width, o.height = e.height, o?.getContext("2d")?.drawImage(e, 0, 0));
1749
+ };
1750
+ if (r === "default") await c(n);
1751
+ else if (s) {
1752
+ let { sx: e = 0, sy: t = 0, sw: r = n.width, sh: i = n.height } = s;
1753
+ await c(await createImageBitmap(n, e, t, r, i));
1754
+ }
1755
+ }
1756
+ } catch {}
1757
+ n.close();
1758
+ };
1759
+ addCut = (e) => {
1760
+ let { key: t, writable: n, offscreen: r, option: i } = {
1761
+ key: "default",
1762
+ ...e
1763
+ };
1764
+ if (n) {
1765
+ let e = n.getWriter();
1766
+ this.renderMap.set(t, {
1767
+ writer: e,
1768
+ option: i,
1769
+ pause: !1
1770
+ });
1771
+ } else this.renderMap.set(t, {
1772
+ offscreen: r,
1773
+ option: i,
1774
+ pause: !1
1775
+ });
1776
+ };
1777
+ delCut = (e) => {
1778
+ this.renderMap.delete(e);
1779
+ };
1780
+ setCut = (e) => {
1781
+ let { key: t, cutOption: n } = {
1782
+ key: "default",
1783
+ ...e
1784
+ }, r = this.renderMap.get(t);
1785
+ r && this.renderMap.set(t, {
1786
+ ...r,
1787
+ option: n
1788
+ });
1789
+ };
1790
+ setPause = (e) => {
1791
+ let { key: t, pause: n } = {
1792
+ key: "default",
1793
+ ...e
1794
+ }, r = this.renderMap.get(t);
1795
+ r && this.renderMap.set(t, {
1796
+ ...r,
1797
+ pause: n
1798
+ });
1799
+ };
1800
+ destroy = () => {
1801
+ this.renderMap = /* @__PURE__ */ new Map();
1802
+ };
1710
1803
  };
1804
+ //#endregion
1805
+ export { j as Decoder, s as DecoderWorker, A as Demuxer, r as DemuxerWorker, w as PrPlayer, M as Render, d as RenderWorker };