pr-player 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PrPlayer.d.ts +4 -1
- package/dist/audioPlayer/audioPlayer.d.ts +4 -1
- package/dist/decoder/type.d.ts +4 -1
- package/dist/index.js +134 -132
- package/dist/index.umd.cjs +4 -4
- package/package.json +2 -2
package/dist/PrPlayer.d.ts
CHANGED
|
@@ -7,7 +7,10 @@ interface On {
|
|
|
7
7
|
sei?: (_payload: Uint8Array) => void;
|
|
8
8
|
};
|
|
9
9
|
decoder: {
|
|
10
|
-
audio?: (
|
|
10
|
+
audio?: (_audio: {
|
|
11
|
+
audioData: AudioData;
|
|
12
|
+
playbackRate?: number;
|
|
13
|
+
}) => void;
|
|
11
14
|
video?: (_frame: {
|
|
12
15
|
timestamp: number;
|
|
13
16
|
bitmap: ImageBitmap;
|
|
@@ -8,7 +8,10 @@ export declare class AudioPlayer {
|
|
|
8
8
|
pendingSources: AudioBufferSourceNode[];
|
|
9
9
|
constructor();
|
|
10
10
|
init: (audioContext?: AudioContext) => void;
|
|
11
|
-
push(
|
|
11
|
+
push(audio: {
|
|
12
|
+
audioData: AudioData;
|
|
13
|
+
playbackRate?: number;
|
|
14
|
+
}): Promise<void>;
|
|
12
15
|
getStream: () => MediaStream | undefined;
|
|
13
16
|
destroy(): void;
|
|
14
17
|
}
|
package/dist/decoder/type.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -46,7 +46,7 @@ class N {
|
|
|
46
46
|
this.worker.postMessage({ action: "destroy", data: {} }), this.worker.terminate();
|
|
47
47
|
};
|
|
48
48
|
}
|
|
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)}}})();
|
|
49
|
+
const S = `(function(){"use strict";class n{audioDecoderConfig;audioDecoder;videoDecoderConfig;videoDecoder;hasKeyFrame=!1;baseTime=0;pendingChunks=[];isProcessing=!1;decodeTimer=0;frameTrack=!1;minFrameTrackCacheNum=20;decodingSpeed=40;decodingSpeedRatio=1;maxDecodingSpeedRatio=2;nextRenderTime;on={audio:{},video:{}};constructor(){this.baseTime=new Date().getTime()-performance.now(),this.initDecodeInterval()}init=e=>{const{decodingSpeed:i,frameTrack:d,minFrameTrackCacheNum:o}=e;i!==void 0&&(this.decodingSpeed=i),d!==void 0&&(this.frameTrack=d),o!==void 0&&(this.minFrameTrackCacheNum=o)};setFrameTrack=e=>{this.frameTrack=e,this.frameTrack===!1&&(this.decodingSpeedRatio=1)};initDecodeInterval=()=>{let e=this.decodingSpeed/this.decodingSpeedRatio;const i=this.baseTime+performance.now();if(this.nextRenderTime){const d=i-this.nextRenderTime;e-=d}this.nextRenderTime=i+e,this.decodeTimer=setTimeout(()=>{this.decode(),this.initDecodeInterval()},e)};decode=()=>{if(this.isProcessing!==!0){for(this.isProcessing=!0;;){const e=this.pendingChunks.shift();if(this.frameTrack){const o=this.pendingChunks.length;if(o>=this.minFrameTrackCacheNum){const r=Math.min(1+(o-this.minFrameTrackCacheNum)/100,this.maxDecodingSpeedRatio);this.decodingSpeedRatio=Number(r.toFixed(1))}else this.decodingSpeedRatio=1}if(!e)break;const{type:i,init:d}=e;switch(i){case"audio":this.decodeAudio(d);break;case"video":this.decodeVideo(d);break}if(i==="video")break}this.isProcessing=!1}};decodeAudio=e=>{if(!this.audioDecoder)return;const i=new EncodedAudioChunk(e);this.audioDecoder.decode(i)};decodeVideo=e=>{if(this.videoDecoder&&(e.type==="key"&&(this.hasKeyFrame=!0),this.hasKeyFrame)){const i=new EncodedVideoChunk(e);this.videoDecoder.decode(i)}};destroy=()=>{this.audio.destroy(),this.video.destroy(),clearInterval(this.decodeTimer)};audio={init:e=>{this.audio.destroy(),this.audioDecoderConfig={...e},this.audioDecoder=new AudioDecoder({output:i=>{const d=this.decodingSpeedRatio;this.on.audio.decode&&this.on.audio.decode({audioData:i,playbackRate:d})},error:i=>{this.on.audio.error&&this.on.audio.error(i)}}),this.audioDecoder.configure(this.audioDecoderConfig)},push:e=>{this.pendingChunks.push({type:"audio",init:e})},flush:()=>{this.audioDecoder?.flush()},destroy:()=>{this.audioDecoderConfig=void 0,this.audioDecoder?.close(),this.audioDecoder=void 0}};video={init:e=>{this.video.destroy(),this.videoDecoderConfig={...e},this.videoDecoder=new VideoDecoder({output:async i=>{const d=i.timestamp+this.baseTime*1e3,o=await createImageBitmap(i);i.close(),o.width>0&&o.height>0?this.on.video.decode&&this.on.video.decode({timestamp:d,bitmap:o}):o.close()},error:i=>{this.on.video.error&&this.on.video.error(i)}}),this.videoDecoder.configure(this.videoDecoderConfig)},push:e=>{this.pendingChunks.push({type:"video",init:e})},flush:()=>{this.videoDecoder?.flush()},destroy:()=>{this.videoDecoderConfig=void 0,this.videoDecoder?.close(),this.videoDecoder=void 0,this.hasKeyFrame=!1}}}const s=new n;s.on.audio.decode=t=>postMessage({type:"audio",action:"onDecode",data:t}),s.on.audio.error=t=>postMessage({type:"audio",action:"onError",data:t}),s.on.video.decode=t=>postMessage({type:"video",action:"onDecode",data:t}),s.on.video.error=t=>postMessage({type:"video",action:"onError",data:t}),onmessage=t=>{const{type:e,action:i,data:d}=t.data;if(e){const o=s[e][i];o&&o(d)}else{const o=s[i];o&&o(d)}}})();
|
|
50
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;
|
|
@@ -139,12 +139,12 @@ class O {
|
|
|
139
139
|
const d = this.mixAudioMap.get(i);
|
|
140
140
|
d && d.stop();
|
|
141
141
|
}
|
|
142
|
-
const
|
|
143
|
-
this.mixAudioMap.set(i, o), o.buffer = e, o.connect(
|
|
144
|
-
o.disconnect(
|
|
142
|
+
const a = i === "bgs" ? this.bgsGainNode : this.bgmGainNode, o = this.audioContext.createBufferSource();
|
|
143
|
+
this.mixAudioMap.set(i, o), o.buffer = e, o.connect(a), o.onended = () => {
|
|
144
|
+
o.disconnect(a), this.mixAudioMap.delete(i), n(!0);
|
|
145
145
|
}, o.start(0);
|
|
146
|
-
} catch (
|
|
147
|
-
r(
|
|
146
|
+
} catch (a) {
|
|
147
|
+
r(a);
|
|
148
148
|
}
|
|
149
149
|
})), y(this, "mixAudioStop", (e) => {
|
|
150
150
|
const i = this.mixAudioMap.get(e);
|
|
@@ -154,8 +154,8 @@ class O {
|
|
|
154
154
|
i ? n.connect(this.destinationNode) : n.disconnect(this.destinationNode);
|
|
155
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;
|
|
156
156
|
{
|
|
157
|
-
const { sourceNode: e, inputGainNode: i, enhanceGainNode: n, bgsGainNode: r, bgmGainNode:
|
|
158
|
-
e.connect(i), i.connect(n), n.connect(o), r.connect(o),
|
|
157
|
+
const { sourceNode: e, inputGainNode: i, enhanceGainNode: n, bgsGainNode: r, bgmGainNode: a, analyserNode: o, outputGainNode: d, destinationNode: c } = this;
|
|
158
|
+
e.connect(i), i.connect(n), n.connect(o), r.connect(o), a.connect(o), n.connect(c), r.connect(c), a.connect(c), o.connect(d), d.connect(this.audioContext.destination);
|
|
159
159
|
}
|
|
160
160
|
this.setMute(!0), this.audioContext.resume();
|
|
161
161
|
}
|
|
@@ -163,27 +163,27 @@ class O {
|
|
|
163
163
|
const V = async (l, t) => {
|
|
164
164
|
try {
|
|
165
165
|
const { format: s, numberOfChannels: e, numberOfFrames: i, sampleRate: n } = t, r = l.createBuffer(e, i, n);
|
|
166
|
-
for (let
|
|
167
|
-
const o = t.allocationSize({ planeIndex:
|
|
168
|
-
t.copyTo(d, { planeIndex:
|
|
169
|
-
const
|
|
166
|
+
for (let a = 0; a < e; a++) {
|
|
167
|
+
const o = t.allocationSize({ planeIndex: a }), d = new Uint8Array(o);
|
|
168
|
+
t.copyTo(d, { planeIndex: a });
|
|
169
|
+
const c = new DataView(d.buffer), h = r.getChannelData(a);
|
|
170
170
|
for (let p = 0; p < i; p++) {
|
|
171
171
|
let u;
|
|
172
172
|
switch (s) {
|
|
173
173
|
case "s16":
|
|
174
174
|
// 16-bit signed PCM (范围: -32768 ~ 32767)
|
|
175
175
|
case "s16-planar":
|
|
176
|
-
u =
|
|
176
|
+
u = c.getInt16(p * 2, !0) / 32768;
|
|
177
177
|
break;
|
|
178
178
|
case "f32":
|
|
179
179
|
// 32-bit float (范围: -1.0 ~ 1.0)
|
|
180
180
|
case "f32-planar":
|
|
181
|
-
u =
|
|
181
|
+
u = c.getFloat32(p * 4, !0);
|
|
182
182
|
break;
|
|
183
183
|
case "u8":
|
|
184
184
|
// 8-bit unsigned (范围: 0 ~ 255)
|
|
185
185
|
case "u8-planar":
|
|
186
|
-
u = (
|
|
186
|
+
u = (c.getUint8(p) - 128) / 128;
|
|
187
187
|
break;
|
|
188
188
|
default:
|
|
189
189
|
throw new Error(`Unsupported audio format: ${s}`);
|
|
@@ -209,18 +209,19 @@ class W {
|
|
|
209
209
|
t || (t = new (window.AudioContext || window.webkitAudioContext)()), this.audioContext = t, this.destination = this.audioContext.createMediaStreamDestination(), this.stream = new MediaStream(), this.stream.addTrack(this.destination.stream.getAudioTracks()[0]), this.prAudioStream = new O(this.stream, this.audioContext), this.nextStartTime = 0, this.pendingSources = [];
|
|
210
210
|
};
|
|
211
211
|
async push(t) {
|
|
212
|
+
const { audioData: s, playbackRate: e = 1 } = t;
|
|
212
213
|
try {
|
|
213
214
|
if (!this.audioContext || !this.destination) return;
|
|
214
|
-
const
|
|
215
|
-
if (!
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
const
|
|
219
|
-
this.nextStartTime =
|
|
220
|
-
this.pendingSources = this.pendingSources.filter((
|
|
215
|
+
const i = await V(this.audioContext, s);
|
|
216
|
+
if (!i) return;
|
|
217
|
+
const n = this.audioContext.createBufferSource();
|
|
218
|
+
n.buffer = i, n.playbackRate.value = e, n.connect(this.destination);
|
|
219
|
+
const r = Math.max(this.nextStartTime, this.audioContext.currentTime), a = i.duration / e;
|
|
220
|
+
this.nextStartTime = r + a, n.start(r), this.pendingSources.push(n), n.onended = () => {
|
|
221
|
+
this.pendingSources = this.pendingSources.filter((o) => o !== n);
|
|
221
222
|
}, this.audioContext.state === "suspended" && await this.audioContext.resume();
|
|
222
223
|
} finally {
|
|
223
|
-
|
|
224
|
+
s.close();
|
|
224
225
|
}
|
|
225
226
|
}
|
|
226
227
|
getStream = () => this.prAudioStream?.getStream();
|
|
@@ -289,15 +290,15 @@ class $ {
|
|
|
289
290
|
add = (t, s = () => !1, e = 0) => new Promise((i) => {
|
|
290
291
|
if (s()) return i(!0);
|
|
291
292
|
this.resolvesMap.has(t) || this.resolvesMap.set(t, /* @__PURE__ */ new Map()), this.index++;
|
|
292
|
-
const
|
|
293
|
+
const a = `${this.index}`;
|
|
293
294
|
if (e = Math.max(0, e), e === 0) {
|
|
294
|
-
this.resolvesMap.get(t)?.set(
|
|
295
|
+
this.resolvesMap.get(t)?.set(a, { resolve: i, timer: 0 });
|
|
295
296
|
return;
|
|
296
297
|
}
|
|
297
298
|
const o = window.setTimeout(() => {
|
|
298
299
|
this.emit(t);
|
|
299
300
|
}, e);
|
|
300
|
-
this.resolvesMap.get(t)?.set(
|
|
301
|
+
this.resolvesMap.get(t)?.set(a, { resolve: i, timer: o });
|
|
301
302
|
});
|
|
302
303
|
emit = async (t) => {
|
|
303
304
|
const s = this.resolvesMap.get(t);
|
|
@@ -313,7 +314,7 @@ const H = (l, t) => {
|
|
|
313
314
|
const s = new Uint8Array(l), e = new Uint8Array(t), i = new Uint8Array(11 + s.length + e.length);
|
|
314
315
|
let n = 0;
|
|
315
316
|
return i[n++] = 1, i[n++] = s[1], i[n++] = s[2], i[n++] = s[3], i[n++] = 255, i[n++] = 225, i[n++] = s.length >> 8 & 255, i[n++] = s.length & 255, i.set(s, n), n += s.length, i[n++] = 1, i[n++] = e.length >> 8 & 255, i[n++] = e.length & 255, i.set(e, n), i;
|
|
316
|
-
},
|
|
317
|
+
}, R = (l) => {
|
|
317
318
|
let t = 0;
|
|
318
319
|
const s = new DataView(l.buffer), e = s.getUint8(t);
|
|
319
320
|
if (t = t + 1, e !== 1) throw new Error("Invalid AVC version");
|
|
@@ -323,7 +324,7 @@ const H = (l, t) => {
|
|
|
323
324
|
t = t + 1;
|
|
324
325
|
const r = s.getUint8(t) & 255;
|
|
325
326
|
t = t + 1;
|
|
326
|
-
const d = `avc1.${Array.from([i, n, r], (b) => b.toString(16).padStart(2, "0")).join("")}`,
|
|
327
|
+
const d = `avc1.${Array.from([i, n, r], (b) => b.toString(16).padStart(2, "0")).join("")}`, c = (s.getUint8(t) & 3) - 1;
|
|
327
328
|
t = t + 1;
|
|
328
329
|
const h = s.getUint8(t) & 31;
|
|
329
330
|
t = t + 1;
|
|
@@ -336,7 +337,7 @@ const H = (l, t) => {
|
|
|
336
337
|
const f = s.getUint16(t, !1);
|
|
337
338
|
t = t + 2;
|
|
338
339
|
const m = new Uint8Array(s.buffer.slice(t, t + f));
|
|
339
|
-
return t = t + f, { version: e, codec: d, profile: i, compatibility: n, level: r, lengthSizeMinusOne:
|
|
340
|
+
return t = t + f, { version: e, codec: d, profile: i, compatibility: n, level: r, lengthSizeMinusOne: c, numOfSequenceParameterSets: h, sequenceParameterSetLength: p, sps: u, numOfPictureParameterSets: g, pictureParameterSetLength: f, pps: m };
|
|
340
341
|
}, K = (l) => {
|
|
341
342
|
const t = new Uint8Array(4 + l.length);
|
|
342
343
|
return new DataView(t.buffer).setUint32(0, l.length, !1), t.set(l, 4), t;
|
|
@@ -356,8 +357,8 @@ const H = (l, t) => {
|
|
|
356
357
|
let s = 0, e, i, n;
|
|
357
358
|
e = t.getUint32(s, !1), s += 4;
|
|
358
359
|
{
|
|
359
|
-
const r = t.getUint8(s),
|
|
360
|
-
i = { forbidden_zero_bit:
|
|
360
|
+
const r = t.getUint8(s), a = r >> 7 & 1, o = r >> 5 & 3, d = r & 31;
|
|
361
|
+
i = { forbidden_zero_bit: a, nal_ref_idc: o, nal_unit_type: d }, s += 1;
|
|
361
362
|
}
|
|
362
363
|
{
|
|
363
364
|
const r = e - 1;
|
|
@@ -531,17 +532,17 @@ class et {
|
|
|
531
532
|
switch (e) {
|
|
532
533
|
case "audio":
|
|
533
534
|
{
|
|
534
|
-
const { type: i, dts: n, data: r } = s,
|
|
535
|
-
this.decoderWorker.audio.push({ type: i, timestamp:
|
|
535
|
+
const { type: i, dts: n, data: r } = s, a = n * 1;
|
|
536
|
+
this.decoderWorker.audio.push({ type: i, timestamp: a, data: r });
|
|
536
537
|
}
|
|
537
538
|
break;
|
|
538
539
|
case "video":
|
|
539
540
|
{
|
|
540
|
-
const { type: i, dts: n, data: r, nalus:
|
|
541
|
+
const { type: i, dts: n, data: r, nalus: a = [] } = s, o = n * 1e3;
|
|
541
542
|
this.decoderWorker.video.push({ type: i, timestamp: o, data: r });
|
|
542
|
-
for (const d of
|
|
543
|
+
for (const d of a) {
|
|
543
544
|
if (d.byteLength <= 4) continue;
|
|
544
|
-
const { header:
|
|
545
|
+
const { header: c, data: h } = Y(d), { nal_unit_type: p } = c;
|
|
545
546
|
p === 6 && this.on.demuxer.sei && this.on.demuxer.sei(h);
|
|
546
547
|
}
|
|
547
548
|
}
|
|
@@ -624,16 +625,16 @@ class et {
|
|
|
624
625
|
getSegmentsTimer: 0,
|
|
625
626
|
parse: async (t) => {
|
|
626
627
|
const i = new TextDecoder("utf-8").decode(t).split(`
|
|
627
|
-
`).map((
|
|
628
|
-
let r = 4,
|
|
628
|
+
`).map((c) => c.replace("\r", "")), n = this.url.substring(0, this.url.lastIndexOf("/") + 1);
|
|
629
|
+
let r = 4, a = 0, o = !1;
|
|
629
630
|
const d = [];
|
|
630
|
-
for (const
|
|
631
|
-
|
|
632
|
-
url:
|
|
631
|
+
for (const c of i)
|
|
632
|
+
c.startsWith("#EXTINF:") ? r = parseFloat(c.split(":")[1].split(",")[0]) : c.startsWith("#EXT-X-TARGETDURATION:") ? a = parseInt(c.split(":")[1]) : c.startsWith("#EXT-X-ENDLIST") ? o = !1 : c.startsWith("#EXT-X-MEDIA-SEQUENCE:") ? o = !0 : c.includes(".ts") && !c.startsWith("#") && d.push({
|
|
633
|
+
url: c.startsWith("http") ? c : n + c,
|
|
633
634
|
duration: r,
|
|
634
635
|
isLive: o
|
|
635
636
|
});
|
|
636
|
-
return { baseUrl: n, targetDuration:
|
|
637
|
+
return { baseUrl: n, targetDuration: a, isLive: o, segments: d };
|
|
637
638
|
},
|
|
638
639
|
getSegments: async () => {
|
|
639
640
|
try {
|
|
@@ -645,11 +646,11 @@ class et {
|
|
|
645
646
|
for (; ; ) {
|
|
646
647
|
const { done: i, value: n } = await e.read();
|
|
647
648
|
if (n) {
|
|
648
|
-
const r = await this.hls.parse(n), { segments:
|
|
649
|
+
const r = await this.hls.parse(n), { segments: a = [], isLive: o = !1 } = r;
|
|
649
650
|
this.hls.isLive = o, o === !1 && (this.option.frameTrack = !1);
|
|
650
|
-
let d = Array.from(
|
|
651
|
-
const
|
|
652
|
-
|
|
651
|
+
let d = Array.from(a, (h) => h.url);
|
|
652
|
+
const c = d.findIndex((h) => h === this.hls.url);
|
|
653
|
+
c !== -1 && (d = d.slice(c + 1)), this.hls.urls = d;
|
|
653
654
|
}
|
|
654
655
|
if (i) break;
|
|
655
656
|
}
|
|
@@ -753,15 +754,15 @@ class Z {
|
|
|
753
754
|
let e = s;
|
|
754
755
|
const i = this.parseHeader(t, e);
|
|
755
756
|
e += 4;
|
|
756
|
-
const { transport_error_indicator: n, pid: r, payload_unit_start_indicator:
|
|
757
|
+
const { transport_error_indicator: n, pid: r, payload_unit_start_indicator: a, adaptation_field_control: o } = i;
|
|
757
758
|
if (n === 1 || r === void 0) return;
|
|
758
759
|
let d = 184;
|
|
759
760
|
if (o === 2 || o === 3) {
|
|
760
|
-
const
|
|
761
|
-
e += 1, this.parseAdaptationField(t, e), e +=
|
|
761
|
+
const c = t.getUint8(e);
|
|
762
|
+
e += 1, this.parseAdaptationField(t, e), e += c, d -= c;
|
|
762
763
|
}
|
|
763
764
|
if (o === 3 && (d -= 1), o === 1 || o === 3) {
|
|
764
|
-
const
|
|
765
|
+
const c = new Uint8Array(t.buffer.slice(e, e + d));
|
|
765
766
|
if (r === 0) return this.parsePAT(t, e);
|
|
766
767
|
{
|
|
767
768
|
const { programs: u = [] } = this.pat || {};
|
|
@@ -769,7 +770,7 @@ class Z {
|
|
|
769
770
|
}
|
|
770
771
|
const { streams: h = [] } = this.pmt || {}, p = h.find((u) => u.elementary_pid === r);
|
|
771
772
|
if (p) {
|
|
772
|
-
if (
|
|
773
|
+
if (a === 1) {
|
|
773
774
|
const u = this.payloadMap.get(r);
|
|
774
775
|
if (u) {
|
|
775
776
|
switch (p.kind) {
|
|
@@ -791,8 +792,8 @@ class Z {
|
|
|
791
792
|
}
|
|
792
793
|
{
|
|
793
794
|
this.payloadMap.has(r) || this.payloadMap.set(r, new Uint8Array());
|
|
794
|
-
const u = this.payloadMap.get(r), g = new Uint8Array(u.byteLength +
|
|
795
|
-
g.set(u, 0), g.set(
|
|
795
|
+
const u = this.payloadMap.get(r), g = new Uint8Array(u.byteLength + c.byteLength);
|
|
796
|
+
g.set(u, 0), g.set(c, u.byteLength), this.payloadMap.set(r, g);
|
|
796
797
|
}
|
|
797
798
|
}
|
|
798
799
|
}
|
|
@@ -800,36 +801,36 @@ class Z {
|
|
|
800
801
|
// Header
|
|
801
802
|
parseHeader = (t, s) => {
|
|
802
803
|
let e = s;
|
|
803
|
-
const i = t.getUint8(e), n = t.getUint8(e + 1), r = t.getUint8(e + 2),
|
|
804
|
+
const i = t.getUint8(e), n = t.getUint8(e + 1), r = t.getUint8(e + 2), a = t.getUint8(e + 3), o = (n & 128) >> 7;
|
|
804
805
|
if (o === 1) return { sync_byte: i, transport_error_indicator: o };
|
|
805
|
-
const d = (n & 64) >> 6,
|
|
806
|
-
return { sync_byte: i, transport_error_indicator: o, payload_unit_start_indicator: d, transport_priority:
|
|
806
|
+
const d = (n & 64) >> 6, c = (n & 32) >> 5, h = (n & 31) << 8 | r, p = (a & 192) >> 6, u = a >> 4 & 3, g = a & 15;
|
|
807
|
+
return { sync_byte: i, transport_error_indicator: o, payload_unit_start_indicator: d, transport_priority: c, pid: h, transport_scrambling_control: p, adaptation_field_control: u, continuity_counter: g };
|
|
807
808
|
};
|
|
808
809
|
// PAT表
|
|
809
810
|
parsePAT = (t, s) => {
|
|
810
811
|
let e = s, i;
|
|
811
812
|
{
|
|
812
|
-
const
|
|
813
|
+
const a = t.getUint8(e);
|
|
813
814
|
e += 1;
|
|
814
815
|
const o = t.getUint8(e);
|
|
815
816
|
if (e += 1, o !== 0) throw new Error("Invalid PAT table_id");
|
|
816
817
|
const d = t.getUint16(e) & 4095;
|
|
817
818
|
e += 2;
|
|
818
|
-
const
|
|
819
|
+
const c = t.getUint16(e);
|
|
819
820
|
e += 2;
|
|
820
821
|
const h = (t.getUint8(e) & 62) >> 1, p = t.getUint8(e) & 1;
|
|
821
822
|
e += 1;
|
|
822
823
|
const u = t.getUint8(e);
|
|
823
824
|
e += 1;
|
|
824
825
|
const g = t.getUint8(e);
|
|
825
|
-
e += 1, i = { pointer_field:
|
|
826
|
+
e += 1, i = { pointer_field: a, table_id: o, section_length: d, transport_stream_id: c, version_number: h, current_next_indicator: p, section_number: u, last_section_number: g };
|
|
826
827
|
}
|
|
827
828
|
const n = [];
|
|
828
829
|
{
|
|
829
|
-
const
|
|
830
|
+
const a = i.section_length - 5 - 4, o = e + a;
|
|
830
831
|
for (; e < o; ) {
|
|
831
|
-
const d = t.getUint16(e),
|
|
832
|
-
e += 4, d !== 0 &&
|
|
832
|
+
const d = t.getUint16(e), c = t.getUint16(e + 2) & 8191;
|
|
833
|
+
e += 4, d !== 0 && c >= 32 && c <= 8190 && n.push({ program_number: d, pmt_pid: c });
|
|
833
834
|
}
|
|
834
835
|
}
|
|
835
836
|
const r = t.getUint32(e);
|
|
@@ -839,13 +840,13 @@ class Z {
|
|
|
839
840
|
parsePMT = (t, s) => {
|
|
840
841
|
let e = s, i;
|
|
841
842
|
{
|
|
842
|
-
const
|
|
843
|
+
const a = t.getUint8(e);
|
|
843
844
|
e += 1;
|
|
844
845
|
const o = t.getUint8(e);
|
|
845
846
|
if (e += 1, o !== 2) throw new Error("Invalid PMT table_id");
|
|
846
847
|
const d = t.getUint16(e) & 4095;
|
|
847
848
|
e += 2;
|
|
848
|
-
const
|
|
849
|
+
const c = t.getUint16(e);
|
|
849
850
|
e += 2;
|
|
850
851
|
const h = (t.getUint8(e) & 62) >> 1, p = t.getUint8(e) & 1;
|
|
851
852
|
e += 1;
|
|
@@ -856,18 +857,18 @@ class Z {
|
|
|
856
857
|
const f = t.getUint16(e) & 8191;
|
|
857
858
|
e += 2;
|
|
858
859
|
const m = t.getUint16(e) & 4095;
|
|
859
|
-
e += 2, i = { pointer_field:
|
|
860
|
+
e += 2, i = { pointer_field: a, table_id: o, section_length: d, transport_stream_id: c, version_number: h, current_next_indicator: p, section_number: u, last_section_number: g, pcr_pid: f, program_info_length: m };
|
|
860
861
|
}
|
|
861
862
|
const n = [];
|
|
862
863
|
{
|
|
863
|
-
const
|
|
864
|
+
const a = i.section_length - 9 - 4, o = e + a;
|
|
864
865
|
for (; e < o; ) {
|
|
865
|
-
const d = t.getUint8(e),
|
|
866
|
+
const d = t.getUint8(e), c = J(d), h = t.getUint16(e + 1) & 8191, p = t.getUint16(e + 3) & 4095;
|
|
866
867
|
if (e += 5, h < 32 || h > 8190) {
|
|
867
868
|
console.warn(`Invalid elementary_pid: 0x${h.toString(16)}`);
|
|
868
869
|
continue;
|
|
869
870
|
}
|
|
870
|
-
n.push({ kind:
|
|
871
|
+
n.push({ kind: c, stream_type: d, elementary_pid: h, es_info_length: p });
|
|
871
872
|
}
|
|
872
873
|
}
|
|
873
874
|
const r = t.getUint32(e);
|
|
@@ -875,20 +876,20 @@ class Z {
|
|
|
875
876
|
};
|
|
876
877
|
// AdaptationField
|
|
877
878
|
parseAdaptationField = (t, s) => {
|
|
878
|
-
let e = s, i, n, r,
|
|
879
|
-
const o = t.getUint8(e), d = !!(o & 128),
|
|
879
|
+
let e = s, i, n, r, a;
|
|
880
|
+
const o = t.getUint8(e), d = !!(o & 128), c = !!(o & 64), h = !!(o & 32), p = !!(o & 16), u = !!(o & 8), g = !!(o & 4), f = !!(o & 2), m = !!(o & 1);
|
|
880
881
|
e += 1;
|
|
881
882
|
const b = (k, w) => {
|
|
882
883
|
let U = BigInt(0);
|
|
883
884
|
U |= BigInt(k.getUint16(w)) << 25n, U |= BigInt(k.getUint16(w + 1)) << 17n, U |= BigInt(k.getUint16(w + 2)) << 9n, U |= BigInt(k.getUint16(w + 3)) << 1n, U |= BigInt(k.getUint16(w + 4) >> 7);
|
|
884
|
-
const
|
|
885
|
-
return U = U * 300n + BigInt(
|
|
885
|
+
const I = (k.getUint16(w + 4) & 1) << 8 | k.getUint16(w + 5);
|
|
886
|
+
return U = U * 300n + BigInt(I), U;
|
|
886
887
|
};
|
|
887
888
|
if (p && (i = b(t, e), e += 6), u && (n = b(t, e), e += 6), g && (r = t.getInt8(e), e += 1), f) {
|
|
888
889
|
const k = t.getUint8(e);
|
|
889
|
-
e += 1,
|
|
890
|
+
e += 1, a = new Uint8Array(t.buffer, e, k), e += k;
|
|
890
891
|
}
|
|
891
|
-
return { discontinuity_indicator: d, random_access_indicator:
|
|
892
|
+
return { discontinuity_indicator: d, random_access_indicator: c, elementary_stream_priority_indicator: h, pcr_flag: p, opcr_flag: u, splicing_point_flag: g, transport_private_data_flag: f, adaptation_field_extension_flag: m, pcr: i, opcr: n, splice_countdown: r, transport_private_data: a };
|
|
892
893
|
};
|
|
893
894
|
parseAudio = async (t) => {
|
|
894
895
|
const s = new DataView(t.buffer);
|
|
@@ -897,14 +898,14 @@ class Z {
|
|
|
897
898
|
const r = s.getUint8(e) === 0 && s.getUint8(e + 1) === 0 && s.getUint8(e + 2) === 1;
|
|
898
899
|
if (e += 3, !r)
|
|
899
900
|
throw new Error("invalid ts audio payload.");
|
|
900
|
-
const
|
|
901
|
+
const a = s.getUint8(e);
|
|
901
902
|
e += 1;
|
|
902
903
|
const o = s.getUint8(e) << 8 | s.getUint8(e + 1);
|
|
903
904
|
e += 2;
|
|
904
|
-
let d,
|
|
905
|
+
let d, c, h, p, u;
|
|
905
906
|
{
|
|
906
907
|
const m = s.getUint8(e);
|
|
907
|
-
e += 1, d = m >> 4 & 3,
|
|
908
|
+
e += 1, d = m >> 4 & 3, c = (m >> 3 & 1) === 1, h = (m >> 2 & 1) === 1, p = (m >> 1 & 1) === 1, u = (m & 1) === 1;
|
|
908
909
|
}
|
|
909
910
|
let g, f;
|
|
910
911
|
{
|
|
@@ -913,7 +914,7 @@ class Z {
|
|
|
913
914
|
const b = m >> 6, k = s.getUint8(e);
|
|
914
915
|
e += 1, (b & 2) === 2 && (g = this.parsePtsDts(s, e)), (b & 1) === 1 ? f = this.parsePtsDts(s, e + 5) : f = g, e += k;
|
|
915
916
|
}
|
|
916
|
-
i = { stream_id:
|
|
917
|
+
i = { stream_id: a, pes_packet_length: o, scrambling_control: d, priority: c, data_alignment: h, copyright: p, original_copy: u, pts: g, dts: f };
|
|
917
918
|
}
|
|
918
919
|
n = t.slice(e);
|
|
919
920
|
{
|
|
@@ -924,8 +925,8 @@ class Z {
|
|
|
924
925
|
const f = `mp4a.40.${u}`, b = [96e3, 88200, 64e3, 48e3, 44100, 32e3, 24e3, 22050, 16e3, 12e3, 11025, 8e3, 7350][g];
|
|
925
926
|
this.audioConfig = { kind: "audio", codec: f, sampleRate: b, numberOfChannels: u }, this.on.config && this.on.config(this.audioConfig);
|
|
926
927
|
}
|
|
927
|
-
const { dts: r = 0, pts:
|
|
928
|
-
return { kind: "audio", type: "key", dts: r, pts:
|
|
928
|
+
const { dts: r = 0, pts: a = 0 } = i, o = a - r, d = n.slice(7);
|
|
929
|
+
return { kind: "audio", type: "key", dts: r, pts: a, cts: o, data: d };
|
|
929
930
|
}
|
|
930
931
|
};
|
|
931
932
|
parseVideo = async (t) => {
|
|
@@ -935,14 +936,14 @@ class Z {
|
|
|
935
936
|
const r = s.getUint8(e) === 0 && s.getUint8(e + 1) === 0 && s.getUint8(e + 2) === 1;
|
|
936
937
|
if (e += 3, !r)
|
|
937
938
|
throw new Error("invalid ts video payload.");
|
|
938
|
-
const
|
|
939
|
+
const a = s.getUint8(e);
|
|
939
940
|
e += 1;
|
|
940
941
|
const o = s.getUint8(e) << 8 | s.getUint8(e + 1);
|
|
941
942
|
e += 2;
|
|
942
|
-
let d,
|
|
943
|
+
let d, c, h, p, u;
|
|
943
944
|
{
|
|
944
945
|
const m = s.getUint8(e);
|
|
945
|
-
e += 1, d = m >> 4 & 3,
|
|
946
|
+
e += 1, d = m >> 4 & 3, c = (m >> 3 & 1) === 1, h = (m >> 2 & 1) === 1, p = (m >> 1 & 1) === 1, u = (m & 1) === 1;
|
|
946
947
|
}
|
|
947
948
|
let g, f;
|
|
948
949
|
{
|
|
@@ -951,7 +952,7 @@ class Z {
|
|
|
951
952
|
const b = m >> 6, k = s.getUint8(e);
|
|
952
953
|
e += 1, (b & 2) === 2 && (g = this.parsePtsDts(s, e)), (b & 1) === 1 ? f = this.parsePtsDts(s, e + 5) : f = g, e += k;
|
|
953
954
|
}
|
|
954
|
-
i = { stream_id:
|
|
955
|
+
i = { stream_id: a, pes_packet_length: o, scrambling_control: d, priority: c, data_alignment: h, copyright: p, original_copy: u, pts: g, dts: f };
|
|
955
956
|
}
|
|
956
957
|
n = t.slice(e);
|
|
957
958
|
{
|
|
@@ -959,11 +960,11 @@ class Z {
|
|
|
959
960
|
if (!this.videoConfig) {
|
|
960
961
|
let u, g;
|
|
961
962
|
if (u = r.find((m) => m.type === 7)?.nalu.slice(4), g = r.find((m) => m.type === 8)?.nalu.slice(4), u && g) {
|
|
962
|
-
const f = H(u, g), { codec: m } =
|
|
963
|
+
const f = H(u, g), { codec: m } = R(f);
|
|
963
964
|
this.videoConfig = { kind: "video", codec: m, description: f, sps: u, pps: g }, this.on.config && this.on.config(this.videoConfig);
|
|
964
965
|
}
|
|
965
966
|
}
|
|
966
|
-
const
|
|
967
|
+
const a = [];
|
|
967
968
|
let o = "delta";
|
|
968
969
|
for (const u of r) {
|
|
969
970
|
const { type: g, nalu: f } = u;
|
|
@@ -971,25 +972,25 @@ class Z {
|
|
|
971
972
|
case 6:
|
|
972
973
|
// sei
|
|
973
974
|
case 9:
|
|
974
|
-
|
|
975
|
+
a.push(f);
|
|
975
976
|
break;
|
|
976
977
|
case 1:
|
|
977
|
-
o = "delta",
|
|
978
|
+
o = "delta", a.push(f);
|
|
978
979
|
break;
|
|
979
980
|
case 5:
|
|
980
|
-
o = "key",
|
|
981
|
+
o = "key", a.push(f);
|
|
981
982
|
break;
|
|
982
983
|
}
|
|
983
984
|
}
|
|
984
|
-
const d = X(
|
|
985
|
-
return { kind: "video", type: o, dts:
|
|
985
|
+
const d = X(a), { dts: c = 0, pts: h = 0 } = i, p = h - c;
|
|
986
|
+
return { kind: "video", type: o, dts: c, pts: h, cts: p, data: d, nalus: a };
|
|
986
987
|
}
|
|
987
988
|
};
|
|
988
989
|
/**
|
|
989
990
|
* 解析 PTS/DTS 时间戳(33-bit,单位:90kHz)
|
|
990
991
|
*/
|
|
991
992
|
parsePtsDts(t, s) {
|
|
992
|
-
const e = t.getUint8(s), i = t.getUint8(s + 1), n = t.getUint8(s + 2), r = t.getUint8(s + 3),
|
|
993
|
+
const e = t.getUint8(s), i = t.getUint8(s + 1), n = t.getUint8(s + 2), r = t.getUint8(s + 3), a = t.getUint8(s + 4), o = (BigInt(e) & 0b00001110n) << 29n | (BigInt(i) & 0b11111111n) << 22n | (BigInt(n) & 0b11111110n) << 14n | (BigInt(r) & 0b11111111n) << 7n | (BigInt(a) & 0b11111110n) >> 1n;
|
|
993
994
|
return Number(o) / 90;
|
|
994
995
|
}
|
|
995
996
|
getNalus = (t) => {
|
|
@@ -1012,7 +1013,7 @@ class Z {
|
|
|
1012
1013
|
}
|
|
1013
1014
|
let r = e - i;
|
|
1014
1015
|
if (t[e - 1] === 0 && (r -= 1), r !== 0) {
|
|
1015
|
-
const
|
|
1016
|
+
const a = t.slice(i, i + r), o = K(a);
|
|
1016
1017
|
s.push({ type: n, nalu: o });
|
|
1017
1018
|
}
|
|
1018
1019
|
}
|
|
@@ -1032,7 +1033,7 @@ class tt {
|
|
|
1032
1033
|
parse = async (t) => {
|
|
1033
1034
|
let s = 0;
|
|
1034
1035
|
for (this.header || (this.parseHeader(t, s), s += 9); this.isSurplusTag(t, s) !== !1; ) {
|
|
1035
|
-
const i = this.parseTagHeader(t, s + 4), { tagType: n, dataSize: r, timestamp:
|
|
1036
|
+
const i = this.parseTagHeader(t, s + 4), { tagType: n, dataSize: r, timestamp: a } = i;
|
|
1036
1037
|
if (n) {
|
|
1037
1038
|
const o = this.parseTagBody(n, t, s + 4 + 11, r);
|
|
1038
1039
|
switch (n) {
|
|
@@ -1043,11 +1044,11 @@ class tt {
|
|
|
1043
1044
|
{
|
|
1044
1045
|
const { accPacketType: d } = o;
|
|
1045
1046
|
if (d === 0) {
|
|
1046
|
-
const { codec:
|
|
1047
|
-
this.audioConfig = { kind: "audio", codec:
|
|
1047
|
+
const { codec: c, sampleRate: h, channelConfiguration: p } = o;
|
|
1048
|
+
this.audioConfig = { kind: "audio", codec: c, sampleRate: h, numberOfChannels: p }, this.on.config && this.on.config(this.audioConfig);
|
|
1048
1049
|
} else {
|
|
1049
|
-
const { cts:
|
|
1050
|
-
this.on.chunk && this.on.chunk({ kind: "audio", type: p, dts:
|
|
1050
|
+
const { cts: c, data: h } = o, p = "key", u = c === void 0 ? void 0 : c + a;
|
|
1051
|
+
this.on.chunk && this.on.chunk({ kind: "audio", type: p, dts: a, pts: u, cts: c, data: h });
|
|
1051
1052
|
}
|
|
1052
1053
|
}
|
|
1053
1054
|
break;
|
|
@@ -1055,11 +1056,11 @@ class tt {
|
|
|
1055
1056
|
{
|
|
1056
1057
|
const { avcPacketType: d } = o;
|
|
1057
1058
|
if (d === 0) {
|
|
1058
|
-
const { codec:
|
|
1059
|
-
this.videoConfig = { kind: "video", codec:
|
|
1059
|
+
const { codec: c, sps: h, pps: p, data: u } = o;
|
|
1060
|
+
this.videoConfig = { kind: "video", codec: c, description: u, sps: h, pps: p }, this.on.config && this.on.config(this.videoConfig);
|
|
1060
1061
|
} else {
|
|
1061
|
-
const { frameType:
|
|
1062
|
-
this.on.chunk && this.on.chunk({ kind: "video", type: g, dts:
|
|
1062
|
+
const { frameType: c, cts: h, data: p, nalus: u } = o, g = c === 1 ? "key" : "delta", f = h === void 0 ? void 0 : h + a;
|
|
1063
|
+
this.on.chunk && this.on.chunk({ kind: "video", type: g, dts: a, pts: f, cts: h, data: p, nalus: u });
|
|
1063
1064
|
}
|
|
1064
1065
|
}
|
|
1065
1066
|
break;
|
|
@@ -1075,8 +1076,8 @@ class tt {
|
|
|
1075
1076
|
let e, i, n, r;
|
|
1076
1077
|
e = t.getUint8(s) << 16 | t.getUint8(s + 1) << 8 | t.getUint8(s + 2), i = t.getUint8(3);
|
|
1077
1078
|
{
|
|
1078
|
-
const o = t.getUint8(0).toString(2).padStart(5, "0").split(""), [, , d, ,
|
|
1079
|
-
n = { audio:
|
|
1079
|
+
const o = t.getUint8(0).toString(2).padStart(5, "0").split(""), [, , d, , c] = o;
|
|
1080
|
+
n = { audio: c === "1", video: d === "1" };
|
|
1080
1081
|
}
|
|
1081
1082
|
r = t.getUint32(5), this.header = { signature: e, version: i, flags: n, dataOffset: r };
|
|
1082
1083
|
};
|
|
@@ -1095,7 +1096,7 @@ class tt {
|
|
|
1095
1096
|
return e;
|
|
1096
1097
|
};
|
|
1097
1098
|
parseTagHeader = (t, s) => {
|
|
1098
|
-
let e, i, n, r,
|
|
1099
|
+
let e, i, n, r, a;
|
|
1099
1100
|
{
|
|
1100
1101
|
const o = t.getUint8(s);
|
|
1101
1102
|
let d;
|
|
@@ -1112,7 +1113,7 @@ class tt {
|
|
|
1112
1113
|
}
|
|
1113
1114
|
e = d;
|
|
1114
1115
|
}
|
|
1115
|
-
return i = _(t, s + 1), n = _(t, s + 4), r = t.getUint8(s + 7),
|
|
1116
|
+
return i = _(t, s + 1), n = _(t, s + 4), r = t.getUint8(s + 7), a = _(t, s + 8), { tagType: e, dataSize: i, timestamp: n, timestampExtended: r, streamID: a };
|
|
1116
1117
|
};
|
|
1117
1118
|
parseTagBody = (t, s, e, i) => {
|
|
1118
1119
|
let n;
|
|
@@ -1138,8 +1139,8 @@ class tt {
|
|
|
1138
1139
|
const i = t.getUint16(e, !1);
|
|
1139
1140
|
e = e + 2;
|
|
1140
1141
|
{
|
|
1141
|
-
const
|
|
1142
|
-
if ((this.textDecoder?.decode(
|
|
1142
|
+
const a = new Int8Array(t.buffer.slice(e, e + i));
|
|
1143
|
+
if ((this.textDecoder?.decode(a) || "") !== "onMetaData") throw new Error("Expected 'onMetaData' string");
|
|
1143
1144
|
e = e + i;
|
|
1144
1145
|
}
|
|
1145
1146
|
const n = this.getAmfType(t, e);
|
|
@@ -1147,44 +1148,44 @@ class tt {
|
|
|
1147
1148
|
};
|
|
1148
1149
|
parseAudio = (t, s, e) => {
|
|
1149
1150
|
let i = s;
|
|
1150
|
-
const n = t.getUint8(i), r = n >> 4 & 15,
|
|
1151
|
+
const n = t.getUint8(i), r = n >> 4 & 15, a = n >> 2 & 3, o = n >> 1 & 1, d = n & 1;
|
|
1151
1152
|
i = i + 1;
|
|
1152
|
-
const
|
|
1153
|
+
const c = t.getUint8(i);
|
|
1153
1154
|
i = i + 1;
|
|
1154
1155
|
const h = e, p = new Uint8Array(t.buffer.slice(i, i + h));
|
|
1155
|
-
if (r === 10 &&
|
|
1156
|
+
if (r === 10 && c === 0) {
|
|
1156
1157
|
const u = t.getUint8(i), g = t.getUint8(i + 1), f = u >> 3 & 31, m = (u & 7) << 1 | g >> 7, b = g >> 3 & 15, k = [96e3, 88200, 64e3, 48e3, 44100, 32e3, 24e3, 22050, 16e3, 12e3, 11025, 8e3, 7350], w = `mp4a.40.${f}`, U = k[m];
|
|
1157
|
-
return { soundFormat: r, soundRate:
|
|
1158
|
+
return { soundFormat: r, soundRate: a, soundSize: o, soundType: d, accPacketType: c, data: p, samplingFrequencyIndex: m, channelConfiguration: b, codec: w, sampleRate: U };
|
|
1158
1159
|
}
|
|
1159
|
-
return { soundFormat: r, soundRate:
|
|
1160
|
+
return { soundFormat: r, soundRate: a, soundSize: o, soundType: d, accPacketType: c, data: p };
|
|
1160
1161
|
};
|
|
1161
1162
|
parseVideo = (t, s, e) => {
|
|
1162
1163
|
let i = s;
|
|
1163
|
-
const n = t.getUint8(i), r = n >> 4 & 15,
|
|
1164
|
+
const n = t.getUint8(i), r = n >> 4 & 15, a = n & 15;
|
|
1164
1165
|
i = i + 1;
|
|
1165
1166
|
const o = t.getUint8(i);
|
|
1166
1167
|
i = i + 1;
|
|
1167
1168
|
const d = _(t, i);
|
|
1168
1169
|
i = i + 3;
|
|
1169
|
-
const
|
|
1170
|
-
switch (
|
|
1170
|
+
const c = e - 5, h = new Uint8Array(t.buffer.slice(i, i + c));
|
|
1171
|
+
switch (a) {
|
|
1171
1172
|
case 7:
|
|
1172
1173
|
if (o === 0) {
|
|
1173
|
-
const p =
|
|
1174
|
-
return { frameType: r, codecID:
|
|
1174
|
+
const p = R(h);
|
|
1175
|
+
return { frameType: r, codecID: a, avcPacketType: o, cts: d, data: h, ...p };
|
|
1175
1176
|
} else if (o === 1) {
|
|
1176
1177
|
const p = [], u = i + e - 5;
|
|
1177
1178
|
for (; !(i + 4 > u); ) {
|
|
1178
1179
|
const g = t.getUint32(i, !1), f = new Uint8Array(t.buffer.slice(i, i + 4 + g));
|
|
1179
1180
|
i += 4 + g, p.push(f);
|
|
1180
1181
|
}
|
|
1181
|
-
return { frameType: r, codecID:
|
|
1182
|
+
return { frameType: r, codecID: a, avcPacketType: o, cts: d, data: h, nalus: p };
|
|
1182
1183
|
}
|
|
1183
1184
|
break;
|
|
1184
1185
|
default:
|
|
1185
1186
|
throw new Error("Unsupported codecID");
|
|
1186
1187
|
}
|
|
1187
|
-
return { frameType: r, codecID:
|
|
1188
|
+
return { frameType: r, codecID: a, avcPacketType: o, cts: d, data: h };
|
|
1188
1189
|
};
|
|
1189
1190
|
getAmfType = (t, s) => t.getUint8(s);
|
|
1190
1191
|
getAMFName = (t, s, e) => {
|
|
@@ -1216,10 +1217,10 @@ class tt {
|
|
|
1216
1217
|
i = i + 2;
|
|
1217
1218
|
const d = this.getAMFName(t, i, o);
|
|
1218
1219
|
i = i + o;
|
|
1219
|
-
const
|
|
1220
|
-
if (
|
|
1220
|
+
const c = this.getAmfType(t, i);
|
|
1221
|
+
if (c === 6) break;
|
|
1221
1222
|
i = i + 1;
|
|
1222
|
-
const h = this.getAMFValue(t, i,
|
|
1223
|
+
const h = this.getAMFValue(t, i, c);
|
|
1223
1224
|
i = i + h.length, n[d] = h.value, r = 2 + o + 1 + h.length;
|
|
1224
1225
|
}
|
|
1225
1226
|
break;
|
|
@@ -1229,14 +1230,14 @@ class tt {
|
|
|
1229
1230
|
const o = t.getUint32(i, !1);
|
|
1230
1231
|
i = i + 4;
|
|
1231
1232
|
for (let d = 0; d < o; d++) {
|
|
1232
|
-
const
|
|
1233
|
+
const c = t.getUint16(i, !1);
|
|
1233
1234
|
i = i + 2;
|
|
1234
|
-
const h = this.getAMFName(t, i,
|
|
1235
|
-
i = i +
|
|
1235
|
+
const h = this.getAMFName(t, i, c);
|
|
1236
|
+
i = i + c;
|
|
1236
1237
|
const p = this.getAmfType(t, i);
|
|
1237
1238
|
i = i + 1;
|
|
1238
1239
|
const u = this.getAMFValue(t, i, p);
|
|
1239
|
-
i = i + u.length, n[h] = u.value, r = 2 +
|
|
1240
|
+
i = i + u.length, n[h] = u.value, r = 2 + c + 1 + u.length;
|
|
1240
1241
|
}
|
|
1241
1242
|
}
|
|
1242
1243
|
break;
|
|
@@ -1246,9 +1247,9 @@ class tt {
|
|
|
1246
1247
|
const o = t.getUint32(i, !1);
|
|
1247
1248
|
i = i + 4;
|
|
1248
1249
|
for (let d = 0; d < o; d++) {
|
|
1249
|
-
const
|
|
1250
|
+
const c = this.getAmfType(t, i);
|
|
1250
1251
|
i = i + 1;
|
|
1251
|
-
const h = this.getAMFValue(t, i,
|
|
1252
|
+
const h = this.getAMFValue(t, i, c);
|
|
1252
1253
|
i = i + h.length, n.push(h.value), r = 1 + h.length;
|
|
1253
1254
|
}
|
|
1254
1255
|
}
|
|
@@ -1393,7 +1394,8 @@ class it {
|
|
|
1393
1394
|
init: (t) => {
|
|
1394
1395
|
this.audio.destroy(), this.audioDecoderConfig = { ...t }, this.audioDecoder = new AudioDecoder({
|
|
1395
1396
|
output: (s) => {
|
|
1396
|
-
|
|
1397
|
+
const e = this.decodingSpeedRatio;
|
|
1398
|
+
this.on.audio.decode && this.on.audio.decode({ audioData: s, playbackRate: e });
|
|
1397
1399
|
},
|
|
1398
1400
|
error: (s) => {
|
|
1399
1401
|
this.on.audio.error && this.on.audio.error(s);
|
|
@@ -1448,8 +1450,8 @@ class nt {
|
|
|
1448
1450
|
const { timestamp: s } = t;
|
|
1449
1451
|
let { bitmap: e } = t;
|
|
1450
1452
|
if (this.cutOption) {
|
|
1451
|
-
const { sx: n = 0, sy: r = 0, sw:
|
|
1452
|
-
e = await createImageBitmap(e, n, r,
|
|
1453
|
+
const { sx: n = 0, sy: r = 0, sw: a = e.width, sh: o = e.height } = this.cutOption;
|
|
1454
|
+
e = await createImageBitmap(e, n, r, a, o);
|
|
1453
1455
|
}
|
|
1454
1456
|
const i = new VideoFrame(e, { timestamp: s });
|
|
1455
1457
|
this.cutOption && e.close(), this.writer.write(i), i.close();
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(U,T){typeof exports=="object"&&typeof module<"u"?T(exports):typeof define=="function"&&define.amd?define(["exports"],T):(U=typeof globalThis<"u"?globalThis:U||self,T(U["pr-player"]={}))})(this,(function(U){"use strict";const T='(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',A=typeof self<"u"&&self.Blob&&new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);",T],{type:"text/javascript;charset=utf-8"});function B(l){let t;try{if(t=A&&(self.URL||self.webkitURL).createObjectURL(A),!t)throw"";const s=new Worker(t,{name:l?.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(T),{name:l?.name})}}class x{worker=new B;on={};constructor(){this.worker.onmessage=t=>{const{action:s,data:e}=t.data;switch(s){case"onInfo":this.on.info&&this.on.info(e);break;case"onConfig":this.on.config&&this.on.config(e);break;case"onDebug":this.on.debug&&this.on.debug(e);break;case"onChunk":this.on.chunk&&this.on.chunk(e);break}}}init=t=>this.worker.postMessage({action:"init",data:t});push=t=>this.worker.postMessage({action:"push",data:t});destroy=()=>{this.worker.postMessage({action:"destroy",data:{}}),this.worker.terminate()}}const C=`(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)}}})();
|
|
2
|
-
`,
|
|
3
|
-
`,P=typeof self<"u"&&self.Blob&&new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);",M],{type:"text/javascript;charset=utf-8"});function z(l){let t;try{if(t=P&&(self.URL||self.webkitURL).createObjectURL(P),!t)throw"";const s=new Worker(t,{name:l?.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(M),{name:l?.name})}}class
|
|
4
|
-
`).map(a=>a.replace("\r","")),n=this.url.substring(0,this.url.lastIndexOf("/")+1);let r=4,c=0,o=!1;const d=[];for(const a of i)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({url:a.startsWith("http")?a:n+a,duration:r,isLive:o});return{baseUrl:n,targetDuration:c,isLive:o,segments:d}},getSegments:async()=>{try{const t=new F;let s=await t.request(this.url);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.");const e=s.body?.getReader();if(!e)throw new Error("reader is error.");for(;;){const{done:i,value:n}=await e.read();if(n){const r=await this.hls.parse(n),{segments:c=[],isLive:o=!1}=r;this.hls.isLive=o,o===!1&&(this.option.frameTrack=!1);let d=Array.from(c,h=>h.url);const a=d.findIndex(h=>h===this.hls.url);a!==-1&&(d=d.slice(a+1)),this.hls.urls=d}if(i)break}}catch(t){this.on.error&&this.on.error(t)}},start:async()=>{try{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));;){const t=this.hls.urls.shift();if(t){this.hls.url=t;const e=(await this.prFetch.request(t)).body?.getReader();if(!e)throw new Error("segment reader is error.");for(;;){const{done:i,value:n}=await e.read();if(n&&this.demuxerWorker?.push(n),i)break}}else await new Promise(s=>setTimeout(()=>s(!0),300))}}catch(t){if(t?.name!=="AbortError")throw Error(t)}}}}class J{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 Z=l=>{let t="unknown";switch(l){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 tt{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 i=this.parseHeader(t,e);e+=4;const{transport_error_indicator:n,pid:r,payload_unit_start_indicator:c,adaptation_field_control:o}=i;if(n===1||r===void 0)return;let d=184;if(o===2||o===3){const a=t.getUint8(e);e+=1,this.parseAdaptationField(t,e),e+=a,d-=a}if(o===3&&(d-=1),o===1||o===3){const a=new Uint8Array(t.buffer.slice(e,e+d));if(r===0)return this.parsePAT(t,e);{const{programs:u=[]}=this.pat||{};if(u.find(f=>f.pmt_pid===r))return this.parsePMT(t,e)}const{streams:h=[]}=this.pmt||{},p=h.find(u=>u.elementary_pid===r);if(p){if(c===1){const u=this.payloadMap.get(r);if(u){switch(p.kind){case"audio":{const g=await this.parseAudio(u);this.on.chunk&&this.on.chunk(g)}break;case"video":{const g=await this.parseVideo(u);this.on.chunk&&this.on.chunk(g),await new Promise(f=>setTimeout(()=>f(!0),0))}break}this.payloadMap.delete(r)}}{this.payloadMap.has(r)||this.payloadMap.set(r,new Uint8Array);const u=this.payloadMap.get(r),g=new Uint8Array(u.byteLength+a.byteLength);g.set(u,0),g.set(a,u.byteLength),this.payloadMap.set(r,g)}}}};parseHeader=(t,s)=>{let e=s;const i=t.getUint8(e),n=t.getUint8(e+1),r=t.getUint8(e+2),c=t.getUint8(e+3),o=(n&128)>>7;if(o===1)return{sync_byte:i,transport_error_indicator:o};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;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}};parsePAT=(t,s)=>{let e=s,i;{const c=t.getUint8(e);e+=1;const o=t.getUint8(e);if(e+=1,o!==0)throw new Error("Invalid PAT table_id");const d=t.getUint16(e)&4095;e+=2;const a=t.getUint16(e);e+=2;const h=(t.getUint8(e)&62)>>1,p=t.getUint8(e)&1;e+=1;const u=t.getUint8(e);e+=1;const g=t.getUint8(e);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}}const n=[];{const c=i.section_length-5-4,o=e+c;for(;e<o;){const d=t.getUint16(e),a=t.getUint16(e+2)&8191;e+=4,d!==0&&a>=32&&a<=8190&&n.push({program_number:d,pmt_pid:a})}}const r=t.getUint32(e);this.pat={header:i,programs:n,crc32:r},this.on.debug&&this.on.debug({pat:this.pat})};parsePMT=(t,s)=>{let e=s,i;{const c=t.getUint8(e);e+=1;const o=t.getUint8(e);if(e+=1,o!==2)throw new Error("Invalid PMT table_id");const d=t.getUint16(e)&4095;e+=2;const a=t.getUint16(e);e+=2;const h=(t.getUint8(e)&62)>>1,p=t.getUint8(e)&1;e+=1;const u=t.getUint8(e);e+=1;const g=t.getUint8(e);e+=1;const f=t.getUint16(e)&8191;e+=2;const y=t.getUint16(e)&4095;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:y}}const n=[];{const c=i.section_length-9-4,o=e+c;for(;e<o;){const d=t.getUint8(e),a=Z(d),h=t.getUint16(e+1)&8191,p=t.getUint16(e+3)&4095;if(e+=5,h<32||h>8190){console.warn(`Invalid elementary_pid: 0x${h.toString(16)}`);continue}n.push({kind:a,stream_type:d,elementary_pid:h,es_info_length:p})}}const r=t.getUint32(e);this.pmt={header:i,streams:n,crc32:r},this.on.debug&&this.on.debug({pmt:this.pmt})};parseAdaptationField=(t,s)=>{let e=s,i,n,r,c;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),y=!!(o&1);e+=1;const b=(k,_)=>{let w=BigInt(0);w|=BigInt(k.getUint16(_))<<25n,w|=BigInt(k.getUint16(_+1))<<17n,w|=BigInt(k.getUint16(_+2))<<9n,w|=BigInt(k.getUint16(_+3))<<1n,w|=BigInt(k.getUint16(_+4)>>7);const ot=(k.getUint16(_+4)&1)<<8|k.getUint16(_+5);return w=w*300n+BigInt(ot),w};if(p&&(i=b(t,e),e+=6),u&&(n=b(t,e),e+=6),g&&(r=t.getInt8(e),e+=1),f){const k=t.getUint8(e);e+=1,c=new Uint8Array(t.buffer,e,k),e+=k}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:y,pcr:i,opcr:n,splice_countdown:r,transport_private_data:c}};parseAudio=async t=>{const s=new DataView(t.buffer);let e=0,i,n;{const r=s.getUint8(e)===0&&s.getUint8(e+1)===0&&s.getUint8(e+2)===1;if(e+=3,!r)throw new Error("invalid ts audio payload.");const c=s.getUint8(e);e+=1;const o=s.getUint8(e)<<8|s.getUint8(e+1);e+=2;let d,a,h,p,u;{const y=s.getUint8(e);e+=1,d=y>>4&3,a=(y>>3&1)===1,h=(y>>2&1)===1,p=(y>>1&1)===1,u=(y&1)===1}let g,f;{const y=s.getUint8(e);e+=1;const b=y>>6,k=s.getUint8(e);e+=1,(b&2)===2&&(g=this.parsePtsDts(s,e)),(b&1)===1?f=this.parsePtsDts(s,e+5):f=g,e+=k}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}}n=t.slice(e);{if(!this.audioConfig&&s.getUint8(e)===255){const h=s.getUint8(e+2),p=s.getUint8(e+3);let u,g;g=h>>2&15,u=(h&1)<<2|p>>6;const f=`mp4a.40.${u}`,b=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350][g];this.audioConfig={kind:"audio",codec:f,sampleRate:b,numberOfChannels:u},this.on.config&&this.on.config(this.audioConfig)}const{dts:r=0,pts:c=0}=i,o=c-r,d=n.slice(7);return{kind:"audio",type:"key",dts:r,pts:c,cts:o,data:d}}};parseVideo=async t=>{const s=new DataView(t.buffer);let e=0,i,n;{const r=s.getUint8(e)===0&&s.getUint8(e+1)===0&&s.getUint8(e+2)===1;if(e+=3,!r)throw new Error("invalid ts video payload.");const c=s.getUint8(e);e+=1;const o=s.getUint8(e)<<8|s.getUint8(e+1);e+=2;let d,a,h,p,u;{const y=s.getUint8(e);e+=1,d=y>>4&3,a=(y>>3&1)===1,h=(y>>2&1)===1,p=(y>>1&1)===1,u=(y&1)===1}let g,f;{const y=s.getUint8(e);e+=1;const b=y>>6,k=s.getUint8(e);e+=1,(b&2)===2&&(g=this.parsePtsDts(s,e)),(b&1)===1?f=this.parsePtsDts(s,e+5):f=g,e+=k}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}}n=t.slice(e);{const r=this.getNalus(n);if(!this.videoConfig){let u,g;if(u=r.find(y=>y.type===7)?.nalu.slice(4),g=r.find(y=>y.type===8)?.nalu.slice(4),u&&g){const f=H(u,g),{codec:y}=N(f);this.videoConfig={kind:"video",codec:y,description:f,sps:u,pps:g},this.on.config&&this.on.config(this.videoConfig)}}const c=[];let o="delta";for(const u of r){const{type:g,nalu:f}=u;switch(g){case 6:case 9:c.push(f);break;case 1:o="delta",c.push(f);break;case 5:o="key",c.push(f);break}}const d=X(c),{dts:a=0,pts:h=0}=i,p=h-a;return{kind:"video",type:o,dts:a,pts:h,cts:p,data:d,nalus:c}}};parsePtsDts(t,s){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;return Number(o)/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 i=e;const n=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 r=e-i;if(t[e-1]===0&&(r-=1),r!==0){const c=t.slice(i,i+r),o=K(c);s.push({type:n,nalu:o})}}return s}}const v=(l,t)=>l.getUint8(t)<<16|l.getUint8(t+1)<<8|l.getUint8(t+2);class et{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 i=this.parseTagHeader(t,s+4),{tagType:n,dataSize:r,timestamp:c}=i;if(n){const o=this.parseTagBody(n,t,s+4+11,r);switch(n){case"script":this.on.info&&this.on.info(o);break;case"audio":{const{accPacketType:d}=o;if(d===0){const{codec:a,sampleRate:h,channelConfiguration:p}=o;this.audioConfig={kind:"audio",codec:a,sampleRate:h,numberOfChannels:p},this.on.config&&this.on.config(this.audioConfig)}else{const{cts:a,data:h}=o,p="key",u=a===void 0?void 0:a+c;this.on.chunk&&this.on.chunk({kind:"audio",type:p,dts:c,pts:u,cts:a,data:h})}}break;case"video":{const{avcPacketType:d}=o;if(d===0){const{codec:a,sps:h,pps:p,data:u}=o;this.videoConfig={kind:"video",codec:a,description:u,sps:h,pps:p},this.on.config&&this.on.config(this.videoConfig)}else{const{frameType:a,cts:h,data:p,nalus:u}=o,g=a===1?"key":"delta",f=h===void 0?void 0:h+c;this.on.chunk&&this.on.chunk({kind:"video",type:g,dts:c,pts:f,cts:h,data:p,nalus:u})}}break}s=s+4+11+r}await new Promise(o=>setTimeout(()=>o(!0),8))}return s};parseHeader=(t,s)=>{let e,i,n,r;e=t.getUint8(s)<<16|t.getUint8(s+1)<<8|t.getUint8(s+2),i=t.getUint8(3);{const o=t.getUint8(0).toString(2).padStart(5,"0").split(""),[,,d,,a]=o;n={audio:a==="1",video:d==="1"}}r=t.getUint32(5),this.header={signature:e,version:i,flags:n,dataOffset:r}};isSurplusTag=(t,s)=>{let e=!0;const i=t.byteLength;if(s+4>i)e=!1;else if(s+4+11>i)e=!1;else{const n=v(t,s+4+1);s+4+11+n>i&&(e=!1)}return e};parseTagHeader=(t,s)=>{let e,i,n,r,c;{const o=t.getUint8(s);let d;switch(o){case 18:d="script";break;case 8:d="audio";break;case 9:d="video";break}e=d}return i=v(t,s+1),n=v(t,s+4),r=t.getUint8(s+7),c=v(t,s+8),{tagType:e,dataSize:i,timestamp:n,timestampExtended:r,streamID:c}};parseTagBody=(t,s,e,i)=>{let n;switch(t){case"script":n=this.parseMetaData(s,e);break;case"audio":n=this.parseAudio(s,e,i);break;case"video":n=this.parseVideo(s,e,i);break}return n};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 i=t.getUint16(e,!1);e=e+2;{const c=new Int8Array(t.buffer.slice(e,e+i));if((this.textDecoder?.decode(c)||"")!=="onMetaData")throw new Error("Expected 'onMetaData' string");e=e+i}const n=this.getAmfType(t,e);return e=e+1,this.getAMFValue(t,e,n).value};parseAudio=(t,s,e)=>{let i=s;const n=t.getUint8(i),r=n>>4&15,c=n>>2&3,o=n>>1&1,d=n&1;i=i+1;const a=t.getUint8(i);i=i+1;const h=e,p=new Uint8Array(t.buffer.slice(i,i+h));if(r===10&&a===0){const u=t.getUint8(i),g=t.getUint8(i+1),f=u>>3&31,y=(u&7)<<1|g>>7,b=g>>3&15,k=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],_=`mp4a.40.${f}`,w=k[y];return{soundFormat:r,soundRate:c,soundSize:o,soundType:d,accPacketType:a,data:p,samplingFrequencyIndex:y,channelConfiguration:b,codec:_,sampleRate:w}}return{soundFormat:r,soundRate:c,soundSize:o,soundType:d,accPacketType:a,data:p}};parseVideo=(t,s,e)=>{let i=s;const n=t.getUint8(i),r=n>>4&15,c=n&15;i=i+1;const o=t.getUint8(i);i=i+1;const d=v(t,i);i=i+3;const a=e-5,h=new Uint8Array(t.buffer.slice(i,i+a));switch(c){case 7:if(o===0){const p=N(h);return{frameType:r,codecID:c,avcPacketType:o,cts:d,data:h,...p}}else if(o===1){const p=[],u=i+e-5;for(;!(i+4>u);){const g=t.getUint32(i,!1),f=new Uint8Array(t.buffer.slice(i,i+4+g));i+=4+g,p.push(f)}return{frameType:r,codecID:c,avcPacketType:o,cts:d,data:h,nalus:p}}break;default:throw new Error("Unsupported codecID")}return{frameType:r,codecID:c,avcPacketType:o,cts:d,data:h}};getAmfType=(t,s)=>t.getUint8(s);getAMFName=(t,s,e)=>{const i=new Uint8Array(t.buffer.slice(s,s+e));return this.textDecoder?.decode(i)||""};getAMFValue=(t,s,e)=>{let i=s,n,r=0;switch(e){case 0:n=t.getFloat64(i,!1),r=8;break;case 1:n=!!t.getUint8(i),r=1;break;case 2:{n="";const o=t.getUint16(i,!1);i=i+2;const d=new Int8Array(t.buffer,i,o).filter(h=>h!==0);n=(this.textDecoder?.decode(d)||"").trim(),r=2+o}break;case 3:for(n={};i<t.byteLength;){const o=t.getUint16(i,!1);if(o===0)break;i=i+2;const d=this.getAMFName(t,i,o);i=i+o;const a=this.getAmfType(t,i);if(a===6)break;i=i+1;const h=this.getAMFValue(t,i,a);i=i+h.length,n[d]=h.value,r=2+o+1+h.length}break;case 8:{n={};const o=t.getUint32(i,!1);i=i+4;for(let d=0;d<o;d++){const a=t.getUint16(i,!1);i=i+2;const h=this.getAMFName(t,i,a);i=i+a;const p=this.getAmfType(t,i);i=i+1;const u=this.getAMFValue(t,i,p);i=i+u.length,n[h]=u.value,r=2+a+1+u.length}}break;case 10:{n=[];const o=t.getUint32(i,!1);i=i+4;for(let d=0;d<o;d++){const a=this.getAmfType(t,i);i=i+1;const h=this.getAMFValue(t,i,a);i=i+h.length,n.push(h.value),r=1+h.length}}break}return{amfType:e,length:r,value:n}}}class st{pattern;cacher=new J;isParseing=!1;offset=0;on={};parser;constructor(){}init=t=>{switch(this.destroy(),this.pattern=t,this.pattern){case"flv":this.parser=new et;break;case"hls":this.parser=new tt;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()}}}class it{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=t=>{const{decodingSpeed:s,frameTrack:e,minFrameTrackCacheNum:i}=t;s!==void 0&&(this.decodingSpeed=s),e!==void 0&&(this.frameTrack=e),i!==void 0&&(this.minFrameTrackCacheNum=i)};setFrameTrack=t=>{this.frameTrack=t,this.frameTrack===!1&&(this.decodingSpeedRatio=1)};initDecodeInterval=()=>{let t=this.decodingSpeed/this.decodingSpeedRatio;const s=this.baseTime+performance.now();if(this.nextRenderTime){const e=s-this.nextRenderTime;t-=e}this.nextRenderTime=s+t,this.decodeTimer=setTimeout(()=>{this.decode(),this.initDecodeInterval()},t)};decode=()=>{if(this.isProcessing!==!0){for(this.isProcessing=!0;;){const t=this.pendingChunks.shift();if(this.frameTrack){const i=this.pendingChunks.length;if(i>=this.minFrameTrackCacheNum){const n=Math.min(1+(i-this.minFrameTrackCacheNum)/100,this.maxDecodingSpeedRatio);this.decodingSpeedRatio=Number(n.toFixed(1))}else this.decodingSpeedRatio=1}if(!t)break;const{type:s,init:e}=t;switch(s){case"audio":this.decodeAudio(e);break;case"video":this.decodeVideo(e);break}if(s==="video")break}this.isProcessing=!1}};decodeAudio=t=>{if(!this.audioDecoder)return;const s=new EncodedAudioChunk(t);this.audioDecoder.decode(s)};decodeVideo=t=>{if(this.videoDecoder&&(t.type==="key"&&(this.hasKeyFrame=!0),this.hasKeyFrame)){const s=new EncodedVideoChunk(t);this.videoDecoder.decode(s)}};destroy=()=>{this.audio.destroy(),this.video.destroy(),clearInterval(this.decodeTimer)};audio={init:t=>{this.audio.destroy(),this.audioDecoderConfig={...t},this.audioDecoder=new AudioDecoder({output:s=>{this.on.audio.decode&&this.on.audio.decode(s)},error:s=>{this.on.audio.error&&this.on.audio.error(s)}}),this.audioDecoder.configure(this.audioDecoderConfig)},push:t=>{this.pendingChunks.push({type:"audio",init:t})},flush:()=>{this.audioDecoder?.flush()},destroy:()=>{this.audioDecoderConfig=void 0,this.audioDecoder?.close(),this.audioDecoder=void 0}};video={init:t=>{this.video.destroy(),this.videoDecoderConfig={...t},this.videoDecoder=new VideoDecoder({output:async s=>{const e=s.timestamp+this.baseTime*1e3,i=await createImageBitmap(s);s.close(),i.width>0&&i.height>0?this.on.video.decode&&this.on.video.decode({timestamp:e,bitmap:i}):i.close()},error:s=>{this.on.video.error&&this.on.video.error(s)}}),this.videoDecoder.configure(this.videoDecoderConfig)},push:t=>{this.pendingChunks.push({type:"video",init:t})},flush:()=>{this.videoDecoder?.flush()},destroy:()=>{this.videoDecoderConfig=void 0,this.videoDecoder?.close(),this.videoDecoder=void 0,this.hasKeyFrame=!1}}}class nt{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:e}=t;if(this.cutOption){const{sx:n=0,sy:r=0,sw:c=e.width,sh:o=e.height}=this.cutOption;e=await createImageBitmap(e,n,r,c,o)}const i=new VideoFrame(e,{timestamp:s});this.cutOption&&e.close(),this.writer.write(i),i.close()};setCut=t=>{this.cutOption=t};setPause=t=>{this.pause=t};destroy=()=>{this.writable=void 0,this.writer=void 0,this.cutOption=void 0}}U.Decoder=it,U.DecoderWorker=S,U.Demuxer=st,U.DemuxerWorker=x,U.PrPlayer=Q,U.Render=nt,U.RenderWorker=I,Object.defineProperty(U,Symbol.toStringTag,{value:"Module"})}));
|
|
1
|
+
(function(U,T){typeof exports=="object"&&typeof module<"u"?T(exports):typeof define=="function"&&define.amd?define(["exports"],T):(U=typeof globalThis<"u"?globalThis:U||self,T(U["pr-player"]={}))})(this,(function(U){"use strict";const T='(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',A=typeof self<"u"&&self.Blob&&new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);",T],{type:"text/javascript;charset=utf-8"});function B(l){let t;try{if(t=A&&(self.URL||self.webkitURL).createObjectURL(A),!t)throw"";const s=new Worker(t,{name:l?.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(T),{name:l?.name})}}class x{worker=new B;on={};constructor(){this.worker.onmessage=t=>{const{action:s,data:e}=t.data;switch(s){case"onInfo":this.on.info&&this.on.info(e);break;case"onConfig":this.on.config&&this.on.config(e);break;case"onDebug":this.on.debug&&this.on.debug(e);break;case"onChunk":this.on.chunk&&this.on.chunk(e);break}}}init=t=>this.worker.postMessage({action:"init",data:t});push=t=>this.worker.postMessage({action:"push",data:t});destroy=()=>{this.worker.postMessage({action:"destroy",data:{}}),this.worker.terminate()}}const D=`(function(){"use strict";class n{audioDecoderConfig;audioDecoder;videoDecoderConfig;videoDecoder;hasKeyFrame=!1;baseTime=0;pendingChunks=[];isProcessing=!1;decodeTimer=0;frameTrack=!1;minFrameTrackCacheNum=20;decodingSpeed=40;decodingSpeedRatio=1;maxDecodingSpeedRatio=2;nextRenderTime;on={audio:{},video:{}};constructor(){this.baseTime=new Date().getTime()-performance.now(),this.initDecodeInterval()}init=e=>{const{decodingSpeed:i,frameTrack:d,minFrameTrackCacheNum:o}=e;i!==void 0&&(this.decodingSpeed=i),d!==void 0&&(this.frameTrack=d),o!==void 0&&(this.minFrameTrackCacheNum=o)};setFrameTrack=e=>{this.frameTrack=e,this.frameTrack===!1&&(this.decodingSpeedRatio=1)};initDecodeInterval=()=>{let e=this.decodingSpeed/this.decodingSpeedRatio;const i=this.baseTime+performance.now();if(this.nextRenderTime){const d=i-this.nextRenderTime;e-=d}this.nextRenderTime=i+e,this.decodeTimer=setTimeout(()=>{this.decode(),this.initDecodeInterval()},e)};decode=()=>{if(this.isProcessing!==!0){for(this.isProcessing=!0;;){const e=this.pendingChunks.shift();if(this.frameTrack){const o=this.pendingChunks.length;if(o>=this.minFrameTrackCacheNum){const r=Math.min(1+(o-this.minFrameTrackCacheNum)/100,this.maxDecodingSpeedRatio);this.decodingSpeedRatio=Number(r.toFixed(1))}else this.decodingSpeedRatio=1}if(!e)break;const{type:i,init:d}=e;switch(i){case"audio":this.decodeAudio(d);break;case"video":this.decodeVideo(d);break}if(i==="video")break}this.isProcessing=!1}};decodeAudio=e=>{if(!this.audioDecoder)return;const i=new EncodedAudioChunk(e);this.audioDecoder.decode(i)};decodeVideo=e=>{if(this.videoDecoder&&(e.type==="key"&&(this.hasKeyFrame=!0),this.hasKeyFrame)){const i=new EncodedVideoChunk(e);this.videoDecoder.decode(i)}};destroy=()=>{this.audio.destroy(),this.video.destroy(),clearInterval(this.decodeTimer)};audio={init:e=>{this.audio.destroy(),this.audioDecoderConfig={...e},this.audioDecoder=new AudioDecoder({output:i=>{const d=this.decodingSpeedRatio;this.on.audio.decode&&this.on.audio.decode({audioData:i,playbackRate:d})},error:i=>{this.on.audio.error&&this.on.audio.error(i)}}),this.audioDecoder.configure(this.audioDecoderConfig)},push:e=>{this.pendingChunks.push({type:"audio",init:e})},flush:()=>{this.audioDecoder?.flush()},destroy:()=>{this.audioDecoderConfig=void 0,this.audioDecoder?.close(),this.audioDecoder=void 0}};video={init:e=>{this.video.destroy(),this.videoDecoderConfig={...e},this.videoDecoder=new VideoDecoder({output:async i=>{const d=i.timestamp+this.baseTime*1e3,o=await createImageBitmap(i);i.close(),o.width>0&&o.height>0?this.on.video.decode&&this.on.video.decode({timestamp:d,bitmap:o}):o.close()},error:i=>{this.on.video.error&&this.on.video.error(i)}}),this.videoDecoder.configure(this.videoDecoderConfig)},push:e=>{this.pendingChunks.push({type:"video",init:e})},flush:()=>{this.videoDecoder?.flush()},destroy:()=>{this.videoDecoderConfig=void 0,this.videoDecoder?.close(),this.videoDecoder=void 0,this.hasKeyFrame=!1}}}const s=new n;s.on.audio.decode=t=>postMessage({type:"audio",action:"onDecode",data:t}),s.on.audio.error=t=>postMessage({type:"audio",action:"onError",data:t}),s.on.video.decode=t=>postMessage({type:"video",action:"onDecode",data:t}),s.on.video.error=t=>postMessage({type:"video",action:"onError",data:t}),onmessage=t=>{const{type:e,action:i,data:d}=t.data;if(e){const o=s[e][i];o&&o(d)}else{const o=s[i];o&&o(d)}}})();
|
|
2
|
+
`,C=typeof self<"u"&&self.Blob&&new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);",D],{type:"text/javascript;charset=utf-8"});function E(l){let t;try{if(t=C&&(self.URL||self.webkitURL).createObjectURL(C),!t)throw"";const s=new Worker(t,{name:l?.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(D),{name:l?.name})}}class S{worker=new E;on={audio:{},video:{}};constructor(){this.worker.onmessage=t=>{const{type:s,action:e,data:i}=t.data;switch(s){case"audio":e==="onDecode"&&this.on.audio.decode&&this.on.audio.decode(i),e==="onError"&&this.on.audio.error&&this.on.audio.error(i);break;case"video":e==="onDecode"&&this.on.video.decode&&this.on.video.decode(i),e==="onError"&&this.on.video.error&&this.on.video.error(i);break}}}init=t=>this.worker.postMessage({action:"init",data:t});setFrameTrack=t=>this.worker.postMessage({action:"setFrameTrack",data:t});audio={init:t=>this.worker.postMessage({type:"audio",action:"init",data:t}),push:t=>this.worker.postMessage({type:"audio",action:"push",data:t}),flush:()=>this.worker.postMessage({type:"audio",action:"flush"}),destroy:()=>{this.worker.postMessage({type:"audio",action:"destroy"})}};video={init:t=>this.worker.postMessage({type:"video",action:"init",data:t}),push:t=>this.worker.postMessage({type:"video",action:"push",data:t}),flush:()=>this.worker.postMessage({type:"video",action:"flush"}),destroy:()=>{this.worker.postMessage({type:"video",action:"destroy",data:{}})}};destroy=()=>{this.worker.postMessage({action:"destroy"}),this.worker.terminate()}}var G=Object.defineProperty,O=(l,t,s)=>t in l?G(l,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):l[t]=s,m=(l,t,s)=>O(l,typeof t!="symbol"?t+"":t,s);class W{constructor(t,s){m(this,"inputStream",new MediaStream),m(this,"outputStream",new MediaStream),m(this,"inputGain",1),m(this,"enhanceGain",1),m(this,"bgsGain",1),m(this,"bgmGain",1),m(this,"outputGain",1),m(this,"mixAudioMap",new Map),m(this,"audioContext",new AudioContext),m(this,"sourceNode"),m(this,"inputGainNode"),m(this,"enhanceGainNode"),m(this,"bgsGainNode"),m(this,"bgmGainNode"),m(this,"analyserNode"),m(this,"analyserArrayData"),m(this,"outputGainNode"),m(this,"destinationNode"),m(this,"filterStream",e=>e),m(this,"stop",()=>{{const e=this.inputStream.getTracks();for(const i of e)i.stop(),this.inputStream.removeTrack(i)}}),m(this,"getStream",()=>this.filterStream(this.outputStream)),m(this,"setMute",(e=!0)=>{e?this.analyserNode.disconnect(this.outputGainNode):this.analyserNode.connect(this.outputGainNode)}),m(this,"setInputGain",e=>{this.inputGain=e,this.inputGainNode.gain.setValueAtTime(e,this.audioContext.currentTime)}),m(this,"setEnhanceGain",async e=>{this.enhanceGain=e+1,this.enhanceGainNode.gain.setValueAtTime(this.enhanceGain,this.audioContext.currentTime)}),m(this,"setBgsGain",e=>{this.bgsGain=e,this.bgsGainNode.gain.setValueAtTime(e,this.audioContext.currentTime)}),m(this,"setBgmGain",e=>{this.bgmGain=e,this.bgmGainNode.gain.setValueAtTime(e,this.audioContext.currentTime)}),m(this,"setOutputGain",e=>{this.outputGain=e,this.outputGainNode.gain.setValueAtTime(this.outputGain,this.audioContext.currentTime)}),m(this,"getVolume",()=>{const{analyserNode:e,analyserArrayData:i}=this;e.getByteFrequencyData(i);let n=0;for(let r=0;r<i.length;r++)n+=i[r];return Math.ceil(n/i.length)}),m(this,"mixAudio",(e,i="bgm")=>new Promise(async(n,r)=>{try{{const d=this.mixAudioMap.get(i);d&&d.stop()}const a=i==="bgs"?this.bgsGainNode:this.bgmGainNode,o=this.audioContext.createBufferSource();this.mixAudioMap.set(i,o),o.buffer=e,o.connect(a),o.onended=()=>{o.disconnect(a),this.mixAudioMap.delete(i),n(!0)},o.start(0)}catch(a){r(a)}})),m(this,"mixAudioStop",e=>{const i=this.mixAudioMap.get(e);i?.stop()}),m(this,"changeMix",(e,i)=>{const n=e==="bgs"?this.bgsGainNode:this.bgmGainNode;i?n.connect(this.destinationNode):n.disconnect(this.destinationNode)}),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;{const{sourceNode:e,inputGainNode:i,enhanceGainNode:n,bgsGainNode:r,bgmGainNode:a,analyserNode:o,outputGainNode:d,destinationNode:c}=this;e.connect(i),i.connect(n),n.connect(o),r.connect(o),a.connect(o),n.connect(c),r.connect(c),a.connect(c),o.connect(d),d.connect(this.audioContext.destination)}this.setMute(!0),this.audioContext.resume()}}const V=async(l,t)=>{try{const{format:s,numberOfChannels:e,numberOfFrames:i,sampleRate:n}=t,r=l.createBuffer(e,i,n);for(let a=0;a<e;a++){const o=t.allocationSize({planeIndex:a}),d=new Uint8Array(o);t.copyTo(d,{planeIndex:a});const c=new DataView(d.buffer),h=r.getChannelData(a);for(let p=0;p<i;p++){let u;switch(s){case"s16":case"s16-planar":u=c.getInt16(p*2,!0)/32768;break;case"f32":case"f32-planar":u=c.getFloat32(p*4,!0);break;case"u8":case"u8-planar":u=(c.getUint8(p)-128)/128;break;default:throw new Error(`Unsupported audio format: ${s}`)}h[p]=Math.max(-1,Math.min(1,u))}}return r}catch(s){throw console.error("Failed to convert AudioData to AudioBuffer:",s),s}};class j{prAudioStream;audioContext;destination;stream=new MediaStream;nextStartTime=0;pendingSources=[];constructor(){}init=t=>{t||(t=new(window.AudioContext||window.webkitAudioContext)),this.audioContext=t,this.destination=this.audioContext.createMediaStreamDestination(),this.stream=new MediaStream,this.stream.addTrack(this.destination.stream.getAudioTracks()[0]),this.prAudioStream=new W(this.stream,this.audioContext),this.nextStartTime=0,this.pendingSources=[]};async push(t){const{audioData:s,playbackRate:e=1}=t;try{if(!this.audioContext||!this.destination)return;const i=await V(this.audioContext,s);if(!i)return;const n=this.audioContext.createBufferSource();n.buffer=i,n.playbackRate.value=e,n.connect(this.destination);const r=Math.max(this.nextStartTime,this.audioContext.currentTime),a=i.duration/e;this.nextStartTime=r+a,n.start(r),this.pendingSources.push(n),n.onended=()=>{this.pendingSources=this.pendingSources.filter(o=>o!==n)},this.audioContext.state==="suspended"&&await this.audioContext.resume()}finally{s.close()}}getStream=()=>this.prAudioStream?.getStream();destroy(){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=[]}}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)}})();
|
|
3
|
+
`,P=typeof self<"u"&&self.Blob&&new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);",M],{type:"text/javascript;charset=utf-8"});function z(l){let t;try{if(t=P&&(self.URL||self.webkitURL).createObjectURL(P),!t)throw"";const s=new Worker(t,{name:l?.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(M),{name:l?.name})}}class R{worker=new z;constructor(){}init=({writable:t})=>this.worker.postMessage({action:"init",data:{writable:t}},[t]);push=t=>this.worker.postMessage({action:"push",data:t});setCut=async t=>this.worker.postMessage({action:"setCut",data:t});setPause=t=>this.worker.postMessage({action:"setPause",data:t});destroy=()=>{this.worker.postMessage({action:"destroy",data:{}}),this.worker.terminate()}}const q=l=>{const t=l.toLowerCase();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"},I=l=>{const t=l?.getTracks()||[];for(const s of t)s.stop()},L=()=>{const l=new MediaStreamTrackGenerator({kind:"video"}),t=new MediaStream([l]),s=new R;return s.init({writable:l.writable}),{worker:s,stream:t,destroy:()=>{s.destroy(),I(t)}}};class ${resolvesMap=new Map;index=0;constructor(){}add=(t,s=()=>!1,e=0)=>new Promise(i=>{if(s())return i(!0);this.resolvesMap.has(t)||this.resolvesMap.set(t,new Map),this.index++;const a=`${this.index}`;if(e=Math.max(0,e),e===0){this.resolvesMap.get(t)?.set(a,{resolve:i,timer:0});return}const o=window.setTimeout(()=>{this.emit(t)},e);this.resolvesMap.get(t)?.set(a,{resolve:i,timer:o})});emit=async t=>{const s=this.resolvesMap.get(t);if(!s)return;const e=[...s.keys()];for(const i of e){const n=s.get(i);n&&(clearTimeout(n.timer),n.resolve(),s.delete(i))}}}const H=(l,t)=>{const s=new Uint8Array(l),e=new Uint8Array(t),i=new Uint8Array(11+s.length+e.length);let n=0;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},N=l=>{let t=0;const s=new DataView(l.buffer),e=s.getUint8(t);if(t=t+1,e!==1)throw new Error("Invalid AVC version");const i=s.getUint8(t)&255;t=t+1;const n=s.getUint8(t)&255;t=t+1;const r=s.getUint8(t)&255;t=t+1;const d=`avc1.${Array.from([i,n,r],b=>b.toString(16).padStart(2,"0")).join("")}`,c=(s.getUint8(t)&3)-1;t=t+1;const h=s.getUint8(t)&31;t=t+1;const p=s.getUint16(t,!1);t=t+2;const u=new Uint8Array(s.buffer.slice(t,t+p));t=t+p;const g=s.getUint8(t)&31;t=t+1;const f=s.getUint16(t,!1);t=t+2;const y=new Uint8Array(s.buffer.slice(t,t+f));return t=t+f,{version:e,codec:d,profile:i,compatibility:n,level:r,lengthSizeMinusOne:c,numOfSequenceParameterSets:h,sequenceParameterSetLength:p,sps:u,numOfPictureParameterSets:g,pictureParameterSetLength:f,pps:y}},K=l=>{const t=new Uint8Array(4+l.length);return new DataView(t.buffer).setUint32(0,l.length,!1),t.set(l,4),t},X=l=>{let t=0;for(const i of l)t+=i.length;const s=new Uint8Array(t);let e=0;for(const i of l){const n=i;s.set(n,e),e+=n.length}return s},Y=l=>{const t=new DataView(l.buffer);let s=0,e,i,n;e=t.getUint32(s,!1),s+=4;{const r=t.getUint8(s),a=r>>7&1,o=r>>5&3,d=r&31;i={forbidden_zero_bit:a,nal_ref_idc:o,nal_unit_type:d},s+=1}{const r=e-1;n=new Uint8Array(t.buffer.slice(s,s+r))}return{size:e,header:i,data:n}};class F{#e={timeout:5*1e3,check:!1};#t;constructor(t={}){this.#e={...this.#e,...t}}check=(t,s)=>new Promise(async(e,i)=>{this.stop(),this.#t=new AbortController;const n=window.setTimeout(()=>{this.#t?.abort("Timeout."),i({status:"timeout",reason:""})},this.#e.timeout);try{const r=await fetch(t,{...s,method:"HEAD",signal:this.#t?.signal});r.status===200?e({status:"successed",reason:""}):i({status:"failed",reason:`${r.status}`})}catch(r){i({status:"error",reason:r.message})}clearTimeout(n)});request=async(t,s)=>new Promise(async(e,i)=>{try{this.#e.check&&await this.check(t,s),this.#t=new AbortController;const n=await fetch(t,{...s,signal:this.#t?.signal});e(n)}catch(n){this.stop(),i(n)}});stop=()=>{this.#t?.signal.aborted===!1&&this.#t.abort("Actively stop.")}}class Q{option={debug:!1,frameTrack:!1};prFetch=new F;prResolves=new $;url="";demuxerWorker;decoderWorker;audioPlayer;renderWorker;stream;on={demuxer:{},decoder:{}};cutRenders=new Map;trackGenerator;constructor(t={}){const{debug:s=!1}=t;this.option.debug=s}init=()=>{this.initDecoder(),this.initRender(),this.audioPlayer=new j,this.audioPlayer.init()};start=async t=>{this.stop(),this.url=t,this.init();const s=q(t);if(s==="unknown")throw new Error("This address cannot be parsed.");switch(this.initDemuxer(s),s){case"flv":this.flv.start();break;case"hls":this.hls.start();break}};stop=async()=>{try{clearInterval(this.hls.getSegmentsTimer),this.prFetch.stop()}catch(t){console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m","color:#0097ff;","------->pr-player: error",t)}this.demuxerWorker?.destroy(),this.decoderWorker?.destroy(),this.renderWorker?.destroy(),I(this.stream),this.audioPlayer?.destroy()};getStream=()=>this.stream;setPause=t=>{this.renderWorker?.setPause(t)};setMute=t=>this.audioPlayer?.prAudioStream?.setMute(t);setFrameTrack=t=>{this.decoderWorker?.setFrameTrack(t)};isReady=()=>{const t=()=>this.stream?.active===!0;return this.prResolves.add("isReady",t)};initDemuxer=t=>{this.demuxerWorker=new x,this.demuxerWorker.init(t),this.demuxerWorker.on.debug=s=>{this.option.debug&&console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m","color:#0097ff;","------->pr-player: debug",s)},this.demuxerWorker.on.info=s=>{this.option.debug&&console.log("\x1B[38;2;0;151;255m%c%s\x1B[0m","color:#0097ff;","------->pr-player: info",s);const{framerate:e=25}=s,i=1e3/e;this.decoderWorker?.init({decodingSpeed:i}),this.on.demuxer.info&&this.on.demuxer.info(s)},this.demuxerWorker.on.config=s=>{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);const{kind:e}=s;switch(e){case"audio":{const{codec:i,sampleRate:n,numberOfChannels:r}=s;this.decoderWorker?.audio.init({codec:i,sampleRate:n,numberOfChannels:r})}break;case"video":{const{codec:i,description:n}=s;this.decoderWorker?.video.init({codec:i,description:n})}break}},this.demuxerWorker.on.chunk=s=>{if(this.on.demuxer.chunk&&this.on.demuxer.chunk(s),!this.decoderWorker)return;const{kind:e}=s;switch(e){case"audio":{const{type:i,dts:n,data:r}=s,a=n*1;this.decoderWorker.audio.push({type:i,timestamp:a,data:r})}break;case"video":{const{type:i,dts:n,data:r,nalus:a=[]}=s,o=n*1e3;this.decoderWorker.video.push({type:i,timestamp:o,data:r});for(const d of a){if(d.byteLength<=4)continue;const{header:c,data:h}=Y(d),{nal_unit_type:p}=c;p===6&&this.on.demuxer.sei&&this.on.demuxer.sei(h)}}break}}};initDecoder=()=>{this.decoderWorker=new S,this.decoderWorker.on.audio.decode=t=>{this.audioPlayer?.push(t),this.on.decoder.audio&&this.on.decoder.audio(t)},this.decoderWorker.on.audio.error=t=>{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)},this.decoderWorker.on.video.decode=async t=>{this.renderWorker?.push(t);const s=[...this.cutRenders.keys()];for(const e of s)this.cutRenders.get(e)?.worker.push(t);this.on.decoder.video&&this.on.decoder.video(t),t.bitmap.close()},this.decoderWorker.on.video.error=t=>{this.stop(),this.on.error&&this.on.error(t)}};initRender=()=>{const{worker:t,stream:s}=L();this.renderWorker=t,this.stream=s,this.renderWorker.setPause(!1)};cut={create:(t,s)=>{let e=this.cutRenders.get(t);return e?(e.worker.setCut(s),e.worker.setPause(!1),e):(e=L(),e.worker.setCut(s),this.cutRenders.set(t,e),e)},getStream:t=>this.cutRenders.get(t)?.stream,setPause:(t,s)=>{this.cutRenders.get(t)?.worker.setPause(s)},remove:t=>{this.cutRenders.get(t)?.destroy(),this.cutRenders.delete(t)}};flv={start:async()=>{try{let t=await this.prFetch.request(this.url);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.");const s=t.body?.getReader();if(!s)throw new Error("reader is error.");for(;;){const{done:e,value:i}=await s.read();if(i&&this.demuxerWorker?.push(i),e)break}}catch(t){if(t?.name!=="AbortError")throw Error(t);this.on.error&&this.on.error(t)}}};hls={isLive:!1,urls:[],url:"",getSegmentsTimer:0,parse:async t=>{const i=new TextDecoder("utf-8").decode(t).split(`
|
|
4
|
+
`).map(c=>c.replace("\r","")),n=this.url.substring(0,this.url.lastIndexOf("/")+1);let r=4,a=0,o=!1;const d=[];for(const c of i)c.startsWith("#EXTINF:")?r=parseFloat(c.split(":")[1].split(",")[0]):c.startsWith("#EXT-X-TARGETDURATION:")?a=parseInt(c.split(":")[1]):c.startsWith("#EXT-X-ENDLIST")?o=!1:c.startsWith("#EXT-X-MEDIA-SEQUENCE:")?o=!0:c.includes(".ts")&&!c.startsWith("#")&&d.push({url:c.startsWith("http")?c:n+c,duration:r,isLive:o});return{baseUrl:n,targetDuration:a,isLive:o,segments:d}},getSegments:async()=>{try{const t=new F;let s=await t.request(this.url);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.");const e=s.body?.getReader();if(!e)throw new Error("reader is error.");for(;;){const{done:i,value:n}=await e.read();if(n){const r=await this.hls.parse(n),{segments:a=[],isLive:o=!1}=r;this.hls.isLive=o,o===!1&&(this.option.frameTrack=!1);let d=Array.from(a,h=>h.url);const c=d.findIndex(h=>h===this.hls.url);c!==-1&&(d=d.slice(c+1)),this.hls.urls=d}if(i)break}}catch(t){this.on.error&&this.on.error(t)}},start:async()=>{try{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));;){const t=this.hls.urls.shift();if(t){this.hls.url=t;const e=(await this.prFetch.request(t)).body?.getReader();if(!e)throw new Error("segment reader is error.");for(;;){const{done:i,value:n}=await e.read();if(n&&this.demuxerWorker?.push(n),i)break}}else await new Promise(s=>setTimeout(()=>s(!0),300))}}catch(t){if(t?.name!=="AbortError")throw Error(t)}}}}class J{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 Z=l=>{let t="unknown";switch(l){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 tt{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 i=this.parseHeader(t,e);e+=4;const{transport_error_indicator:n,pid:r,payload_unit_start_indicator:a,adaptation_field_control:o}=i;if(n===1||r===void 0)return;let d=184;if(o===2||o===3){const c=t.getUint8(e);e+=1,this.parseAdaptationField(t,e),e+=c,d-=c}if(o===3&&(d-=1),o===1||o===3){const c=new Uint8Array(t.buffer.slice(e,e+d));if(r===0)return this.parsePAT(t,e);{const{programs:u=[]}=this.pat||{};if(u.find(f=>f.pmt_pid===r))return this.parsePMT(t,e)}const{streams:h=[]}=this.pmt||{},p=h.find(u=>u.elementary_pid===r);if(p){if(a===1){const u=this.payloadMap.get(r);if(u){switch(p.kind){case"audio":{const g=await this.parseAudio(u);this.on.chunk&&this.on.chunk(g)}break;case"video":{const g=await this.parseVideo(u);this.on.chunk&&this.on.chunk(g),await new Promise(f=>setTimeout(()=>f(!0),0))}break}this.payloadMap.delete(r)}}{this.payloadMap.has(r)||this.payloadMap.set(r,new Uint8Array);const u=this.payloadMap.get(r),g=new Uint8Array(u.byteLength+c.byteLength);g.set(u,0),g.set(c,u.byteLength),this.payloadMap.set(r,g)}}}};parseHeader=(t,s)=>{let e=s;const i=t.getUint8(e),n=t.getUint8(e+1),r=t.getUint8(e+2),a=t.getUint8(e+3),o=(n&128)>>7;if(o===1)return{sync_byte:i,transport_error_indicator:o};const d=(n&64)>>6,c=(n&32)>>5,h=(n&31)<<8|r,p=(a&192)>>6,u=a>>4&3,g=a&15;return{sync_byte:i,transport_error_indicator:o,payload_unit_start_indicator:d,transport_priority:c,pid:h,transport_scrambling_control:p,adaptation_field_control:u,continuity_counter:g}};parsePAT=(t,s)=>{let e=s,i;{const a=t.getUint8(e);e+=1;const o=t.getUint8(e);if(e+=1,o!==0)throw new Error("Invalid PAT table_id");const d=t.getUint16(e)&4095;e+=2;const c=t.getUint16(e);e+=2;const h=(t.getUint8(e)&62)>>1,p=t.getUint8(e)&1;e+=1;const u=t.getUint8(e);e+=1;const g=t.getUint8(e);e+=1,i={pointer_field:a,table_id:o,section_length:d,transport_stream_id:c,version_number:h,current_next_indicator:p,section_number:u,last_section_number:g}}const n=[];{const a=i.section_length-5-4,o=e+a;for(;e<o;){const d=t.getUint16(e),c=t.getUint16(e+2)&8191;e+=4,d!==0&&c>=32&&c<=8190&&n.push({program_number:d,pmt_pid:c})}}const r=t.getUint32(e);this.pat={header:i,programs:n,crc32:r},this.on.debug&&this.on.debug({pat:this.pat})};parsePMT=(t,s)=>{let e=s,i;{const a=t.getUint8(e);e+=1;const o=t.getUint8(e);if(e+=1,o!==2)throw new Error("Invalid PMT table_id");const d=t.getUint16(e)&4095;e+=2;const c=t.getUint16(e);e+=2;const h=(t.getUint8(e)&62)>>1,p=t.getUint8(e)&1;e+=1;const u=t.getUint8(e);e+=1;const g=t.getUint8(e);e+=1;const f=t.getUint16(e)&8191;e+=2;const y=t.getUint16(e)&4095;e+=2,i={pointer_field:a,table_id:o,section_length:d,transport_stream_id:c,version_number:h,current_next_indicator:p,section_number:u,last_section_number:g,pcr_pid:f,program_info_length:y}}const n=[];{const a=i.section_length-9-4,o=e+a;for(;e<o;){const d=t.getUint8(e),c=Z(d),h=t.getUint16(e+1)&8191,p=t.getUint16(e+3)&4095;if(e+=5,h<32||h>8190){console.warn(`Invalid elementary_pid: 0x${h.toString(16)}`);continue}n.push({kind:c,stream_type:d,elementary_pid:h,es_info_length:p})}}const r=t.getUint32(e);this.pmt={header:i,streams:n,crc32:r},this.on.debug&&this.on.debug({pmt:this.pmt})};parseAdaptationField=(t,s)=>{let e=s,i,n,r,a;const o=t.getUint8(e),d=!!(o&128),c=!!(o&64),h=!!(o&32),p=!!(o&16),u=!!(o&8),g=!!(o&4),f=!!(o&2),y=!!(o&1);e+=1;const b=(k,_)=>{let w=BigInt(0);w|=BigInt(k.getUint16(_))<<25n,w|=BigInt(k.getUint16(_+1))<<17n,w|=BigInt(k.getUint16(_+2))<<9n,w|=BigInt(k.getUint16(_+3))<<1n,w|=BigInt(k.getUint16(_+4)>>7);const ot=(k.getUint16(_+4)&1)<<8|k.getUint16(_+5);return w=w*300n+BigInt(ot),w};if(p&&(i=b(t,e),e+=6),u&&(n=b(t,e),e+=6),g&&(r=t.getInt8(e),e+=1),f){const k=t.getUint8(e);e+=1,a=new Uint8Array(t.buffer,e,k),e+=k}return{discontinuity_indicator:d,random_access_indicator:c,elementary_stream_priority_indicator:h,pcr_flag:p,opcr_flag:u,splicing_point_flag:g,transport_private_data_flag:f,adaptation_field_extension_flag:y,pcr:i,opcr:n,splice_countdown:r,transport_private_data:a}};parseAudio=async t=>{const s=new DataView(t.buffer);let e=0,i,n;{const r=s.getUint8(e)===0&&s.getUint8(e+1)===0&&s.getUint8(e+2)===1;if(e+=3,!r)throw new Error("invalid ts audio payload.");const a=s.getUint8(e);e+=1;const o=s.getUint8(e)<<8|s.getUint8(e+1);e+=2;let d,c,h,p,u;{const y=s.getUint8(e);e+=1,d=y>>4&3,c=(y>>3&1)===1,h=(y>>2&1)===1,p=(y>>1&1)===1,u=(y&1)===1}let g,f;{const y=s.getUint8(e);e+=1;const b=y>>6,k=s.getUint8(e);e+=1,(b&2)===2&&(g=this.parsePtsDts(s,e)),(b&1)===1?f=this.parsePtsDts(s,e+5):f=g,e+=k}i={stream_id:a,pes_packet_length:o,scrambling_control:d,priority:c,data_alignment:h,copyright:p,original_copy:u,pts:g,dts:f}}n=t.slice(e);{if(!this.audioConfig&&s.getUint8(e)===255){const h=s.getUint8(e+2),p=s.getUint8(e+3);let u,g;g=h>>2&15,u=(h&1)<<2|p>>6;const f=`mp4a.40.${u}`,b=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350][g];this.audioConfig={kind:"audio",codec:f,sampleRate:b,numberOfChannels:u},this.on.config&&this.on.config(this.audioConfig)}const{dts:r=0,pts:a=0}=i,o=a-r,d=n.slice(7);return{kind:"audio",type:"key",dts:r,pts:a,cts:o,data:d}}};parseVideo=async t=>{const s=new DataView(t.buffer);let e=0,i,n;{const r=s.getUint8(e)===0&&s.getUint8(e+1)===0&&s.getUint8(e+2)===1;if(e+=3,!r)throw new Error("invalid ts video payload.");const a=s.getUint8(e);e+=1;const o=s.getUint8(e)<<8|s.getUint8(e+1);e+=2;let d,c,h,p,u;{const y=s.getUint8(e);e+=1,d=y>>4&3,c=(y>>3&1)===1,h=(y>>2&1)===1,p=(y>>1&1)===1,u=(y&1)===1}let g,f;{const y=s.getUint8(e);e+=1;const b=y>>6,k=s.getUint8(e);e+=1,(b&2)===2&&(g=this.parsePtsDts(s,e)),(b&1)===1?f=this.parsePtsDts(s,e+5):f=g,e+=k}i={stream_id:a,pes_packet_length:o,scrambling_control:d,priority:c,data_alignment:h,copyright:p,original_copy:u,pts:g,dts:f}}n=t.slice(e);{const r=this.getNalus(n);if(!this.videoConfig){let u,g;if(u=r.find(y=>y.type===7)?.nalu.slice(4),g=r.find(y=>y.type===8)?.nalu.slice(4),u&&g){const f=H(u,g),{codec:y}=N(f);this.videoConfig={kind:"video",codec:y,description:f,sps:u,pps:g},this.on.config&&this.on.config(this.videoConfig)}}const a=[];let o="delta";for(const u of r){const{type:g,nalu:f}=u;switch(g){case 6:case 9:a.push(f);break;case 1:o="delta",a.push(f);break;case 5:o="key",a.push(f);break}}const d=X(a),{dts:c=0,pts:h=0}=i,p=h-c;return{kind:"video",type:o,dts:c,pts:h,cts:p,data:d,nalus:a}}};parsePtsDts(t,s){const e=t.getUint8(s),i=t.getUint8(s+1),n=t.getUint8(s+2),r=t.getUint8(s+3),a=t.getUint8(s+4),o=(BigInt(e)&0b00001110n)<<29n|(BigInt(i)&0b11111111n)<<22n|(BigInt(n)&0b11111110n)<<14n|(BigInt(r)&0b11111111n)<<7n|(BigInt(a)&0b11111110n)>>1n;return Number(o)/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 i=e;const n=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 r=e-i;if(t[e-1]===0&&(r-=1),r!==0){const a=t.slice(i,i+r),o=K(a);s.push({type:n,nalu:o})}}return s}}const v=(l,t)=>l.getUint8(t)<<16|l.getUint8(t+1)<<8|l.getUint8(t+2);class et{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 i=this.parseTagHeader(t,s+4),{tagType:n,dataSize:r,timestamp:a}=i;if(n){const o=this.parseTagBody(n,t,s+4+11,r);switch(n){case"script":this.on.info&&this.on.info(o);break;case"audio":{const{accPacketType:d}=o;if(d===0){const{codec:c,sampleRate:h,channelConfiguration:p}=o;this.audioConfig={kind:"audio",codec:c,sampleRate:h,numberOfChannels:p},this.on.config&&this.on.config(this.audioConfig)}else{const{cts:c,data:h}=o,p="key",u=c===void 0?void 0:c+a;this.on.chunk&&this.on.chunk({kind:"audio",type:p,dts:a,pts:u,cts:c,data:h})}}break;case"video":{const{avcPacketType:d}=o;if(d===0){const{codec:c,sps:h,pps:p,data:u}=o;this.videoConfig={kind:"video",codec:c,description:u,sps:h,pps:p},this.on.config&&this.on.config(this.videoConfig)}else{const{frameType:c,cts:h,data:p,nalus:u}=o,g=c===1?"key":"delta",f=h===void 0?void 0:h+a;this.on.chunk&&this.on.chunk({kind:"video",type:g,dts:a,pts:f,cts:h,data:p,nalus:u})}}break}s=s+4+11+r}await new Promise(o=>setTimeout(()=>o(!0),8))}return s};parseHeader=(t,s)=>{let e,i,n,r;e=t.getUint8(s)<<16|t.getUint8(s+1)<<8|t.getUint8(s+2),i=t.getUint8(3);{const o=t.getUint8(0).toString(2).padStart(5,"0").split(""),[,,d,,c]=o;n={audio:c==="1",video:d==="1"}}r=t.getUint32(5),this.header={signature:e,version:i,flags:n,dataOffset:r}};isSurplusTag=(t,s)=>{let e=!0;const i=t.byteLength;if(s+4>i)e=!1;else if(s+4+11>i)e=!1;else{const n=v(t,s+4+1);s+4+11+n>i&&(e=!1)}return e};parseTagHeader=(t,s)=>{let e,i,n,r,a;{const o=t.getUint8(s);let d;switch(o){case 18:d="script";break;case 8:d="audio";break;case 9:d="video";break}e=d}return i=v(t,s+1),n=v(t,s+4),r=t.getUint8(s+7),a=v(t,s+8),{tagType:e,dataSize:i,timestamp:n,timestampExtended:r,streamID:a}};parseTagBody=(t,s,e,i)=>{let n;switch(t){case"script":n=this.parseMetaData(s,e);break;case"audio":n=this.parseAudio(s,e,i);break;case"video":n=this.parseVideo(s,e,i);break}return n};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 i=t.getUint16(e,!1);e=e+2;{const a=new Int8Array(t.buffer.slice(e,e+i));if((this.textDecoder?.decode(a)||"")!=="onMetaData")throw new Error("Expected 'onMetaData' string");e=e+i}const n=this.getAmfType(t,e);return e=e+1,this.getAMFValue(t,e,n).value};parseAudio=(t,s,e)=>{let i=s;const n=t.getUint8(i),r=n>>4&15,a=n>>2&3,o=n>>1&1,d=n&1;i=i+1;const c=t.getUint8(i);i=i+1;const h=e,p=new Uint8Array(t.buffer.slice(i,i+h));if(r===10&&c===0){const u=t.getUint8(i),g=t.getUint8(i+1),f=u>>3&31,y=(u&7)<<1|g>>7,b=g>>3&15,k=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],_=`mp4a.40.${f}`,w=k[y];return{soundFormat:r,soundRate:a,soundSize:o,soundType:d,accPacketType:c,data:p,samplingFrequencyIndex:y,channelConfiguration:b,codec:_,sampleRate:w}}return{soundFormat:r,soundRate:a,soundSize:o,soundType:d,accPacketType:c,data:p}};parseVideo=(t,s,e)=>{let i=s;const n=t.getUint8(i),r=n>>4&15,a=n&15;i=i+1;const o=t.getUint8(i);i=i+1;const d=v(t,i);i=i+3;const c=e-5,h=new Uint8Array(t.buffer.slice(i,i+c));switch(a){case 7:if(o===0){const p=N(h);return{frameType:r,codecID:a,avcPacketType:o,cts:d,data:h,...p}}else if(o===1){const p=[],u=i+e-5;for(;!(i+4>u);){const g=t.getUint32(i,!1),f=new Uint8Array(t.buffer.slice(i,i+4+g));i+=4+g,p.push(f)}return{frameType:r,codecID:a,avcPacketType:o,cts:d,data:h,nalus:p}}break;default:throw new Error("Unsupported codecID")}return{frameType:r,codecID:a,avcPacketType:o,cts:d,data:h}};getAmfType=(t,s)=>t.getUint8(s);getAMFName=(t,s,e)=>{const i=new Uint8Array(t.buffer.slice(s,s+e));return this.textDecoder?.decode(i)||""};getAMFValue=(t,s,e)=>{let i=s,n,r=0;switch(e){case 0:n=t.getFloat64(i,!1),r=8;break;case 1:n=!!t.getUint8(i),r=1;break;case 2:{n="";const o=t.getUint16(i,!1);i=i+2;const d=new Int8Array(t.buffer,i,o).filter(h=>h!==0);n=(this.textDecoder?.decode(d)||"").trim(),r=2+o}break;case 3:for(n={};i<t.byteLength;){const o=t.getUint16(i,!1);if(o===0)break;i=i+2;const d=this.getAMFName(t,i,o);i=i+o;const c=this.getAmfType(t,i);if(c===6)break;i=i+1;const h=this.getAMFValue(t,i,c);i=i+h.length,n[d]=h.value,r=2+o+1+h.length}break;case 8:{n={};const o=t.getUint32(i,!1);i=i+4;for(let d=0;d<o;d++){const c=t.getUint16(i,!1);i=i+2;const h=this.getAMFName(t,i,c);i=i+c;const p=this.getAmfType(t,i);i=i+1;const u=this.getAMFValue(t,i,p);i=i+u.length,n[h]=u.value,r=2+c+1+u.length}}break;case 10:{n=[];const o=t.getUint32(i,!1);i=i+4;for(let d=0;d<o;d++){const c=this.getAmfType(t,i);i=i+1;const h=this.getAMFValue(t,i,c);i=i+h.length,n.push(h.value),r=1+h.length}}break}return{amfType:e,length:r,value:n}}}class st{pattern;cacher=new J;isParseing=!1;offset=0;on={};parser;constructor(){}init=t=>{switch(this.destroy(),this.pattern=t,this.pattern){case"flv":this.parser=new et;break;case"hls":this.parser=new tt;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()}}}class it{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=t=>{const{decodingSpeed:s,frameTrack:e,minFrameTrackCacheNum:i}=t;s!==void 0&&(this.decodingSpeed=s),e!==void 0&&(this.frameTrack=e),i!==void 0&&(this.minFrameTrackCacheNum=i)};setFrameTrack=t=>{this.frameTrack=t,this.frameTrack===!1&&(this.decodingSpeedRatio=1)};initDecodeInterval=()=>{let t=this.decodingSpeed/this.decodingSpeedRatio;const s=this.baseTime+performance.now();if(this.nextRenderTime){const e=s-this.nextRenderTime;t-=e}this.nextRenderTime=s+t,this.decodeTimer=setTimeout(()=>{this.decode(),this.initDecodeInterval()},t)};decode=()=>{if(this.isProcessing!==!0){for(this.isProcessing=!0;;){const t=this.pendingChunks.shift();if(this.frameTrack){const i=this.pendingChunks.length;if(i>=this.minFrameTrackCacheNum){const n=Math.min(1+(i-this.minFrameTrackCacheNum)/100,this.maxDecodingSpeedRatio);this.decodingSpeedRatio=Number(n.toFixed(1))}else this.decodingSpeedRatio=1}if(!t)break;const{type:s,init:e}=t;switch(s){case"audio":this.decodeAudio(e);break;case"video":this.decodeVideo(e);break}if(s==="video")break}this.isProcessing=!1}};decodeAudio=t=>{if(!this.audioDecoder)return;const s=new EncodedAudioChunk(t);this.audioDecoder.decode(s)};decodeVideo=t=>{if(this.videoDecoder&&(t.type==="key"&&(this.hasKeyFrame=!0),this.hasKeyFrame)){const s=new EncodedVideoChunk(t);this.videoDecoder.decode(s)}};destroy=()=>{this.audio.destroy(),this.video.destroy(),clearInterval(this.decodeTimer)};audio={init:t=>{this.audio.destroy(),this.audioDecoderConfig={...t},this.audioDecoder=new AudioDecoder({output:s=>{const e=this.decodingSpeedRatio;this.on.audio.decode&&this.on.audio.decode({audioData:s,playbackRate:e})},error:s=>{this.on.audio.error&&this.on.audio.error(s)}}),this.audioDecoder.configure(this.audioDecoderConfig)},push:t=>{this.pendingChunks.push({type:"audio",init:t})},flush:()=>{this.audioDecoder?.flush()},destroy:()=>{this.audioDecoderConfig=void 0,this.audioDecoder?.close(),this.audioDecoder=void 0}};video={init:t=>{this.video.destroy(),this.videoDecoderConfig={...t},this.videoDecoder=new VideoDecoder({output:async s=>{const e=s.timestamp+this.baseTime*1e3,i=await createImageBitmap(s);s.close(),i.width>0&&i.height>0?this.on.video.decode&&this.on.video.decode({timestamp:e,bitmap:i}):i.close()},error:s=>{this.on.video.error&&this.on.video.error(s)}}),this.videoDecoder.configure(this.videoDecoderConfig)},push:t=>{this.pendingChunks.push({type:"video",init:t})},flush:()=>{this.videoDecoder?.flush()},destroy:()=>{this.videoDecoderConfig=void 0,this.videoDecoder?.close(),this.videoDecoder=void 0,this.hasKeyFrame=!1}}}class nt{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:e}=t;if(this.cutOption){const{sx:n=0,sy:r=0,sw:a=e.width,sh:o=e.height}=this.cutOption;e=await createImageBitmap(e,n,r,a,o)}const i=new VideoFrame(e,{timestamp:s});this.cutOption&&e.close(),this.writer.write(i),i.close()};setCut=t=>{this.cutOption=t};setPause=t=>{this.pause=t};destroy=()=>{this.writable=void 0,this.writer=void 0,this.cutOption=void 0}}U.Decoder=it,U.DecoderWorker=S,U.Demuxer=st,U.DemuxerWorker=x,U.PrPlayer=Q,U.Render=nt,U.RenderWorker=R,Object.defineProperty(U,Symbol.toStringTag,{value:"Module"})}));
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pr-player",
|
|
3
|
-
"description": "对 flv 格式的地址进行解析 并输出
|
|
4
|
-
"version": "0.2.
|
|
3
|
+
"description": "对 flv 格式的地址进行解析 并输出 stream,提供 SEI 回调,以及 cut 等相关能力,以支持根据业务层 SEI 对视频进行剪切渲染。",
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|