mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-10-03 13:53:53 +02:00
Add language getter to InputTrack
This commit is contained in:
@@ -43,6 +43,8 @@
|
||||
const videoTrack = await input.getPrimaryVideoTrack();
|
||||
const sink = new Metamuxer.VideoFrameSink(videoTrack);
|
||||
|
||||
console.log(await videoTrack.getLanguageCode());
|
||||
|
||||
for await (const thing of sink.framesAtTimestamps([0.2, 1, 2, 423])) {
|
||||
console.log(thing)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface InputTrackBacking {
|
||||
getCodec(): Promise<MediaCodec | null>;
|
||||
getFirstTimestamp(): Promise<number>;
|
||||
computeDuration(): Promise<number>;
|
||||
getLanguageCode(): Promise<string>;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
@@ -39,6 +40,10 @@ export abstract class InputTrack {
|
||||
computeDuration() {
|
||||
return this._backing.computeDuration();
|
||||
}
|
||||
|
||||
getLanguageCode() {
|
||||
return this._backing.getLanguageCode();
|
||||
}
|
||||
}
|
||||
|
||||
export interface InputVideoTrackBacking extends InputTrackBacking {
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
colorSpaceIsComplete,
|
||||
IDENTITY_MATRIX,
|
||||
rotationMatrix,
|
||||
UNDETERMINED_LANGUAGE,
|
||||
} from '../misc';
|
||||
import {
|
||||
AudioCodec,
|
||||
@@ -429,7 +430,7 @@ export const mdhd = (
|
||||
const u32OrU64 = needsU64 ? u64 : u32;
|
||||
|
||||
let language = 0;
|
||||
for (const character of (trackData.track.metadata.languageCode ?? 'und')) {
|
||||
for (const character of (trackData.track.metadata.languageCode ?? UNDETERMINED_LANGUAGE)) {
|
||||
language <<= 5;
|
||||
language += character.charCodeAt(0) - 0x60;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
last,
|
||||
AsyncMutex,
|
||||
findLastIndex,
|
||||
UNDETERMINED_LANGUAGE,
|
||||
} from '../misc';
|
||||
import { Reader } from '../reader';
|
||||
import { EncodedAudioSample, EncodedVideoSample, PLACEHOLDER_DATA, SampleType } from '../sample';
|
||||
@@ -47,6 +48,7 @@ type InternalTrack = {
|
||||
durationInMovieTimescale: number;
|
||||
durationInMediaTimescale: number;
|
||||
rotation: Rotation;
|
||||
languageCode: string;
|
||||
sampleTableByteOffset: number;
|
||||
sampleTable: SampleTable | null;
|
||||
fragmentLookupTable: FragmentLookupTableEntry[] | null;
|
||||
@@ -557,6 +559,7 @@ export class IsobmffDemuxer extends Demuxer {
|
||||
durationInMovieTimescale: -1,
|
||||
durationInMediaTimescale: -1,
|
||||
rotation: 0,
|
||||
languageCode: UNDETERMINED_LANGUAGE,
|
||||
sampleTableByteOffset: -1,
|
||||
sampleTable: null,
|
||||
fragmentLookupTable: null,
|
||||
@@ -642,6 +645,17 @@ export class IsobmffDemuxer extends Demuxer {
|
||||
track.timescale = this.isobmffReader.readU32();
|
||||
track.durationInMediaTimescale = this.isobmffReader.readU64();
|
||||
}
|
||||
|
||||
let language = this.isobmffReader.readU16();
|
||||
|
||||
if (language > 0) {
|
||||
track.languageCode = '';
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
track.languageCode = String.fromCharCode(0x60 + (language & 0b11111)) + track.languageCode;
|
||||
language >>= 5;
|
||||
}
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 'hdlr': {
|
||||
@@ -1689,6 +1703,10 @@ abstract class IsobmffTrackBacking<
|
||||
return (lastSample?.timestamp ?? 0) + (lastSample?.duration ?? 0);
|
||||
}
|
||||
|
||||
async getLanguageCode() {
|
||||
return this.internalTrack.languageCode;
|
||||
}
|
||||
|
||||
async getFirstTimestamp() {
|
||||
const firstSample = await this.getFirstSample({ metadataOnly: true });
|
||||
return firstSample?.timestamp ?? 0;
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
MATRIX_COEFFICIENTS_MAP_INVERSE,
|
||||
Rotation,
|
||||
TRANSFER_CHARACTERISTICS_MAP_INVERSE,
|
||||
UNDETERMINED_LANGUAGE,
|
||||
} from '../misc';
|
||||
import { Reader } from '../reader';
|
||||
import { EncodedAudioSample, EncodedVideoSample, PLACEHOLDER_DATA, SampleType } from '../sample';
|
||||
@@ -107,6 +108,7 @@ type InternalTrack = {
|
||||
inputTrack: InputTrack | null;
|
||||
codecId: string | null;
|
||||
codecPrivate: Uint8Array | null;
|
||||
languageCode: string;
|
||||
info:
|
||||
| null
|
||||
| {
|
||||
@@ -583,6 +585,7 @@ export class MatroskaDemuxer extends Demuxer {
|
||||
inputTrack: null,
|
||||
codecId: null,
|
||||
codecPrivate: null,
|
||||
languageCode: UNDETERMINED_LANGUAGE,
|
||||
info: null,
|
||||
};
|
||||
|
||||
@@ -733,6 +736,12 @@ export class MatroskaDemuxer extends Demuxer {
|
||||
this.currentTrack.codecPrivate = reader.readBytes(size);
|
||||
}; break;
|
||||
|
||||
case EBMLId.Language: {
|
||||
if (!this.currentTrack) break;
|
||||
|
||||
this.currentTrack.languageCode = reader.readString(size);
|
||||
}; break;
|
||||
|
||||
case EBMLId.Video: {
|
||||
if (this.currentTrack?.info?.type !== 'video') break;
|
||||
|
||||
@@ -967,6 +976,10 @@ abstract class MatroskaTrackBacking<
|
||||
return (lastSample?.timestamp ?? 0) + (lastSample?.duration ?? 0);
|
||||
}
|
||||
|
||||
async getLanguageCode() {
|
||||
return this.internalTrack.languageCode;
|
||||
}
|
||||
|
||||
async getFirstTimestamp() {
|
||||
const firstSample = await this.getFirstSample({ metadataOnly: true });
|
||||
return firstSample?.timestamp ?? 0;
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
COLOR_PRIMARIES_MAP,
|
||||
MATRIX_COEFFICIENTS_MAP,
|
||||
TRANSFER_CHARACTERISTICS_MAP,
|
||||
UNDETERMINED_LANGUAGE,
|
||||
assert,
|
||||
colorSpaceIsComplete,
|
||||
readBits,
|
||||
@@ -241,7 +242,7 @@ export class MatroskaMuxer extends Muxer {
|
||||
{ id: EBMLId.TrackUID, data: trackData.track.id },
|
||||
{ id: EBMLId.TrackType, data: TRACK_TYPE_MAP[trackData.type] },
|
||||
{ id: EBMLId.FlagLacing, data: 0 },
|
||||
{ id: EBMLId.Language, data: trackData.track.metadata.languageCode ?? 'und' },
|
||||
{ id: EBMLId.Language, data: trackData.track.metadata.languageCode ?? UNDETERMINED_LANGUAGE },
|
||||
{ id: EBMLId.CodecID, data: codecId },
|
||||
{ id: EBMLId.CodecDelay, data: 0 },
|
||||
{ id: EBMLId.SeekPreRoll, data: seekPreRollNs },
|
||||
|
||||
@@ -329,3 +329,5 @@ export const mapAsyncGenerator = <T, U>(
|
||||
export const clamp = (value: number, min: number, max: number) => {
|
||||
return Math.max(min, Math.min(max, value));
|
||||
};
|
||||
|
||||
export const UNDETERMINED_LANGUAGE = 'und';
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Demuxer } from '../demuxer';
|
||||
import { Input } from '../input';
|
||||
import { InputAudioTrack, InputAudioTrackBacking } from '../input-track';
|
||||
import { SampleRetrievalOptions } from '../media-sink';
|
||||
import { assert } from '../misc';
|
||||
import { assert, UNDETERMINED_LANGUAGE } from '../misc';
|
||||
import { Reader } from '../reader';
|
||||
import { EncodedAudioSample, PLACEHOLDER_DATA } from '../sample';
|
||||
import { RiffReader } from './riff-reader';
|
||||
@@ -215,6 +215,10 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
|
||||
return this.demuxer.audioInfo.sampleRate;
|
||||
}
|
||||
|
||||
async getLanguageCode() {
|
||||
return UNDETERMINED_LANGUAGE;
|
||||
}
|
||||
|
||||
async getFirstTimestamp() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user