@editframe/assets 0.18.3-beta.0 → 0.18.7-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Probe.d.ts +441 -29
- package/dist/Probe.js +156 -21
- package/dist/generateTrackFragmentIndexMediabunny.d.ts +3 -0
- package/dist/generateTrackFragmentIndexMediabunny.js +343 -0
- package/dist/generateTrackMediabunny.d.ts +8 -0
- package/dist/generateTrackMediabunny.js +69 -0
- package/dist/idempotentTask.js +33 -35
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/tasks/findOrCreateCaptions.js +1 -1
- package/dist/tasks/generateTrack.d.ts +1 -2
- package/dist/tasks/generateTrack.js +5 -32
- package/dist/tasks/generateTrackFragmentIndex.js +11 -75
- package/dist/truncateDecimal.d.ts +1 -0
- package/dist/truncateDecimal.js +5 -0
- package/package.json +2 -14
- package/src/tasks/generateTrack.test.ts +90 -0
- package/src/tasks/generateTrack.ts +7 -48
- package/src/tasks/generateTrackFragmentIndex.test.ts +115 -0
- package/src/tasks/generateTrackFragmentIndex.ts +27 -98
- package/types.json +1 -1
- package/dist/DecoderManager.d.ts +0 -62
- package/dist/DecoderManager.js +0 -114
- package/dist/EncodedAsset.d.ts +0 -143
- package/dist/EncodedAsset.js +0 -443
- package/dist/FrameBuffer.d.ts +0 -62
- package/dist/FrameBuffer.js +0 -89
- package/dist/MP4File.d.ts +0 -37
- package/dist/MP4File.js +0 -209
- package/dist/MP4SampleAnalyzer.d.ts +0 -59
- package/dist/MP4SampleAnalyzer.js +0 -119
- package/dist/SeekStrategy.d.ts +0 -82
- package/dist/SeekStrategy.js +0 -101
- package/dist/memoize.js +0 -11
- package/dist/mp4FileWritable.d.ts +0 -3
- package/dist/mp4FileWritable.js +0 -19
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { idempotentTask } from "../idempotentTask.js";
|
|
2
|
-
import { MP4File } from "../MP4File.js";
|
|
3
2
|
import debug from "debug";
|
|
4
|
-
import { mp4FileWritable } from "../mp4FileWritable.js";
|
|
5
3
|
import { basename } from "node:path";
|
|
6
|
-
import { Probe
|
|
4
|
+
import { Probe } from "../Probe.js";
|
|
5
|
+
import { generateTrackFragmentIndexMediabunny } from "../generateTrackFragmentIndexMediabunny.js";
|
|
6
|
+
import type { TrackFragmentIndex } from "../Probe.js";
|
|
7
7
|
|
|
8
8
|
export const generateTrackFragmentIndexFromPath = async (
|
|
9
9
|
absolutePath: string,
|
|
@@ -29,109 +29,38 @@ export const generateTrackFragmentIndexFromPath = async (
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const mp4File = new MP4File();
|
|
35
|
-
|
|
36
|
-
log(`Generating track fragment index for ${absolutePath}`);
|
|
37
|
-
readStream.pipe(mp4FileWritable(mp4File));
|
|
38
|
-
await new Promise((resolve, reject) => {
|
|
39
|
-
readStream.on("end", resolve);
|
|
40
|
-
readStream.on("error", reject);
|
|
41
|
-
});
|
|
32
|
+
log(`Generating track fragment index for ${absolutePath} using single-track approach`);
|
|
42
33
|
|
|
34
|
+
// FIXED: Generate fragment indexes from individual single-track files
|
|
35
|
+
// This ensures byte offsets match the actual single-track files that clients will request
|
|
43
36
|
const trackFragmentIndexes: Record<number, TrackFragmentIndex> = {};
|
|
44
|
-
const trackByteOffsets: Record<number, number> = {};
|
|
45
|
-
for await (const fragment of mp4File.fragmentIterator()) {
|
|
46
|
-
const track = mp4File
|
|
47
|
-
.getInfo()
|
|
48
|
-
.tracks.find((track) => track.id === fragment.track);
|
|
49
37
|
|
|
50
|
-
|
|
51
|
-
|
|
38
|
+
// Process each audio/video stream as a separate track
|
|
39
|
+
for (let streamIndex = 0; streamIndex < probe.streams.length; streamIndex++) {
|
|
40
|
+
const stream = probe.streams[streamIndex]!;
|
|
41
|
+
|
|
42
|
+
// Only process audio and video streams
|
|
43
|
+
if (stream.codec_type !== 'audio' && stream.codec_type !== 'video') {
|
|
44
|
+
continue;
|
|
52
45
|
}
|
|
53
46
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (track?.type === "video") {
|
|
57
|
-
const videoTrack = mp4File
|
|
58
|
-
.getInfo()
|
|
59
|
-
.videoTracks.find((track) => track.id === fragment.track);
|
|
60
|
-
if (!videoTrack) {
|
|
61
|
-
throw new Error("Video track not found");
|
|
62
|
-
}
|
|
63
|
-
trackFragmentIndexes[fragment.track] = {
|
|
64
|
-
track: fragment.track,
|
|
65
|
-
type: "video",
|
|
66
|
-
width: videoTrack.video.width,
|
|
67
|
-
height: videoTrack.video.height,
|
|
68
|
-
timescale: track.timescale,
|
|
69
|
-
sample_count: videoTrack.nb_samples,
|
|
70
|
-
codec: videoTrack.codec,
|
|
71
|
-
duration: videoTrack.duration,
|
|
72
|
-
startTimeOffsetMs: startTimeOffsetMs, // Add FFmpeg start_time offset
|
|
73
|
-
initSegment: {
|
|
74
|
-
offset: 0,
|
|
75
|
-
size: fragment.data.byteLength,
|
|
76
|
-
},
|
|
77
|
-
segments: [],
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
if (track?.type === "audio") {
|
|
81
|
-
const audioTrack = mp4File
|
|
82
|
-
.getInfo()
|
|
83
|
-
.audioTracks.find((track) => track.id === fragment.track);
|
|
84
|
-
if (!audioTrack) {
|
|
85
|
-
throw new Error("Audio track not found");
|
|
86
|
-
}
|
|
87
|
-
trackFragmentIndexes[fragment.track] = {
|
|
88
|
-
track: fragment.track,
|
|
89
|
-
type: "audio",
|
|
90
|
-
channel_count: audioTrack.audio.channel_count,
|
|
91
|
-
sample_rate: audioTrack.audio.sample_rate,
|
|
92
|
-
sample_size: audioTrack.audio.sample_size,
|
|
93
|
-
sample_count: audioTrack.nb_samples,
|
|
94
|
-
timescale: track.timescale,
|
|
95
|
-
codec: audioTrack.codec,
|
|
96
|
-
duration: audioTrack.duration,
|
|
97
|
-
initSegment: {
|
|
98
|
-
offset: 0,
|
|
99
|
-
size: fragment.data.byteLength,
|
|
100
|
-
},
|
|
101
|
-
segments: [],
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
} else {
|
|
105
|
-
const fragmentIndex = trackFragmentIndexes[fragment.track];
|
|
106
|
-
if (trackByteOffsets[fragment.track] === undefined) {
|
|
107
|
-
throw new Error("Fragment index not found");
|
|
108
|
-
}
|
|
109
|
-
if (!fragmentIndex) {
|
|
110
|
-
throw new Error("Fragment index not found");
|
|
111
|
-
}
|
|
47
|
+
const trackId = streamIndex + 1; // Convert to 1-based track ID
|
|
48
|
+
log(`Processing track ${trackId} (${stream.codec_type})`);
|
|
112
49
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
fragmentIndex.startTimeOffsetMs === undefined &&
|
|
117
|
-
fragment.cts > fragment.dts) {
|
|
118
|
-
// Calculate composition time offset in milliseconds
|
|
119
|
-
const compositionOffsetMs = ((fragment.cts - fragment.dts) / fragmentIndex.timescale) * 1000;
|
|
120
|
-
fragmentIndex.startTimeOffsetMs = compositionOffsetMs;
|
|
121
|
-
log(`Detected composition time offset from first video segment: ${compositionOffsetMs}ms (CTS=${fragment.cts}, DTS=${fragment.dts}, timescale=${fragmentIndex.timescale})`);
|
|
122
|
-
}
|
|
50
|
+
// Generate single-track file and its fragment index
|
|
51
|
+
const trackStream = probe.createTrackReadstream(streamIndex);
|
|
52
|
+
const trackIdMapping = { 1: trackId }; // Map single-track ID 1 to original track ID
|
|
123
53
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
trackByteOffsets[fragment.track]! += fragment.data.byteLength;
|
|
133
|
-
}
|
|
54
|
+
const singleTrackIndexes = await generateTrackFragmentIndexMediabunny(
|
|
55
|
+
trackStream,
|
|
56
|
+
startTimeOffsetMs,
|
|
57
|
+
trackIdMapping
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
// Merge the single-track index into the combined result
|
|
61
|
+
Object.assign(trackFragmentIndexes, singleTrackIndexes);
|
|
134
62
|
}
|
|
63
|
+
|
|
135
64
|
return trackFragmentIndexes;
|
|
136
65
|
};
|
|
137
66
|
|