feat(OPTIP-303): bridge inBandMetadataTrackDispatchType to React Native#833
Conversation
Add inBandMetadataTrackDispatchType property to the TextTrack TypeScript interface and bridge it from native Android and iOS SDKs. - TypeScript: add readonly inBandMetadataTrackDispatchType: string to TextTrack - Android: serialize via TrackListAdapter.fromTextTrack() - iOS: serialize via THEOplayerRCTTrackMetadataAggregator.aggregatedTextTrackInfo() Co-Authored-By: daniel.dallos <daniel.dallos@dolby.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| 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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Good question. I'd say no — aggregatedMetadataAndChapterTrackInfo() 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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
@Danesz what do you prefer?
Note: I think we should at least add the property to fromNativeTextTrack in TrackUtils.ts?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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;
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I'm missing the defaulting to "" for sideloaded tracks in the commit
There was a problem hiding this comment.
Added in d55fafb — track[PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE] = "" in aggregatedMetadataAndChapterTrackInfo() for sideloaded tracks.
…tTrack in TrackUtils Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ing for sideloaded tracks Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
| textTrackPayload.putBoolean(PROP_FORCED, textTrack.isForced) | ||
|
|
||
| // THEOplayer v10.13+ | ||
| textTrack.inBandMetadataTrackDispatchType?.let { textTrackPayload.putString(PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE, it) } |
There was a problem hiding this comment.
maybe I'm missing something in the flow, but if this is optional here, how will it arrive on the React Native side as non-optinal empty string?
There was a problem hiding this comment.
You're not missing anything — this is a bug. With ?.let, when the Android SDK returns null the key is simply omitted from the payload, so it arrives as undefined on the RN side despite the TS type being non-optional string.
Fix: default to "" when null:
textTrackPayload.putString(PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE, textTrack.inBandMetadataTrackDispatchType ?: "")This aligns with iOS/Web where the native SDK always returns a non-null String/string. I'll push this fix once you confirm the approach (you told me to hold on committing).
…ing on Android when null Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Summary
Bridge the
inBandMetadataTrackDispatchTypeproperty from the native THEOplayer SDK to the React Native TextTrack API across all platforms.TypeScript/Web — Added
readonly inBandMetadataTrackDispatchType: stringto theTextTrackinterface. Web needs no explicit bridging (pass-through).Android — Serialize via
textTrack.inBandMetadataTrackDispatchType?.let { putString(...) }inTrackListAdapter.fromTextTrack(), following the existingcaptionChannelpattern.iOS — Serialize via
entry[PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE] = textTrack.inBandMetadataTrackDispatchTypeinaggregatedTextTrackInfo(), following the existingforcedpattern.No type conversion needed —
stringon all platforms.