loadVideo options
Overview
This page describes the options given to the loadVideo
method, which is the
method to use to load a new video.
These options take the form of a single objects with multiple properties, like this:
// Simply loading a DASH MPD
const options = {
transport: "dash",
url: myManifestUrl
};
player.loadVideo(options);
Properties
transport
type: string|undefined
The transport protocol used for this content.
Can be either:
-
"dash"
- for DASH contents -
"smooth"
- for Microsoft Smooth Streaming contents -
"directfile"
- for loading a video in DirectFile mode, which allows to directly play media files (example:.mp4
or.webm
files) without using a transport protocol.⚠️ In that mode, multiple APIs won’t have any effect. This is documented in the documentation of each concerned method, option or event in the API.
-
"metaplaylist"
for MetaPlaylist streams
This property is mandatory.
url
type: string|undefined
For Smooth, DASH or MetaPlaylist contents, the URL to the Manifest (or equivalent)
For DirectFile mode contents, the URL of the content (the supported contents depends on the current browser).
This property is mandatory unless a manifestLoader
is defined in the
transportOptions, in which case that callback will be
called instead any time we want to load the Manifest.
keySystems
type: Array.<Object>|undefined
This property is mandatory if the content uses DRM.
It is here that is defined every options relative to the encryption of your content. There’s a lot of configuration possible here. In the case you find this documentation hard to grasp, we’ve written a tutorial on DRM configuration here.
This property is an array of objects with the following properties (only
type
and getLicense
are mandatory here):
-
type
(string
): name of the DRM system used. Can be either"widevine"
,"playready"
orclearkey
or the type (reversed domain name) of the keySystem (e.g."com.widevine.alpha"
,"com.microsoft.playready"
…). -
getLicense
(Function
): Callback which will be triggered everytime a message is sent by the Content Decryption Module (CDM), usually to fetch/renew the license.Gets two arguments when called:
- the message (
Uint8Array
): The message, formatted to an Array of bytes. - the messageType (
string
): String describing the type of message received. There is only 4 possible message types, all defined in the w3c specification.
This function should return either synchronously the license,
null
to not set a license for thismessage
event or a Promise which should either: - resolves if the license was fetched, with the licence in argument - resolve withnull
if you do not want to set a license for thismessage
event - reject if an error was encountered.Note: We set a 10 seconds timeout by default on this request (configurable through the
getLicenseConfig
object). If the returned Promise do not resolve or reject under this limit, the player will stop with an error.In any case, the license provided by this function should be of a
BufferSource
type (example: anUint8Array
or anArrayBuffer
).Even in case of an error, you can (this is not mandatory) set any of the following properties on the rejected value which will be interpreted by the RxPlayer:
- `noRetry` (`Boolean`): If set to `true`, we will throw directly a `KEY_LOAD_ERROR` to call `getLicense`. If not set or set to `false`, the current retry parameters will be applied (see `getLicenseConfig`) - `message` (`string`): If the `message` property is set as a "string", this message will be set as the `message` property of the corresponding `EncryptedMediaError` (either communicated through an `"error"` event if we're not retrying or through a `"warning"` event if we're retrying). As every other `getLicense`-related errors, this error will have the `KEY_LOAD_ERROR` `code` property. - `fallbackOnLastTry`: If this getLicense is the last retry (if the `noRetry` property is set to `true`, this is always true), we will not throw immediately but rather try to fallback on other Representations (e.g. qualities) which might have a different decryption key. If no Representation is left, we will throw a MediaError with a `NO_PLAYABLE_REPRESENTATION` code, as documented [in the errors documentation](./errors.md#types-media_error). You will receive a `decipherabilityUpdate` event when we fallback from a given Representation. You can find documentation on this event [in the corresponding chapter of the events documentation](./player_events.md#events-decipherabilityUpdate). This option is thus only useful for contents depending on multiple licenses. When fallbacking, we might need to reload the current MediaSource, leading to a black screen during a brief instant. When reloading, the RxPlayer will have the `"reloading"` [player state](./states.md). on most situations, we will however not reload the media source but only perform a very little seek (of some milliseconds). you might see the stream stutter for a very brief instant at that point. On the Edge browser, we found an issue that can arise when this option is set if PlayReady is used. This issue can make the player loads the content indefinitely. Sadly, no work-around has been found for now for this issue. We're currently trying to create a reproducible scenario and document that issue so it can hopefully be fixed in the future. In the meantime, you're encouraged either to use Widevine (only on Chromium-based Edge) or to not make use of the `fallBackOnLastTry` option on that browser.
- the message (
-
getLicenseConfig
(Object|undefined
): Optional configuration for thegetLicense
callback. Can contain the following properties:-
retry
(Number
|undefined
) (default:2
): number of timegetLicense
is retried on error or on timeout before we fail on aKEY_LOAD_ERROR
-
timeout
(Number
|undefined
) (default:10000
): timeout, in ms, after which we consider thegetLicense
callback to have failed.Set it to
-1
to disable any timeout.
-
-
serverCertificate
(BufferSource|undefined
): Eventual certificate used to encrypt messages to the license server. If set, we will try to set this certificate on the CDM. If it fails, we will still continue to try deciphering the content (albeit a warning will be emitted in that case with the code"LICENSE_SERVER_CERTIFICATE_ERROR"
). -
persistentLicense
(Boolean|undefined
): Set it totrue
if you want the ability to persist the license for later retrieval. In that case, you will also need to set thelicenseStorage
attribute to be able to persist the license through your preferred method. This is not needed for most usecases. -
licenseStorage
(Object|undefined
): Required only ifpersistentLicense
has been set totrue
. It’s an object containing two functionsload
andsave
:save
: take into argument anArray.<Object>
which will be the set of sessionId to save. No return value needed.load
: take no argument and returns the storedArray.<Object>
(the last given tosave
) synchronously.
-
persistentStateRequired
(Boolean|undefined
): Set it totrue
if the chosen CDM should have the ability to persist a license,false
if you don’t care. This is not needed for most usecases.false
by default. You do not have to set it totrue
if thepersistentLicense
option is set. -
distinctiveIdentifierRequired
(Boolean|undefined
): When set totrue
, the use of Distinctive Indentifier(s) or Distinctive Permanent Identifier(s) will be required. This is not needed for most usecases.false
if you do not care.false
by default. -
throwOnLicenseExpiration
(Boolean|undefined
):true
by default.If set to
true
or not set, the playback will be interrupted as soon as one of the current licenses expires. In that situation, you will be warned with anerror
event with, as a payload, an error with the codeKEY_STATUS_CHANGE_ERROR
.If set to
false
, the playback of the current content will not be interrupted even if one of the current licenses is expired. It might however stop decoding in that situation. It’s then up to you to update the problematic license, usually through the usualgetLicense
callback.You may want to set this value to
false
if a session expiration leads to a license renewal. In that case, content may continue to play once the license has been updated. -
fallbackOn
(Object
): This advanced option allows to fallback on other Representations (e.g. qualities) when one of them has its decription key refused.This option is thus only useful for contents depending on multiple keys.
This object can have two properties: -
keyInternalError
: fallback when the corresponding key has the status"internal-error"
. We found that most widevine implementation use this error when a key is refused. -keyOutputRestricted
: fallback when the corresponding key has the status"output-restricted"
. This is the proper status for a key refused due to output restrictions.For most cases where you want to fallback in case of a refused key, we recommend setting both properties to
true
.You will receive a
decipherabilityUpdate
event when we fallback from a given Representation. You can find documentation on this event in the corresponding chapter of the events documentation.When fallbacking, we might need to reload the current MediaSource, leading to a black screen during a brief instant. When reloading, the RxPlayer will have the
"reloading"
player state. on most situations, we will however not reload the media source but only perform a very little seek (of some milliseconds). you might see the stream twitch for a very brief instant at that point.If we have no Representation to fallback to anymore, we will throw a MediaError with a
NO_PLAYABLE_REPRESENTATION
code, as documented in the errors documentation. -
onKeyStatusesChange
(Function|undefined
): Not needed for most usecases.Triggered each time the key statuses of the current session changes, except for the following statuses (which throws immediately):
expired
if (and only if)throwOnLicenseExpiration
is not set tofalse
internal-error
Takes 2 arguments:
- The keystatuseschange event
{Event}
- The session associated with the event
{MediaKeySession}
Like
getLicense
, this function should return a promise which emit a license ornull
(for no license) when resolved. It can also return directly the license ornull
if it can be done synchronously.In case of an error, you can set the
message
property on the rejected value as a “string”. This message will be set as themessage
property of the correspondingEncryptedMediaError
communicated through an"error"
event. As every otheronKeyStatusesChange
-related errors, this error will have theKEY_STATUS_CHANGE_ERROR
code
property. -
closeSessionsOnStop
(Boolean|undefined
): If set totrue
, theMediaKeySession
created for a content will be immediately closed when the content stops its playback. This might be required by your key system implementation (most often, it is not).If set to
false
or not set, theMediaKeySession
can be reused if the same content needs to be re-decrypted. -
disableMediaKeysAttachmentLock
(Boolean|undefined
): In regular conditions, we might want to wait for the media element to have decryption capabilities (what we call here “MediaKeys attachment”) before beginning to load the actual content.Waiting for that capability validation allows for example to play a content which contains both encrypted and unencrypted data on the Chrome browser.
However, we found that in some peculiar devices (like some set-top boxes) this can create a deadlock: the browser sometimes wait for some content to be loaded before validating the media element’s decryption capabilities.
Because we didn’t find a good enough compromise for now, we added the
disableMediaKeysAttachmentLock
boolean. By setting it totrue
, we won’t wait for “MediaKeys attachment” before pushing the first content. The downside being that content of mixed unencrypted/encrypted data might not be playable with that configuration.You can try that property if your encrypted contents seems to load indefinitely on peculiar targets.
Example
Example of a simple DRM configuration for widevine and playready DRMs:
player.loadVideo({
url: manifestURL,
transport: "dash",
keySystems: [{
type: "widevine",
getLicense(challenge) {
// ajaxPromise is here an AJAX implementation doing a POST request on the
// widevineLicenseServer with the challenge in its body.
return ajaxPromise(widevineLicenseServer, challenge);
}
}, {
type: "playready",
getLicense(challenge) {
// idem
// Note: you may need to format the challenge before doing the request
// depending on the server configuration.
return ajaxPromise(playreadyLicenseServer, challenge);
}
}]
})
autoPlay
type: Boolean|undefined
defaults: false
If set to true
, the video will play immediately after being loaded.
Note: On some browsers, auto-playing a media without user interaction is blocked
due to the browser’s policy.
In that case, the player won’t be able to play (it will stay in a "LOADED"
state) and you will receive a warning event containing a
MEDIA_ERROR
with the code: MEDIA_ERR_BLOCKED_AUTOPLAY
.
A solution in that case would be to propose to your users an UI element to
trigger the play with an interaction.
startAt
type: Object|undefined
startAt
allows to define a starting position in the played content whether
it is a live content or not.
This option is only defining the starting position, not the beginning of the
content. The user will then be able to navigate anywhere in the content through
the seekTo
API.
If defined, this property must be an object containing a single key. This key can be either:
-
position
(Number
): The starting position, in seconds. -
wallClockTime
(Number|Date
): The starting wall-clock time (re-scaled position from Manifest information to obtain a timestamp on live contents), in seconds. Useful to use the type of time returned by thegetWallClockTime
API for live contents. If a Date object is given, it will automatically be converted into seconds. -
fromFirstPosition
(Number
): relative position from the minimum possible one, in seconds. That is:- for live contents, from the beginning of the buffer depth (as defined by the Manifest).
- for non-live contents, from the position
0
(this option should be equivalent toposition
)
-
fromLastPosition
(Number
): relative position from the maximum possible one, in seconds. Should be a negative number:- for live contents, it is the difference between the starting position and the live edge (as defined by the manifest)
- for non-live contents, it is the difference between the starting position and the end position of the content.
-
percentage
(Number
): percentage of the wanted position.0
being the minimum position possible (0 for static content, buffer depth for live contents) and100
being the maximum position possible (duration
for static content, live edge for live contents).
Note: Only one of those properties will be considered, in the same order of priority they are written here.
If the value set is inferior to the minimum possible position, the minimum possible position will be used instead. If it is superior to the maximum possible position, the maximum will be used instead as well.
More information on how the initial position is chosen can be found in the specific documentation page on this subject.
Notes for live contents
For live contents, startAt
could work not as expected:
-
Depending on the type of Manifest, it will be more or less precize to guess the live edge of the content. This will mostly affect the
fromLastPosition
option. -
If the Manifest does not allow to go far enough in the past (not enough buffer, server-side) to respect the position wanted, the maximum buffer depth will be used as a starting time instead.
-
If the Manifest does not allow to go far enough in the future (live edge sooner) to respect the position wanted, the live edge will be used to define the starting time instead.
If startAt
is not set on live contents, the time suggested by the Manifest
will be considered. If it is also not set, the initial position will be based on
the real live edge.
Example
// using position
player.loadVideo({
// ...
startAt: {
position: 10 // start at position == 10 (in seconds)
}
});
// using wall-clock time
player.loadVideo({
// ...
startAt: {
wallClockTime: Date.now() / 1000 - 60 // 1 minute before what's broadcasted
// now
}
});
// using fromFirstPosition
player.loadVideo({
// ...
startAt: {
fromFirstPosition: 30 // 30 seconds after the beginning of the buffer
}
})
// using fromLastPosition
player.loadVideo({
// ...
startAt: {
fromLastPosition: -60 // 1 minute before the end (before the live edge
// for live contents)
}
})
transportOptions
type: Object|undefined
⚠️ This option is not available in DirectFile mode (see transport option).
Options concerning the “transport”.
That is, the part of the code:
- performing Manifest and segment requests
- parsing the Manifest
- parsing/updating/creating segments
This Object can contain multiple properties. Only those documented here are considered stable:
-
segmentLoader
(Function
): defines a custom segment loader. More info on it can be found here. -
manifestLoader
(Function
): defines a custom Manifest loader. More info on it can be found here. -
representationFilter
(Function
): allows to filter outRepresentation
s (i.e. media qualities) from the Manifest to avoid playing them. More infos on it can be found here. -
checkMediaSegmentIntegrity
(Boolean
): If set to true, the RxPlayer will retry a media segment request - with the same retry rules than other retry-able HTTP errors (like an HTTP 404) - if that segment seems corrupted.If not set or set to false, the RxPlayer might interrupt playback in the same situation.
You can set this option if you suspect the CDN providing your contents to sometimes send you incomplete/corrupted segments.
-
aggressiveMode
(Boolean
): If set to true, we will download segments much sooner, even if we are not sure they had time to be completely generated.For the moment, this mode has only an effect for all Smooth contents and some DASH contents relying on a number-based SegmentTemplate segment indexing scheme.
The upside is that you might have more segments close to the live edge.
The downside is that requests for segments which did not had time to generate might trigger a
NetworkError
. Depending on your other settings (especially thenetworkConfig
loadVideo options), those errors might just be sent as warnings and the corresponding requests be retried. -
referenceDateTime
(Number
): Only useful for live contents. This is the default amount of time, in seconds, to add as an offset to a given media content’s time, to obtain the real live time. For example, if the media has it’s0
time corresponding to the 30th of January 2010 at midnight, you can set thereferenceDateTime
tonew Date(2010-01-30) / 1000
. This value is useful to communicate back to you the “live time”, for example through thegetWallClockTime
method.This will only be taken into account for live contents, and if the Manifest / MPD does not already contain an offset (example: an availabilityStartTime in a DASH MPD).
-
minimumManifestUpdateInterval
(Number
): Set the minimum time, in milliseconds, we have to wait between Manifest updates.A Manifest may need to be updated in regular intervals (e.g. many DASH dynamic contents depend on that behavior).
The frequency at which we normally update a Manifest depends on multiple factors: the information taken from the Manifest, the transport chosen or the current playback conditions. You might want to use
minimumManifestUpdateInterval
to limit that frequency to a minimum.This option is principally useful on some embedded devices where resources are scarce. The request and data decompression done at each Manifest update might be too heavy for some and reducing the interval at which they are done might help.
Please note however than reducing that frequency can raise the chance of rebuffering, as we might be aware of newly generated segments later than we would be without that option.
-
serverSyncInfos
(Object
): Mainly useful for live DASH contents based on a SegmentTemplate scheme without SegmentTimeline elements.Allows to provide a time synchronization mechanism between the client and the server. The
serverSyncInfos
object contains two keys:serverTimestamp
(number
): Unix timestamp of the server at a given point in time, in milliseconds.clientTime
(number
): Value of theperformance.now()
API at the time theserverTimestamp
value was true. Please note that if your page contains multiple worker, theperformance.now()
call should be done on the same worker than the one in which loadVideo is called.
The
performance.now()
API is used here because it is the main API to obtain a monotically increasing clock on the client-side.Example:
const timeResponse = await fetch(serverTimeURL); const serverTimestamp = await timeResponse.text(); const clientTime = performance.now(); const serverSyncInfos = { serverTimestamp, clientTime }; rxPlayer.loadVideo({ // ... transportOptions: { serverSyncInfos } })
If indicated, we will ignore any time indication on the MPD and only consider
serverSyncInfos
to calculate the time on the server side.This value is mostly useful for low-latency contents, as some of them do not indicate any server’s time, relying on the client one instead.
Note that there is a risk of us losing synchronization when leap seconds are added/substracted to unix time. However we consider those situations rare enough (and the effect should be relatively weak) to let this as is for the moment. For a more complete explanation, you can look at the corresponding chapter of the low-latency documentation.
textTrackMode
type: string
defaults: "native"
⚠️ This option is not available in DirectFile mode (see transport option).
This option allows to specify how the text tracks should be displayed.
There is two possible values:
"native"
"html"
In the default "native"
mode, a <track>
element will be created on the
video and the subtitles will be displayed by it, with a minimal style.
There is no action on your side, the subtitles will be correctly displayed at
the right time.
In "html"
mode, the text tracks will be displayed on a specific HTML
element. This mode allows us to do much more stylisation, such as the one
defined by TTML styling attributes or SAMI’s CSS. It is particularly useful to
correctly manage complex closed captions (with multiple colors, positionning
etc.).
With this mode, you will need to provide a wrapper HTML element with the
textTrackElement option.
All text track formats supported in "native"
mode also work in "html"
mode.
More infos on supported text tracks can be found in the text track documentation.
textTrackElement
type: HTMLElement
⚠️ This option is not available in DirectFile mode (see transport option).
textTrackElement
is only required and used if you provided a "html"
textTrackMode.
This property will be the element on which text tracks will be set, as child elements, at the right time. We expect that this element is the exact same size than the media element it applies to (this allows us to properly place the subtitles position without polling where the video is in your UI). You can however re-size or update the style of it as you wish, to better suit your UI needs.
manualBitrateSwitchingMode
type: string
defaults: "seamless"
⚠️ This option is not available in DirectFile mode (see transport option).
Strategy you want to adopt when updating “manually” the video and audio quality
through respectively the setVideoBitrate
and setAudioBitrate
API while
the content is playing.
There is two possible values:
-
"seamless"
: Manual quality updates will be only visible after a little time. This gives the advantage of a very smooth “seamless” transition.In this mode, you will have the following behavior:
- there will be no visual “cut” between the previous and new quality
- parts of the content with a better (or the same) quality won’t be replaced.
- parts of the content with a lower quality will be only replaced when the better quality is downloaded.
-
"direct"
: Manual quality updates will be visible more directly, but with a complete reload of the current content. You might encounter a black screen while the player go through the"RELOADING"
state [1].In this mode, you will have the following behavior:
- there will be a black screen between the previous and new quality
- the previous content will be entirely removed
- you will only have content with the new quality
[1] More information about the
"RELOADING"
state can be found in the player states documentation.
lowLatencyMode
type: Boolean
defaults: false
Allow to play DASH low-latency contents (with Chunk-encoded and chunk-transferred CMAF segments) with a low latency efficiently.
In the some rare browsers who do not support the fetch
API (like IE11 or the
BlackBerry browser), we might be more prone to rebuffering in that mode the
first few seconds. If you want to have a better experience on those browsers,
you might want to begin to play further from the live edge in those cases
through the startAt
option.
More information on playing low-latency DASH contents can be found in the corresponding documentation page.
supplementaryTextTracks
type: Array.<Object>|Object|undefined
defaults: []
⚠️ This option is not available in DirectFile mode (see transport option).
This option allows to specify information about supplementary text tracks you might want to add to those already declared in the Manifest.
This only work under the following conditions:
-
the text track is not fragmented
-
the text track can be retrieved by fetching a single URL
-
the text track is in an understood format and enough information has been given to infer it.
Each of those can have the following properties:
const supplementaryTextTracks = [{
url: textTrackURL, // {string} The url on which the complete text track can be
// obtained
language: "eng", // {string} The language the text track is in
// (ISO 639-1, ISO 639-2 or ISO 639-3 language code)
// Note for SAMI subtitles:
// For SAMI subtitles, you have to provide the same language
// string than the one indicated in the CSS and p elements.
// It usually follows the ISO639-ISO3166 naming conventions
// (e.g. en-US or fr-FR).
// If we cannot find the provided language in the downloaded
// SAMI text track, it won't be displayed.
closedCaption: false // {Boolean} Whether the text track is a closed caption
// for the hard of hearing
mimeType: "application/mp4", // {string} A mimeType used to describe
// the text format. Can be "application/mp4" when
// encapsulated in an mp4 file. In that case, the
// "codecs" argument will be needed.
codecs: "stpp" // {string|undefined} Depending on the mimeType,
// you might need to add codec information.
// Here the mimeType is too generic, the codec
// helps us understand this is ttml in an mp4
// container
}];
To know which type of formats are supported and how to add them, you can read the text track documentation.
supplementaryImageTracks
type: Array.<Object>|Object|undefined
defaults: []
⚠️ This option is not available in DirectFile mode (see transport option).
This option allows to specify information about supplementary image tracks you might want to add to those already declared in the Manifest.
This only work under the following conditions:
-
the image track is not fragmented
-
the image track can be retrieved by fetching a single URL
-
the image track is in an understood format and enough information has been given to infer it.
Each of those can have the following properties:
const supplementaryImageTracks = [{
url: ImageTrackURL, // {string} The url on which the complete image track can
// be obtained
mimeType: "application/bif", // {string} A mimeType used to describe
// the image format.
}];
hideNativeSubtitle
type: Boolean
defaults: false
⚠️ This option is not available in DirectFile mode (see transport option).
If set to true
, the eventual
This has an effect only if:
-
the current
textTrackMode
is equal to"native"
(see textTrackMode option) -
a text track is currently active
-
the text track format is understood by the rx-player
networkConfig
type: Object
defaults: {}
⚠️ This option is not available in DirectFile mode (see transport option).
Configuration linked to Manifest and segment requests. This object can take the following properties (all are optional):
-
segmentRetry
(Number
): Maximum number of times a segment request will be retried when an error happen - only on some condition [1].Those retry will be done with a progressive delay, to avoid overloading a CDN. When this count is reached, the player will stop and throw a fatal error.
Defaults to
4
. -
manifestRetry
(Number
): Maximum number of times a Manifest request will be retried when a request error happen - only on some condition [1]. Defaults to4
.Those retry will be done with a progressive delay, to avoid overloading a CDN. When this count is reached, the player will stop and throw a fatal error.
Defaults to
4
. -
offlineRetry
(Number
): Maximum number of times a request will be retried when the request fails because the user is offline.Those retry will be done with a progressive delay, to avoid overloading the user’s ressources. When this count is reached, the player will stop and throw a fatal error.
Defaults to
Infinity
.
[1] To retry a request, one of the following condition should be met:
-
The request failed because of a
404
HTTP code -
The request failed because of an HTTP code in the
500
family -
The request failed because of a timeout
-
the request failed because of an unknown XHR error (might be a parsing/interface error)
defaultAudioTrack
⚠️ This option is deprecated, it will disappear in the next major
release v4.0.0
(see Deprecated APIs).
Please use the preferredAudioTracks
constructor
option or the
setPreferredAudioTracks
method
instead.
type: Object|string|undefined
The starting default audio track.
This can be under the form of an object with the following properties:
const defaultAudioTrack = {
language: "fra", // {string} The wanted language
// (ISO 639-1, ISO 639-2 or ISO 639-3 language code)
audioDescription: false // {Boolean} Whether the audio track should be an
// audio description for the visually impaired
};
or under the form of the language string directly, in which case the
"audioDescription"
option is inferred to be false.
// equivalent to the previous example
const defaultAudioTrack = "fra";
If the corresponding audio track is not found, the first track defined will be taken instead.
⚠️ This option is not available in DirectFile mode (see transport option).
defaultTextTrack
⚠️ This option is deprecated, it will disappear in the next major
release v4.0.0
(see Deprecated APIs).
Please use the preferredTextTracks
constructor
option or the
setPreferredTextTracks
method
instead.
type: Object|string|undefined
The starting default text track.
This can be under the form of an object with the following properties:
const defaultTextTrack = {
language: "fra", // {string} The wanted language
// (ISO 639-1, ISO 639-2 or ISO 639-3 language code)
closedCaption: false // {Boolean} Whether the text track should be a closed
// caption for the hard of hearing
};
or under the form of the language string directly, in which case the
"closedCaption"
option is inferred to be false:
// equivalent to the previous example
const defaultTextTrack = "fra";
If the corresponding text track is not found, the first track defined will be taken instead.
⚠️ This option is not available in DirectFile mode (see transport option).