@invintusmedia/tomp4 1.3.0 → 1.3.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/tomp4.js +2 -2
- package/package.json +1 -1
- package/src/hls-clip.js +16 -14
- package/src/index.js +1 -1
package/dist/tomp4.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* toMp4.js v1.3.
|
|
2
|
+
* toMp4.js v1.3.1
|
|
3
3
|
* Convert MPEG-TS and fMP4 to standard MP4
|
|
4
4
|
* https://github.com/TVWIT/toMp4.js
|
|
5
5
|
* MIT License
|
|
@@ -1186,7 +1186,7 @@
|
|
|
1186
1186
|
toMp4.isMpegTs = isMpegTs;
|
|
1187
1187
|
toMp4.isFmp4 = isFmp4;
|
|
1188
1188
|
toMp4.isStandardMp4 = isStandardMp4;
|
|
1189
|
-
toMp4.version = '1.3.
|
|
1189
|
+
toMp4.version = '1.3.1';
|
|
1190
1190
|
|
|
1191
1191
|
return toMp4;
|
|
1192
1192
|
});
|
package/package.json
CHANGED
package/src/hls-clip.js
CHANGED
|
@@ -78,8 +78,13 @@ function remuxToFragment(parser, sequenceNumber, videoBaseTime, audioBaseTime, a
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
|
-
* Clip a parsed TS segment at the start
|
|
82
|
-
*
|
|
81
|
+
* Clip a parsed TS segment at the start and/or end.
|
|
82
|
+
*
|
|
83
|
+
* Starts at the nearest keyframe at or before startTime (required for
|
|
84
|
+
* decoding). No preroll/edit-list — hls.js doesn't read edit lists, so
|
|
85
|
+
* every frame in the fMP4 gets played. The EXTINF duration matches the
|
|
86
|
+
* actual content, which means the clip may start slightly before the
|
|
87
|
+
* requested time (at the keyframe).
|
|
83
88
|
*/
|
|
84
89
|
function clipSegment(parser, startTime, endTime) {
|
|
85
90
|
const startPts = (startTime !== undefined ? startTime : 0) * PTS_PER_SECOND;
|
|
@@ -104,9 +109,8 @@ function clipSegment(parser, startTime, endTime) {
|
|
|
104
109
|
if (clippedVideo.length === 0) return null;
|
|
105
110
|
|
|
106
111
|
const keyframePts = clippedVideo[0].pts;
|
|
107
|
-
const prerollPts = Math.max(0, startPts - keyframePts);
|
|
108
112
|
|
|
109
|
-
// Clip audio from keyframe (for A/V sync
|
|
113
|
+
// Clip audio from keyframe (same start as video for A/V sync)
|
|
110
114
|
const lastVideoPts = clippedVideo[clippedVideo.length - 1].pts;
|
|
111
115
|
const audioEndPts = Math.min(endPts, lastVideoPts + PTS_PER_SECOND);
|
|
112
116
|
const clippedAudio = audioAUs.filter(au => au.pts >= keyframePts && au.pts < audioEndPts);
|
|
@@ -116,19 +120,16 @@ function clipSegment(parser, startTime, endTime) {
|
|
|
116
120
|
for (const au of clippedVideo) { au.pts -= offset; au.dts -= offset; }
|
|
117
121
|
for (const au of clippedAudio) { au.pts -= offset; }
|
|
118
122
|
|
|
119
|
-
//
|
|
120
|
-
const
|
|
123
|
+
// Duration = full content from keyframe (no preroll subtraction)
|
|
124
|
+
const duration = clippedVideo.length > 1
|
|
121
125
|
? clippedVideo[clippedVideo.length - 1].dts - clippedVideo[0].dts +
|
|
122
|
-
(clippedVideo[1].dts - clippedVideo[0].dts)
|
|
126
|
+
(clippedVideo[1].dts - clippedVideo[0].dts)
|
|
123
127
|
: 3003;
|
|
124
|
-
const playbackDuration = (videoDuration - prerollPts) / PTS_PER_SECOND;
|
|
125
128
|
|
|
126
129
|
return {
|
|
127
130
|
videoSamples: clippedVideo,
|
|
128
131
|
audioSamples: clippedAudio,
|
|
129
|
-
|
|
130
|
-
playbackDuration: Math.max(0, playbackDuration),
|
|
131
|
-
mediaDuration: videoDuration / PTS_PER_SECOND,
|
|
132
|
+
duration: duration / PTS_PER_SECOND,
|
|
132
133
|
};
|
|
133
134
|
}
|
|
134
135
|
|
|
@@ -383,13 +384,13 @@ export async function clipHls(source, options = {}) {
|
|
|
383
384
|
});
|
|
384
385
|
|
|
385
386
|
clipSegments.push({
|
|
386
|
-
duration: firstClipped.
|
|
387
|
+
duration: firstClipped.duration,
|
|
387
388
|
data: firstFragment, // pre-clipped, in memory
|
|
388
389
|
originalUrl: null,
|
|
389
390
|
timelineOffset: 0,
|
|
390
391
|
isBoundary: true,
|
|
391
392
|
});
|
|
392
|
-
timelineOffset += firstClipped.
|
|
393
|
+
timelineOffset += firstClipped.duration;
|
|
393
394
|
|
|
394
395
|
// ── Middle segments (pass-through, remuxed on demand) ──
|
|
395
396
|
for (let i = 1; i < overlapping.length - 1; i++) {
|
|
@@ -410,6 +411,7 @@ export async function clipHls(source, options = {}) {
|
|
|
410
411
|
const lastRelEnd = endTime - lastSeg.startTime;
|
|
411
412
|
const lastClipped = clipSegment(lastParser, undefined, lastRelEnd);
|
|
412
413
|
if (lastClipped && lastClipped.videoSamples.length > 0) {
|
|
414
|
+
const lastDuration = lastClipped.duration;
|
|
413
415
|
const lastSeqNum = overlapping.length;
|
|
414
416
|
const lastVideoBaseTime = Math.round(timelineOffset * PTS_PER_SECOND);
|
|
415
417
|
const lastAudioBaseTime = Math.round(timelineOffset * audioTimescale);
|
|
@@ -426,7 +428,7 @@ export async function clipHls(source, options = {}) {
|
|
|
426
428
|
});
|
|
427
429
|
|
|
428
430
|
clipSegments.push({
|
|
429
|
-
duration: lastClipped.
|
|
431
|
+
duration: lastClipped.duration,
|
|
430
432
|
data: lastFragment,
|
|
431
433
|
originalUrl: null,
|
|
432
434
|
timelineOffset,
|
package/src/index.js
CHANGED