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