init commit
This commit is contained in:
10
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/cluster-segment.d.ts
generated
vendored
Normal file
10
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/cluster-segment.d.ts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
export declare const CLUSTER_MIN_VINT_WIDTH = 8;
|
||||
export declare const createClusterSegment: (timestamp: number) => import("./matroska-utils").BytesAndOffset;
|
||||
export declare const makeSimpleBlock: ({ bytes, trackNumber, timecodeRelativeToCluster, keyframe, invisible, lacing, }: {
|
||||
bytes: Uint8Array;
|
||||
trackNumber: number;
|
||||
timecodeRelativeToCluster: number;
|
||||
keyframe: boolean;
|
||||
invisible: boolean;
|
||||
lacing: number;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
38
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/cluster-segment.js
generated
vendored
Normal file
38
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/cluster-segment.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeSimpleBlock = exports.createClusterSegment = exports.CLUSTER_MIN_VINT_WIDTH = void 0;
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
exports.CLUSTER_MIN_VINT_WIDTH = 8;
|
||||
const createClusterSegment = (timestamp) => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Cluster',
|
||||
value: [
|
||||
{
|
||||
type: 'Timestamp',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: timestamp,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
minVintWidth: exports.CLUSTER_MIN_VINT_WIDTH,
|
||||
});
|
||||
};
|
||||
exports.createClusterSegment = createClusterSegment;
|
||||
const makeSimpleBlock = ({ bytes, trackNumber, timecodeRelativeToCluster, keyframe, invisible, lacing, }) => {
|
||||
const simpleBlockHeader = (0, matroska_utils_1.matroskaToHex)('0xa3');
|
||||
const headerByte = (Number(keyframe) << 7) | (Number(invisible) << 3) | (lacing << 1);
|
||||
const body = (0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, matroska_utils_1.getVariableInt)(trackNumber, null),
|
||||
(0, matroska_utils_1.serializeUint16)(timecodeRelativeToCluster),
|
||||
new Uint8Array([headerByte]),
|
||||
bytes,
|
||||
]);
|
||||
return (0, matroska_utils_1.combineUint8Arrays)([
|
||||
simpleBlockHeader,
|
||||
(0, matroska_utils_1.getVariableInt)(body.length, null),
|
||||
body,
|
||||
]);
|
||||
};
|
||||
exports.makeSimpleBlock = makeSimpleBlock;
|
||||
24
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/cluster.d.ts
generated
vendored
Normal file
24
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/cluster.d.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import type { MediaParserInternalTypes, MediaParserLogLevel } from '@remotion/media-parser';
|
||||
import { type MediaParserAudioSample, type MediaParserVideoSample } from '@remotion/media-parser';
|
||||
export declare const timestampToClusterTimestamp: (timestamp: number, timescale: number) => number;
|
||||
export declare const canFitInCluster: ({ clusterStartTimestamp, chunk, timescale, }: {
|
||||
clusterStartTimestamp: number;
|
||||
chunk: MediaParserAudioSample | MediaParserVideoSample;
|
||||
timescale: number;
|
||||
}) => boolean;
|
||||
export declare const makeCluster: ({ writer, clusterStartTimestamp, timescale, logLevel, }: {
|
||||
writer: MediaParserInternalTypes["Writer"];
|
||||
clusterStartTimestamp: number;
|
||||
timescale: number;
|
||||
logLevel: MediaParserLogLevel;
|
||||
}) => Promise<{
|
||||
addSample: (chunk: MediaParserAudioSample | MediaParserVideoSample, trackNumber: number) => Promise<{
|
||||
timecodeRelativeToCluster: number;
|
||||
}>;
|
||||
shouldMakeNewCluster: ({ isVideo, chunk, newT, }: {
|
||||
newT: number;
|
||||
chunk: MediaParserAudioSample | MediaParserVideoSample;
|
||||
isVideo: boolean;
|
||||
}) => boolean;
|
||||
startTimestamp: number;
|
||||
}>;
|
||||
76
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/cluster.js
generated
vendored
Normal file
76
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/cluster.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeCluster = exports.canFitInCluster = exports.timestampToClusterTimestamp = void 0;
|
||||
const media_parser_1 = require("@remotion/media-parser");
|
||||
const log_1 = require("../../log");
|
||||
const cluster_segment_1 = require("./cluster-segment");
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const maxClusterTimestamp = 2 ** 15;
|
||||
const timestampToClusterTimestamp = (timestamp, timescale) => {
|
||||
return Math.round((timestamp / timescale) * 1000);
|
||||
};
|
||||
exports.timestampToClusterTimestamp = timestampToClusterTimestamp;
|
||||
const canFitInCluster = ({ clusterStartTimestamp, chunk, timescale, }) => {
|
||||
const timecodeRelativeToCluster = (0, exports.timestampToClusterTimestamp)(chunk.timestamp, timescale) -
|
||||
(0, exports.timestampToClusterTimestamp)(clusterStartTimestamp, timescale);
|
||||
if (timecodeRelativeToCluster < 0) {
|
||||
throw new Error(`timecodeRelativeToCluster is negative, tried to add ${chunk.timestamp} to ${clusterStartTimestamp}`);
|
||||
}
|
||||
return timecodeRelativeToCluster <= maxClusterTimestamp;
|
||||
};
|
||||
exports.canFitInCluster = canFitInCluster;
|
||||
const makeCluster = async ({ writer, clusterStartTimestamp, timescale, logLevel, }) => {
|
||||
log_1.Log.verbose(logLevel, `Making new Matroska cluster with timestamp ${clusterStartTimestamp}`);
|
||||
const cluster = (0, cluster_segment_1.createClusterSegment)((0, exports.timestampToClusterTimestamp)(clusterStartTimestamp, timescale));
|
||||
const clusterVIntPosition = writer.getWrittenByteCount() +
|
||||
cluster.offsets.offset +
|
||||
(0, matroska_utils_1.matroskaToHex)(media_parser_1.MediaParserInternals.matroskaElements.Cluster).byteLength;
|
||||
let clusterSize = cluster.bytes.byteLength -
|
||||
(0, matroska_utils_1.matroskaToHex)(media_parser_1.MediaParserInternals.matroskaElements.Cluster).byteLength -
|
||||
cluster_segment_1.CLUSTER_MIN_VINT_WIDTH;
|
||||
await writer.write(cluster.bytes);
|
||||
const addSample = async (chunk, trackNumber) => {
|
||||
const timecodeRelativeToCluster = (0, exports.timestampToClusterTimestamp)(chunk.timestamp, timescale) -
|
||||
(0, exports.timestampToClusterTimestamp)(clusterStartTimestamp, timescale);
|
||||
if (!(0, exports.canFitInCluster)({ clusterStartTimestamp, chunk, timescale })) {
|
||||
throw new Error(`timecodeRelativeToCluster is too big: ${timecodeRelativeToCluster} > ${maxClusterTimestamp}`);
|
||||
}
|
||||
const keyframe = chunk.type === 'key';
|
||||
const simpleBlock = (0, cluster_segment_1.makeSimpleBlock)({
|
||||
bytes: chunk.data,
|
||||
invisible: false,
|
||||
keyframe,
|
||||
lacing: 0,
|
||||
trackNumber,
|
||||
timecodeRelativeToCluster,
|
||||
});
|
||||
clusterSize += simpleBlock.byteLength;
|
||||
await writer.updateDataAt(clusterVIntPosition, (0, matroska_utils_1.getVariableInt)(clusterSize, cluster_segment_1.CLUSTER_MIN_VINT_WIDTH));
|
||||
await writer.write(simpleBlock);
|
||||
return { timecodeRelativeToCluster };
|
||||
};
|
||||
const shouldMakeNewCluster = ({ isVideo, chunk, newT, }) => {
|
||||
const newTimestamp = (0, exports.timestampToClusterTimestamp)(newT, timescale);
|
||||
const oldTimestamp = (0, exports.timestampToClusterTimestamp)(clusterStartTimestamp, timescale);
|
||||
const canFit = (0, exports.canFitInCluster)({
|
||||
chunk,
|
||||
clusterStartTimestamp,
|
||||
timescale,
|
||||
});
|
||||
if (!canFit) {
|
||||
// We must create a new cluster
|
||||
// This is for example if we have an audio-only file
|
||||
log_1.Log.verbose(logLevel, `Cannot fit ${chunk.timestamp} in cluster ${clusterStartTimestamp}. Creating new cluster`);
|
||||
return true;
|
||||
}
|
||||
const keyframe = chunk.type === 'key';
|
||||
// TODO: Timestamp falls apart when video only
|
||||
return newTimestamp - oldTimestamp >= 2000 && keyframe && isVideo;
|
||||
};
|
||||
return {
|
||||
addSample,
|
||||
shouldMakeNewCluster,
|
||||
startTimestamp: clusterStartTimestamp,
|
||||
};
|
||||
};
|
||||
exports.makeCluster = makeCluster;
|
||||
2
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/color.d.ts
generated
vendored
Normal file
2
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/color.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import type { MediaParserAdvancedColor } from '@remotion/media-parser';
|
||||
export declare const makeMatroskaColorBytes: ({ transfer: transferCharacteristics, matrix: matrixCoefficients, primaries, fullRange, }: MediaParserAdvancedColor) => import("./matroska-utils").BytesAndOffset;
|
||||
142
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/color.js
generated
vendored
Normal file
142
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/color.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeMatroskaColorBytes = void 0;
|
||||
const truthy_1 = require("../../truthy");
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const getRangeValue = ({ transferCharacteristics, matrixCoefficients, fullRange, }) => {
|
||||
return transferCharacteristics && matrixCoefficients
|
||||
? 3
|
||||
: fullRange === true
|
||||
? 2
|
||||
: fullRange === false
|
||||
? 1
|
||||
: 0;
|
||||
};
|
||||
// https://w3c.github.io/webcodecs/#videocolorprimaries
|
||||
const getPrimariesValue = (primaries) => {
|
||||
if (primaries === null) {
|
||||
return null;
|
||||
}
|
||||
if (primaries === 'bt709') {
|
||||
return 1;
|
||||
}
|
||||
if (primaries === 'bt470bg') {
|
||||
return 5;
|
||||
}
|
||||
if (primaries === 'smpte170m') {
|
||||
return 6;
|
||||
}
|
||||
if (primaries === 'bt2020') {
|
||||
return 9;
|
||||
}
|
||||
if (primaries === 'smpte432') {
|
||||
return 12;
|
||||
}
|
||||
throw new Error('Unknown primaries ' + primaries);
|
||||
};
|
||||
const getTransferCharacteristicsValue = (transferCharacteristics) => {
|
||||
if (transferCharacteristics === null) {
|
||||
return null;
|
||||
}
|
||||
if (transferCharacteristics === 'bt709') {
|
||||
return 1;
|
||||
}
|
||||
if (transferCharacteristics === 'smpte170m') {
|
||||
return 6;
|
||||
}
|
||||
if (transferCharacteristics === 'iec61966-2-1') {
|
||||
return 13;
|
||||
}
|
||||
if (transferCharacteristics === 'linear') {
|
||||
return 8;
|
||||
}
|
||||
if (transferCharacteristics === 'pq') {
|
||||
return 16;
|
||||
}
|
||||
if (transferCharacteristics === 'hlg') {
|
||||
return 18;
|
||||
}
|
||||
throw new Error('Unknown transfer characteristics ' +
|
||||
transferCharacteristics);
|
||||
};
|
||||
const getMatrixCoefficientsValue = (matrixCoefficients) => {
|
||||
if (matrixCoefficients === null) {
|
||||
return null;
|
||||
}
|
||||
if (matrixCoefficients === 'rgb') {
|
||||
return 0;
|
||||
}
|
||||
if (matrixCoefficients === 'bt709') {
|
||||
return 1;
|
||||
}
|
||||
if (matrixCoefficients === 'bt470bg') {
|
||||
return 5;
|
||||
}
|
||||
if (matrixCoefficients === 'smpte170m') {
|
||||
return 6;
|
||||
}
|
||||
if (matrixCoefficients === 'bt2020-ncl') {
|
||||
return 9;
|
||||
}
|
||||
throw new Error('Unknown matrix coefficients ' + matrixCoefficients);
|
||||
};
|
||||
const makeMatroskaColorBytes = ({ transfer: transferCharacteristics, matrix: matrixCoefficients, primaries, fullRange, }) => {
|
||||
const rangeValue = getRangeValue({
|
||||
transferCharacteristics,
|
||||
matrixCoefficients,
|
||||
fullRange,
|
||||
});
|
||||
// https://datatracker.ietf.org/doc/draft-ietf-cellar-matroska/
|
||||
// 5.1.4.1.28.27
|
||||
const primariesValue = getPrimariesValue(primaries);
|
||||
const transferChracteristicsValue = getTransferCharacteristicsValue(transferCharacteristics);
|
||||
if (matrixCoefficients === 'rgb') {
|
||||
throw new Error('Cannot encode Matroska in RGB');
|
||||
}
|
||||
const matrixCoefficientsValue = getMatrixCoefficientsValue(matrixCoefficients);
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Colour',
|
||||
minVintWidth: null,
|
||||
value: [
|
||||
transferChracteristicsValue === null
|
||||
? null
|
||||
: {
|
||||
type: 'TransferCharacteristics',
|
||||
value: {
|
||||
value: transferChracteristicsValue,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
matrixCoefficientsValue === null
|
||||
? null
|
||||
: {
|
||||
type: 'MatrixCoefficients',
|
||||
value: {
|
||||
value: matrixCoefficientsValue,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
primariesValue === null
|
||||
? null
|
||||
: {
|
||||
type: 'Primaries',
|
||||
value: {
|
||||
value: primariesValue,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'Range',
|
||||
value: {
|
||||
value: rangeValue,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
].filter(truthy_1.truthy),
|
||||
});
|
||||
};
|
||||
exports.makeMatroskaColorBytes = makeMatroskaColorBytes;
|
||||
2
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/create-matroska-media.d.ts
generated
vendored
Normal file
2
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/create-matroska-media.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import type { MediaFn, MediaFnGeneratorInput } from '../media-fn';
|
||||
export declare const createMatroskaMedia: ({ writer, onBytesProgress, onMillisecondsProgress, filename, logLevel, progressTracker, }: MediaFnGeneratorInput) => Promise<MediaFn>;
|
||||
206
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/create-matroska-media.js
generated
vendored
Normal file
206
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/create-matroska-media.js
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMatroskaMedia = void 0;
|
||||
const media_parser_1 = require("@remotion/media-parser");
|
||||
const cluster_1 = require("./cluster");
|
||||
const make_duration_with_padding_1 = require("./make-duration-with-padding");
|
||||
const matroska_cues_1 = require("./matroska-cues");
|
||||
const matroska_header_1 = require("./matroska-header");
|
||||
const matroska_info_1 = require("./matroska-info");
|
||||
const matroska_seek_1 = require("./matroska-seek");
|
||||
const matroska_segment_1 = require("./matroska-segment");
|
||||
const matroska_trackentry_1 = require("./matroska-trackentry");
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const { matroskaElements } = media_parser_1.MediaParserInternals;
|
||||
const timescale = 1000000;
|
||||
const createMatroskaMedia = async ({ writer, onBytesProgress, onMillisecondsProgress, filename, logLevel, progressTracker, }) => {
|
||||
const header = (0, matroska_header_1.makeMatroskaHeader)();
|
||||
const w = await writer.createContent({
|
||||
filename,
|
||||
mimeType: 'video/webm',
|
||||
logLevel,
|
||||
});
|
||||
await w.write(header.bytes);
|
||||
const matroskaInfo = (0, matroska_info_1.makeMatroskaInfo)({
|
||||
timescale,
|
||||
});
|
||||
const currentTracks = [];
|
||||
const seeks = [];
|
||||
const cues = [];
|
||||
const trackNumbers = [];
|
||||
const matroskaSegment = (0, matroska_segment_1.createMatroskaSegment)([
|
||||
...(0, matroska_seek_1.createMatroskaSeekHead)(seeks),
|
||||
matroskaInfo,
|
||||
...(0, matroska_trackentry_1.makeMatroskaTracks)(currentTracks),
|
||||
]);
|
||||
const infoSegment = matroskaSegment.offsets.children.find((o) => o.field === 'Info');
|
||||
const durationOffset = (infoSegment?.children.find((c) => c.field === 'Duration')?.offset ?? 0) +
|
||||
w.getWrittenByteCount();
|
||||
const tracksOffset = (matroskaSegment.offsets.children.find((o) => o.field === 'Tracks')
|
||||
?.offset ?? 0) + w.getWrittenByteCount();
|
||||
const seekHeadOffset = (matroskaSegment.offsets.children.find((o) => o.field === 'SeekHead')
|
||||
?.offset ?? 0) + w.getWrittenByteCount();
|
||||
const infoOffset = (infoSegment?.offset ?? 0) + w.getWrittenByteCount();
|
||||
if (!seekHeadOffset) {
|
||||
throw new Error('could not get seek offset');
|
||||
}
|
||||
if (!durationOffset) {
|
||||
throw new Error('could not get duration offset');
|
||||
}
|
||||
if (!tracksOffset) {
|
||||
throw new Error('could not get tracks offset');
|
||||
}
|
||||
if (!infoOffset) {
|
||||
throw new Error('could not get tracks offset');
|
||||
}
|
||||
seeks.push({
|
||||
hexString: matroskaElements.Info,
|
||||
byte: infoOffset - seekHeadOffset,
|
||||
});
|
||||
seeks.push({
|
||||
hexString: matroskaElements.Tracks,
|
||||
byte: tracksOffset - seekHeadOffset,
|
||||
});
|
||||
const updateSeekWrite = async () => {
|
||||
const updatedSeek = (0, matroska_seek_1.createMatroskaSeekHead)(seeks);
|
||||
await w.updateDataAt(seekHeadOffset, (0, matroska_utils_1.combineUint8Arrays)(updatedSeek.map((b) => b.bytes)));
|
||||
onBytesProgress(w.getWrittenByteCount());
|
||||
};
|
||||
const segmentOffset = w.getWrittenByteCount();
|
||||
const updateSegmentSize = async (size) => {
|
||||
const data = (0, matroska_utils_1.getVariableInt)(size, matroska_segment_1.MATROSKA_SEGMENT_MIN_VINT_WIDTH);
|
||||
await w.updateDataAt(segmentOffset + (0, matroska_utils_1.matroskaToHex)(matroskaElements.Segment).byteLength, data);
|
||||
onBytesProgress(w.getWrittenByteCount());
|
||||
};
|
||||
await w.write(matroskaSegment.bytes);
|
||||
const clusterOffset = w.getWrittenByteCount();
|
||||
let currentCluster = await (0, cluster_1.makeCluster)({
|
||||
writer: w,
|
||||
clusterStartTimestamp: 0,
|
||||
timescale,
|
||||
logLevel,
|
||||
});
|
||||
seeks.push({
|
||||
hexString: matroskaElements.Cluster,
|
||||
byte: clusterOffset - seekHeadOffset,
|
||||
});
|
||||
const getClusterOrMakeNew = async ({ chunk, isVideo, }) => {
|
||||
// In Safari, samples can arrive out of order, e.g public/bigbuckbunny.mp4
|
||||
// Therefore, only updating track number progress if it is a keyframe
|
||||
// to allow for timestamps to be lower than the previous one
|
||||
progressTracker.setPossibleLowestTimestamp(Math.min(chunk.timestamp, chunk.decodingTimestamp ?? Infinity));
|
||||
const smallestProgress = progressTracker.getSmallestProgress();
|
||||
if (!currentCluster.shouldMakeNewCluster({
|
||||
newT: smallestProgress,
|
||||
isVideo,
|
||||
chunk,
|
||||
})) {
|
||||
return {
|
||||
cluster: currentCluster,
|
||||
isNew: false,
|
||||
smallestProgress,
|
||||
};
|
||||
}
|
||||
currentCluster = await (0, cluster_1.makeCluster)({
|
||||
writer: w,
|
||||
clusterStartTimestamp: smallestProgress,
|
||||
timescale,
|
||||
logLevel,
|
||||
});
|
||||
return {
|
||||
cluster: currentCluster,
|
||||
isNew: true,
|
||||
smallestProgress,
|
||||
};
|
||||
};
|
||||
const updateDuration = async (newDuration) => {
|
||||
const blocks = (0, make_duration_with_padding_1.makeDurationWithPadding)(newDuration);
|
||||
await w.updateDataAt(durationOffset, blocks.bytes);
|
||||
onBytesProgress(w.getWrittenByteCount());
|
||||
};
|
||||
const addSample = async ({ chunk, trackNumber, isVideo, }) => {
|
||||
const offset = w.getWrittenByteCount();
|
||||
const { cluster, isNew, smallestProgress } = await getClusterOrMakeNew({
|
||||
chunk,
|
||||
isVideo,
|
||||
});
|
||||
const newDuration = Math.round((chunk.timestamp + (chunk.duration ?? 0)) / 1000);
|
||||
await updateDuration(newDuration);
|
||||
const { timecodeRelativeToCluster } = await cluster.addSample(chunk, trackNumber);
|
||||
if (isNew) {
|
||||
if (offset === null) {
|
||||
throw new Error('offset is null');
|
||||
}
|
||||
cues.push({
|
||||
time: (0, cluster_1.timestampToClusterTimestamp)(smallestProgress, timescale) +
|
||||
timecodeRelativeToCluster,
|
||||
clusterPosition: offset - seekHeadOffset,
|
||||
trackNumber,
|
||||
});
|
||||
}
|
||||
if (chunk.type === 'key') {
|
||||
progressTracker.updateTrackProgress(trackNumber, chunk.timestamp);
|
||||
}
|
||||
onBytesProgress(w.getWrittenByteCount());
|
||||
onMillisecondsProgress(newDuration);
|
||||
};
|
||||
const addTrack = async (track) => {
|
||||
currentTracks.push(track);
|
||||
const newTracks = (0, matroska_trackentry_1.makeMatroskaTracks)(currentTracks);
|
||||
progressTracker.registerTrack(track.trackNumber);
|
||||
await w.updateDataAt(tracksOffset, (0, matroska_utils_1.combineUint8Arrays)(newTracks.map((b) => b.bytes)));
|
||||
};
|
||||
const operationProm = { current: Promise.resolve() };
|
||||
const waitForFinishPromises = [];
|
||||
return {
|
||||
updateTrackSampleRate: ({ sampleRate, trackNumber }) => {
|
||||
currentTracks.forEach((track) => {
|
||||
if (track.trackNumber === trackNumber) {
|
||||
if (track.type !== 'audio') {
|
||||
throw new Error('track is not audio');
|
||||
}
|
||||
track.sampleRate = sampleRate;
|
||||
}
|
||||
});
|
||||
},
|
||||
getBlob: () => {
|
||||
return w.getBlob();
|
||||
},
|
||||
remove: async () => {
|
||||
await w.remove();
|
||||
},
|
||||
addSample: ({ chunk, trackNumber, isVideo }) => {
|
||||
operationProm.current = operationProm.current.then(() => addSample({ chunk, trackNumber, isVideo }));
|
||||
return operationProm.current;
|
||||
},
|
||||
addTrack: (track) => {
|
||||
const trackNumber = currentTracks.length + 1;
|
||||
operationProm.current = operationProm.current.then(() => addTrack({ ...track, trackNumber }));
|
||||
trackNumbers.push(trackNumber);
|
||||
return operationProm.current.then(() => ({ trackNumber }));
|
||||
},
|
||||
addWaitForFinishPromise: (promise) => {
|
||||
waitForFinishPromises.push(promise);
|
||||
},
|
||||
async waitForFinish() {
|
||||
await Promise.all(waitForFinishPromises.map((p) => p()));
|
||||
await operationProm.current;
|
||||
const cuesBytes = (0, matroska_cues_1.createMatroskaCues)(cues);
|
||||
if (cuesBytes) {
|
||||
seeks.push({
|
||||
hexString: matroskaElements.Cues,
|
||||
byte: w.getWrittenByteCount() - seekHeadOffset,
|
||||
});
|
||||
await w.write(cuesBytes.bytes);
|
||||
}
|
||||
await updateSeekWrite();
|
||||
const segmentSize = w.getWrittenByteCount() -
|
||||
segmentOffset -
|
||||
(0, matroska_utils_1.matroskaToHex)(matroskaElements.Segment).byteLength -
|
||||
matroska_segment_1.MATROSKA_SEGMENT_MIN_VINT_WIDTH;
|
||||
await updateSegmentSize(segmentSize);
|
||||
await w.finish();
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.createMatroskaMedia = createMatroskaMedia;
|
||||
1
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/make-duration-with-padding.d.ts
generated
vendored
Normal file
1
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/make-duration-with-padding.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export declare const makeDurationWithPadding: (newDuration: number) => import("./matroska-utils").BytesAndOffset;
|
||||
15
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/make-duration-with-padding.js
generated
vendored
Normal file
15
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/make-duration-with-padding.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeDurationWithPadding = void 0;
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const makeDurationWithPadding = (newDuration) => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Duration',
|
||||
value: {
|
||||
value: newDuration,
|
||||
size: '64',
|
||||
},
|
||||
minVintWidth: 8,
|
||||
});
|
||||
};
|
||||
exports.makeDurationWithPadding = makeDurationWithPadding;
|
||||
7
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-cues.d.ts
generated
vendored
Normal file
7
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-cues.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { BytesAndOffset } from './matroska-utils';
|
||||
export type Cue = {
|
||||
time: number;
|
||||
clusterPosition: number;
|
||||
trackNumber: number;
|
||||
};
|
||||
export declare const createMatroskaCues: (cues: Cue[]) => BytesAndOffset | null;
|
||||
52
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-cues.js
generated
vendored
Normal file
52
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-cues.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMatroskaCues = void 0;
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const createMatroskaCues = (cues) => {
|
||||
if (cues.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Cues',
|
||||
minVintWidth: null,
|
||||
value: cues.map((cue) => {
|
||||
return {
|
||||
type: 'CuePoint',
|
||||
value: [
|
||||
{
|
||||
type: 'CueTime',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: cue.time,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'CueTrackPositions',
|
||||
value: [
|
||||
{
|
||||
type: 'CueTrack',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: cue.trackNumber,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'CueClusterPosition',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: cue.clusterPosition,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
minVintWidth: null,
|
||||
},
|
||||
],
|
||||
minVintWidth: null,
|
||||
};
|
||||
}),
|
||||
});
|
||||
};
|
||||
exports.createMatroskaCues = createMatroskaCues;
|
||||
1
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-header.d.ts
generated
vendored
Normal file
1
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-header.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export declare const makeMatroskaHeader: () => import("./matroska-utils").BytesAndOffset;
|
||||
66
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-header.js
generated
vendored
Normal file
66
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-header.js
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeMatroskaHeader = void 0;
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const makeMatroskaHeader = () => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Header',
|
||||
value: [
|
||||
{
|
||||
minVintWidth: null,
|
||||
type: 'EBMLVersion',
|
||||
value: {
|
||||
value: 1,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
minVintWidth: null,
|
||||
type: 'EBMLReadVersion',
|
||||
value: {
|
||||
value: 1,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'EBMLMaxIDLength',
|
||||
value: {
|
||||
byteLength: null,
|
||||
value: 4,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'EBMLMaxSizeLength',
|
||||
value: {
|
||||
byteLength: null,
|
||||
value: 8,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'DocType',
|
||||
value: 'webm',
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'DocTypeVersion',
|
||||
value: {
|
||||
byteLength: null,
|
||||
value: 4,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'DocTypeReadVersion',
|
||||
value: {
|
||||
byteLength: null,
|
||||
value: 2,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
],
|
||||
minVintWidth: null,
|
||||
});
|
||||
};
|
||||
exports.makeMatroskaHeader = makeMatroskaHeader;
|
||||
3
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-info.d.ts
generated
vendored
Normal file
3
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-info.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export declare const makeMatroskaInfo: ({ timescale }: {
|
||||
timescale: number;
|
||||
}) => import("./matroska-utils").BytesAndOffset;
|
||||
33
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-info.js
generated
vendored
Normal file
33
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-info.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeMatroskaInfo = void 0;
|
||||
const make_duration_with_padding_1 = require("./make-duration-with-padding");
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const makeMatroskaInfo = ({ timescale }) => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Info',
|
||||
value: [
|
||||
{
|
||||
type: 'TimestampScale',
|
||||
value: {
|
||||
value: timescale,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'MuxingApp',
|
||||
value: '@remotion/webcodecs',
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'WritingApp',
|
||||
value: '@remotion/webcodecs',
|
||||
minVintWidth: null,
|
||||
},
|
||||
(0, make_duration_with_padding_1.makeDurationWithPadding)(0),
|
||||
],
|
||||
minVintWidth: null,
|
||||
});
|
||||
};
|
||||
exports.makeMatroskaInfo = makeMatroskaInfo;
|
||||
6
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-seek.d.ts
generated
vendored
Normal file
6
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-seek.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { MediaParserInternalTypes } from '@remotion/media-parser';
|
||||
export type Seek = {
|
||||
hexString: MediaParserInternalTypes['MatroskaElement'];
|
||||
byte: number;
|
||||
};
|
||||
export declare const createMatroskaSeekHead: (seeks: Seek[]) => import("./matroska-utils").BytesAndOffset[];
|
||||
32
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-seek.js
generated
vendored
Normal file
32
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-seek.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMatroskaSeekHead = void 0;
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const createMatroskaSeekHead = (seeks) => {
|
||||
return (0, matroska_utils_1.padMatroskaBytes)((0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'SeekHead',
|
||||
minVintWidth: null,
|
||||
value: seeks.map((seek) => {
|
||||
return {
|
||||
type: 'Seek',
|
||||
minVintWidth: null,
|
||||
value: [
|
||||
{
|
||||
type: 'SeekID',
|
||||
minVintWidth: null,
|
||||
value: seek.hexString,
|
||||
},
|
||||
{
|
||||
type: 'SeekPosition',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: seek.byte,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}),
|
||||
}), 200);
|
||||
};
|
||||
exports.createMatroskaSeekHead = createMatroskaSeekHead;
|
||||
3
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-segment.d.ts
generated
vendored
Normal file
3
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-segment.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import type { BytesAndOffset } from './matroska-utils';
|
||||
export declare const MATROSKA_SEGMENT_MIN_VINT_WIDTH = 8;
|
||||
export declare const createMatroskaSegment: (children: BytesAndOffset[]) => BytesAndOffset;
|
||||
13
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-segment.js
generated
vendored
Normal file
13
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-segment.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMatroskaSegment = exports.MATROSKA_SEGMENT_MIN_VINT_WIDTH = void 0;
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
exports.MATROSKA_SEGMENT_MIN_VINT_WIDTH = 8;
|
||||
const createMatroskaSegment = (children) => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Segment',
|
||||
value: children,
|
||||
minVintWidth: exports.MATROSKA_SEGMENT_MIN_VINT_WIDTH,
|
||||
});
|
||||
};
|
||||
exports.createMatroskaSegment = createMatroskaSegment;
|
||||
10
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-trackentry.d.ts
generated
vendored
Normal file
10
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-trackentry.d.ts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { MediaParserAdvancedColor } from '@remotion/media-parser';
|
||||
import type { MakeTrackAudio, MakeTrackVideo } from '../make-track-info';
|
||||
export declare const makeMatroskaVideoBytes: ({ color, width, height, }: {
|
||||
color: MediaParserAdvancedColor;
|
||||
width: number;
|
||||
height: number;
|
||||
}) => import("./matroska-utils").BytesAndOffset;
|
||||
export declare const makeMatroskaAudioTrackEntryBytes: ({ trackNumber, codec, numberOfChannels, sampleRate, codecPrivate, }: MakeTrackAudio) => import("./matroska-utils").BytesAndOffset;
|
||||
export declare const makeMatroskaVideoTrackEntryBytes: ({ color, width, height, trackNumber, codec, codecPrivate, }: MakeTrackVideo) => import("./matroska-utils").BytesAndOffset;
|
||||
export declare const makeMatroskaTracks: (tracks: (MakeTrackAudio | MakeTrackVideo)[]) => import("./matroska-utils").BytesAndOffset[];
|
||||
229
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-trackentry.js
generated
vendored
Normal file
229
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-trackentry.js
generated
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeMatroskaTracks = exports.makeMatroskaVideoTrackEntryBytes = exports.makeMatroskaAudioTrackEntryBytes = exports.makeMatroskaVideoBytes = void 0;
|
||||
const color_1 = require("./color");
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const makeMatroskaVideoBytes = ({ color, width, height, }) => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Video',
|
||||
value: [
|
||||
{
|
||||
type: 'PixelWidth',
|
||||
value: {
|
||||
value: width,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'PixelHeight',
|
||||
value: {
|
||||
value: height,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'FlagInterlaced',
|
||||
value: {
|
||||
// https://datatracker.ietf.org/doc/draft-ietf-cellar-matroska/
|
||||
// 5.1.4.1.28.1.
|
||||
value: 2, // 2 - progressive, no interlaced
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
(0, color_1.makeMatroskaColorBytes)(color),
|
||||
],
|
||||
minVintWidth: null,
|
||||
});
|
||||
};
|
||||
exports.makeMatroskaVideoBytes = makeMatroskaVideoBytes;
|
||||
const makeVideoCodecId = (codecId) => {
|
||||
if (codecId === 'vp8') {
|
||||
return 'V_VP8';
|
||||
}
|
||||
if (codecId === 'vp9') {
|
||||
return 'V_VP9';
|
||||
}
|
||||
if (codecId === 'h264') {
|
||||
return 'V_MPEG4/ISO/AVC';
|
||||
}
|
||||
if (codecId === 'av1') {
|
||||
return 'V_AV1';
|
||||
}
|
||||
if (codecId === 'h265') {
|
||||
return 'V_MPEGH/ISO/HEVC';
|
||||
}
|
||||
if (codecId === 'prores') {
|
||||
return 'V_PRORES';
|
||||
}
|
||||
throw new Error(`Unknown codec: ${codecId}`);
|
||||
};
|
||||
const makeAudioCodecId = (codecId) => {
|
||||
if (codecId === 'opus') {
|
||||
return 'A_OPUS';
|
||||
}
|
||||
if (codecId === 'aac') {
|
||||
return 'A_AAC';
|
||||
}
|
||||
if (codecId === 'ac3') {
|
||||
return 'A_AC3';
|
||||
}
|
||||
if (codecId === 'mp3') {
|
||||
return 'A_MPEG/L3';
|
||||
}
|
||||
if (codecId === 'vorbis') {
|
||||
return 'A_VORBIS';
|
||||
}
|
||||
if (codecId === 'flac') {
|
||||
return 'A_FLAC';
|
||||
}
|
||||
if (codecId === 'pcm-u8') {
|
||||
return 'A_PCM/INT/LIT';
|
||||
}
|
||||
if (codecId === 'pcm-s16') {
|
||||
return 'A_PCM/INT/LIT';
|
||||
}
|
||||
if (codecId === 'pcm-s24') {
|
||||
return 'A_PCM/INT/LIT';
|
||||
}
|
||||
if (codecId === 'pcm-s32') {
|
||||
return 'A_PCM/INT/LIT';
|
||||
}
|
||||
if (codecId === 'pcm-f32') {
|
||||
return 'A_PCM/INT/LIT';
|
||||
}
|
||||
if (codecId === 'aiff') {
|
||||
throw new Error('aiff is not supported in Matroska');
|
||||
}
|
||||
throw new Error(`Unknown codec: ${codecId}`);
|
||||
};
|
||||
const makeMatroskaAudioTrackEntryBytes = ({ trackNumber, codec, numberOfChannels, sampleRate, codecPrivate, }) => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'TrackEntry',
|
||||
minVintWidth: null,
|
||||
value: [
|
||||
{
|
||||
type: 'TrackNumber',
|
||||
value: {
|
||||
value: trackNumber,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'TrackType',
|
||||
value: {
|
||||
value: 2,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'CodecID',
|
||||
value: makeAudioCodecId(codec),
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'Audio',
|
||||
value: [
|
||||
{
|
||||
type: 'Channels',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: numberOfChannels,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'SamplingFrequency',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: sampleRate,
|
||||
size: '64',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'BitDepth',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: 32,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
minVintWidth: null,
|
||||
},
|
||||
codecPrivate
|
||||
? {
|
||||
type: 'CodecPrivate',
|
||||
minVintWidth: null,
|
||||
value: codecPrivate,
|
||||
}
|
||||
: null,
|
||||
].filter(Boolean),
|
||||
});
|
||||
};
|
||||
exports.makeMatroskaAudioTrackEntryBytes = makeMatroskaAudioTrackEntryBytes;
|
||||
const makeMatroskaVideoTrackEntryBytes = ({ color, width, height, trackNumber, codec, codecPrivate, }) => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'TrackEntry',
|
||||
minVintWidth: null,
|
||||
value: [
|
||||
{
|
||||
type: 'TrackNumber',
|
||||
value: {
|
||||
value: trackNumber,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'Language',
|
||||
value: 'und',
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'CodecID',
|
||||
value: makeVideoCodecId(codec),
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'TrackType',
|
||||
value: {
|
||||
value: 1, // 'video'
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
(0, exports.makeMatroskaVideoBytes)({
|
||||
color,
|
||||
width,
|
||||
height,
|
||||
}),
|
||||
codecPrivate
|
||||
? {
|
||||
type: 'CodecPrivate',
|
||||
minVintWidth: null,
|
||||
value: codecPrivate,
|
||||
}
|
||||
: null,
|
||||
].filter(Boolean),
|
||||
});
|
||||
};
|
||||
exports.makeMatroskaVideoTrackEntryBytes = makeMatroskaVideoTrackEntryBytes;
|
||||
const makeMatroskaTracks = (tracks) => {
|
||||
const bytesArr = tracks.map((t) => {
|
||||
const bytes = t.type === 'video'
|
||||
? (0, exports.makeMatroskaVideoTrackEntryBytes)(t)
|
||||
: (0, exports.makeMatroskaAudioTrackEntryBytes)(t);
|
||||
return bytes;
|
||||
});
|
||||
return (0, matroska_utils_1.padMatroskaBytes)((0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Tracks',
|
||||
value: bytesArr,
|
||||
minVintWidth: null,
|
||||
}), 500);
|
||||
};
|
||||
exports.makeMatroskaTracks = makeMatroskaTracks;
|
||||
34
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-utils.d.ts
generated
vendored
Normal file
34
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-utils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { _InternalEbmlValue, MediaParserInternalTypes } from '@remotion/media-parser';
|
||||
import { MediaParserInternals } from '@remotion/media-parser';
|
||||
type Prettify<T> = {
|
||||
[K in keyof T]: T[K];
|
||||
} & {};
|
||||
export declare const getIdForName: (name: string) => EbmlMapKey;
|
||||
export declare const combineUint8Arrays: (arrays: Uint8Array[]) => Uint8Array<ArrayBufferLike>;
|
||||
export type OffsetAndChildren = {
|
||||
offset: number;
|
||||
children: OffsetAndChildren[];
|
||||
field: keyof typeof MediaParserInternals.matroskaElements;
|
||||
};
|
||||
export declare const incrementOffsetAndChildren: (offset: OffsetAndChildren, increment: number) => OffsetAndChildren;
|
||||
export declare const matroskaToHex: (matrId: (typeof MediaParserInternals.matroskaElements)[keyof typeof MediaParserInternals.matroskaElements]) => Uint8Array<ArrayBufferLike>;
|
||||
export type BytesAndOffset = {
|
||||
bytes: Uint8Array;
|
||||
offsets: OffsetAndChildren;
|
||||
};
|
||||
export type EbmlValueOrUint8Array<T extends MediaParserInternalTypes['Ebml']> = Uint8Array | _InternalEbmlValue<T, PossibleEbmlOrUint8Array>;
|
||||
export type EbmlParsedOrUint8Array<T extends MediaParserInternalTypes['Ebml']> = {
|
||||
type: T['name'];
|
||||
value: EbmlValueOrUint8Array<T>;
|
||||
minVintWidth: number | null;
|
||||
};
|
||||
export declare const measureEBMLVarInt: (value: number) => 1 | 2 | 4 | 3 | 5 | 6;
|
||||
export declare const getVariableInt: (value: number, minWidth: number | null) => Uint8Array<ArrayBuffer>;
|
||||
export declare const makeMatroskaBytes: (fields: PossibleEbmlOrUint8Array) => BytesAndOffset;
|
||||
export type PossibleEbmlOrUint8Array = Prettify<{
|
||||
[key in keyof typeof MediaParserInternals.ebmlMap]: EbmlParsedOrUint8Array<(typeof MediaParserInternals.ebmlMap)[key]>;
|
||||
}[keyof typeof MediaParserInternals.ebmlMap]> | BytesAndOffset;
|
||||
export type EbmlMapKey = keyof typeof MediaParserInternals.ebmlMap;
|
||||
export declare const padMatroskaBytes: (fields: PossibleEbmlOrUint8Array, totalLength: number) => BytesAndOffset[];
|
||||
export declare function serializeUint16(value: number): Uint8Array;
|
||||
export {};
|
||||
291
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-utils.js
generated
vendored
Normal file
291
remotion/node_modules/@remotion/webcodecs/dist/create/matroska/matroska-utils.js
generated
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.padMatroskaBytes = exports.makeMatroskaBytes = exports.getVariableInt = exports.measureEBMLVarInt = exports.matroskaToHex = exports.incrementOffsetAndChildren = exports.combineUint8Arrays = exports.getIdForName = void 0;
|
||||
exports.serializeUint16 = serializeUint16;
|
||||
const media_parser_1 = require("@remotion/media-parser");
|
||||
const getIdForName = (name) => {
|
||||
const value = Object.entries(media_parser_1.MediaParserInternals.matroskaElements).find(([key]) => key === name)?.[1];
|
||||
if (!value) {
|
||||
throw new Error(`Could not find id for name ${name}`);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
exports.getIdForName = getIdForName;
|
||||
function putUintDynamic(number, minimumLength) {
|
||||
if (number < 0) {
|
||||
throw new Error('This function is designed for non-negative integers only.');
|
||||
}
|
||||
// Calculate the minimum number of bytes needed to store the integer
|
||||
const length = Math.max(minimumLength ?? 1, Math.ceil(Math.log2(number + 1) / 8));
|
||||
const bytes = new Uint8Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
// Extract each byte from the number
|
||||
bytes[length - 1 - i] = (number >> (8 * i)) & 0xff;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
const makeFromStructure = (fields) => {
|
||||
if ('bytes' in fields) {
|
||||
return fields;
|
||||
}
|
||||
const arrays = [];
|
||||
const struct = media_parser_1.MediaParserInternals.ebmlMap[(0, exports.getIdForName)(fields.type)];
|
||||
if (struct.type === 'uint8array') {
|
||||
return {
|
||||
bytes: fields.value,
|
||||
offsets: { offset: 0, children: [], field: fields.type },
|
||||
};
|
||||
}
|
||||
if (struct.type === 'children') {
|
||||
const children = [];
|
||||
let bytesWritten = 0;
|
||||
for (const item of fields.value) {
|
||||
const { bytes, offsets } = (0, exports.makeMatroskaBytes)(item);
|
||||
arrays.push(bytes);
|
||||
children.push((0, exports.incrementOffsetAndChildren)(offsets, bytesWritten));
|
||||
bytesWritten += bytes.byteLength;
|
||||
}
|
||||
return {
|
||||
bytes: (0, exports.combineUint8Arrays)(arrays),
|
||||
offsets: { offset: 0, children, field: fields.type },
|
||||
};
|
||||
}
|
||||
if (struct.type === 'string') {
|
||||
return {
|
||||
bytes: new TextEncoder().encode(fields.value),
|
||||
offsets: {
|
||||
children: [],
|
||||
offset: 0,
|
||||
field: fields.type,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (struct.type === 'uint') {
|
||||
return {
|
||||
bytes: putUintDynamic(fields.value.value, fields.value.byteLength),
|
||||
offsets: {
|
||||
children: [],
|
||||
offset: 0,
|
||||
field: fields.type,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (struct.type === 'hex-string') {
|
||||
const hex = fields.value.substring(2);
|
||||
const arr = new Uint8Array(hex.length / 2);
|
||||
for (let i = 0; i < hex.length; i += 2) {
|
||||
const byte = parseInt(hex.substring(i, i + 2), 16);
|
||||
arr[i / 2] = byte;
|
||||
}
|
||||
return {
|
||||
bytes: arr,
|
||||
offsets: {
|
||||
children: [],
|
||||
offset: 0,
|
||||
field: fields.type,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (struct.type === 'float') {
|
||||
const value = fields.value;
|
||||
if (value.size === '32') {
|
||||
const dataView = new DataView(new ArrayBuffer(4));
|
||||
dataView.setFloat32(0, value.value);
|
||||
return {
|
||||
bytes: new Uint8Array(dataView.buffer),
|
||||
offsets: {
|
||||
children: [],
|
||||
offset: 0,
|
||||
field: fields.type,
|
||||
},
|
||||
};
|
||||
}
|
||||
const dataView2 = new DataView(new ArrayBuffer(8));
|
||||
dataView2.setFloat64(0, value.value);
|
||||
return {
|
||||
bytes: new Uint8Array(dataView2.buffer),
|
||||
offsets: {
|
||||
children: [],
|
||||
offset: 0,
|
||||
field: fields.type,
|
||||
},
|
||||
};
|
||||
}
|
||||
throw new Error('Unexpected type');
|
||||
};
|
||||
const combineUint8Arrays = (arrays) => {
|
||||
if (arrays.length === 0) {
|
||||
return new Uint8Array([]);
|
||||
}
|
||||
if (arrays.length === 1) {
|
||||
return arrays[0];
|
||||
}
|
||||
let totalLength = 0;
|
||||
for (const array of arrays) {
|
||||
totalLength += array.length;
|
||||
}
|
||||
const result = new Uint8Array(totalLength);
|
||||
let offset = 0;
|
||||
for (const array of arrays) {
|
||||
result.set(array, offset);
|
||||
offset += array.length;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
exports.combineUint8Arrays = combineUint8Arrays;
|
||||
const incrementOffsetAndChildren = (offset, increment) => {
|
||||
return {
|
||||
offset: offset.offset + increment,
|
||||
children: offset.children.map((c) => (0, exports.incrementOffsetAndChildren)(c, increment)),
|
||||
field: offset.field,
|
||||
};
|
||||
};
|
||||
exports.incrementOffsetAndChildren = incrementOffsetAndChildren;
|
||||
const matroskaToHex = (matrId) => {
|
||||
const numbers = new Uint8Array((matrId.length - 2) / 2);
|
||||
for (let i = 2; i < matrId.length; i += 2) {
|
||||
const hex = matrId.substring(i, i + 2);
|
||||
numbers[(i - 2) / 2] = parseInt(hex, 16);
|
||||
}
|
||||
return numbers;
|
||||
};
|
||||
exports.matroskaToHex = matroskaToHex;
|
||||
// https://github.com/Vanilagy/webm-muxer/blob/main/src/ebml.ts#L101
|
||||
const measureEBMLVarInt = (value) => {
|
||||
if (value < (1 << 7) - 1) {
|
||||
/** Top bit is set, leaving 7 bits to hold the integer, but we can't store
|
||||
* 127 because "all bits set to one" is a reserved value. Same thing for the
|
||||
* other cases below:
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
if (value < (1 << 14) - 1) {
|
||||
return 2;
|
||||
}
|
||||
if (value < (1 << 21) - 1) {
|
||||
return 3;
|
||||
}
|
||||
if (value < (1 << 28) - 1) {
|
||||
return 4;
|
||||
}
|
||||
if (value < 2 ** 35 - 1) {
|
||||
return 5;
|
||||
}
|
||||
if (value < 2 ** 42 - 1) {
|
||||
return 6;
|
||||
}
|
||||
throw new Error('EBML VINT size not supported ' + value);
|
||||
};
|
||||
exports.measureEBMLVarInt = measureEBMLVarInt;
|
||||
const getVariableInt = (value, minWidth) => {
|
||||
const width = Math.max((0, exports.measureEBMLVarInt)(value), minWidth ?? 0);
|
||||
switch (width) {
|
||||
case 1:
|
||||
return new Uint8Array([(1 << 7) | value]);
|
||||
case 2:
|
||||
return new Uint8Array([(1 << 6) | (value >> 8), value]);
|
||||
case 3:
|
||||
return new Uint8Array([(1 << 5) | (value >> 16), value >> 8, value]);
|
||||
case 4:
|
||||
return new Uint8Array([
|
||||
(1 << 4) | (value >> 24),
|
||||
value >> 16,
|
||||
value >> 8,
|
||||
value,
|
||||
]);
|
||||
case 5:
|
||||
/**
|
||||
* JavaScript converts its doubles to 32-bit integers for bitwise
|
||||
* operations, so we need to do a division by 2^32 instead of a
|
||||
* right-shift of 32 to retain those top 3 bits
|
||||
*/
|
||||
return new Uint8Array([
|
||||
(1 << 3) | ((value / 2 ** 32) & 0x7),
|
||||
value >> 24,
|
||||
value >> 16,
|
||||
value >> 8,
|
||||
value,
|
||||
]);
|
||||
case 6:
|
||||
return new Uint8Array([
|
||||
(1 << 2) | ((value / 2 ** 40) & 0x3),
|
||||
(value / 2 ** 32) | 0,
|
||||
value >> 24,
|
||||
value >> 16,
|
||||
value >> 8,
|
||||
value,
|
||||
]);
|
||||
case 7:
|
||||
return new Uint8Array([
|
||||
(1 << 1) | ((value / 2 ** 48) & 0x1),
|
||||
(value / 2 ** 40) | 0,
|
||||
(value / 2 ** 32) | 0,
|
||||
value >> 24,
|
||||
value >> 16,
|
||||
value >> 8,
|
||||
value,
|
||||
]);
|
||||
case 8:
|
||||
return new Uint8Array([
|
||||
(1 << 0) | ((value / 2 ** 56) & 0x1),
|
||||
(value / 2 ** 48) | 0,
|
||||
(value / 2 ** 40) | 0,
|
||||
(value / 2 ** 32) | 0,
|
||||
value >> 24,
|
||||
value >> 16,
|
||||
value >> 8,
|
||||
value,
|
||||
]);
|
||||
default:
|
||||
throw new Error('Bad EBML VINT size ' + width);
|
||||
}
|
||||
};
|
||||
exports.getVariableInt = getVariableInt;
|
||||
const makeMatroskaBytes = (fields) => {
|
||||
if ('bytes' in fields) {
|
||||
return fields;
|
||||
}
|
||||
const value = makeFromStructure(fields);
|
||||
const header = (0, exports.matroskaToHex)((0, exports.getIdForName)(fields.type));
|
||||
const size = (0, exports.getVariableInt)(value.bytes.length, fields.minVintWidth);
|
||||
const bytes = (0, exports.combineUint8Arrays)([header, size, value.bytes]);
|
||||
return {
|
||||
bytes,
|
||||
offsets: {
|
||||
offset: value.offsets.offset,
|
||||
field: value.offsets.field,
|
||||
children: value.offsets.children.map((c) => {
|
||||
return (0, exports.incrementOffsetAndChildren)(c, header.byteLength + size.byteLength);
|
||||
}),
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.makeMatroskaBytes = makeMatroskaBytes;
|
||||
const padMatroskaBytes = (fields, totalLength) => {
|
||||
const regular = (0, exports.makeMatroskaBytes)(fields);
|
||||
const paddingLength = totalLength -
|
||||
regular.bytes.byteLength -
|
||||
(0, exports.matroskaToHex)(media_parser_1.MediaParserInternals.matroskaElements.Void).byteLength;
|
||||
if (paddingLength < 0) {
|
||||
throw new Error('ooops');
|
||||
}
|
||||
const padding = (0, exports.makeMatroskaBytes)({
|
||||
type: 'Void',
|
||||
value: new Uint8Array(paddingLength).fill(0),
|
||||
minVintWidth: null,
|
||||
});
|
||||
return [
|
||||
regular,
|
||||
{
|
||||
bytes: padding.bytes,
|
||||
offsets: (0, exports.incrementOffsetAndChildren)(padding.offsets, regular.bytes.length),
|
||||
},
|
||||
];
|
||||
};
|
||||
exports.padMatroskaBytes = padMatroskaBytes;
|
||||
function serializeUint16(value) {
|
||||
const buffer = new ArrayBuffer(2);
|
||||
const view = new DataView(buffer);
|
||||
view.setUint16(0, value);
|
||||
return new Uint8Array(buffer);
|
||||
}
|
||||
Reference in New Issue
Block a user