@give-tech/ec-player 0.0.1-beta.31 → 0.0.1-beta.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +76 -10
- package/dist/index.js.map +1 -1
- package/dist/player/FLVPlayer.d.ts +1 -0
- package/dist/player/FLVPlayer.d.ts.map +1 -1
- package/dist/player/HLSPlayer.d.ts +5 -1
- package/dist/player/HLSPlayer.d.ts.map +1 -1
- package/dist/prefetch/SegmentPrefetcher.d.ts +2 -1
- package/dist/prefetch/SegmentPrefetcher.d.ts.map +1 -1
- package/dist/prefetch/types.d.ts +2 -0
- package/dist/prefetch/types.d.ts.map +1 -1
- package/package.json +1 -4
- package/wasm/decoder.js +19 -0
- package/wasm/decoder.wasm +0 -0
package/dist/index.js
CHANGED
|
@@ -1238,7 +1238,8 @@ class SegmentPrefetcher extends BasePrefetcher {
|
|
|
1238
1238
|
this.prefetchQueue.push({
|
|
1239
1239
|
data,
|
|
1240
1240
|
segmentIndex: nextIndex,
|
|
1241
|
-
fetchTime
|
|
1241
|
+
fetchTime,
|
|
1242
|
+
segmentDuration: segment.duration
|
|
1242
1243
|
});
|
|
1243
1244
|
this.fetchedSegmentCount++;
|
|
1244
1245
|
this.updateStatus({
|
|
@@ -1276,7 +1277,7 @@ class SegmentPrefetcher extends BasePrefetcher {
|
|
|
1276
1277
|
this.prefetchQueue.shift();
|
|
1277
1278
|
this.updateStatus({ prefetchQueueSize: this.prefetchQueue.length });
|
|
1278
1279
|
const parseStart = performance.now();
|
|
1279
|
-
const itemCount = this.parseSegment(item.data, item.segmentIndex);
|
|
1280
|
+
const itemCount = this.parseSegment(item.data, item.segmentIndex, item.segmentDuration);
|
|
1280
1281
|
const parseTime = performance.now() - parseStart;
|
|
1281
1282
|
this.currentSegmentIndex++;
|
|
1282
1283
|
this.updateStatus({ currentSegmentIndex: this.currentSegmentIndex });
|
|
@@ -1548,11 +1549,11 @@ class HLSSegmentPrefetcher extends SegmentPrefetcher {
|
|
|
1548
1549
|
/**
|
|
1549
1550
|
* 解析分片数据
|
|
1550
1551
|
*/
|
|
1551
|
-
parseSegment(data, index) {
|
|
1552
|
+
parseSegment(data, index, segmentDuration) {
|
|
1552
1553
|
if (this.player.isFMP4) {
|
|
1553
1554
|
return this.player.parseFMP4Data(data);
|
|
1554
1555
|
} else {
|
|
1555
|
-
return this.player.parseTSData(data);
|
|
1556
|
+
return this.player.parseTSData(data, segmentDuration);
|
|
1556
1557
|
}
|
|
1557
1558
|
}
|
|
1558
1559
|
/**
|
|
@@ -1584,14 +1585,36 @@ class HLSPlayer extends BasePlayer {
|
|
|
1584
1585
|
this.currentPlaylistUrl = "";
|
|
1585
1586
|
this._nalQueue = [];
|
|
1586
1587
|
this._sampleQueue = [];
|
|
1588
|
+
this._currentSegmentDuration = 0;
|
|
1587
1589
|
this.prefetcher = null;
|
|
1590
|
+
this._nalCountInCurrentSegment = 0;
|
|
1588
1591
|
this.lastRenderTime = 0;
|
|
1589
1592
|
this.playStartTime = 0;
|
|
1590
1593
|
this.accumulatedMediaTime = 0;
|
|
1591
1594
|
this._lastLogTime = 0;
|
|
1595
|
+
this._lastRafTime = 0;
|
|
1592
1596
|
this.renderLoop = (timestamp = 0) => {
|
|
1593
1597
|
if (!this.isPlaying) return;
|
|
1594
1598
|
const now = performance.now();
|
|
1599
|
+
const BACKGROUND_PAUSE_THRESHOLD = 500;
|
|
1600
|
+
if (this._lastRafTime > 0 && now - this._lastRafTime > BACKGROUND_PAUSE_THRESHOLD) {
|
|
1601
|
+
const pauseDuration = now - this._lastRafTime;
|
|
1602
|
+
console.log("[renderLoop] Background pause detected, duration:", pauseDuration.toFixed(0), "ms");
|
|
1603
|
+
if (this.config.isLive) {
|
|
1604
|
+
const KEEP_FRAMES = 5;
|
|
1605
|
+
if (this.frameBuffer.length > KEEP_FRAMES) {
|
|
1606
|
+
const droppedCount = this.frameBuffer.length - KEEP_FRAMES;
|
|
1607
|
+
this.frameBuffer = this.frameBuffer.slice(-KEEP_FRAMES);
|
|
1608
|
+
this.droppedFrames += droppedCount;
|
|
1609
|
+
console.log("[renderLoop] Live resume: dropped", droppedCount, "old frames, keeping latest", KEEP_FRAMES);
|
|
1610
|
+
}
|
|
1611
|
+
this.playStartTime = now;
|
|
1612
|
+
this.accumulatedMediaTime = 0;
|
|
1613
|
+
} else {
|
|
1614
|
+
this.playStartTime = now - this.accumulatedMediaTime;
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
this._lastRafTime = now;
|
|
1595
1618
|
if (!this._lastLogTime || now - this._lastLogTime > 1e3) {
|
|
1596
1619
|
this._lastLogTime = now;
|
|
1597
1620
|
console.log("[renderLoop] frameBuffer=", this.frameBuffer.length, "renderer=", !!this.renderer);
|
|
@@ -1696,6 +1719,8 @@ class HLSPlayer extends BasePlayer {
|
|
|
1696
1719
|
isLoaded: true,
|
|
1697
1720
|
totalSegments: segments.length
|
|
1698
1721
|
});
|
|
1722
|
+
this.initPrefetcher();
|
|
1723
|
+
this.prefetcher.start();
|
|
1699
1724
|
}
|
|
1700
1725
|
/**
|
|
1701
1726
|
* 初始化解码器(覆盖基类方法,添加 fMP4 支持)
|
|
@@ -1792,11 +1817,12 @@ class HLSPlayer extends BasePlayer {
|
|
|
1792
1817
|
while (this.nalQueue.length > 0 && decodedInBatch < batchSize) {
|
|
1793
1818
|
const queuedNal = this.nalQueue.shift();
|
|
1794
1819
|
const nalUnit = queuedNal.nalUnit;
|
|
1820
|
+
const segmentDuration = queuedNal.segmentDuration;
|
|
1795
1821
|
if (!this.decoderInitialized && (nalUnit.type === 7 || nalUnit.type === 8)) {
|
|
1796
1822
|
this.initDecoderParamsSync([nalUnit]);
|
|
1797
1823
|
}
|
|
1798
1824
|
if (nalUnit.type === 5 || nalUnit.type === 1) {
|
|
1799
|
-
const frame = this.decodeNAL(nalUnit);
|
|
1825
|
+
const frame = this.decodeNAL(nalUnit, segmentDuration);
|
|
1800
1826
|
if (frame) {
|
|
1801
1827
|
this.frameBuffer.push(frame);
|
|
1802
1828
|
decodedInBatch++;
|
|
@@ -1910,7 +1936,7 @@ class HLSPlayer extends BasePlayer {
|
|
|
1910
1936
|
/**
|
|
1911
1937
|
* 解析 TS 数据
|
|
1912
1938
|
*/
|
|
1913
|
-
parseTSData(tsData) {
|
|
1939
|
+
parseTSData(tsData, segmentDuration) {
|
|
1914
1940
|
const packets = this.tsDemuxer.parse(tsData);
|
|
1915
1941
|
let nalCount = 0;
|
|
1916
1942
|
if (packets.video.length > 0) {
|
|
@@ -1920,8 +1946,15 @@ class HLSPlayer extends BasePlayer {
|
|
|
1920
1946
|
if (!this.decoderInitialized) {
|
|
1921
1947
|
this.initDecoderParamsSync(nalUnits);
|
|
1922
1948
|
}
|
|
1949
|
+
if (segmentDuration !== void 0) {
|
|
1950
|
+
this._currentSegmentDuration = segmentDuration;
|
|
1951
|
+
}
|
|
1923
1952
|
for (const nalUnit of nalUnits) {
|
|
1924
|
-
this._nalQueue.push({
|
|
1953
|
+
this._nalQueue.push({
|
|
1954
|
+
nalUnit,
|
|
1955
|
+
pts: 0,
|
|
1956
|
+
segmentDuration: this._currentSegmentDuration
|
|
1957
|
+
});
|
|
1925
1958
|
}
|
|
1926
1959
|
nalCount = nalUnits.length;
|
|
1927
1960
|
}
|
|
@@ -1978,7 +2011,13 @@ class HLSPlayer extends BasePlayer {
|
|
|
1978
2011
|
this._sampleQueue.length = 0;
|
|
1979
2012
|
this._nalQueue.length = 0;
|
|
1980
2013
|
const url = uri.startsWith("http") ? uri : this.currentPlaylistUrl.substring(0, this.currentPlaylistUrl.lastIndexOf("/") + 1) + uri;
|
|
1981
|
-
const
|
|
2014
|
+
const headers = {};
|
|
2015
|
+
if (this.initSegment?.uri === uri && this.initSegment.byteRange) {
|
|
2016
|
+
const { start, end } = this.initSegment.byteRange;
|
|
2017
|
+
headers["Range"] = `bytes=${start}-${end}`;
|
|
2018
|
+
console.log("[fMP4] Using byte range for init segment:", { start, end });
|
|
2019
|
+
}
|
|
2020
|
+
const response = await fetch(url, { headers });
|
|
1982
2021
|
const data = new Uint8Array(await response.arrayBuffer());
|
|
1983
2022
|
console.log("[fMP4] New init segment data size:", data.length, "bytes");
|
|
1984
2023
|
const initInfo = this.fmp4Demuxer.parseInitSegment(data);
|
|
@@ -2297,16 +2336,22 @@ class HLSPlayer extends BasePlayer {
|
|
|
2297
2336
|
/**
|
|
2298
2337
|
* 解码单个 NAL 单元
|
|
2299
2338
|
*/
|
|
2300
|
-
decodeNAL(nalUnit) {
|
|
2339
|
+
decodeNAL(nalUnit, segmentDuration) {
|
|
2301
2340
|
if (!this.decoder) return null;
|
|
2302
2341
|
const nalWithStartCode = new Uint8Array(nalUnit.size + 4);
|
|
2303
2342
|
nalWithStartCode.set([0, 0, 0, 1], 0);
|
|
2304
2343
|
nalWithStartCode.set(nalUnit.data, 4);
|
|
2305
|
-
|
|
2344
|
+
const frame = this.decoder.decode({
|
|
2306
2345
|
type: nalUnit.type,
|
|
2307
2346
|
data: nalWithStartCode,
|
|
2308
2347
|
size: nalWithStartCode.length
|
|
2309
2348
|
});
|
|
2349
|
+
if (frame && segmentDuration && segmentDuration > 0) {
|
|
2350
|
+
const timescale = 1e3;
|
|
2351
|
+
const frameDuration = timescale / 60;
|
|
2352
|
+
frame.duration = frameDuration;
|
|
2353
|
+
}
|
|
2354
|
+
return frame;
|
|
2310
2355
|
}
|
|
2311
2356
|
}
|
|
2312
2357
|
const FLV_SIGNATURE = [70, 76, 86];
|
|
@@ -2842,6 +2887,7 @@ class FLVPlayer extends BasePlayer {
|
|
|
2842
2887
|
this.bufferEmptyStartTime = 0;
|
|
2843
2888
|
this.playStartTimeOffset = 0;
|
|
2844
2889
|
this.resyncCount = 0;
|
|
2890
|
+
this._lastRafTime = 0;
|
|
2845
2891
|
this.renderLoop = () => {
|
|
2846
2892
|
if (!this.isPlaying) return;
|
|
2847
2893
|
this.updateState({
|
|
@@ -2851,12 +2897,32 @@ class FLVPlayer extends BasePlayer {
|
|
|
2851
2897
|
});
|
|
2852
2898
|
const now = performance.now();
|
|
2853
2899
|
const isLive = this.config.isLive;
|
|
2900
|
+
const BACKGROUND_PAUSE_THRESHOLD = 500;
|
|
2901
|
+
if (this._lastRafTime > 0 && now - this._lastRafTime > BACKGROUND_PAUSE_THRESHOLD) {
|
|
2902
|
+
const pauseDuration = now - this._lastRafTime;
|
|
2903
|
+
console.log("[FLVPlayer] Background pause detected, duration:", pauseDuration.toFixed(0), "ms, isLive:", isLive, "queue:", this._videoTagQueue.length, "buffer:", this._timedFrameBuffer.length);
|
|
2904
|
+
if (isLive) {
|
|
2905
|
+
const droppedDecoded = this._timedFrameBuffer.length;
|
|
2906
|
+
const droppedQueue = this._videoTagQueue.length;
|
|
2907
|
+
this._timedFrameBuffer = [];
|
|
2908
|
+
this._videoTagQueue = [];
|
|
2909
|
+
this.droppedFrames += droppedDecoded;
|
|
2910
|
+
this.playStartTime = 0;
|
|
2911
|
+
this.firstFrameDts = -1;
|
|
2912
|
+
this.pausedTime = 0;
|
|
2913
|
+
console.log("[FLVPlayer] Live resume: cleared all buffers (decoded:", droppedDecoded, ", queue:", droppedQueue, "), waiting for new data");
|
|
2914
|
+
} else {
|
|
2915
|
+
this.playStartTimeOffset += pauseDuration;
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
this._lastRafTime = now;
|
|
2854
2919
|
if (this._timedFrameBuffer.length > 0 && this.renderer) {
|
|
2855
2920
|
this.consecutiveEmptyBuffer = 0;
|
|
2856
2921
|
if (this.playStartTime <= 0) {
|
|
2857
2922
|
this.firstFrameDts = this._timedFrameBuffer[0].dts;
|
|
2858
2923
|
this.playStartTime = now;
|
|
2859
2924
|
this.playStartTimeOffset = 0;
|
|
2925
|
+
this.pausedTime = 0;
|
|
2860
2926
|
console.log("[FLVPlayer] RenderLoop initialized, firstFrameDts:", this.firstFrameDts, "isLive:", isLive);
|
|
2861
2927
|
}
|
|
2862
2928
|
if (isLive) {
|