Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ private const val PROP_NAME = "name"
private const val PROP_ENABLED = "enabled"
private const val PROP_SRC = "src"
private const val PROP_FORCED = "forced"
private const val PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE = "inBandMetadataTrackDispatchType"
private const val PROP_CAPTION_CHANNEL = "captionChannel"
private const val PROP_AUDIO_SAMPLING_RATE = "audioSamplingRate"
private const val PROP_BANDWIDTH = "bandwidth"
Expand Down Expand Up @@ -71,6 +72,7 @@ object TrackListAdapter {
textTrackPayload.putBoolean(PROP_FORCED, textTrack.isForced)

// THEOplayer v10.13+
textTrackPayload.putString(PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE, textTrack.inBandMetadataTrackDispatchType ?: "")
textTrack.captionChannel?.let { textTrackPayload.putInt(PROP_CAPTION_CHANNEL, it) }

// Optionally pass cue list.
Expand Down
3 changes: 3 additions & 0 deletions ios/THEOplayerRCTTrackMetadataAggregator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ let PROP_CUE_CONTENT: String = "content"
let PROP_CUE_CUSTOM_ATTRIBUTES: String = "customAttributes"
let PROP_SRC: String = "src"
let PROP_FORCED: String = "forced"
let PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE: String = "inBandMetadataTrackDispatchType"
let PROP_START_DATE: String = "startDate"
let PROP_END_DATE: String = "endDate"
let PROP_ATTRIBUTE_CLASS: String = "class"
Expand Down Expand Up @@ -78,6 +79,7 @@ class THEOplayerRCTTrackMetadataAggregator {
entry[PROP_TYPE] = textTrack.type
entry[PROP_SRC] = textTrack.src
entry[PROP_FORCED] = textTrack.forced
entry[PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE] = textTrack.inBandMetadataTrackDispatchType

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class also aggregates TextTracks from sideloaded metadata (not supported on native iOS player) which are handled by the iOS bridge (function: aggregatedMetadataAndChapterTrackInfo())

Should we also add the property there?

The iOS API is not very clear on the usage:
/** The text track in-band metadata track dispatch type of the text track that the TextTrack object represents. */

It's just a string, so what could these be?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I'd say noaggregatedMetadataAndChapterTrackInfo() constructs entries from TextTrackDescription (sideloaded WebVTT files), which are out-of-band by definition. inBandMetadataTrackDispatchType is specifically about metadata embedded within the stream (DASH EventStream, HLS ID3, CMAF emsg, etc.), so it wouldn't apply to sideloaded tracks — and TextTrackDescription doesn't expose this property.

As for what the values can be: it originates from the W3C MSE spec. Typical values are scheme URIs or type identifiers that disambiguate in-band metadata tracks — e.g. an EventStream schemeIdUri in DASH, or an ID3 metadata type in HLS. The native SDK passes it through as an opaque string so consumers can identify which kind of in-band metadata a track carries.

Happy to add it there too if you disagree, but I think leaving sideloaded tracks without it is correct.

@wvanhaevre wvanhaevre Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wanted to make sure the bridging of the property works fine. It's not optional on the Typescript side.
I'm adding it to the fromNativeTextTrack TrackUtil and will set the value explicitely to "" on the metadata track aggregation

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch on the non-optional TS type. Since on Android we already guard with ?.let (so the key is omitted when null), and on iOS native it can also be nil, an alternative would be to make the TS property optional: readonly inBandMetadataTrackDispatchType?: string. That would match the native nullability and avoid needing to set "" explicitly for sideloaded tracks.

Happy to make that change here if you'd prefer, or leave it as-is if you'd rather default to "" on the sideloaded path. Let me know which approach you prefer.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Danesz what do you prefer?

Note: I think we should at least add the property to fromNativeTextTrack in TrackUtils.ts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right about TrackUtils.ts — I missed adding it to fromNativeTextTrack. The destructuring on line 44 and the return object need inBandMetadataTrackDispatchType as well. I'll add it once you and @Danesz decide on optional vs non-optional.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the iOS SDK the property is not nullable?

public protocol TextTrack : THEOplayerSDK.Track {
    var inBandMetadataTrackDispatchType: String { get }

On web either?

interface TextTrack extends Track, EventDispatcher<TextTrackEventMap> {
    readonly inBandMetadataTrackDispatchType: string;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right — it's non-optional on both iOS and web native SDKs. My suggestion about making it optional was wrong. Keeping it as string (non-optional) is correct, and defaulting to "" for sideloaded tracks makes sense.

I'll go ahead and add it to fromNativeTextTrack in TrackUtils.ts now.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm missing the defaulting to "" for sideloaded tracks in the commit

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in d55fafbtrack[PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE] = "" in aggregatedMetadataAndChapterTrackInfo() for sideloaded tracks.

// process cues when texttrack contains them
if !textTrack.cues.isEmpty {
var cueList: [[String:Any]] = []
Expand Down Expand Up @@ -311,6 +313,7 @@ class THEOplayerRCTTrackMetadataAggregator {
track[PROP_LABEL] = trackDescription.label ?? "no label"
track[PROP_TYPE] = "webvtt"
track[PROP_SRC] = trackDescription.src.absoluteString
track[PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE] = ""
var cueList: [[String:Any]] = []
var cueIndex = 0
for c in cues {
Expand Down
5 changes: 5 additions & 0 deletions src/api/track/TextTrack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ export interface TextTrack extends Track {
*/
readonly forced: boolean;

/**
* The in-band metadata track dispatch type of the text track.
*/
readonly inBandMetadataTrackDispatchType: string;

/**
* The closed caption service number of the text track.
*
Expand Down
3 changes: 2 additions & 1 deletion src/internal/adapter/web/TrackUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function fromNativeTextTrackList(tracks: NativeTextTrackList): TextTrack[
}

export function fromNativeTextTrack(track: NativeTextTrack): TextTrack {
const { id, uid, kind, label, language, mode, type, src, forced, captionChannel } = track;
const { id, uid, kind, label, language, mode, type, src, forced, inBandMetadataTrackDispatchType, captionChannel } = track;

return {
id,
Expand All @@ -53,6 +53,7 @@ export function fromNativeTextTrack(track: NativeTextTrack): TextTrack {
type,
src,
forced,
inBandMetadataTrackDispatchType,
captionChannel,
cues: track.cues ? track.cues.map((cue) => fromNativeCue(cue)) : [],
} as TextTrack;
Expand Down
Loading