@remotion/media-parser 4.0.227 → 4.0.229
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/boxes/iso-base-media/mdat/mdat.js +5 -6
- package/dist/boxes/webm/ebml.d.ts +1 -1
- package/dist/boxes/webm/get-sample-from-block.js +1 -0
- package/dist/create/cluster.d.ts +9 -10
- package/dist/create/cluster.js +33 -14
- package/dist/create/create-media.d.ts +7 -3
- package/dist/create/create-media.js +7 -2
- package/dist/create/polyfill-audio-sample.d.ts +3 -0
- package/dist/create/polyfill-audio-sample.js +15 -0
- package/dist/esm/buffer.mjs +6 -7
- package/dist/esm/from-fetch.mjs +1 -1
- package/dist/esm/index.mjs +85 -23
- package/dist/esm/web-fs.mjs +6 -0
- package/dist/index.d.ts +17 -3
- package/dist/index.js +2 -0
- package/dist/log.d.ts +10 -0
- package/dist/log.js +37 -0
- package/dist/options.d.ts +6 -3
- package/dist/readers/from-fetch.js +1 -1
- package/dist/webcodec-sample-types.d.ts +7 -0
- package/dist/writers/buffer-implementation/multi-buffer.d.ts +0 -0
- package/dist/writers/buffer-implementation/multi-buffer.js +1 -0
- package/dist/writers/buffer-implementation/writer.d.ts +2 -0
- package/dist/writers/buffer-implementation/writer.js +54 -0
- package/dist/writers/buffer.js +2 -53
- package/dist/writers/web-fs.js +7 -0
- package/dist/writers/writer.d.ts +1 -1
- package/package.json +4 -4
|
@@ -73,21 +73,20 @@ const parseMdat = async ({ data, size, fileOffset, existingBoxes, options, signa
|
|
|
73
73
|
break;
|
|
74
74
|
}
|
|
75
75
|
const bytes = data.getSlice(samplesWithIndex.samplePosition.size);
|
|
76
|
+
const timestamp = Math.floor((samplesWithIndex.samplePosition.cts * 1000000) /
|
|
77
|
+
samplesWithIndex.track.timescale);
|
|
78
|
+
const duration = Math.floor((samplesWithIndex.samplePosition.duration * 1000000) /
|
|
79
|
+
samplesWithIndex.track.timescale);
|
|
76
80
|
if (samplesWithIndex.track.type === 'audio') {
|
|
77
|
-
const timestamp = Math.floor((samplesWithIndex.samplePosition.cts * 1000000) /
|
|
78
|
-
samplesWithIndex.track.timescale);
|
|
79
81
|
await options.parserState.onAudioSample(samplesWithIndex.track.trackId, {
|
|
80
82
|
data: bytes,
|
|
81
83
|
timestamp,
|
|
82
84
|
trackId: samplesWithIndex.track.trackId,
|
|
83
85
|
type: samplesWithIndex.samplePosition.isKeyframe ? 'key' : 'delta',
|
|
86
|
+
duration,
|
|
84
87
|
});
|
|
85
88
|
}
|
|
86
89
|
if (samplesWithIndex.track.type === 'video') {
|
|
87
|
-
const timestamp = Math.floor((samplesWithIndex.samplePosition.cts * 1000000) /
|
|
88
|
-
samplesWithIndex.track.timescale);
|
|
89
|
-
const duration = Math.floor((samplesWithIndex.samplePosition.duration * 1000000) /
|
|
90
|
-
samplesWithIndex.track.timescale);
|
|
91
90
|
await options.parserState.onVideoSample(samplesWithIndex.track.trackId, {
|
|
92
91
|
data: bytes,
|
|
93
92
|
timestamp,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const measureEBMLVarInt: (value: number) =>
|
|
1
|
+
export declare const measureEBMLVarInt: (value: number) => 1 | 4 | 2 | 3 | 5 | 6;
|
|
2
2
|
export declare const getVariableInt: (value: number, minWidth: number | null) => Uint8Array;
|
package/dist/create/cluster.d.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
+
import type { AudioOrVideoSample } from '../webcodec-sample-types';
|
|
1
2
|
import type { Writer } from '../writers/writer';
|
|
2
|
-
export type AudioOrVideoSample = {
|
|
3
|
-
timestamp: number;
|
|
4
|
-
type: 'key' | 'delta';
|
|
5
|
-
copyTo(destination: AllowSharedBufferSource): void;
|
|
6
|
-
byteLength: number;
|
|
7
|
-
duration: number | null;
|
|
8
|
-
};
|
|
9
3
|
export declare const timestampToClusterTimestamp: (timestamp: number) => number;
|
|
10
|
-
export declare const
|
|
4
|
+
export declare const canFitInCluster: ({ clusterStartTimestamp, chunk, }: {
|
|
5
|
+
clusterStartTimestamp: number;
|
|
6
|
+
chunk: AudioOrVideoSample;
|
|
7
|
+
}) => boolean;
|
|
8
|
+
export declare const makeCluster: (w: Writer, clusterStartTimestamp: number) => Promise<{
|
|
11
9
|
addSample: (chunk: AudioOrVideoSample, trackNumber: number) => Promise<{
|
|
12
10
|
timecodeRelativeToCluster: number;
|
|
13
11
|
}>;
|
|
14
|
-
shouldMakeNewCluster: ({ isVideo,
|
|
12
|
+
shouldMakeNewCluster: ({ isVideo, chunk, newT, }: {
|
|
15
13
|
newT: number;
|
|
16
|
-
|
|
14
|
+
chunk: AudioOrVideoSample;
|
|
17
15
|
isVideo: boolean;
|
|
18
16
|
}) => boolean;
|
|
17
|
+
startTimestamp: number;
|
|
19
18
|
}>;
|
package/dist/create/cluster.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.makeCluster = exports.timestampToClusterTimestamp = void 0;
|
|
3
|
+
exports.makeCluster = exports.canFitInCluster = exports.timestampToClusterTimestamp = void 0;
|
|
4
4
|
const ebml_1 = require("../boxes/webm/ebml");
|
|
5
5
|
const make_header_1 = require("../boxes/webm/make-header");
|
|
6
6
|
const all_segments_1 = require("../boxes/webm/segments/all-segments");
|
|
@@ -11,8 +11,17 @@ const timestampToClusterTimestamp = (timestamp) => {
|
|
|
11
11
|
return Math.round((timestamp / timescale_1.CREATE_TIME_SCALE) * 1000);
|
|
12
12
|
};
|
|
13
13
|
exports.timestampToClusterTimestamp = timestampToClusterTimestamp;
|
|
14
|
-
const
|
|
15
|
-
const
|
|
14
|
+
const canFitInCluster = ({ clusterStartTimestamp, chunk, }) => {
|
|
15
|
+
const timecodeRelativeToCluster = (0, exports.timestampToClusterTimestamp)(chunk.timestamp) -
|
|
16
|
+
(0, exports.timestampToClusterTimestamp)(clusterStartTimestamp);
|
|
17
|
+
if (timecodeRelativeToCluster < 0) {
|
|
18
|
+
throw new Error(`timecodeRelativeToCluster is negative`);
|
|
19
|
+
}
|
|
20
|
+
return timecodeRelativeToCluster <= maxClusterTimestamp;
|
|
21
|
+
};
|
|
22
|
+
exports.canFitInCluster = canFitInCluster;
|
|
23
|
+
const makeCluster = async (w, clusterStartTimestamp) => {
|
|
24
|
+
const cluster = (0, cluster_segment_1.createClusterSegment)((0, exports.timestampToClusterTimestamp)(clusterStartTimestamp));
|
|
16
25
|
const clusterVIntPosition = w.getWrittenByteCount() +
|
|
17
26
|
cluster.offsets.offset +
|
|
18
27
|
(0, make_header_1.matroskaToHex)(all_segments_1.matroskaElements.Cluster).byteLength;
|
|
@@ -21,19 +30,14 @@ const makeCluster = async (w, timestamp) => {
|
|
|
21
30
|
cluster_segment_1.CLUSTER_MIN_VINT_WIDTH;
|
|
22
31
|
await w.write(cluster.bytes);
|
|
23
32
|
const addSample = async (chunk, trackNumber) => {
|
|
24
|
-
const arr = new Uint8Array(chunk.byteLength);
|
|
25
|
-
chunk.copyTo(arr);
|
|
26
33
|
const timecodeRelativeToCluster = (0, exports.timestampToClusterTimestamp)(chunk.timestamp) -
|
|
27
|
-
(0, exports.timestampToClusterTimestamp)(
|
|
28
|
-
if (
|
|
29
|
-
throw new Error(`timecodeRelativeToCluster is negative (track ${trackNumber})`);
|
|
30
|
-
}
|
|
31
|
-
if (timecodeRelativeToCluster > maxClusterTimestamp) {
|
|
34
|
+
(0, exports.timestampToClusterTimestamp)(clusterStartTimestamp);
|
|
35
|
+
if (!(0, exports.canFitInCluster)({ clusterStartTimestamp, chunk })) {
|
|
32
36
|
throw new Error(`timecodeRelativeToCluster is too big: ${timecodeRelativeToCluster} > ${maxClusterTimestamp}`);
|
|
33
37
|
}
|
|
34
38
|
const keyframe = chunk.type === 'key';
|
|
35
39
|
const simpleBlock = (0, cluster_segment_1.makeSimpleBlock)({
|
|
36
|
-
bytes:
|
|
40
|
+
bytes: chunk.data,
|
|
37
41
|
invisible: false,
|
|
38
42
|
keyframe,
|
|
39
43
|
lacing: 0,
|
|
@@ -45,11 +49,26 @@ const makeCluster = async (w, timestamp) => {
|
|
|
45
49
|
await w.write(simpleBlock);
|
|
46
50
|
return { timecodeRelativeToCluster };
|
|
47
51
|
};
|
|
48
|
-
const shouldMakeNewCluster = ({ isVideo,
|
|
52
|
+
const shouldMakeNewCluster = ({ isVideo, chunk, newT, }) => {
|
|
49
53
|
const newTimestamp = (0, exports.timestampToClusterTimestamp)(newT);
|
|
50
|
-
const oldTimestamp = (0, exports.timestampToClusterTimestamp)(
|
|
54
|
+
const oldTimestamp = (0, exports.timestampToClusterTimestamp)(clusterStartTimestamp);
|
|
55
|
+
const canFit = (0, exports.canFitInCluster)({
|
|
56
|
+
chunk,
|
|
57
|
+
clusterStartTimestamp,
|
|
58
|
+
});
|
|
59
|
+
if (!canFit) {
|
|
60
|
+
// We must create a new cluster
|
|
61
|
+
// This is for example if we have an audio-only file
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
const keyframe = chunk.type === 'key';
|
|
65
|
+
// TODO: Timestamp falls apart when video only
|
|
51
66
|
return newTimestamp - oldTimestamp >= 2000 && keyframe && isVideo;
|
|
52
67
|
};
|
|
53
|
-
return {
|
|
68
|
+
return {
|
|
69
|
+
addSample,
|
|
70
|
+
shouldMakeNewCluster,
|
|
71
|
+
startTimestamp: clusterStartTimestamp,
|
|
72
|
+
};
|
|
54
73
|
};
|
|
55
74
|
exports.makeCluster = makeCluster;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import type { AudioOrVideoSample } from '../webcodec-sample-types';
|
|
1
2
|
import type { WriterInterface } from '../writers/writer';
|
|
2
|
-
import type { AudioOrVideoSample } from './cluster';
|
|
3
3
|
import type { MakeTrackAudio, MakeTrackVideo } from './matroska-trackentry';
|
|
4
4
|
export type MediaFn = {
|
|
5
|
-
save: () => Promise<
|
|
5
|
+
save: () => Promise<Blob>;
|
|
6
6
|
remove: () => Promise<void>;
|
|
7
7
|
addSample: (chunk: AudioOrVideoSample, trackNumber: number, isVideo: boolean) => Promise<void>;
|
|
8
8
|
updateDuration: (duration: number) => Promise<void>;
|
|
@@ -12,4 +12,8 @@ export type MediaFn = {
|
|
|
12
12
|
addWaitForFinishPromise: (promise: () => Promise<void>) => void;
|
|
13
13
|
waitForFinish: () => Promise<void>;
|
|
14
14
|
};
|
|
15
|
-
export declare const createMedia: (writer
|
|
15
|
+
export declare const createMedia: ({ writer, onBytesProgress, onMillisecondsProgress, }: {
|
|
16
|
+
writer: WriterInterface;
|
|
17
|
+
onBytesProgress: (totalBytes: number) => void;
|
|
18
|
+
onMillisecondsProgress: (totalMilliseconds: number) => void;
|
|
19
|
+
}) => Promise<MediaFn>;
|
|
@@ -13,7 +13,7 @@ const matroska_seek_1 = require("./matroska-seek");
|
|
|
13
13
|
const matroska_segment_1 = require("./matroska-segment");
|
|
14
14
|
const matroska_trackentry_1 = require("./matroska-trackentry");
|
|
15
15
|
const timescale_1 = require("./timescale");
|
|
16
|
-
const createMedia = async (writer) => {
|
|
16
|
+
const createMedia = async ({ writer, onBytesProgress, onMillisecondsProgress, }) => {
|
|
17
17
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
18
18
|
const header = (0, matroska_header_1.makeMatroskaHeader)();
|
|
19
19
|
const w = await writer.createContent();
|
|
@@ -59,11 +59,13 @@ const createMedia = async (writer) => {
|
|
|
59
59
|
const updateSeekWrite = async () => {
|
|
60
60
|
const updatedSeek = (0, matroska_seek_1.createMatroskaSeekHead)(seeks);
|
|
61
61
|
await w.updateDataAt(seekHeadOffset, (0, make_header_1.combineUint8Arrays)(updatedSeek.map((b) => b.bytes)));
|
|
62
|
+
onBytesProgress(w.getWrittenByteCount());
|
|
62
63
|
};
|
|
63
64
|
const segmentOffset = w.getWrittenByteCount();
|
|
64
65
|
const updateSegmentSize = async (size) => {
|
|
65
66
|
const data = (0, ebml_1.getVariableInt)(size, matroska_segment_1.MATROSKA_SEGMENT_MIN_VINT_WIDTH);
|
|
66
67
|
await w.updateDataAt(segmentOffset + (0, make_header_1.matroskaToHex)(all_segments_1.matroskaElements.Segment).byteLength, data);
|
|
68
|
+
onBytesProgress(w.getWrittenByteCount());
|
|
67
69
|
};
|
|
68
70
|
await w.write(matroskaSegment.bytes);
|
|
69
71
|
const clusterOffset = w.getWrittenByteCount();
|
|
@@ -77,8 +79,8 @@ const createMedia = async (writer) => {
|
|
|
77
79
|
const smallestProgress = Math.min(...Object.values(trackNumberProgresses));
|
|
78
80
|
if (!currentCluster.shouldMakeNewCluster({
|
|
79
81
|
newT: smallestProgress,
|
|
80
|
-
keyframe: chunk.type === 'key',
|
|
81
82
|
isVideo,
|
|
83
|
+
chunk,
|
|
82
84
|
})) {
|
|
83
85
|
return { cluster: currentCluster, isNew: false, smallestProgress };
|
|
84
86
|
}
|
|
@@ -88,6 +90,7 @@ const createMedia = async (writer) => {
|
|
|
88
90
|
const updateDuration = async (newDuration) => {
|
|
89
91
|
const blocks = (0, make_duration_with_padding_1.makeDurationWithPadding)(newDuration);
|
|
90
92
|
await w.updateDataAt(durationOffset, blocks.bytes);
|
|
93
|
+
onBytesProgress(w.getWrittenByteCount());
|
|
91
94
|
};
|
|
92
95
|
const addSample = async (chunk, trackNumber, isVideo) => {
|
|
93
96
|
var _a;
|
|
@@ -108,6 +111,8 @@ const createMedia = async (writer) => {
|
|
|
108
111
|
trackNumber,
|
|
109
112
|
});
|
|
110
113
|
}
|
|
114
|
+
onBytesProgress(w.getWrittenByteCount());
|
|
115
|
+
onMillisecondsProgress(newDuration);
|
|
111
116
|
};
|
|
112
117
|
const addTrack = async (track) => {
|
|
113
118
|
currentTracks.push(track);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.polyfillAudioChunk = void 0;
|
|
4
|
+
const polyfillAudioChunk = (audioSample) => {
|
|
5
|
+
var _a;
|
|
6
|
+
return {
|
|
7
|
+
...audioSample,
|
|
8
|
+
duration: (_a = audioSample.duration) !== null && _a !== void 0 ? _a : null,
|
|
9
|
+
copyTo(destination) {
|
|
10
|
+
return destination.write(audioSample.data);
|
|
11
|
+
},
|
|
12
|
+
byteLength: audioSample.data.length,
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
exports.polyfillAudioChunk = polyfillAudioChunk;
|
package/dist/esm/buffer.mjs
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
// src/writers/buffer.ts
|
|
1
|
+
// src/writers/buffer-implementation/writer.ts
|
|
2
2
|
var createContent = () => {
|
|
3
3
|
const buf = new ArrayBuffer(0, {
|
|
4
|
-
maxByteLength:
|
|
4
|
+
maxByteLength: 200000000
|
|
5
5
|
});
|
|
6
6
|
if (!buf.resize) {
|
|
7
7
|
throw new Error("Could not create buffer writer");
|
|
8
8
|
}
|
|
9
|
-
let data = new Uint8Array(buf);
|
|
10
9
|
const write = (newData) => {
|
|
11
10
|
const oldLength = buf.byteLength;
|
|
12
11
|
const newLength = oldLength + newData.byteLength;
|
|
13
12
|
buf.resize(newLength);
|
|
14
13
|
const newArray = new Uint8Array(buf);
|
|
15
14
|
newArray.set(newData, oldLength);
|
|
16
|
-
data = newArray;
|
|
17
15
|
};
|
|
18
16
|
const updateDataAt = (position, newData) => {
|
|
19
17
|
const newArray = new Uint8Array(buf);
|
|
20
18
|
newArray.set(newData, position);
|
|
21
|
-
data = newArray;
|
|
22
19
|
};
|
|
23
20
|
let writPromise = Promise.resolve();
|
|
24
21
|
let removed = false;
|
|
@@ -31,11 +28,11 @@ var createContent = () => {
|
|
|
31
28
|
if (removed) {
|
|
32
29
|
return Promise.reject(new Error("Already called .remove() on the result"));
|
|
33
30
|
}
|
|
34
|
-
|
|
31
|
+
const arr = new Uint8Array(buf);
|
|
32
|
+
return Promise.resolve(new File([arr.slice()], "hi", { type: "video/webm" }));
|
|
35
33
|
},
|
|
36
34
|
remove() {
|
|
37
35
|
removed = true;
|
|
38
|
-
data = new Uint8Array(0);
|
|
39
36
|
return Promise.resolve();
|
|
40
37
|
},
|
|
41
38
|
getWrittenByteCount: () => buf.byteLength,
|
|
@@ -49,6 +46,8 @@ var createContent = () => {
|
|
|
49
46
|
};
|
|
50
47
|
return Promise.resolve(writer);
|
|
51
48
|
};
|
|
49
|
+
|
|
50
|
+
// src/writers/buffer.ts
|
|
52
51
|
var bufferWriter = {
|
|
53
52
|
createContent
|
|
54
53
|
};
|
package/dist/esm/from-fetch.mjs
CHANGED
|
@@ -55,7 +55,7 @@ var fetchReader = {
|
|
|
55
55
|
const parsedContentRange = contentRange ? parseContentRange(contentRange) : null;
|
|
56
56
|
const { supportsContentRange } = validateContentRangeAndDetectIfSupported(actualRange, parsedContentRange, res.status);
|
|
57
57
|
signal?.addEventListener("abort", () => {
|
|
58
|
-
controller.abort();
|
|
58
|
+
controller.abort(new Error("Aborted by user"));
|
|
59
59
|
}, { once: true });
|
|
60
60
|
if (res.status.toString().startsWith("4") || res.status.toString().startsWith("5")) {
|
|
61
61
|
throw new Error(`Server returned status code ${res.status} for ${src} and range ${actualRange}`);
|
package/dist/esm/index.mjs
CHANGED
|
@@ -55,7 +55,7 @@ var fetchReader = {
|
|
|
55
55
|
const parsedContentRange = contentRange ? parseContentRange(contentRange) : null;
|
|
56
56
|
const { supportsContentRange } = validateContentRangeAndDetectIfSupported(actualRange, parsedContentRange, res.status);
|
|
57
57
|
signal?.addEventListener("abort", () => {
|
|
58
|
-
controller.abort();
|
|
58
|
+
controller.abort(new Error("Aborted by user"));
|
|
59
59
|
}, { once: true });
|
|
60
60
|
if (res.status.toString().startsWith("4") || res.status.toString().startsWith("5")) {
|
|
61
61
|
throw new Error(`Server returned status code ${res.status} for ${src} and range ${actualRange}`);
|
|
@@ -1070,24 +1070,29 @@ var maxClusterTimestamp = 2 ** 15;
|
|
|
1070
1070
|
var timestampToClusterTimestamp = (timestamp) => {
|
|
1071
1071
|
return Math.round(timestamp / CREATE_TIME_SCALE * 1000);
|
|
1072
1072
|
};
|
|
1073
|
-
var
|
|
1074
|
-
|
|
1073
|
+
var canFitInCluster = ({
|
|
1074
|
+
clusterStartTimestamp,
|
|
1075
|
+
chunk
|
|
1076
|
+
}) => {
|
|
1077
|
+
const timecodeRelativeToCluster = timestampToClusterTimestamp(chunk.timestamp) - timestampToClusterTimestamp(clusterStartTimestamp);
|
|
1078
|
+
if (timecodeRelativeToCluster < 0) {
|
|
1079
|
+
throw new Error(`timecodeRelativeToCluster is negative`);
|
|
1080
|
+
}
|
|
1081
|
+
return timecodeRelativeToCluster <= maxClusterTimestamp;
|
|
1082
|
+
};
|
|
1083
|
+
var makeCluster = async (w, clusterStartTimestamp) => {
|
|
1084
|
+
const cluster = createClusterSegment(timestampToClusterTimestamp(clusterStartTimestamp));
|
|
1075
1085
|
const clusterVIntPosition = w.getWrittenByteCount() + cluster.offsets.offset + matroskaToHex(matroskaElements.Cluster).byteLength;
|
|
1076
1086
|
let clusterSize = cluster.bytes.byteLength - matroskaToHex(matroskaElements.Cluster).byteLength - CLUSTER_MIN_VINT_WIDTH;
|
|
1077
1087
|
await w.write(cluster.bytes);
|
|
1078
1088
|
const addSample = async (chunk, trackNumber2) => {
|
|
1079
|
-
const
|
|
1080
|
-
chunk
|
|
1081
|
-
const timecodeRelativeToCluster = timestampToClusterTimestamp(chunk.timestamp) - timestampToClusterTimestamp(timestamp);
|
|
1082
|
-
if (timecodeRelativeToCluster < 0) {
|
|
1083
|
-
throw new Error(`timecodeRelativeToCluster is negative (track ${trackNumber2})`);
|
|
1084
|
-
}
|
|
1085
|
-
if (timecodeRelativeToCluster > maxClusterTimestamp) {
|
|
1089
|
+
const timecodeRelativeToCluster = timestampToClusterTimestamp(chunk.timestamp) - timestampToClusterTimestamp(clusterStartTimestamp);
|
|
1090
|
+
if (!canFitInCluster({ clusterStartTimestamp, chunk })) {
|
|
1086
1091
|
throw new Error(`timecodeRelativeToCluster is too big: ${timecodeRelativeToCluster} > ${maxClusterTimestamp}`);
|
|
1087
1092
|
}
|
|
1088
1093
|
const keyframe = chunk.type === "key";
|
|
1089
1094
|
const simpleBlock2 = makeSimpleBlock({
|
|
1090
|
-
bytes:
|
|
1095
|
+
bytes: chunk.data,
|
|
1091
1096
|
invisible: false,
|
|
1092
1097
|
keyframe,
|
|
1093
1098
|
lacing: 0,
|
|
@@ -1101,14 +1106,26 @@ var makeCluster = async (w, timestamp) => {
|
|
|
1101
1106
|
};
|
|
1102
1107
|
const shouldMakeNewCluster = ({
|
|
1103
1108
|
isVideo,
|
|
1104
|
-
|
|
1109
|
+
chunk,
|
|
1105
1110
|
newT
|
|
1106
1111
|
}) => {
|
|
1107
1112
|
const newTimestamp = timestampToClusterTimestamp(newT);
|
|
1108
|
-
const oldTimestamp = timestampToClusterTimestamp(
|
|
1113
|
+
const oldTimestamp = timestampToClusterTimestamp(clusterStartTimestamp);
|
|
1114
|
+
const canFit = canFitInCluster({
|
|
1115
|
+
chunk,
|
|
1116
|
+
clusterStartTimestamp
|
|
1117
|
+
});
|
|
1118
|
+
if (!canFit) {
|
|
1119
|
+
return true;
|
|
1120
|
+
}
|
|
1121
|
+
const keyframe = chunk.type === "key";
|
|
1109
1122
|
return newTimestamp - oldTimestamp >= 2000 && keyframe && isVideo;
|
|
1110
1123
|
};
|
|
1111
|
-
return {
|
|
1124
|
+
return {
|
|
1125
|
+
addSample,
|
|
1126
|
+
shouldMakeNewCluster,
|
|
1127
|
+
startTimestamp: clusterStartTimestamp
|
|
1128
|
+
};
|
|
1112
1129
|
};
|
|
1113
1130
|
|
|
1114
1131
|
// src/create/make-duration-with-padding.ts
|
|
@@ -1815,7 +1832,11 @@ var makeMatroskaTracks = (tracks2) => {
|
|
|
1815
1832
|
};
|
|
1816
1833
|
|
|
1817
1834
|
// src/create/create-media.ts
|
|
1818
|
-
var createMedia = async (
|
|
1835
|
+
var createMedia = async ({
|
|
1836
|
+
writer,
|
|
1837
|
+
onBytesProgress,
|
|
1838
|
+
onMillisecondsProgress
|
|
1839
|
+
}) => {
|
|
1819
1840
|
const header = makeMatroskaHeader();
|
|
1820
1841
|
const w = await writer.createContent();
|
|
1821
1842
|
await w.write(header.bytes);
|
|
@@ -1859,11 +1880,13 @@ var createMedia = async (writer) => {
|
|
|
1859
1880
|
const updateSeekWrite = async () => {
|
|
1860
1881
|
const updatedSeek = createMatroskaSeekHead(seeks);
|
|
1861
1882
|
await w.updateDataAt(seekHeadOffset, combineUint8Arrays(updatedSeek.map((b) => b.bytes)));
|
|
1883
|
+
onBytesProgress(w.getWrittenByteCount());
|
|
1862
1884
|
};
|
|
1863
1885
|
const segmentOffset = w.getWrittenByteCount();
|
|
1864
1886
|
const updateSegmentSize = async (size) => {
|
|
1865
1887
|
const data = getVariableInt(size, MATROSKA_SEGMENT_MIN_VINT_WIDTH);
|
|
1866
1888
|
await w.updateDataAt(segmentOffset + matroskaToHex(matroskaElements.Segment).byteLength, data);
|
|
1889
|
+
onBytesProgress(w.getWrittenByteCount());
|
|
1867
1890
|
};
|
|
1868
1891
|
await w.write(matroskaSegment.bytes);
|
|
1869
1892
|
const clusterOffset = w.getWrittenByteCount();
|
|
@@ -1880,8 +1903,8 @@ var createMedia = async (writer) => {
|
|
|
1880
1903
|
const smallestProgress = Math.min(...Object.values(trackNumberProgresses));
|
|
1881
1904
|
if (!currentCluster.shouldMakeNewCluster({
|
|
1882
1905
|
newT: smallestProgress,
|
|
1883
|
-
|
|
1884
|
-
|
|
1906
|
+
isVideo,
|
|
1907
|
+
chunk
|
|
1885
1908
|
})) {
|
|
1886
1909
|
return { cluster: currentCluster, isNew: false, smallestProgress };
|
|
1887
1910
|
}
|
|
@@ -1891,6 +1914,7 @@ var createMedia = async (writer) => {
|
|
|
1891
1914
|
const updateDuration = async (newDuration) => {
|
|
1892
1915
|
const blocks = makeDurationWithPadding(newDuration);
|
|
1893
1916
|
await w.updateDataAt(durationOffset, blocks.bytes);
|
|
1917
|
+
onBytesProgress(w.getWrittenByteCount());
|
|
1894
1918
|
};
|
|
1895
1919
|
const addSample = async (chunk, trackNumber2, isVideo) => {
|
|
1896
1920
|
trackNumberProgresses[trackNumber2] = chunk.timestamp;
|
|
@@ -1909,6 +1933,8 @@ var createMedia = async (writer) => {
|
|
|
1909
1933
|
trackNumber: trackNumber2
|
|
1910
1934
|
});
|
|
1911
1935
|
}
|
|
1936
|
+
onBytesProgress(w.getWrittenByteCount());
|
|
1937
|
+
onMillisecondsProgress(newDuration);
|
|
1912
1938
|
};
|
|
1913
1939
|
const addTrack = async (track) => {
|
|
1914
1940
|
currentTracks.push(track);
|
|
@@ -1959,6 +1985,40 @@ var createMedia = async (writer) => {
|
|
|
1959
1985
|
};
|
|
1960
1986
|
};
|
|
1961
1987
|
|
|
1988
|
+
// src/log.ts
|
|
1989
|
+
var logLevels = ["trace", "verbose", "info", "warn", "error"];
|
|
1990
|
+
var getNumberForLogLevel = (level) => {
|
|
1991
|
+
return logLevels.indexOf(level);
|
|
1992
|
+
};
|
|
1993
|
+
var isEqualOrBelowLogLevel = (currentLevel, level) => {
|
|
1994
|
+
return getNumberForLogLevel(currentLevel) <= getNumberForLogLevel(level);
|
|
1995
|
+
};
|
|
1996
|
+
var Log = {
|
|
1997
|
+
trace: (logLevel, ...args) => {
|
|
1998
|
+
if (isEqualOrBelowLogLevel(logLevel, "trace")) {
|
|
1999
|
+
return console.log(...args);
|
|
2000
|
+
}
|
|
2001
|
+
},
|
|
2002
|
+
verbose: (logLevel, ...args) => {
|
|
2003
|
+
if (isEqualOrBelowLogLevel(logLevel, "verbose")) {
|
|
2004
|
+
return console.log(...args);
|
|
2005
|
+
}
|
|
2006
|
+
},
|
|
2007
|
+
info: (logLevel, ...args) => {
|
|
2008
|
+
if (isEqualOrBelowLogLevel(logLevel, "info")) {
|
|
2009
|
+
return console.log(...args);
|
|
2010
|
+
}
|
|
2011
|
+
},
|
|
2012
|
+
warn: (logLevel, ...args) => {
|
|
2013
|
+
if (isEqualOrBelowLogLevel(logLevel, "warn")) {
|
|
2014
|
+
return console.warn(...args);
|
|
2015
|
+
}
|
|
2016
|
+
},
|
|
2017
|
+
error: (...args) => {
|
|
2018
|
+
return console.error(...args);
|
|
2019
|
+
}
|
|
2020
|
+
};
|
|
2021
|
+
|
|
1962
2022
|
// src/boxes/iso-base-media/traversal.ts
|
|
1963
2023
|
var getMoovBox = (segments) => {
|
|
1964
2024
|
const moovBox = segments.find((s) => s.type === "moov-box");
|
|
@@ -4337,18 +4397,18 @@ var parseMdat = async ({
|
|
|
4337
4397
|
break;
|
|
4338
4398
|
}
|
|
4339
4399
|
const bytes = data.getSlice(samplesWithIndex.samplePosition.size);
|
|
4400
|
+
const timestamp = Math.floor(samplesWithIndex.samplePosition.cts * 1e6 / samplesWithIndex.track.timescale);
|
|
4401
|
+
const duration2 = Math.floor(samplesWithIndex.samplePosition.duration * 1e6 / samplesWithIndex.track.timescale);
|
|
4340
4402
|
if (samplesWithIndex.track.type === "audio") {
|
|
4341
|
-
const timestamp = Math.floor(samplesWithIndex.samplePosition.cts * 1e6 / samplesWithIndex.track.timescale);
|
|
4342
4403
|
await options.parserState.onAudioSample(samplesWithIndex.track.trackId, {
|
|
4343
4404
|
data: bytes,
|
|
4344
4405
|
timestamp,
|
|
4345
4406
|
trackId: samplesWithIndex.track.trackId,
|
|
4346
|
-
type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta"
|
|
4407
|
+
type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta",
|
|
4408
|
+
duration: duration2
|
|
4347
4409
|
});
|
|
4348
4410
|
}
|
|
4349
4411
|
if (samplesWithIndex.track.type === "video") {
|
|
4350
|
-
const timestamp = Math.floor(samplesWithIndex.samplePosition.cts * 1e6 / samplesWithIndex.track.timescale);
|
|
4351
|
-
const duration2 = Math.floor(samplesWithIndex.samplePosition.duration * 1e6 / samplesWithIndex.track.timescale);
|
|
4352
4412
|
await options.parserState.onVideoSample(samplesWithIndex.track.trackId, {
|
|
4353
4413
|
data: bytes,
|
|
4354
4414
|
timestamp,
|
|
@@ -6126,7 +6186,8 @@ var getSampleFromBlock = (ebml, parserContext, offset) => {
|
|
|
6126
6186
|
data: iterator.getSlice(remainingNow),
|
|
6127
6187
|
trackId: trackNumber2,
|
|
6128
6188
|
timestamp: timecodeInMicroseconds,
|
|
6129
|
-
type: "key"
|
|
6189
|
+
type: "key",
|
|
6190
|
+
duration: undefined
|
|
6130
6191
|
};
|
|
6131
6192
|
iterator.destroy();
|
|
6132
6193
|
return {
|
|
@@ -6818,7 +6879,8 @@ var parseMedia = async ({
|
|
|
6818
6879
|
};
|
|
6819
6880
|
// src/index.ts
|
|
6820
6881
|
var MediaParserInternals = {
|
|
6821
|
-
createMedia
|
|
6882
|
+
createMedia,
|
|
6883
|
+
Log
|
|
6822
6884
|
};
|
|
6823
6885
|
export {
|
|
6824
6886
|
parseMedia,
|
package/dist/esm/web-fs.mjs
CHANGED
|
@@ -54,6 +54,12 @@ var webFsWriter = {
|
|
|
54
54
|
createContent
|
|
55
55
|
};
|
|
56
56
|
var canUseWebFsWriter = async () => {
|
|
57
|
+
if (!("storage" in navigator)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (!("getDirectory" in navigator.storage)) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
57
63
|
const directoryHandle = await navigator.storage.getDirectory();
|
|
58
64
|
const fileHandle = await directoryHandle.getFileHandle("remotion-probe-web-fs-support", {
|
|
59
65
|
create: true
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
|
+
import type { LogLevel } from './log';
|
|
2
|
+
export { WriterInterface } from './writers/writer';
|
|
1
3
|
export { AudioTrack, MediaParserAudioCodec, MediaParserVideoCodec, OtherTrack, Track, VideoTrack, VideoTrackColorParams, } from './get-tracks';
|
|
2
|
-
export type { Options, ParseMediaContainer, ParseMediaFields, ParseMediaResult, TracksField, } from './options';
|
|
4
|
+
export type { Options, ParseMediaContainer, ParseMediaDynamicOptions, ParseMediaFields, ParseMediaOptions, ParseMediaResult, TracksField, } from './options';
|
|
3
5
|
export { parseMedia } from './parse-media';
|
|
4
|
-
export { AudioSample, OnAudioSample, OnAudioTrack, OnVideoSample, OnVideoTrack, VideoSample, } from './webcodec-sample-types';
|
|
6
|
+
export { AudioOrVideoSample, AudioSample, OnAudioSample, OnAudioTrack, OnVideoSample, OnVideoTrack, VideoSample, } from './webcodec-sample-types';
|
|
5
7
|
export type { MediaFn } from './create/create-media';
|
|
6
8
|
export { Dimensions } from './get-dimensions';
|
|
7
9
|
export type { ReaderInterface } from './readers/reader';
|
|
10
|
+
export type { LogLevel };
|
|
8
11
|
export declare const MediaParserInternals: {
|
|
9
|
-
createMedia: (
|
|
12
|
+
createMedia: ({ writer, onBytesProgress, onMillisecondsProgress, }: {
|
|
13
|
+
writer: import("./writers/writer").WriterInterface;
|
|
14
|
+
onBytesProgress: (totalBytes: number) => void;
|
|
15
|
+
onMillisecondsProgress: (totalMilliseconds: number) => void;
|
|
16
|
+
}) => Promise<import("./create/create-media").MediaFn>;
|
|
17
|
+
Log: {
|
|
18
|
+
trace: (logLevel: LogLevel, ...args: Parameters<typeof console.log>) => void;
|
|
19
|
+
verbose: (logLevel: LogLevel, ...args: Parameters<typeof console.log>) => void;
|
|
20
|
+
info: (logLevel: LogLevel, ...args: Parameters<typeof console.log>) => void;
|
|
21
|
+
warn: (logLevel: LogLevel, ...args: Parameters<typeof console.log>) => void;
|
|
22
|
+
error: (...args: Parameters<typeof console.log>) => void;
|
|
23
|
+
};
|
|
10
24
|
};
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MediaParserInternals = exports.parseMedia = void 0;
|
|
4
4
|
const create_media_1 = require("./create/create-media");
|
|
5
|
+
const log_1 = require("./log");
|
|
5
6
|
var parse_media_1 = require("./parse-media");
|
|
6
7
|
Object.defineProperty(exports, "parseMedia", { enumerable: true, get: function () { return parse_media_1.parseMedia; } });
|
|
7
8
|
exports.MediaParserInternals = {
|
|
8
9
|
createMedia: create_media_1.createMedia,
|
|
10
|
+
Log: log_1.Log,
|
|
9
11
|
};
|
package/dist/log.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const logLevels: readonly ["trace", "verbose", "info", "warn", "error"];
|
|
2
|
+
export type LogLevel = (typeof logLevels)[number];
|
|
3
|
+
export declare const isEqualOrBelowLogLevel: (currentLevel: LogLevel, level: LogLevel) => boolean;
|
|
4
|
+
export declare const Log: {
|
|
5
|
+
trace: (logLevel: LogLevel, ...args: Parameters<typeof console.log>) => void;
|
|
6
|
+
verbose: (logLevel: LogLevel, ...args: Parameters<typeof console.log>) => void;
|
|
7
|
+
info: (logLevel: LogLevel, ...args: Parameters<typeof console.log>) => void;
|
|
8
|
+
warn: (logLevel: LogLevel, ...args: Parameters<typeof console.log>) => void;
|
|
9
|
+
error: (...args: Parameters<typeof console.log>) => void;
|
|
10
|
+
};
|
package/dist/log.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Log = exports.isEqualOrBelowLogLevel = exports.logLevels = void 0;
|
|
4
|
+
/* eslint-disable no-console */
|
|
5
|
+
exports.logLevels = ['trace', 'verbose', 'info', 'warn', 'error'];
|
|
6
|
+
const getNumberForLogLevel = (level) => {
|
|
7
|
+
return exports.logLevels.indexOf(level);
|
|
8
|
+
};
|
|
9
|
+
const isEqualOrBelowLogLevel = (currentLevel, level) => {
|
|
10
|
+
return getNumberForLogLevel(currentLevel) <= getNumberForLogLevel(level);
|
|
11
|
+
};
|
|
12
|
+
exports.isEqualOrBelowLogLevel = isEqualOrBelowLogLevel;
|
|
13
|
+
exports.Log = {
|
|
14
|
+
trace: (logLevel, ...args) => {
|
|
15
|
+
if ((0, exports.isEqualOrBelowLogLevel)(logLevel, 'trace')) {
|
|
16
|
+
return console.log(...args);
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
verbose: (logLevel, ...args) => {
|
|
20
|
+
if ((0, exports.isEqualOrBelowLogLevel)(logLevel, 'verbose')) {
|
|
21
|
+
return console.log(...args);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
info: (logLevel, ...args) => {
|
|
25
|
+
if ((0, exports.isEqualOrBelowLogLevel)(logLevel, 'info')) {
|
|
26
|
+
return console.log(...args);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
warn: (logLevel, ...args) => {
|
|
30
|
+
if ((0, exports.isEqualOrBelowLogLevel)(logLevel, 'warn')) {
|
|
31
|
+
return console.warn(...args);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
error: (...args) => {
|
|
35
|
+
return console.error(...args);
|
|
36
|
+
},
|
|
37
|
+
};
|
package/dist/options.d.ts
CHANGED
|
@@ -107,11 +107,14 @@ export type ParseMediaResult<Fields extends Options<ParseMediaFields>> = (Fields
|
|
|
107
107
|
} : {}) & (Fields['container'] extends true ? {
|
|
108
108
|
container: ParseMediaContainer | null;
|
|
109
109
|
} : {});
|
|
110
|
-
export type
|
|
111
|
-
src: string | File;
|
|
110
|
+
export type ParseMediaDynamicOptions<F extends Options<ParseMediaFields>> = {
|
|
112
111
|
fields?: F;
|
|
112
|
+
} & ParseMediaCallbacks<F>;
|
|
113
|
+
export type ParseMediaOptions<F extends Options<ParseMediaFields>> = {
|
|
114
|
+
src: string | File;
|
|
113
115
|
reader?: ReaderInterface;
|
|
114
116
|
onAudioTrack?: OnAudioTrack;
|
|
115
117
|
onVideoTrack?: OnVideoTrack;
|
|
116
118
|
signal?: AbortSignal;
|
|
117
|
-
} &
|
|
119
|
+
} & ParseMediaDynamicOptions<F>;
|
|
120
|
+
export type ParseMedia = <F extends Options<ParseMediaFields>>(options: ParseMediaOptions<F>) => Promise<ParseMediaResult<F>>;
|
|
@@ -80,7 +80,7 @@ exports.fetchReader = {
|
|
|
80
80
|
: null;
|
|
81
81
|
const { supportsContentRange } = validateContentRangeAndDetectIfSupported(actualRange, parsedContentRange, res.status);
|
|
82
82
|
signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', () => {
|
|
83
|
-
controller.abort();
|
|
83
|
+
controller.abort(new Error('Aborted by user'));
|
|
84
84
|
}, { once: true });
|
|
85
85
|
if (res.status.toString().startsWith('4') ||
|
|
86
86
|
res.status.toString().startsWith('5')) {
|
|
@@ -4,6 +4,7 @@ export type AudioSample = {
|
|
|
4
4
|
timestamp: number;
|
|
5
5
|
trackId: number;
|
|
6
6
|
type: 'key' | 'delta';
|
|
7
|
+
duration: number | undefined;
|
|
7
8
|
};
|
|
8
9
|
export type VideoSample = {
|
|
9
10
|
data: Uint8Array;
|
|
@@ -18,3 +19,9 @@ export type OnAudioSample = (sample: AudioSample) => void | Promise<void>;
|
|
|
18
19
|
export type OnVideoSample = (sample: VideoSample) => void | Promise<void>;
|
|
19
20
|
export type OnAudioTrack = (track: AudioTrack) => OnAudioSample | Promise<OnAudioSample | null> | null;
|
|
20
21
|
export type OnVideoTrack = (track: VideoTrack) => OnVideoSample | Promise<OnVideoSample | null> | null;
|
|
22
|
+
export type AudioOrVideoSample = {
|
|
23
|
+
timestamp: number;
|
|
24
|
+
type: 'key' | 'delta';
|
|
25
|
+
data: Uint8Array;
|
|
26
|
+
duration: number | undefined;
|
|
27
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createContent = void 0;
|
|
4
|
+
const createContent = () => {
|
|
5
|
+
const buf = new ArrayBuffer(0, {
|
|
6
|
+
// TODO: Educate that the buffer is limited to 2GB
|
|
7
|
+
maxByteLength: 200000000,
|
|
8
|
+
});
|
|
9
|
+
if (!buf.resize) {
|
|
10
|
+
throw new Error('Could not create buffer writer');
|
|
11
|
+
}
|
|
12
|
+
const write = (newData) => {
|
|
13
|
+
const oldLength = buf.byteLength;
|
|
14
|
+
const newLength = oldLength + newData.byteLength;
|
|
15
|
+
buf.resize(newLength);
|
|
16
|
+
const newArray = new Uint8Array(buf);
|
|
17
|
+
newArray.set(newData, oldLength);
|
|
18
|
+
};
|
|
19
|
+
const updateDataAt = (position, newData) => {
|
|
20
|
+
const newArray = new Uint8Array(buf);
|
|
21
|
+
newArray.set(newData, position);
|
|
22
|
+
};
|
|
23
|
+
let writPromise = Promise.resolve();
|
|
24
|
+
let removed = false;
|
|
25
|
+
const writer = {
|
|
26
|
+
write: (arr) => {
|
|
27
|
+
writPromise = writPromise.then(() => write(arr));
|
|
28
|
+
return writPromise;
|
|
29
|
+
},
|
|
30
|
+
save: () => {
|
|
31
|
+
if (removed) {
|
|
32
|
+
return Promise.reject(new Error('Already called .remove() on the result'));
|
|
33
|
+
}
|
|
34
|
+
const arr = new Uint8Array(buf);
|
|
35
|
+
return Promise.resolve(
|
|
36
|
+
// TODO: Unhardcode MIME type and file name
|
|
37
|
+
new File([arr.slice()], 'hi', { type: 'video/webm' }));
|
|
38
|
+
},
|
|
39
|
+
remove() {
|
|
40
|
+
removed = true;
|
|
41
|
+
return Promise.resolve();
|
|
42
|
+
},
|
|
43
|
+
getWrittenByteCount: () => buf.byteLength,
|
|
44
|
+
updateDataAt: (position, newData) => {
|
|
45
|
+
writPromise = writPromise.then(() => updateDataAt(position, newData));
|
|
46
|
+
return writPromise;
|
|
47
|
+
},
|
|
48
|
+
waitForFinish: async () => {
|
|
49
|
+
await writPromise;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
return Promise.resolve(writer);
|
|
53
|
+
};
|
|
54
|
+
exports.createContent = createContent;
|
package/dist/writers/buffer.js
CHANGED
|
@@ -1,58 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.bufferWriter = void 0;
|
|
4
|
-
const
|
|
5
|
-
const buf = new ArrayBuffer(0, {
|
|
6
|
-
// TODO: Educate that the buffer is limited to 100MB
|
|
7
|
-
maxByteLength: 100000000,
|
|
8
|
-
});
|
|
9
|
-
if (!buf.resize) {
|
|
10
|
-
throw new Error('Could not create buffer writer');
|
|
11
|
-
}
|
|
12
|
-
let data = new Uint8Array(buf);
|
|
13
|
-
const write = (newData) => {
|
|
14
|
-
const oldLength = buf.byteLength;
|
|
15
|
-
const newLength = oldLength + newData.byteLength;
|
|
16
|
-
buf.resize(newLength);
|
|
17
|
-
const newArray = new Uint8Array(buf);
|
|
18
|
-
newArray.set(newData, oldLength);
|
|
19
|
-
data = newArray;
|
|
20
|
-
};
|
|
21
|
-
const updateDataAt = (position, newData) => {
|
|
22
|
-
const newArray = new Uint8Array(buf);
|
|
23
|
-
newArray.set(newData, position);
|
|
24
|
-
data = newArray;
|
|
25
|
-
};
|
|
26
|
-
let writPromise = Promise.resolve();
|
|
27
|
-
let removed = false;
|
|
28
|
-
const writer = {
|
|
29
|
-
write: (arr) => {
|
|
30
|
-
writPromise = writPromise.then(() => write(arr));
|
|
31
|
-
return writPromise;
|
|
32
|
-
},
|
|
33
|
-
save: () => {
|
|
34
|
-
if (removed) {
|
|
35
|
-
return Promise.reject(new Error('Already called .remove() on the result'));
|
|
36
|
-
}
|
|
37
|
-
// TODO: Unhardcode name
|
|
38
|
-
return Promise.resolve(new File([data], 'hithere', {}));
|
|
39
|
-
},
|
|
40
|
-
remove() {
|
|
41
|
-
removed = true;
|
|
42
|
-
data = new Uint8Array(0);
|
|
43
|
-
return Promise.resolve();
|
|
44
|
-
},
|
|
45
|
-
getWrittenByteCount: () => buf.byteLength,
|
|
46
|
-
updateDataAt: (position, newData) => {
|
|
47
|
-
writPromise = writPromise.then(() => updateDataAt(position, newData));
|
|
48
|
-
return writPromise;
|
|
49
|
-
},
|
|
50
|
-
waitForFinish: async () => {
|
|
51
|
-
await writPromise;
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
return Promise.resolve(writer);
|
|
55
|
-
};
|
|
4
|
+
const writer_1 = require("./buffer-implementation/writer");
|
|
56
5
|
exports.bufferWriter = {
|
|
57
|
-
createContent,
|
|
6
|
+
createContent: writer_1.createContent,
|
|
58
7
|
};
|
package/dist/writers/web-fs.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.canUseWebFsWriter = exports.webFsWriter = void 0;
|
|
4
4
|
const createContent = async () => {
|
|
5
5
|
const directoryHandle = await navigator.storage.getDirectory();
|
|
6
|
+
// TODO: Unhardcode WebM
|
|
6
7
|
const filename = `media-parser-${Math.random().toString().replace('0.', '')}.webm`;
|
|
7
8
|
const fileHandle = await directoryHandle.getFileHandle(filename, {
|
|
8
9
|
create: true,
|
|
@@ -58,6 +59,12 @@ exports.webFsWriter = {
|
|
|
58
59
|
createContent,
|
|
59
60
|
};
|
|
60
61
|
const canUseWebFsWriter = async () => {
|
|
62
|
+
if (!('storage' in navigator)) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (!('getDirectory' in navigator.storage)) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
61
68
|
const directoryHandle = await navigator.storage.getDirectory();
|
|
62
69
|
const fileHandle = await directoryHandle.getFileHandle('remotion-probe-web-fs-support', {
|
|
63
70
|
create: true,
|
package/dist/writers/writer.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type Writer = {
|
|
2
2
|
write: (arr: Uint8Array) => Promise<void>;
|
|
3
|
-
save: () => Promise<File>;
|
|
3
|
+
save: () => Promise<File | Blob>;
|
|
4
4
|
getWrittenByteCount: () => number;
|
|
5
5
|
updateDataAt: (position: number, data: Uint8Array) => Promise<void>;
|
|
6
6
|
waitForFinish: () => Promise<void>;
|
package/package.json
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/media-parser"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/media-parser",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.229",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"devDependencies": {
|
|
10
10
|
"@types/wicg-file-system-access": "2023.10.5",
|
|
11
11
|
"eslint": "9.14.0",
|
|
12
|
-
"@remotion/
|
|
13
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
12
|
+
"@remotion/example-videos": "4.0.229",
|
|
13
|
+
"@remotion/eslint-config-internal": "4.0.229"
|
|
14
14
|
},
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public"
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
}
|
|
78
78
|
},
|
|
79
79
|
"author": "Jonny Burger <jonny@remotion.dev>",
|
|
80
|
-
"license": "
|
|
80
|
+
"license": "Remotion License https://remotion.dev/license",
|
|
81
81
|
"keywords": [
|
|
82
82
|
"remotion",
|
|
83
83
|
"ffmpeg",
|