Add track name support

This commit is contained in:
Vanilagy
2025-08-23 15:33:44 +02:00
parent 0e03779169
commit bb1b20afa7
17 changed files with 196 additions and 16 deletions
+34 -1
View File
@@ -7,13 +7,22 @@
*/
import { MediaCodec } from '../codec';
import { assertNever, textDecoder, textEncoder } from '../misc';
import { Reader } from '../reader';
import { Writer } from '../writer';
export interface EBMLElement {
id: number;
size?: number;
data: number | string | Uint8Array | EBMLFloat32 | EBMLFloat64 | EBMLSignedInt | (EBML | null)[];
data:
| number
| string
| Uint8Array
| EBMLFloat32
| EBMLFloat64
| EBMLSignedInt
| EBMLUnicodeString
| (EBML | null)[];
}
export type EBML = EBMLElement | Uint8Array | (EBML | null)[];
@@ -45,6 +54,10 @@ export class EBMLSignedInt {
}
}
export class EBMLUnicodeString {
constructor(public value: string) {}
}
/** Defines some of the EBML IDs used by Matroska files. */
export enum EBMLId {
EBML = 0x1a45dfa3,
@@ -73,6 +86,7 @@ export enum EBMLId {
FlagDefault = 0x88,
FlagForced = 0x55aa,
FlagLacing = 0x9c,
Name = 0x536e,
Language = 0x22b59c,
CodecID = 0x86,
CodecPrivate = 0x63a2,
@@ -371,6 +385,12 @@ export class EBMLWriter {
const size = data.size ?? measureSignedInt(data.data.value);
this.writeVarInt(size);
this.writeSignedInt(data.data.value, size);
} else if (data.data instanceof EBMLUnicodeString) {
const bytes = textEncoder.encode(data.data.value);
this.writeVarInt(bytes.length);
this.writer.write(bytes);
} else {
assertNever(data.data);
}
}
}
@@ -514,6 +534,19 @@ export class EBMLReader {
return String.fromCharCode(...new Uint8Array(view.buffer, offset, strLength));
}
readUnicodeString(length: number) {
const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + length);
this.pos += length;
// Actual string length might be shorter due to null terminators
let strLength = 0;
while (strLength < length && view.getUint8(offset + strLength) !== 0) {
strLength += 1;
}
return textDecoder.decode(new Uint8Array(view.buffer, offset, strLength));
}
readElementId() {
const size = this.readVarIntSize();
if (size === null) {
+12
View File
@@ -145,6 +145,7 @@ type InternalTrack = {
codecId: string | null;
codecPrivate: Uint8Array | null;
defaultDuration: number | null;
name: string | null;
languageCode: string;
info:
| null
@@ -836,6 +837,7 @@ export class MatroskaDemuxer extends Demuxer {
codecId: null,
codecPrivate: null,
defaultDuration: null,
name: null,
languageCode: UNDETERMINED_LANGUAGE,
info: null,
};
@@ -1004,6 +1006,12 @@ export class MatroskaDemuxer extends Demuxer {
= this.currentTrack.segment.timestampFactor * reader.readUnsignedInt(size) / 1e9;
}; break;
case EBMLId.Name: {
if (!this.currentTrack) break;
this.currentTrack.name = reader.readUnicodeString(size);
}; break;
case EBMLId.Language: {
if (!this.currentTrack) break;
@@ -1261,6 +1269,10 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
}
getName() {
return this.internalTrack.name;
}
getLanguageCode() {
return this.internalTrack.languageCode;
}
+4
View File
@@ -29,6 +29,7 @@ import {
EBMLFloat64,
EBMLId,
EBMLSignedInt,
EBMLUnicodeString,
EBMLWriter,
} from './ebml';
import { buildMatroskaMimeType } from './matroska-misc';
@@ -272,6 +273,9 @@ export class MatroskaMuxer extends Muxer {
{ id: EBMLId.CodecID, data: codecId },
{ id: EBMLId.CodecDelay, data: 0 },
{ id: EBMLId.SeekPreRoll, data: seekPreRollNs },
trackData.track.metadata.name !== undefined
? { id: EBMLId.Name, data: new EBMLUnicodeString(trackData.track.metadata.name) }
: null,
(trackData.type === 'video' ? this.videoSpecificTrackInfo(trackData) : null),
(trackData.type === 'audio' ? this.audioSpecificTrackInfo(trackData) : null),
(trackData.type === 'subtitle' ? this.subtitleSpecificTrackInfo(trackData) : null),