@remotion/media-parser
Version:
A pure JavaScript library for parsing video files
1,873 lines (1,851 loc) • 510 kB
JavaScript
// src/aac-codecprivate.ts
var getSampleRateFromSampleFrequencyIndex = (samplingFrequencyIndex) => {
switch (samplingFrequencyIndex) {
case 0:
return 96000;
case 1:
return 88200;
case 2:
return 64000;
case 3:
return 48000;
case 4:
return 44100;
case 5:
return 32000;
case 6:
return 24000;
case 7:
return 22050;
case 8:
return 16000;
case 9:
return 12000;
case 10:
return 11025;
case 11:
return 8000;
case 12:
return 7350;
default:
throw new Error(`Unexpected sampling frequency index ${samplingFrequencyIndex}`);
}
};
var getConfigForSampleRate = (sampleRate) => {
if (sampleRate === 96000) {
return 0;
}
if (sampleRate === 88200) {
return 1;
}
if (sampleRate === 64000) {
return 2;
}
if (sampleRate === 48000) {
return 3;
}
if (sampleRate === 44100) {
return 4;
}
if (sampleRate === 32000) {
return 5;
}
if (sampleRate === 24000) {
return 6;
}
if (sampleRate === 22050) {
return 7;
}
if (sampleRate === 16000) {
return 8;
}
if (sampleRate === 12000) {
return 9;
}
if (sampleRate === 11025) {
return 10;
}
if (sampleRate === 8000) {
return 11;
}
if (sampleRate === 7350) {
return 12;
}
throw new Error(`Unexpected sample rate ${sampleRate}`);
};
var createAacCodecPrivate = ({
audioObjectType,
sampleRate,
channelConfiguration,
codecPrivate
}) => {
if (codecPrivate !== null && codecPrivate.length > 2) {
return codecPrivate;
}
const bits = `${audioObjectType.toString(2).padStart(5, "0")}${getConfigForSampleRate(sampleRate).toString(2).padStart(4, "0")}${channelConfiguration.toString(2).padStart(4, "0")}000`;
if (bits.length !== 16) {
throw new Error("Invalid AAC codec private " + bits.length);
}
if (channelConfiguration === 0 || channelConfiguration > 7) {
throw new Error("Invalid channel configuration " + channelConfiguration);
}
const firstByte = parseInt(bits.slice(0, 8), 2);
const secondByte = parseInt(bits.slice(8, 16), 2);
return new Uint8Array([firstByte, secondByte]);
};
var parseAacCodecPrivate = (bytes) => {
if (bytes.length < 2) {
throw new Error("Invalid AAC codec private length");
}
const bits = [...bytes].map((b) => b.toString(2).padStart(8, "0")).join("");
let offset = 0;
const audioObjectType = parseInt(bits.slice(offset, offset + 5), 2);
offset += 5;
const samplingFrequencyIndex = parseInt(bits.slice(offset, offset + 4), 2);
offset += 4;
if (samplingFrequencyIndex === 15) {
offset += 24;
}
const channelConfiguration = parseInt(bits.slice(offset, offset + 4), 2);
offset += 4;
if (audioObjectType === 5) {
const extensionSamplingFrequencyIndex = parseInt(bits.slice(offset, offset + 4), 2);
offset += 4;
const newAudioObjectType = parseInt(bits.slice(offset, offset + 5), 2);
offset += 5;
return {
audioObjectType: newAudioObjectType,
sampleRate: getSampleRateFromSampleFrequencyIndex(extensionSamplingFrequencyIndex),
channelConfiguration
};
}
const sampleRate = getSampleRateFromSampleFrequencyIndex(samplingFrequencyIndex);
return {
audioObjectType,
sampleRate,
channelConfiguration
};
};
var mapAudioObjectTypeToCodecString = (audioObjectType) => {
switch (audioObjectType) {
case 1:
return "mp4a.40.2";
case 2:
return "mp4a.40.5";
case 3:
return "mp4a.40.29";
case 4:
return "mp4a.40.1";
case 5:
return "mp4a.40.3";
case 6:
return "mp4a.40.4";
case 17:
return "mp4a.40.17";
case 23:
return "mp4a.40.23";
default:
throw new Error(`Unexpected audio object type ${audioObjectType}`);
}
};
// src/containers/iso-base-media/ftyp.ts
var parseFtyp = ({
iterator,
size,
offset
}) => {
const majorBrand = iterator.getByteString(4, false);
const minorVersion = iterator.getFourByteNumber();
const types = (size - iterator.counter.getOffset()) / 4;
const compatibleBrands = [];
for (let i = 0;i < types; i++) {
compatibleBrands.push(iterator.getByteString(4, false).trim());
}
const offsetAtEnd = iterator.counter.getOffset();
return {
type: "ftyp-box",
majorBrand,
minorVersion,
compatibleBrands,
offset,
boxSize: offsetAtEnd - offset
};
};
// src/containers/webm/segments/all-segments.ts
var matroskaElements = {
Header: "0x1a45dfa3",
EBMLMaxIDLength: "0x42f2",
EBMLVersion: "0x4286",
EBMLReadVersion: "0x42f7",
EBMLMaxSizeLength: "0x42f3",
DocType: "0x4282",
DocTypeVersion: "0x4287",
DocTypeReadVersion: "0x4285",
Segment: "0x18538067",
SeekHead: "0x114d9b74",
Seek: "0x4dbb",
SeekID: "0x53ab",
SeekPosition: "0x53ac",
Info: "0x1549a966",
SegmentUUID: "0x73a4",
SegmentFilename: "0x7384",
PrevUUID: "0x3cb923",
PrevFilename: "0x3c83ab",
NextUUID: "0x3eb923",
NextFilename: "0x3e83bb",
SegmentFamily: "0x4444",
ChapterTranslate: "0x6924",
ChapterTranslateID: "0x69a5",
ChapterTranslateCodec: "0x69bf",
ChapterTranslateEditionUID: "0x69fc",
TimestampScale: "0x2ad7b1",
Duration: "0x4489",
DateUTC: "0x4461",
Title: "0x7ba9",
MuxingApp: "0x4d80",
WritingApp: "0x5741",
Cluster: "0x1f43b675",
Timestamp: "0xe7",
SilentTracks: "0x5854",
SilentTrackNumber: "0x58d7",
Position: "0xa7",
PrevSize: "0xab",
SimpleBlock: "0xa3",
BlockGroup: "0xa0",
Block: "0xa1",
BlockVirtual: "0xa2",
BlockAdditions: "0x75a1",
BlockMore: "0xa6",
BlockAdditional: "0xa5",
BlockAddID: "0xee",
BlockDuration: "0x9b",
ReferencePriority: "0xfa",
ReferenceBlock: "0xfb",
ReferenceVirtual: "0xfd",
CodecState: "0xa4",
DiscardPadding: "0x75a2",
Slices: "0x8e",
TimeSlice: "0xe8",
LaceNumber: "0xcc",
FrameNumber: "0xcd",
BlockAdditionID: "0xcb",
Delay: "0xce",
SliceDuration: "0xcf",
ReferenceFrame: "0xc8",
ReferenceOffset: "0xc9",
ReferenceTimestamp: "0xca",
EncryptedBlock: "0xaf",
Tracks: "0x1654ae6b",
TrackEntry: "0xae",
TrackNumber: "0xd7",
TrackUID: "0x73c5",
TrackType: "0x83",
FlagEnabled: "0xb9",
FlagDefault: "0x88",
FlagForced: "0x55aa",
FlagHearingImpaired: "0x55ab",
FlagVisualImpaired: "0x55ac",
FlagTextDescriptions: "0x55ad",
FlagOriginal: "0x55ae",
FlagCommentary: "0x55af",
FlagLacing: "0x9c",
MinCache: "0x6de7",
MaxCache: "0x6df8",
DefaultDuration: "0x23e383",
DefaultDecodedFieldDuration: "0x234e7a",
TrackTimestampScale: "0x23314f",
TrackOffset: "0x537f",
MaxBlockAdditionID: "0x55ee",
BlockAdditionMapping: "0x41e4",
BlockAddIDValue: "0x41f0",
BlockAddIDName: "0x41a4",
BlockAddIDType: "0x41e7",
BlockAddIDExtraData: "0x41ed",
Name: "0x536e",
Language: "0x22b59c",
LanguageBCP47: "0x22b59d",
CodecID: "0x86",
CodecPrivate: "0x63a2",
CodecName: "0x258688",
AttachmentLink: "0x7446",
CodecSettings: "0x3a9697",
CodecInfoURL: "0x3b4040",
CodecDownloadURL: "0x26b240",
CodecDecodeAll: "0xaa",
TrackOverlay: "0x6fab",
CodecDelay: "0x56aa",
SeekPreRoll: "0x56bb",
TrackTranslate: "0x6624",
TrackTranslateTrackID: "0x66a5",
TrackTranslateCodec: "0x66bf",
TrackTranslateEditionUID: "0x66fc",
Video: "0xe0",
FlagInterlaced: "0x9a",
FieldOrder: "0x9d",
StereoMode: "0x53b8",
AlphaMode: "0x53c0",
OldStereoMode: "0x53b9",
PixelWidth: "0xb0",
PixelHeight: "0xba",
PixelCropBottom: "0x54aa",
PixelCropTop: "0x54bb",
PixelCropLeft: "0x54cc",
PixelCropRight: "0x54dd",
DisplayWidth: "0x54b0",
DisplayHeight: "0x54ba",
DisplayUnit: "0x54b2",
AspectRatioType: "0x54b3",
UncompressedFourCC: "0x2eb524",
GammaValue: "0x2fb523",
FrameRate: "0x2383e3",
Colour: "0x55b0",
MatrixCoefficients: "0x55b1",
BitsPerChannel: "0x55b2",
ChromaSubsamplingHorz: "0x55b3",
ChromaSubsamplingVert: "0x55b4",
CbSubsamplingHorz: "0x55b5",
CbSubsamplingVert: "0x55b6",
ChromaSitingHorz: "0x55b7",
ChromaSitingVert: "0x55b8",
Range: "0x55b9",
TransferCharacteristics: "0x55ba",
Primaries: "0x55bb",
MaxCLL: "0x55bc",
MaxFALL: "0x55bd",
MasteringMetadata: "0x55d0",
PrimaryRChromaticityX: "0x55d1",
PrimaryRChromaticityY: "0x55d2",
PrimaryGChromaticityX: "0x55d3",
PrimaryGChromaticityY: "0x55d4",
PrimaryBChromaticityX: "0x55d5",
PrimaryBChromaticityY: "0x55d6",
WhitePointChromaticityX: "0x55d7",
WhitePointChromaticityY: "0x55d8",
LuminanceMax: "0x55d9",
LuminanceMin: "0x55da",
Projection: "0x7670",
ProjectionType: "0x7671",
ProjectionPrivate: "0x7672",
ProjectionPoseYaw: "0x7673",
ProjectionPosePitch: "0x7674",
ProjectionPoseRoll: "0x7675",
Audio: "0xe1",
SamplingFrequency: "0xb5",
OutputSamplingFrequency: "0x78b5",
Channels: "0x9f",
ChannelPositions: "0x7d7b",
BitDepth: "0x6264",
Emphasis: "0x52f1",
TrackOperation: "0xe2",
TrackCombinePlanes: "0xe3",
TrackPlane: "0xe4",
TrackPlaneUID: "0xe5",
TrackPlaneType: "0xe6",
TrackJoinBlocks: "0xe9",
TrackJoinUID: "0xed",
TrickTrackUID: "0xc0",
TrickTrackSegmentUID: "0xc1",
TrickTrackFlag: "0xc6",
TrickMasterTrackUID: "0xc7",
TrickMasterTrackSegmentUID: "0xc4",
ContentEncodings: "0x6d80",
ContentEncoding: "0x6240",
ContentEncodingOrder: "0x5031",
ContentEncodingScope: "0x5032",
ContentEncodingType: "0x5033",
ContentCompression: "0x5034",
ContentCompAlgo: "0x4254",
ContentCompSettings: "0x4255",
ContentEncryption: "0x5035",
ContentEncAlgo: "0x47e1",
ContentEncKeyID: "0x47e2",
ContentEncAESSettings: "0x47e7",
AESSettingsCipherMode: "0x47e8",
ContentSignature: "0x47e3",
ContentSigKeyID: "0x47e4",
ContentSigAlgo: "0x47e5",
ContentSigHashAlgo: "0x47e6",
Cues: "0x1c53bb6b",
CuePoint: "0xbb",
CueTime: "0xb3",
CueTrackPositions: "0xb7",
CueTrack: "0xf7",
CueClusterPosition: "0xf1",
CueRelativePosition: "0xf0",
CueDuration: "0xb2",
CueBlockNumber: "0x5378",
CueCodecState: "0xea",
CueReference: "0xdb",
CueRefTime: "0x96",
CueRefCluster: "0x97",
CueRefNumber: "0x535f",
CueRefCodecState: "0xeb",
Attachments: "0x1941a469",
AttachedFile: "0x61a7",
FileDescription: "0x467e",
FileName: "0x466e",
FileMediaType: "0x4660",
FileData: "0x465c",
FileUID: "0x46ae",
FileReferral: "0x4675",
FileUsedStartTime: "0x4661",
FileUsedEndTime: "0x4662",
Chapters: "0x1043a770",
EditionEntry: "0x45b9",
EditionUID: "0x45bc",
EditionFlagHidden: "0x45bd",
EditionFlagDefault: "0x45db",
EditionFlagOrdered: "0x45dd",
EditionDisplay: "0x4520",
EditionString: "0x4521",
EditionLanguageIETF: "0x45e4",
ChapterAtom: "0xb6",
ChapterUID: "0x73c4",
ChapterStringUID: "0x5654",
ChapterTimeStart: "0x91",
ChapterTimeEnd: "0x92",
ChapterFlagHidden: "0x98",
ChapterFlagEnabled: "0x4598",
ChapterSegmentUUID: "0x6e67",
ChapterSkipType: "0x4588",
ChapterSegmentEditionUID: "0x6ebc",
ChapterPhysicalEquiv: "0x63c3",
ChapterTrack: "0x8f",
ChapterTrackUID: "0x89",
ChapterDisplay: "0x80",
ChapString: "0x85",
ChapLanguage: "0x437c",
ChapLanguageBCP47: "0x437d",
ChapCountry: "0x437e",
ChapProcess: "0x6944",
ChapProcessCodecID: "0x6955",
ChapProcessPrivate: "0x450d",
ChapProcessCommand: "0x6911",
ChapProcessTime: "0x6922",
ChapProcessData: "0x6933",
Tags: "0x1254c367",
Tag: "0x7373",
Targets: "0x63c0",
TargetTypeValue: "0x68ca",
TargetType: "0x63ca",
TagTrackUID: "0x63c5",
TagEditionUID: "0x63c9",
TagChapterUID: "0x63c4",
TagAttachmentUID: "0x63c6",
SimpleTag: "0x67c8",
TagName: "0x45a3",
TagLanguage: "0x447a",
TagLanguageBCP47: "0x447b",
TagDefault: "0x4484",
TagDefaultBogus: "0x44b4",
TagString: "0x4487",
TagBinary: "0x4485",
Void: "0xec",
Crc32: "0xbf"
};
var matroskaIds = Object.values(matroskaElements);
var knownIdsWithOneLength = matroskaIds.filter((id) => id.length === 4);
var knownIdsWithTwoLength = matroskaIds.filter((id) => id.length === 6);
var knownIdsWithThreeLength = matroskaIds.filter((id) => id.length === 8);
var ebmlVersion = {
name: "EBMLVersion",
type: "uint"
};
var ebmlReadVersion = {
name: "EBMLReadVersion",
type: "uint"
};
var ebmlMaxIdLength = {
name: "EBMLMaxIDLength",
type: "uint"
};
var ebmlMaxSizeLength = {
name: "EBMLMaxSizeLength",
type: "uint"
};
var docType = {
name: "DocType",
type: "string"
};
var docTypeVersion = {
name: "DocTypeVersion",
type: "uint"
};
var docTypeReadVersion = {
name: "DocTypeReadVersion",
type: "uint"
};
var voidEbml = {
name: "Void",
type: "uint8array"
};
var matroskaHeader = {
name: "Header",
type: "children"
};
var seekId = {
name: "SeekID",
type: "hex-string"
};
var _name = {
name: "Name",
type: "string"
};
var minCache = {
name: "MinCache",
type: "uint"
};
var maxCache = {
name: "MaxCache",
type: "uint"
};
var seekPosition = {
name: "SeekPosition",
type: "uint"
};
var seek = {
name: "Seek",
type: "children"
};
var seekHead = {
name: "SeekHead",
type: "children"
};
var trackType = {
name: "TrackType",
type: "uint"
};
var widthType = {
name: "PixelWidth",
type: "uint"
};
var heightType = {
name: "PixelHeight",
type: "uint"
};
var muxingApp = {
name: "MuxingApp",
type: "string"
};
var duration = {
name: "Duration",
type: "float"
};
var timestampScale = {
name: "TimestampScale",
type: "uint"
};
var infoType = {
name: "Info",
type: "children"
};
var titleType = {
name: "Title",
type: "string"
};
var tagTrackUidType = {
name: "TagTrackUID",
type: "hex-string"
};
var samplingFrequency = {
name: "SamplingFrequency",
type: "float"
};
var channels = {
name: "Channels",
type: "uint"
};
var alphaMode = {
name: "AlphaMode",
type: "uint"
};
var interlaced = {
name: "FlagInterlaced",
type: "uint"
};
var bitDepth = {
name: "BitDepth",
type: "uint"
};
var displayWidth = {
name: "DisplayWidth",
type: "uint"
};
var displayHeight = {
name: "DisplayHeight",
type: "uint"
};
var displayUnit = {
name: "DisplayUnit",
type: "uint"
};
var flagLacing = {
name: "FlagLacing",
type: "uint"
};
var tagSegment = {
name: "Tag",
type: "children"
};
var tags = {
name: "Tags",
type: "children"
};
var trackNumber = {
name: "TrackNumber",
type: "uint"
};
var trackUID = {
name: "TrackUID",
type: "hex-string"
};
var color = {
name: "Colour",
type: "children"
};
var transferCharacteristics = {
name: "TransferCharacteristics",
type: "uint"
};
var matrixCoefficients = {
name: "MatrixCoefficients",
type: "uint"
};
var primaries = {
name: "Primaries",
type: "uint"
};
var range = {
name: "Range",
type: "uint"
};
var ChromaSitingHorz = {
name: "ChromaSitingHorz",
type: "uint"
};
var ChromaSitingVert = {
name: "ChromaSitingVert",
type: "uint"
};
var language = {
name: "Language",
type: "string"
};
var defaultDuration = {
name: "DefaultDuration",
type: "uint"
};
var codecPrivate = {
name: "CodecPrivate",
type: "uint8array"
};
var blockAdditionsSegment = {
name: "BlockAdditions",
type: "uint8array"
};
var maxBlockAdditionIdSegment = {
name: "MaxBlockAdditionID",
type: "uint"
};
var audioSegment = {
name: "Audio",
type: "children"
};
var videoSegment = {
name: "Video",
type: "children"
};
var flagDefault = {
name: "FlagDefault",
type: "uint"
};
var referenceBlock = {
name: "ReferenceBlock",
type: "uint"
};
var blockDurationSegment = {
name: "BlockDuration",
type: "uint"
};
var codecName = {
name: "CodecName",
type: "string"
};
var trackTimestampScale = {
name: "TrackTimestampScale",
type: "float"
};
var trackEntry = {
name: "TrackEntry",
type: "children"
};
var tracks = {
name: "Tracks",
type: "children"
};
var block = {
name: "Block",
type: "uint8array"
};
var simpleBlock = {
name: "SimpleBlock",
type: "uint8array"
};
var blockGroup = {
name: "BlockGroup",
type: "children"
};
var targetsType = {
name: "Targets",
type: "children"
};
var simpleTagType = {
name: "SimpleTag",
type: "children"
};
var tagNameType = {
name: "TagName",
type: "string"
};
var tagStringType = {
name: "TagString",
type: "string"
};
var ebmlMap = {
[matroskaElements.Header]: matroskaHeader,
[matroskaElements.DocType]: docType,
[matroskaElements.Targets]: targetsType,
[matroskaElements.SimpleTag]: simpleTagType,
[matroskaElements.TagName]: tagNameType,
[matroskaElements.TagString]: tagStringType,
[matroskaElements.DocTypeVersion]: docTypeVersion,
[matroskaElements.DocTypeReadVersion]: docTypeReadVersion,
[matroskaElements.EBMLVersion]: ebmlVersion,
[matroskaElements.EBMLReadVersion]: ebmlReadVersion,
[matroskaElements.EBMLMaxIDLength]: ebmlMaxIdLength,
[matroskaElements.EBMLMaxSizeLength]: ebmlMaxSizeLength,
[matroskaElements.Void]: voidEbml,
[matroskaElements.Cues]: {
name: "Cues",
type: "children"
},
[matroskaElements.CuePoint]: {
name: "CuePoint",
type: "children"
},
[matroskaElements.CueTime]: {
name: "CueTime",
type: "uint"
},
[matroskaElements.CueTrackPositions]: {
name: "CueTrackPositions",
type: "children"
},
[matroskaElements.CueClusterPosition]: {
name: "CueClusterPosition",
type: "uint"
},
[matroskaElements.CueRelativePosition]: {
name: "CueRelativePosition",
type: "uint"
},
[matroskaElements.CueBlockNumber]: {
name: "CueBlockNumber",
type: "uint"
},
[matroskaElements.CueTrack]: {
name: "CueTrack",
type: "uint"
},
[matroskaElements.DateUTC]: {
name: "DateUTC",
type: "uint8array"
},
[matroskaElements.TrackTimestampScale]: trackTimestampScale,
[matroskaElements.CodecDelay]: {
name: "CodecDelay",
type: "uint8array"
},
[matroskaElements.SeekPreRoll]: {
name: "SeekPreRoll",
type: "uint8array"
},
[matroskaElements.DiscardPadding]: {
name: "DiscardPadding",
type: "uint8array"
},
[matroskaElements.OutputSamplingFrequency]: {
name: "OutputSamplingFrequency",
type: "uint8array"
},
[matroskaElements.CodecName]: codecName,
[matroskaElements.Position]: {
name: "Position",
type: "uint8array"
},
[matroskaElements.SliceDuration]: {
name: "SliceDuration",
type: "uint8array"
},
[matroskaElements.TagTrackUID]: tagTrackUidType,
[matroskaElements.SeekHead]: seekHead,
[matroskaElements.Seek]: seek,
[matroskaElements.SeekID]: seekId,
[matroskaElements.Name]: _name,
[matroskaElements.MinCache]: minCache,
[matroskaElements.MaxCache]: maxCache,
[matroskaElements.SeekPosition]: seekPosition,
[matroskaElements.Crc32]: {
name: "Crc32",
type: "uint8array"
},
[matroskaElements.MuxingApp]: muxingApp,
[matroskaElements.WritingApp]: {
name: "WritingApp",
type: "string"
},
[matroskaElements.SegmentUUID]: {
name: "SegmentUUID",
type: "string"
},
[matroskaElements.Duration]: duration,
[matroskaElements.CodecID]: {
name: "CodecID",
type: "string"
},
[matroskaElements.TrackType]: trackType,
[matroskaElements.PixelWidth]: widthType,
[matroskaElements.PixelHeight]: heightType,
[matroskaElements.TimestampScale]: timestampScale,
[matroskaElements.Info]: infoType,
[matroskaElements.Title]: titleType,
[matroskaElements.SamplingFrequency]: samplingFrequency,
[matroskaElements.Channels]: channels,
[matroskaElements.AlphaMode]: alphaMode,
[matroskaElements.FlagInterlaced]: interlaced,
[matroskaElements.BitDepth]: bitDepth,
[matroskaElements.DisplayHeight]: displayHeight,
[matroskaElements.DisplayWidth]: displayWidth,
[matroskaElements.DisplayUnit]: displayUnit,
[matroskaElements.FlagLacing]: flagLacing,
[matroskaElements.Tags]: tags,
[matroskaElements.Tag]: tagSegment,
[matroskaElements.TrackNumber]: trackNumber,
[matroskaElements.TrackUID]: trackUID,
[matroskaElements.Colour]: color,
[matroskaElements.Language]: language,
[matroskaElements.DefaultDuration]: defaultDuration,
[matroskaElements.CodecPrivate]: codecPrivate,
[matroskaElements.BlockDuration]: blockDurationSegment,
[matroskaElements.BlockAdditions]: blockAdditionsSegment,
[matroskaElements.MaxBlockAdditionID]: maxBlockAdditionIdSegment,
[matroskaElements.Audio]: audioSegment,
[matroskaElements.Video]: videoSegment,
[matroskaElements.FlagDefault]: flagDefault,
[matroskaElements.ReferenceBlock]: referenceBlock,
[matroskaElements.TrackEntry]: trackEntry,
[matroskaElements.Timestamp]: {
name: "Timestamp",
type: "uint"
},
[matroskaElements.Tracks]: tracks,
[matroskaElements.Block]: block,
[matroskaElements.SimpleBlock]: simpleBlock,
[matroskaElements.BlockGroup]: blockGroup,
[matroskaElements.Segment]: {
name: "Segment",
type: "children"
},
[matroskaElements.Cluster]: {
name: "Cluster",
type: "children"
},
[matroskaElements.TransferCharacteristics]: transferCharacteristics,
[matroskaElements.MatrixCoefficients]: matrixCoefficients,
[matroskaElements.Primaries]: primaries,
[matroskaElements.Range]: range,
[matroskaElements.ChromaSitingHorz]: ChromaSitingHorz,
[matroskaElements.ChromaSitingVert]: ChromaSitingVert
};
// src/file-types/detect-file-type.ts
var webmPattern = new Uint8Array([26, 69, 223, 163]);
var matchesPattern = (pattern) => {
return (data) => {
return pattern.every((value, index) => data[index] === value);
};
};
var isRiffAvi = (data) => {
const riffPattern = new Uint8Array([82, 73, 70, 70]);
if (!matchesPattern(riffPattern)(data.subarray(0, 4))) {
return false;
}
const fileType = data.subarray(8, 12);
const aviPattern = new Uint8Array([65, 86, 73, 32]);
return matchesPattern(aviPattern)(fileType);
};
var isRiffWave = (data) => {
const riffPattern = new Uint8Array([82, 73, 70, 70]);
if (!matchesPattern(riffPattern)(data.subarray(0, 4))) {
return false;
}
const fileType = data.subarray(8, 12);
const wavePattern = new Uint8Array([87, 65, 86, 69]);
return matchesPattern(wavePattern)(fileType);
};
var isWebm = (data) => {
return matchesPattern(webmPattern)(data.subarray(0, 4));
};
var isIsoBaseMedia = (data) => {
const isoBaseMediaMp4Pattern = new TextEncoder().encode("ftyp");
return matchesPattern(isoBaseMediaMp4Pattern)(data.subarray(4, 8));
};
var isTransportStream = (data) => {
return data[0] === 71 && data[188] === 71;
};
var isMp3 = (data) => {
const mpegPattern = new Uint8Array([255, 243]);
const mpegPattern2 = new Uint8Array([255, 251]);
const id3v4Pattern = new Uint8Array([73, 68, 51, 4]);
const id3v3Pattern = new Uint8Array([73, 68, 51, 3]);
const id3v2Pattern = new Uint8Array([73, 68, 51, 2]);
const subarray = data.subarray(0, 4);
return matchesPattern(mpegPattern)(subarray) || matchesPattern(mpegPattern2)(subarray) || matchesPattern(id3v4Pattern)(subarray) || matchesPattern(id3v3Pattern)(subarray) || matchesPattern(id3v2Pattern)(subarray);
};
var isAac = (data) => {
const aacPattern = new Uint8Array([255, 241]);
return matchesPattern(aacPattern)(data.subarray(0, 2));
};
var isFlac = (data) => {
const flacPattern = new Uint8Array([102, 76, 97, 67]);
return matchesPattern(flacPattern)(data.subarray(0, 4));
};
var isM3u = (data) => {
return new TextDecoder("utf-8").decode(data.slice(0, 7)) === "#EXTM3U";
};
// src/file-types/bmp.ts
function getBmpDimensions(bmpData) {
if (bmpData.length < 26) {
return null;
}
const view = new DataView(bmpData.buffer, bmpData.byteOffset);
return {
width: view.getUint32(18, true),
height: Math.abs(view.getInt32(22, true))
};
}
var isBmp = (data) => {
const bmpPattern = new Uint8Array([66, 77]);
if (matchesPattern(bmpPattern)(data.subarray(0, 2))) {
const bmp = getBmpDimensions(data);
return { dimensions: bmp, type: "bmp" };
}
return null;
};
// src/file-types/gif.ts
var getGifDimensions = (data) => {
const view = new DataView(data.buffer, data.byteOffset);
const width = view.getUint16(6, true);
const height = view.getUint16(8, true);
return { width, height };
};
var isGif = (data) => {
const gifPattern = new Uint8Array([71, 73, 70, 56]);
if (matchesPattern(gifPattern)(data.subarray(0, 4))) {
return { type: "gif", dimensions: getGifDimensions(data) };
}
return null;
};
// src/file-types/jpeg.ts
function getJpegDimensions(data) {
let offset = 0;
function readUint16BE(o) {
return data[o] << 8 | data[o + 1];
}
if (readUint16BE(offset) !== 65496) {
return null;
}
offset += 2;
while (offset < data.length) {
if (data[offset] === 255) {
const marker = data[offset + 1];
if (marker === 192 || marker === 194) {
const height = readUint16BE(offset + 5);
const width = readUint16BE(offset + 7);
return { width, height };
}
const length = readUint16BE(offset + 2);
offset += length + 2;
} else {
offset++;
}
}
return null;
}
var isJpeg = (data) => {
const jpegPattern = new Uint8Array([255, 216]);
const jpeg = matchesPattern(jpegPattern)(data.subarray(0, 2));
if (!jpeg) {
return null;
}
const dim = getJpegDimensions(data);
return { dimensions: dim, type: "jpeg" };
};
// src/file-types/pdf.ts
var isPdf = (data) => {
if (data.length < 4) {
return null;
}
const pdfPattern = new Uint8Array([37, 80, 68, 70]);
return matchesPattern(pdfPattern)(data.subarray(0, 4)) ? { type: "pdf" } : null;
};
// src/file-types/png.ts
function getPngDimensions(pngData) {
if (pngData.length < 24) {
return null;
}
const view = new DataView(pngData.buffer, pngData.byteOffset);
const pngSignature = [137, 80, 78, 71, 13, 10, 26, 10];
for (let i = 0;i < 8; i++) {
if (pngData[i] !== pngSignature[i]) {
return null;
}
}
return {
width: view.getUint32(16, false),
height: view.getUint32(20, false)
};
}
var isPng = (data) => {
const pngPattern = new Uint8Array([137, 80, 78, 71]);
if (matchesPattern(pngPattern)(data.subarray(0, 4))) {
const png = getPngDimensions(data);
return { dimensions: png, type: "png" };
}
return null;
};
// src/file-types/webp.ts
function getWebPDimensions(bytes) {
if (bytes.length < 30) {
return null;
}
if (bytes[0] !== 82 || bytes[1] !== 73 || bytes[2] !== 70 || bytes[3] !== 70 || bytes[8] !== 87 || bytes[9] !== 69 || bytes[10] !== 66 || bytes[11] !== 80) {
return null;
}
if (bytes[12] === 86 && bytes[13] === 80 && bytes[14] === 56) {
if (bytes[15] === 32) {
return {
width: bytes[26] | bytes[27] << 8 & 16383,
height: bytes[28] | bytes[29] << 8 & 16383
};
}
}
if (bytes[12] === 86 && bytes[13] === 80 && bytes[14] === 56 && bytes[15] === 76) {
return {
width: 1 + (bytes[21] | (bytes[22] & 63) << 8),
height: 1 + ((bytes[22] & 192) >> 6 | bytes[23] << 2 | (bytes[24] & 15) << 10)
};
}
if (bytes[12] === 86 && bytes[13] === 80 && bytes[14] === 56 && bytes[15] === 88) {
return {
width: 1 + (bytes[24] | bytes[25] << 8 | bytes[26] << 16),
height: 1 + (bytes[27] | bytes[28] << 8 | bytes[29] << 16)
};
}
return null;
}
var isWebp = (data) => {
const webpPattern = new Uint8Array([82, 73, 70, 70]);
if (matchesPattern(webpPattern)(data.subarray(0, 4))) {
return {
type: "webp",
dimensions: getWebPDimensions(data)
};
}
return null;
};
// src/file-types/index.ts
var detectFileType = (data) => {
if (isRiffWave(data)) {
return { type: "wav" };
}
if (isRiffAvi(data)) {
return { type: "riff" };
}
if (isAac(data)) {
return { type: "aac" };
}
if (isFlac(data)) {
return { type: "flac" };
}
if (isM3u(data)) {
return { type: "m3u" };
}
const webp = isWebp(data);
if (webp) {
return webp;
}
if (isWebm(data)) {
return { type: "webm" };
}
if (isIsoBaseMedia(data)) {
return { type: "iso-base-media" };
}
if (isTransportStream(data)) {
return { type: "transport-stream" };
}
if (isMp3(data)) {
return { type: "mp3" };
}
const gif = isGif(data);
if (gif) {
return gif;
}
const png = isPng(data);
if (png) {
return png;
}
const pdf = isPdf(data);
if (pdf) {
return pdf;
}
const bmp = isBmp(data);
if (bmp) {
return bmp;
}
const jpeg = isJpeg(data);
if (jpeg) {
return jpeg;
}
return { type: "unknown" };
};
// src/log.ts
var logLevels = ["trace", "verbose", "info", "warn", "error"];
var getNumberForLogLevel = (level) => {
return logLevels.indexOf(level);
};
var isEqualOrBelowLogLevel = (currentLevel, level) => {
return getNumberForLogLevel(currentLevel) <= getNumberForLogLevel(level);
};
var Log = {
trace: (logLevel, ...args) => {
if (isEqualOrBelowLogLevel(logLevel, "trace")) {
return console.log(...args);
}
},
verbose: (logLevel, ...args) => {
if (isEqualOrBelowLogLevel(logLevel, "verbose")) {
return console.log(...args);
}
},
info: (logLevel, ...args) => {
if (isEqualOrBelowLogLevel(logLevel, "info")) {
return console.log(...args);
}
},
warn: (logLevel, ...args) => {
if (isEqualOrBelowLogLevel(logLevel, "warn")) {
return console.warn(...args);
}
},
error: (...args) => {
return console.error(...args);
}
};
// src/iterator/buffer-manager.ts
var makeBufferWithMaxBytes = (initialData, maxBytes) => {
const maxByteLength = Math.min(maxBytes, 2 ** 31);
try {
const buf = new ArrayBuffer(initialData.byteLength, {
maxByteLength
});
return buf;
} catch (e) {
if (e instanceof RangeError && maxBytes > 2 ** 27) {
return new ArrayBuffer(initialData.byteLength, {
maxByteLength: 2 ** 27
});
}
throw e;
}
};
var bufferManager = ({
initialData,
maxBytes,
counter
}) => {
const buf = makeBufferWithMaxBytes(initialData, maxBytes);
if (!buf.resize) {
throw new Error("`ArrayBuffer.resize` is not supported in this Runtime. On the server: Use at least Node.js 20 or Bun. In the browser: Chrome 111, Edge 111, Safari 16.4, Firefox 128, Opera 111");
}
let uintArray = new Uint8Array(buf);
uintArray.set(initialData);
let view = new DataView(uintArray.buffer);
const destroy = () => {
uintArray = new Uint8Array(0);
buf.resize(0);
};
const flushBytesRead = (force, mode) => {
const bytesToRemove = counter.getDiscardedOffset();
if (bytesToRemove < 3000000 && !force) {
return { bytesRemoved: 0, removedData: null };
}
if (view.byteLength < bytesToRemove && !force) {
return { bytesRemoved: 0, removedData: null };
}
counter.discardBytes(bytesToRemove);
const removedData = mode === "download" ? uintArray.slice(0, bytesToRemove) : null;
const newData = uintArray.slice(bytesToRemove);
uintArray.set(newData);
buf.resize(newData.byteLength);
view = new DataView(uintArray.buffer);
return { bytesRemoved: bytesToRemove, removedData };
};
const skipTo = (offset) => {
const becomesSmaller = offset < counter.getOffset();
if (becomesSmaller) {
const toDecrement = counter.getOffset() - offset;
if (toDecrement > counter.getDiscardedOffset()) {
throw new Error("Cannot count backwards, data has already been flushed");
}
counter.decrement(toDecrement);
}
const currentOffset = counter.getOffset();
counter.increment(offset - currentOffset);
};
const addData = (newData) => {
const oldLength = buf.byteLength;
const newLength = oldLength + newData.byteLength;
if (newLength < oldLength) {
throw new Error("Cannot decrement size");
}
if (newLength > (maxBytes ?? Infinity)) {
throw new Error(`Exceeded maximum byte length ${maxBytes} with ${newLength}`);
}
buf.resize(newLength);
uintArray = new Uint8Array(buf);
uintArray.set(newData, oldLength);
view = new DataView(uintArray.buffer);
};
const replaceData = (newData, seekTo) => {
buf.resize(newData.byteLength);
uintArray = new Uint8Array(buf);
uintArray.set(newData);
view = new DataView(uintArray.buffer);
counter.setDiscardedOffset(seekTo);
counter.decrement(counter.getOffset());
counter.increment(seekTo);
};
return {
view,
uintArray,
destroy,
addData,
skipTo,
removeBytesRead: flushBytesRead,
replaceData
};
};
// src/iterator/offset-counter.ts
var makeOffsetCounter = (initial) => {
let offset = initial;
let discardedBytes = 0;
return {
getOffset: () => offset,
discardBytes: (bytes) => {
discardedBytes += bytes;
},
increment: (bytes) => {
if (bytes < 0) {
throw new Error("Cannot increment by a negative amount: " + bytes);
}
offset += bytes;
},
getDiscardedBytes: () => discardedBytes,
setDiscardedOffset: (bytes) => {
discardedBytes = bytes;
},
getDiscardedOffset: () => offset - discardedBytes,
decrement: (bytes) => {
if (bytes < 0) {
throw new Error("Cannot decrement by a negative amount: " + bytes);
}
offset -= bytes;
}
};
};
// src/iterator/buffer-iterator.ts
var getArrayBufferIterator = (initialData, maxBytes) => {
const counter = makeOffsetCounter(0);
const {
uintArray,
view,
addData,
destroy,
removeBytesRead,
skipTo,
replaceData
} = bufferManager({ initialData, maxBytes, counter });
const startCheckpoint = () => {
const checkpoint = counter.getOffset();
return {
returnToCheckpoint: () => {
counter.decrement(counter.getOffset() - checkpoint);
}
};
};
const getSlice = (amount) => {
const value = uintArray.slice(counter.getDiscardedOffset(), counter.getDiscardedOffset() + amount);
counter.increment(value.length);
return value;
};
const discard = (length) => {
counter.increment(length);
};
const readUntilNullTerminator = () => {
const bytes = [];
let byte;
while ((byte = getUint8()) !== 0) {
bytes.push(byte);
}
counter.decrement(1);
return new TextDecoder().decode(new Uint8Array(bytes));
};
const readUntilLineEnd = () => {
const bytes = [];
while (true) {
if (bytesRemaining() === 0) {
return null;
}
const byte = getUint8();
bytes.push(byte);
if (byte === 10) {
break;
}
}
const str = new TextDecoder().decode(new Uint8Array(bytes)).trim();
return str;
};
const getUint8 = () => {
const val = view.getUint8(counter.getDiscardedOffset());
counter.increment(1);
return val;
};
const getEightByteNumber = (littleEndian = false) => {
if (littleEndian) {
const one = getUint8();
const two = getUint8();
const three = getUint8();
const four = getUint8();
const five = getUint8();
const six = getUint8();
const seven = getUint8();
const eight = getUint8();
return (eight << 56 | seven << 48 | six << 40 | five << 32 | four << 24 | three << 16 | two << 8 | one) >>> 0;
}
function byteArrayToBigInt(byteArray) {
let result = BigInt(0);
for (let i = 0;i < byteArray.length; i++) {
result = (result << BigInt(8)) + BigInt(byteArray[i]);
}
return result;
}
const bigInt = byteArrayToBigInt([
getUint8(),
getUint8(),
getUint8(),
getUint8(),
getUint8(),
getUint8(),
getUint8(),
getUint8()
]);
return Number(bigInt);
};
const getFourByteNumber = () => {
const unsigned = getUint8() << 24 | getUint8() << 16 | getUint8() << 8 | getUint8();
return unsigned >>> 0;
};
const getPaddedFourByteNumber = () => {
let lastInt = 128;
while (lastInt = getUint8(), lastInt === 128) {}
return lastInt;
};
const getUint32 = () => {
const val = view.getUint32(counter.getDiscardedOffset());
counter.increment(4);
return val;
};
const getSyncSafeInt32 = () => {
const val = view.getUint32(counter.getDiscardedOffset());
counter.increment(4);
return (val & 2130706432) >> 3 | (val & 8323072) >> 2 | (val & 32512) >> 1 | val & 127;
};
const getUint64 = (littleEndian = false) => {
const val = view.getBigUint64(counter.getDiscardedOffset(), littleEndian);
counter.increment(8);
return val;
};
const getInt64 = (littleEndian = false) => {
const val = view.getBigInt64(counter.getDiscardedOffset(), littleEndian);
counter.increment(8);
return val;
};
const startBox = (size) => {
const startOffset = counter.getOffset();
return {
discardRest: () => discard(size - (counter.getOffset() - startOffset)),
expectNoMoreBytes: () => {
const remaining = size - (counter.getOffset() - startOffset);
if (remaining !== 0) {
throw new Error("expected 0 bytes, got " + remaining);
}
}
};
};
const getUint32Le = () => {
const val = view.getUint32(counter.getDiscardedOffset(), true);
counter.increment(4);
return val;
};
const getInt32Le = () => {
const val = view.getInt32(counter.getDiscardedOffset(), true);
counter.increment(4);
return val;
};
const getInt32 = () => {
const val = view.getInt32(counter.getDiscardedOffset());
counter.increment(4);
return val;
};
const bytesRemaining = () => {
return uintArray.byteLength - counter.getDiscardedOffset();
};
const readExpGolomb = () => {
if (!bitReadingMode) {
throw new Error("Not in bit reading mode");
}
let zerosCount = 0;
while (getBits(1) === 0) {
zerosCount++;
}
let suffix = 0;
for (let i = 0;i < zerosCount; i++) {
suffix = suffix << 1 | getBits(1);
}
return (1 << zerosCount) - 1 + suffix;
};
const peekB = (length) => {
Log.info("info", [...getSlice(length)].map((b) => b.toString(16).padStart(2, "0")));
counter.decrement(length);
};
const peekD = (length) => {
Log.info("info", [...getSlice(length)].map((b) => b.toString(16).padStart(2, "0")));
counter.decrement(length);
};
const leb128 = () => {
let result = 0;
let shift = 0;
let byte;
do {
byte = getBits(8);
result |= (byte & 127) << shift;
shift += 7;
} while (byte >= 128);
return result;
};
let bitIndex = 0;
const stopReadingBits = () => {
bitIndex = 0;
bitReadingMode = false;
};
let byteToShift = 0;
let bitReadingMode = false;
const startReadingBits = () => {
bitReadingMode = true;
byteToShift = getUint8();
};
const getFlacCodecNumber = () => {
let ones = 0;
let bits = 0;
while ((++bits || true) && getBits(1) === 1) {
ones++;
}
if (ones === 0) {
return getBits(7);
}
const bitArray = [];
const firstByteBits = 8 - ones - 1;
for (let i = 0;i < firstByteBits; i++) {
bitArray.unshift(getBits(1));
}
const extraBytes = ones - 1;
for (let i = 0;i < extraBytes; i++) {
for (let j = 0;j < 8; j++) {
const val = getBits(1);
if (j < 2) {
continue;
}
bitArray.unshift(val);
}
}
const encoded = bitArray.reduce((acc, bit, index) => {
return acc | bit << index;
}, 0);
return encoded;
};
const getBits = (bits) => {
let result = 0;
let bitsCollected = 0;
while (bitsCollected < bits) {
if (bitIndex >= 8) {
bitIndex = 0;
byteToShift = getUint8();
}
const remainingBitsInByte = 8 - bitIndex;
const bitsToReadNow = Math.min(bits - bitsCollected, remainingBitsInByte);
const mask = (1 << bitsToReadNow) - 1;
const shift = remainingBitsInByte - bitsToReadNow;
result <<= bitsToReadNow;
result |= byteToShift >> shift & mask;
bitsCollected += bitsToReadNow;
bitIndex += bitsToReadNow;
}
return result;
};
return {
startReadingBits,
stopReadingBits,
skipTo,
addData,
counter,
peekB,
peekD,
getBits,
bytesRemaining,
leb128,
removeBytesRead,
discard,
getEightByteNumber,
getFourByteNumber,
getSlice,
getAtom: () => {
const atom = getSlice(4);
return new TextDecoder().decode(atom);
},
detectFileType: () => {
return detectFileType(uintArray);
},
getPaddedFourByteNumber,
getMatroskaSegmentId: () => {
if (bytesRemaining() === 0) {
return null;
}
const first = getSlice(1);
const firstOneString = `0x${Array.from(new Uint8Array(first)).map((b) => {
return b.toString(16).padStart(2, "0");
}).join("")}`;
if (knownIdsWithOneLength.includes(firstOneString)) {
return firstOneString;
}
if (bytesRemaining() === 0) {
return null;
}
const firstTwo = getSlice(1);
const firstTwoString = `${firstOneString}${Array.from(new Uint8Array(firstTwo)).map((b) => {
return b.toString(16).padStart(2, "0");
}).join("")}`;
if (knownIdsWithTwoLength.includes(firstTwoString)) {
return firstTwoString;
}
if (bytesRemaining() === 0) {
return null;
}
const firstThree = getSlice(1);
const firstThreeString = `${firstTwoString}${Array.from(new Uint8Array(firstThree)).map((b) => {
return b.toString(16).padStart(2, "0");
}).join("")}`;
if (knownIdsWithThreeLength.includes(firstThreeString)) {
return firstThreeString;
}
if (bytesRemaining() === 0) {
return null;
}
const segmentId = getSlice(1);
return `${firstThreeString}${Array.from(new Uint8Array(segmentId)).map((b) => {
return b.toString(16).padStart(2, "0");
}).join("")}`;
},
getVint: () => {
if (bytesRemaining() === 0) {
return null;
}
const firstByte = getUint8();
const totalLength = firstByte;
if (totalLength === 0) {
return 0;
}
let actualLength = 0;
while ((totalLength >> 7 - actualLength & 1) === 0) {
actualLength++;
}
if (bytesRemaining() < actualLength) {
return null;
}
const slice = getSlice(actualLength);
const d = [firstByte, ...Array.from(new Uint8Array(slice))];
actualLength += 1;
let value = 0;
value = totalLength & 255 >> actualLength;
for (let i = 1;i < actualLength; i++) {
value = value << 8 | d[i];
}
if (value === -1) {
return Infinity;
}
return value;
},
getUint8,
getEBML: () => {
const val = getUint8();
const actualValue = val & 127;
return actualValue;
},
getInt8: () => {
const val = view.getInt8(counter.getDiscardedOffset());
counter.increment(1);
return val;
},
getUint16: () => {
const val = view.getUint16(counter.getDiscardedOffset());
counter.increment(2);
return val;
},
getUint16Le: () => {
const val = view.getUint16(counter.getDiscardedOffset(), true);
counter.increment(2);
return val;
},
getUint24: () => {
const val1 = view.getUint8(counter.getDiscardedOffset());
const val2 = view.getUint8(counter.getDiscardedOffset() + 1);
const val3 = view.getUint8(counter.getDiscardedOffset() + 2);
counter.increment(3);
return val1 << 16 | val2 << 8 | val3;
},
getInt24: () => {
const val1 = view.getInt8(counter.getDiscardedOffset());
const val2 = view.getUint8(counter.getDiscardedOffset() + 1);
const val3 = view.getUint8(counter.getDiscardedOffset() + 2);
counter.increment(3);
return val1 << 16 | val2 << 8 | val3;
},
getInt16: () => {
const val = view.getInt16(counter.getDiscardedOffset());
counter.increment(2);
return val;
},
getUint32,
getUint64,
getInt64,
getFixedPointUnsigned1616Number: () => {
const val = getUint32();
return val / 2 ** 16;
},
getFixedPointSigned1616Number: () => {
const val = getInt32();
return val / 2 ** 16;
},
getFixedPointSigned230Number: () => {
const val = getInt32();
return val / 2 ** 30;
},
getPascalString: () => {
const val = getSlice(32);
return [...Array.from(new Uint8Array(val))];
},
getUint(length) {
const bytes = getSlice(length);
const numbers = [...Array.from(new Uint8Array(bytes))];
return numbers.reduce((acc, byte, index) => acc + (byte << 8 * (numbers.length - index - 1)), 0);
},
getByteString(length, trimTrailingZeroes) {
let bytes = getSlice(length);
while (trimTrailingZeroes && bytes[bytes.length - 1] === 0) {
bytes = bytes.slice(0, -1);
}
return new TextDecoder().decode(bytes).trim();
},
planBytes: (size) => {
const currentOffset = counter.getOffset();
return {
discardRest: () => {
const toDiscard = size - (counter.getOffset() - currentOffset);
if (toDiscard < 0) {
throw new Error("read too many bytes");
}
return getSlice(toDiscard);
}
};
},
getFloat64: () => {
const val = view.getFloat64(counter.getDiscardedOffset());
counter.increment(8);
return val;
},
readUntilNullTerminator,
getFloat32: () => {
const val = view.getFloat32(counter.getDiscardedOffset());
counter.increment(4);
return val;
},
getUint32Le,
getInt32Le,
getInt32,
destroy,
startBox,
readExpGolomb,
startCheckpoint,
getFlacCodecNumber,
readUntilLineEnd,
getSyncSafeInt32,
replaceData
};
};
// src/containers/iso-base-media/to-date.ts
var toUnixTimestamp = (value) => {
if (value === 0) {
return null;
}
const baseDate = new Date("1904-01-01T00:00:00Z");
return Math.floor(value + baseDate.getTime() / 1000) * 1000;
};
// src/containers/iso-base-media/moov/mvhd.ts
var parseMvhd = ({
iterator,
offset,
size
}) => {
const version = iterator.getUint8();
iterator.discard(3);
const creationTime = version === 1 ? iterator.getUint64() : iterator.getUint32();
const modificationTime = version === 1 ? iterator.getUint64() : iterator.getUint32();
const timeScale = iterator.getUint32();
const durationInUnits = version === 1 ? iterator.getUint64() : iterator.getUint32();
const durationInSeconds = Number(durationInUnits) / timeScale;
const rateArray = iterator.getSlice(4);
const rateView = getArrayBufferIterator(rateArray, rateArray.length);
const rate = rateView.getInt8() * 10 + rateView.getInt8() + rateView.getInt8() * 0.1 + rateView.getInt8() * 0.01;
const volumeArray = iterator.getSlice(2);
const volumeView = getArrayBufferIterator(volumeArray, volumeArray.length);
const volume = volumeView.getInt8() + volumeView.getInt8() * 0.1;
iterator.discard(2);
iterator.discard(4);
iterator.discard(4);
const matrix = [
iterator.getFixedPointSigned1616Number(),
iterator.getFixedPointSigned1616Number(),
iterator.getFixedPointSigned230Number(),
iterator.getFixedPointSigned1616Number(),
iterator.getFixedPointSigned1616Number(),
iterator.getFixedPointSigned230Number(),
iterator.getFixedPointSigned1616Number(),
iterator.getFixedPointSigned1616Number(),
iterator.getFixedPointSigned230Number()
];
iterator.discard(4 * 6);
const nextTrackId = iterator.getUint32();
volumeView.destroy();
const bytesRemaining = size - (iterator.counter.getOffset() - offset);
if (bytesRemaining !== 0) {
throw new Error("expected 0 bytes " + bytesRemaining);
}
return {
creationTime: toUnixTimestamp(Number(creationTime)),
modificationTime: toUnixTimestamp(Number(modificationTime)),
timeScale,
durationInUnits: Number(durationInUnits),
durationInSeconds,
rate,
volume,
matrix,
nextTrackId,
type: "mvhd-box",
boxSize: size,
offset
};
};
// src/containers/avc/codec-string.ts
var getCodecStringFromSpsAndPps = (sps) => {
return `avc1.${sps.spsData.profile.toString(16).padStart(2, "0")}${sps.spsData.compatibility.toString(16).padStart(2, "0")}${sps.spsData.level.toString(16).padStart(2, "0")}`;
};
// src/combine-uint8-arrays.ts
var 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;
};
// src/truthy.ts
function truthy(value) {
return Boolean(value);
}
// src/containers/avc/create-sps-pps-data.ts
function serializeUint16(value) {
const buffer = new ArrayBuffer(2);
const view = new DataView(buffer);
view.setUint16(0, value);
return new Uint8Array(buffer);
}
var createSpsPpsData = (avc1Profile) => {
return combineUint8Arrays([
new Uint8Array([
1,
avc1Profile.sps.spsData.profile,
avc1Profile.sps.spsData.compatibility,
avc1Profile.sps.spsData.level,
255,
225
]),
serializeUint16(avc1Profile.sps.sps.length),
avc1Profile.sps.sps,
new Uint8Array([1]),
serializeUint16(avc1Profile.pps.pps.length),
avc1Profile.pps.pps,
[66, 77, 88].some((b) => avc1Profile.sps.spsData.profile === b) ? null : new Uint8Array([253, 248, 248, 0])
].filter(truthy));
};
// src/add-avc-profile-to-track.ts
var addAvcProfileToTrack = (track, avc1Profile) => {
if (avc1Profile === null) {
return track;
}
return {
...track,
codec: getCodecStringFromSpsAndPps(avc1Profile.sps),
codecData: { type: "avc-sps-pps", data: createSpsPpsData(avc1Profile) },
description: undefined
};
};
// src/register-track.ts
var registerVideoTrack = async ({
track,
container,
logLevel,
onVideoTrack,
registerVideoSampleCallback,
tracks: tracks2
}) => {
if (tracks2.getTracks().fi