Add internalCodecId field

This commit is contained in:
Vanilagy
2025-08-23 16:24:36 +02:00
parent e6420caea4
commit 803e58a0d2
9 changed files with 49 additions and 1 deletions
+1
View File
@@ -20,6 +20,7 @@
console.log(await videoTrack.getFirstTimestamp(), await videoTrack.computeDuration()); console.log(await videoTrack.getFirstTimestamp(), await videoTrack.computeDuration());
console.log(videoTrack.name); console.log(videoTrack.name);
console.log(videoTrack.internalCodecId);
/* /*
const sink = new Mediabunny.EncodedPacketSink(videoTrack); const sink = new Mediabunny.EncodedPacketSink(videoTrack);
+1 -1
View File
@@ -108,7 +108,7 @@ You can query metadata related to the track's codec:
```ts ```ts
track.codec; // => MediaCodec | null track.codec; // => MediaCodec | null
``` ```
This field is `null` when the track's codec couldn't be recognized or is not supported by Mediabunny. See [Codecs](./supported-formats-and-codecs#codecs) for the full list of supported codecs. This field is `null` when the track's codec couldn't be recognized or is not supported by Mediabunny. See [Codecs](./supported-formats-and-codecs#codecs) for the full list of supported codecs. When Mediabunny doesn't recognize the format, you can still use the `internalCodecId` field to figure out the codec of the track, although its format depends on the container format used and is not homogenized by Mediabunny.
You can also extract the full codec parameter string from the track, as specified in the [WebCodecs Codec Registry](https://www.w3.org/TR/webcodecs-codec-registry/): You can also extract the full codec parameter string from the track, as specified in the [WebCodecs Codec Registry](https://www.w3.org/TR/webcodecs-codec-registry/):
```ts ```ts
+6
View File
@@ -168,6 +168,12 @@ class AdtsAudioTrackBacking implements InputAudioTrackBacking {
return 'aac'; return 'aac';
} }
getInternalCodecId() {
assert(this.demuxer.firstFrameHeader);
return this.demuxer.firstFrameHeader.objectType;
}
getNumberOfChannels() { getNumberOfChannels() {
assert(this.demuxer.firstFrameHeader); assert(this.demuxer.firstFrameHeader);
+17
View File
@@ -30,6 +30,7 @@ export type PacketStats = {
export interface InputTrackBacking { export interface InputTrackBacking {
getId(): number; getId(): number;
getCodec(): MediaCodec | null; getCodec(): MediaCodec | null;
getInternalCodecId(): string | number | Uint8Array | null;
getName(): string | null; getName(): string | null;
getLanguageCode(): string; getLanguageCode(): string;
getTimeResolution(): number; getTimeResolution(): number;
@@ -85,6 +86,22 @@ export abstract class InputTrack {
return this._backing.getId(); return this._backing.getId();
} }
/**
* The identifier of the codec used internally by the container. It is not homogenized by Mediabunny
* and depends entirely on the container format.
*
* This field can be used to determine the codec of a track in case Mediabunny doesn't know that codec.
*
* - For ISOBMFF files, this field returns the name of the Sample Description Box (e.g. 'avc1').
* - For Matroska files, this field returns the value of the CodecID element.
* - For WAVE files, this field returns the value of the format tag in the 'fmt ' chunk.
* - For ADTS files, this field contains the MPEG-4 Audio Object Type.
* - In all other cases, this field is `null`.
*/
get internalCodecId() {
return this._backing.getInternalCodecId();
}
/** The ISO 639-2/T language code for this track. If the language is unknown, this field is 'und' (undetermined). */ /** The ISO 639-2/T language code for this track. If the language is unknown, this field is 'und' (undetermined). */
get languageCode() { get languageCode() {
return this._backing.getLanguageCode(); return this._backing.getLanguageCode();
+7
View File
@@ -71,6 +71,7 @@ type InternalTrack = {
durationInMovieTimescale: number; durationInMovieTimescale: number;
durationInMediaTimescale: number; durationInMediaTimescale: number;
rotation: Rotation; rotation: Rotation;
internalCodecId: string | null;
name: string | null; name: string | null;
languageCode: string; languageCode: string;
sampleTableByteOffset: number; sampleTableByteOffset: number;
@@ -628,6 +629,7 @@ export class IsobmffDemuxer extends Demuxer {
durationInMovieTimescale: -1, durationInMovieTimescale: -1,
durationInMediaTimescale: -1, durationInMediaTimescale: -1,
rotation: 0, rotation: 0,
internalCodecId: null,
name: null, name: null,
languageCode: UNDETERMINED_LANGUAGE, languageCode: UNDETERMINED_LANGUAGE,
sampleTableByteOffset: -1, sampleTableByteOffset: -1,
@@ -847,6 +849,7 @@ export class IsobmffDemuxer extends Demuxer {
break; break;
} }
track.internalCodecId = sampleBoxInfo.name;
const lowercaseBoxName = sampleBoxInfo.name.toLowerCase(); const lowercaseBoxName = sampleBoxInfo.name.toLowerCase();
if (track.info.type === 'video') { if (track.info.type === 'video') {
@@ -1957,6 +1960,10 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
throw new Error('Not implemented on base class.'); throw new Error('Not implemented on base class.');
} }
getInternalCodecId() {
return this.internalTrack.internalCodecId;
}
getName() { getName() {
return this.internalTrack.name; return this.internalTrack.name;
} }
+4
View File
@@ -1282,6 +1282,10 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
throw new Error('Not implemented on base class.'); throw new Error('Not implemented on base class.');
} }
getInternalCodecId() {
return this.internalTrack.codecId;
}
async computeDuration() { async computeDuration() {
const lastPacket = await this.getPacket(Infinity, { metadataOnly: true }); const lastPacket = await this.getPacket(Infinity, { metadataOnly: true });
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0); return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
+4
View File
@@ -180,6 +180,10 @@ class Mp3AudioTrackBacking implements InputAudioTrackBacking {
return 'mp3'; return 'mp3';
} }
getInternalCodecId() {
return null;
}
getNumberOfChannels() { getNumberOfChannels() {
assert(this.demuxer.firstFrameHeader); assert(this.demuxer.firstFrameHeader);
return this.demuxer.firstFrameHeader.channel === 3 ? 1 : 2; return this.demuxer.firstFrameHeader.channel === 3 ? 1 : 2;
+4
View File
@@ -431,6 +431,10 @@ class OggAudioTrackBacking implements InputAudioTrackBacking {
return this.bitstream.codecInfo.codec; return this.bitstream.codecInfo.codec;
} }
getInternalCodecId() {
return null;
}
async getDecoderConfig(): Promise<AudioDecoderConfig | null> { async getDecoderConfig(): Promise<AudioDecoderConfig | null> {
assert(this.bitstream.codecInfo.codec); assert(this.bitstream.codecInfo.codec);
+5
View File
@@ -222,6 +222,11 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
return this.demuxer.getCodec(); return this.demuxer.getCodec();
} }
getInternalCodecId() {
assert(this.demuxer.audioInfo);
return this.demuxer.audioInfo.format;
}
async getDecoderConfig(): Promise<AudioDecoderConfig | null> { async getDecoderConfig(): Promise<AudioDecoderConfig | null> {
const codec = this.demuxer.getCodec(); const codec = this.demuxer.getCodec();
if (!codec) { if (!codec) {