JavaScript Player - Documentation¶
The Red Bee Media Managed OTT JavaScript Player is our playback client for web applications. It acts as a middle layer between your web application, the HTML5 video player APIs and the Red Bee Platform, so you don't have to focus on complicated and time consuming details like device compatibility, authentication, analytics and more.
Installation¶
We recommend installing the player using npm or yarn:
npm install @redbeemedia/javascript-player
or yarn add @redbeemedia/javascript-player
If you prefer using a CDN or downloading the files to be included in your project, you may include the files from the jsdelivr cdn or similar alternatives. Note that using this method, all exports is set on the redBeeMedia
object. So instead of just RedBeePlayer
you'll have to call redBeeMedia.RedBeePlayer
From jsdelivr
<script src="https://cdn.jsdelivr.net/npm/@redbeemedia/javascript-player@latest/dist/redbee-player.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@redbeemedia/javascript-player@latest/style.css">
Requirements¶
The player bundle targets modern browsers. To support all devices and browsers you may need to transpile the code as well as provide polyfills. The SWC platform is recommended, as it has tools for handling both using browserslist
, see supported browsers.
LG WebOS¶
The player requires the WebOSTV.js library needs to be loaded before playback.
Samsung Tizen¶
The player requires the WebAPI script to be loaded before playback.
The player requires the following privileges to be set
- http://developer.samsung.com/privilege/productinfo
- http://developer.samsung.com/privilege/drmplay
- http://developer.samsung.com/privilege/drminfo
Usage¶
The player comes with an easy to use default configuration, but can also be customized and tailored to very complex use cases, should you need to.
Getting Started¶
This example will cover most of your needs, and is a great base to start at.
Set up the wrapper element in which the player will render
<div id="video-wrapper"></div>
import { RedBeePlayer } from "@redbeemedia/javascript-player";
import "@redbeemedia/javascript-player/style.css";
const playerOptions = {
customer: "DemoCustomer",
businessUnit: "DemoBusinessUnit",
username: "MyEndUser",
password: "MyPassword123",
exposureBaseUrl: "", // Provided by Red Bee Media
wrapper: "div#video-wrapper",
assetId: "e720d1da-0915-411b-807c-3e83f451bbb7_29C72F",
}
const player = new RedBeePlayer({ player: playerOptions });
player.load()
.then(() => {
// player is loaded
})
.catch((e) => {
console.error(e);
});
The player emits useful events that you can listen to, such as when the player has loaded, the user pauses, changes the subtitle track and much more.
import { PlayerEvents } from "@redbeemedia/javascript-player";
// Log all events
player.addEventListener(PlayerEvents.ALL, (event, data) => {
const eventName = Object.keys(PlayerEvents).find((key) => PlayerEvents[key] === event);
console.log(`[Red Bee Player] ${eventName}`, data);
});
See (see events for more details.
Authentication¶
If you just need to get a sessionToken for other authorization required scenariros (such as personalized calls against the Exposure API) there is an exposed service to be used. The ExposureService
.
First, get an instance of the Exposure service set up.
import { ExposureService } from "@redbeemedia/javascript-player";
const exposureService = new ExposureService({
customer,
businessUnit,
exposureBaseUrl
});
Then authenticate to get the session token.
const { sessionToken, deviceId } = await exposureService.authenticate({
username,
password
});
If you want to create an anonymous session your can either call the authentication method without username and password
const { sessionToken, deviceId } = await exposureService.authenticate();
Or you can directly call the method authenticateAnonymous
const { sessionToken, deviceId } = await exposureService.authenticateAnonymous();
Available Options¶
There are four different option categories player
, skin
, analytics
and keyboard
. They are provided as separate objects when initializing the player.
new RedBeePlayer({
player: { /* player options here */}
skin: { /* skin options here */}
analytics: { /* analytics options here */}
keyboard: { /* keyboard options here */}
})
Player options¶
Required
customer
businessUnit
exposureBaseUrl
wrapper
One of
assetId
externalAssetId
, if configured to be used instead of the one from our platformsource
, third party streamplaylist
, a playlist of sources or assetIds in the following format[{ assetId: "<id here>", source: "<source here>"}]
see playlist
For playback from the Red Bee platform you will need either
sessionToken
or
username
password
If you initiate the player with a sessionToken
instead of credentials, you can choose to provide a deviceId
to align the analytics session with your definition of the user's device in other contexts of your application. This will otherwise be pulled from the token or auto generated.
If you initiate the player without credentials, nor sessionToken, the player will automatically try to do an anonymous login towards the platform.
Optional
autoplay
, defaulttrue
muted
, defaultfalse
preferredFormats
, default["hls", "dash"]
limitedMemory
, defaultfalse
ads
, defaultundefined
debug
, defaultfalse
, which rather log analytics into the console than sending it to the backend.locale
, the language to use for metadata when casting & for the browser MediaSession.castAppId
, defaults to the default unbranded RBM receiver.disableCast
, defaultfalse
disableAirPlay
, defaultfalse
playlist
, see playlistfullscreenElement
, the element that goes to fullscreen when pressing the fullscreen button, defaults towrapper
. Usable when you want to apply further elements in the full screen experience.audioOnly
, defaultfalse
, will play an audio stream without any video being played.poster
, image to be used when autoplay is blocked or during playback of audio only sources.maxResolution
. Use this to filter out specific variants. Note that this requires a backend configuration for your organization, reach out to your Red Bee representative for help.materialProfile
, Use this to play a specific material variant.metadataURIs
, For MPEG-DASH streams, this is a list with the EventStream schemeIdURIs. Use this to expose one or more timed metadata events when present.customShakaConfiguration
, see shaka api documentationcustomHlsJsConfiguration
, see hls.js api documentationcustomDashJSConfiguration
, see dash.js api documentation
Playlist¶
As of v0.16.0 we support playlists using the playlist
option.
This option expects an array of objects in the following format:
{
assetId?: string;
source?: string;
startTime?: number;
}
Once an item has finished playing, then the next item will start.
startTime
is supported as of v0.65.0. Earlier versions will always start at 0. In v0.65.0 and later if startTime
is not provided and the user previously played this asset, the player will continue where the user left off (aligning with the non-playlist behavior). This can be disabled by setting startTime
to 0 for all playlist items.
If both assetId
and source
is set, source will be used. If an assetId
or source
is provided to the load method as well, then this asset will be added to the start of the playlist.
Note
If the user is casting or airplaying, when the playback for an item finishes on the device, it will continue playing the next item in the browser.
Ads options
export interface IAdsOptions {
uid?: string;
latitude?: string;
longitude?: string;
mute?: boolean;
autoplay?: boolean;
consent?: string;
deviceMake?: string;
deviceType?: TAdDeviceType;
ifa?: string;
gdprOptin?: boolean;
width?: number;
height?: number;
pageUrl?: string;
domain?: string;
/**
* These custom parameters will be added to the querystring of the play request.
* e.g. ?customParam1=value1&customParam2=value2 etc
*/
[key: string]: any;
}
Skin Options¶
Our basic skin creates a great default experience for everything from VOD to Live and Channels. It also brings some functionality in terms of showing Metadata related to the ongoing asset as well as possibility to AirPlay or Cast your content to big screen.
If you want to use it there are some additional settings available to adjust its behavior.
Example
const redbeePlayer = new RedBeePlayer({
player: { ... },
skin: {
disabled: true
}
});
Available settings
disabled
, defaultfalse
. Set totrue
to disable the default skinhideControlsTimer
, default2500
. How many milliseconds until the skin hides when there's no activity.showMetadata
, defaulttrue
. Whether to show the image, title, duration and description for the ongoing asset.showQualitySelector
, defaulttrue
. Whether to show the quality selector or just go by auto quality selection.showJumpButtons
, defaulttrue
. Whether to show buttons that allows the end user to jump back and forth 30 seconds in the stream.showSubtitlesToggleButton
, defaultfalse
. Whether to show a subtitle toggle button. NOTE! This is not currently supported if you have multiple text tracks.allowPictureInPicture
, defaulttrue
.locale
, defaulten
.showWallClock
, to show wall clock rather than zero based when applicable data is available. Will default to the client's timezone.timeZone
, to have a set timezone for the wall clock timestamp to be shown. (The tz database name standard, e.g.Europe/London
)
Keyboard Shortcuts, keyboard
¶
Keyboard shortcuts to allow users to control the player using their keyboard.
These are the currently available shortcuts:
- Spacebar: Toggle play/pause
- Right Arrow: Forward 15 seconds
- Left arrow: Rewind 15 seconds
- m: Toggle mute/unmute
- f: Toggle fullscreen/window
Available settings
disabled
, defaultfalse
. Set totrue
to disable keyboard shortcuts.
Analytics, analytics
¶
Analytics will automatically connect to the Red Bee Platform to send Analytics according to the backend expectation enabling you as a customer to dive deep into the data of your end user's consumption behavior.
Available settings
disabled
, defaultfalse
. Set totrue
to disable analytics. NOTE! This is not recommended and should only be done if you understand the consequences.analyticsBaseUrl
, default set to the value ofexposureBaseUrl
set as player options. For some big events Red Bee will distribute a custom analytics base url for scaling purpose.appName
. To be used when you have multiple applications that will be reported to the same analytics bucket.
Methods¶
Note
Most of the player methods expects the player to be loaded (and not destroyed).
So ensure you either wait for the player.load()
promise, or listen to the PlayerEvents.LOADED
event (see events).
Load¶
The load method will discard the current media session (if any) and load a new one with the provided asset or source URL.
Options
assetId
orsource
(string
), an asset id or a url to a manifest or media url.manifest
({ start?: number, end?: number }
), optional start and end times (in seconds) to limit the stream to. The stream will align to segment boundaries. Note: This is available as ofv0.68.0
.startTime
(number
), optional time (in seconds) to start from. The player will continue where the user left off. If you do not want this, set this to 0. startTime is applied separate from the manifest start property (you can use both).
Example:
player.load({
assetId: "e720d1da-0915-411b-807c-3e83f451bbb7_29C72F",
manifest: { start: 6, end: 318 },
startTime: 0
});
Contextual data
getPlayerInfo
, fetches player engine and its versiongetSession
, fetches assetId, sessionToken, playSessionId, requestId etc. (see session object)getAssetInfo
, fetches the asset object for the currently playing assetgetContractRestrictions
, fetches the restrictions that might exist for timeshift etc (see contract restrictions object)getWrapperElement
, get the wrapper element in which the player is rendered. Any skin or overlay should probably be rendered into this wrapper element.getContainerElement
getVideoElement
getState
see state objectgetTimelineSpriteCues
see Timeline SpriteCues
Set data or trigger behavior
play
, starts playback-
pause
-
setMuted
true|false toggleMuted
toggleFullscreen
seekTo({ time?: number, change?: number }
, seek to either a specific time or a change back or forth in seconds.seekToOffset
, alias forseekTo
with changeseekToUTC(utcTime: number)
, seek to a time in UTC given in milliseconds since epochseekToLive
, alias forseekTo
with seekable end as time argumentsetPlaybackRate
setAudioTrack(track: ITrack)
setSubtitleTrack(track: ITrack)
setQualityLevel(level: IQualityLevel)
setVolume({ percentage }
set volume to a percentage between 0 and 100, this is not supported on iOS devices. See Apple Developer websitetogglePictureInPicture
toggleAirPlay
Get data or state
getSeekable
getCurrentTime
getVolume
getAudioTrack
getAudioTracks
getSubtitleTrack
getSubtitleTracks
-
getQualityLevels
-
isLive
isPlaying
isPictureInPictureSupported
, check if PiP is supported, currently works on later version of Chrome & SafariisPictureInPicture
isAirplaySupported
, check if AirPlay is supported, currently works on Safari.-
isAirplaying
-
isBrowserSupported
, might be used by your site to check whether this is a user that we will be able to officially support or not. -
destroy
, kill the player
Session Object¶
export interface IPlayerSession {
assetId?: string;
initOptions?: IPlayerCoreOptions;
sessionToken?: string;
playSessionId?: string;
requestId?: string;
playbackFormat?: FormatType;
playerEngine: IPlayerEngine;
cdnProvider?: string;
analyticsPostInterval?: number;
analyticsBucket?: number;
analyticsTag?: string;
}
Contract Restrictions Object¶
export interface IContractRestrictions {
airplayEnabled?: boolean;
ffEnabled?: boolean;
maxBitrate?: number;
maxResHeight?: number;
minBitrate?: number;
rwEnabled?: boolean;
timeshiftEnabled?: boolean;
}
State Object¶
interface IPlayerState extends IInternalPlayerState {
isCasting: boolean;
isCastAvailable: boolean;
isAirPlaying: boolean;
isAirPlayAvailable: boolean;
contractRestrictions?: ContractRestrictions;
contentMarkers?: MarkerPoint[];
}
interface IInternalPlayerState {
state: State;
contentType?: ContentType | null;
mediaType?: MediaType | null;
currentTime: number;
duration: number;
seekable: ISeekable;
utcCurrentTime: number;
utcDuration: number;
utcSeekable: ISeekable;
currentAd?: IAdDataRepresentation | null;
adMarkers?: IAdBlockMarker[];
contentMarkers?: MarkerPoint[];
volume: number;
subtitleTrack: ITrack | null;
subtitleTracks: ITrack[];
audioTrack: ITrack | null;
audioTracks: ITrack[];
qualityLevel: IQualityLevel;
qualityLevels: IQualityLevel[];
droppedFrames: number;
bufferingEvents: number;
hasStarted: boolean;
isMuted: boolean;
isLive: boolean;
isSeekable: boolean;
isAtLiveEdge: boolean;
}
enum State {
IDLE = "idle",
LOADING = "loading",
PLAYING = "playing",
PAUSED = "paused",
BUFFERING = "buffering",
SEEKING = "seeking",
ENDED = "ended",
ERROR = "error"
}
enum ContentType {
VOD = "vod",
LIVE = "live",
AD = "ad",
PODCAST = "podcast"
}
interface ISeekable {
start: number;
end: number;
}
interface IAdBlockMarker {
startTime: number;
duration: number;
watched: boolean;
}
interface ITrack {
id: string;
language: string;
label: string;
}
interface IQualityLevel {
id: number;
name?: string;
bandwidth?: number;
width?: number;
height?: number;
framerate?: number;
}
Timeline SpriteCues¶
The method getTimelineSpriteCues
is used to get an array of SpriteCues which are objects describing a sprite within a spritesheet that represents the playing content at a specific time.
This is used to in the included skin to show thumbnails above the progressbar when seeking.
The SpriteCue object looks like this
interface ISpriteCue {
image: string; // URL to the spritesheet image
start: number; // The first second on the timeline that this SpriteCue represents
end: number; // The last second on the timeline that this SpriteCue represents
dimensions: {
x: number; // The X coordinate in the spritesheet of the sprite, in px
y: number; // The Y coordinate in the spritesheet of the sprite, in px
width: number; // The width of the sprite, in px
height: number; // The height of the sprite, in px
};
}
The size of the sprites varies depending on content.
By default getTimelineSpriteCues
will look for Sprites that are as close as possible to a quarter of the width of the player, the most common size available is 160px wide.
Note
Only VOD assets have SpriteCues.
Events¶
To listen on events from the player you can add an event listener to the player instance, e.g
player.addEventListener(PlayerEvents.ALL, (event, data) => {
const eventName = Object.keys(PlayerEvents).find((key) => PlayerEvents[key] === event);
console.log(`[Red Bee Player] ${eventName}`, data);
});
If you want to add type information to the event handler you can use a type variable. Currently, you need to manually create the handlers. In the future these will be provided for you
player.addEventListener<(data: IPlayerState) => void>(
PlayerEvents.STATE_CHANGED,
(data) => {
// data will now have the type IPlayerState
}
);
available events when not casting
export enum PlayerEvents {
ALL = "*",
PLAY = "player:play",
PAUSE = "player:pause",
STOP = "player:stopped",
START = "player:start",
RESUME = "player:resume",
PLAYING = "player:playing",
SEEKING = "player:seeking",
SEEK_TIME_CHANGE = "player:seek_time_change",
SEEKED = "player:seeked",
TIME_UPDATE = "player:timeupdate",
ENDED = "player:ended",
VOLUME_CHANGE = "player:volumechange",
ERROR = "player:error",
LOADING = "player.loading",
LOADED = "player:loaded",
LOAD_START = "player:load_start",
BUFFERING = "player:buffering",
BUFFERED = "player:buffered",
ID3 = "player:id3",
BITRATE_CHANGED = "player:bitrate_changed",
CDN_CHANGED = "player:cdn_changed",
AUDIO_CHANGED = "player:audio_changed",
SUBTITLE_CHANGED = "player:subtitle_changed",
LICENSE_EXPIRED = "player:license_expired",
DROPPED_FRAMES = "player:dropped_frames",
DRM_UPDATE = "player:drm:update",
STATE_CHANGED = "player:state_changed",
PROGRAM_CHANGED = "player:program_changed",
NOT_ENTITLED = "player:not_entitled",
BLACKOUT = "player:blackout",
EMPTY_SLOT = "player:empty_slot",
CAST_START = "player:cast:start",
CAST_STOP = "player:cast:stop",
AIRPLAY_START = "player:airplay:start",
AIRPLAY_STOP = "player:airplay:stop",
AD_START = "player:ad:start",
AD_COMPLETE = "player:ad:complete",
ADBLOCK_START = "player:adblock:start",
ADBLOCK_COMPLETE = "player:adblock:complete",
INTRO_START = "player:intro:start",
INTRO_END = "player:intro:end",
CHAPTER_START = "player:chapter:start",
CHAPTER_END = "player:chapter:end",
MARKER = "player:marker",
METADATA_EVENT = "player:metadata_event",
SESSION_ACQUIRED = "player:session_acquired",
PLAYER_SETUP_COMPLETED = "player:setup_completed",
ENTITLEMENT_GRANTED = "player:entitlement_granted",
}
available events when casting
export enum PlayerEvents {
ALL = "*",
STATE_CHANGED = "player:state_changed",
PROGRAM_CHANGED = "player:program_changed",
CAST_START = "player:cast:start",
CAST_STOP = "player:cast:stop",
}
Timed metadata events¶
The player will emit a METADATA_EVENT
when a EXT-X-DATERANGE tag is encountered in the HLS manifest. Similarly, the player will emit a METADATA_EVENT
when a period with an EventStream schemeIdUri appears in the schema that matches the metadataURIs
that can be set in the Player options. Important to note is that if the metadataURIs
is set to an empty list, the player will emit all events that appear in the MPEG-DASH stream. if the metadataURIs
option is not set the player will not emit any METADATA_EVENT
events.
The event will have the following properties:
interface IMetadataEvent {
event: any; // The event
engineName: string; // The name of the player engine that generated the event
engineVersion?: string; // The version of the player engine that generated the event
}
Depending on the engine type the event will have different properties. The default behavior of the player is to prioritize the use of the MPEG-DASH stream when available over the HLS stream for non Safari browsers.
For HLS on non Safari browsers the event will be a list with the following properties:
engineName: "Hls.js"
engineVersion: "1.1.5"
event: [
"EXT-X-DATERANGE",
"ID=\"123456\",START-DATE=\"2022-08-30T12:31:55.040Z\",X-COM-DAICONNECT-TRACK=\"abc1234",
...
]
For HLS on Safari browsers the event object will have the following properties:
engineName: "Native HTML Video"
event: [
DataCue {
data: null,
value: {key: "X-COM-DAICONNECT-TRACK", data: "abc1234"},
type: "com.apple.quicktime.HLS",
}
...
]
For MPEG-DASH the event object will have the following properties: See: https://shaka-player-demo.appspot.com/docs/api/shaka.extern.html#.TimelineRegionInfo for more information.
engineName: "Shaka Player"
engineVersion: "v4.1.2"
event: {
endTime: 1661864509.842636
eventElement: Event, // The event with the tracking elements
schemeIdUri: "urn:daiconnect:dai:2019:xml",
startTime: 1661864509.842636,
timeStamp: 870455.3000000119,
type: "timelineregionenter",
seekable: {start: 1661863914.943625, end: 1661864514.943625},
utcCurrentTime: 1661864514572.273,
utcDuration: 1661864519445.625,
utcSeekable: {start: 1661863919445.625, end: 1661864519445.625},
...
}
Player Cue Points¶
The asset may contain an array of MarkerPoints
. Depending on the type of Marker, it gets treated differently:
A marker of type INTRO will trigger PlayerEvents
of either INTRO_START
or INTRO_END
.
The trigger PlayerEvents.INTRO_START
will, as part of the player, present a button inside the video element containing a skip icon and whatever title is given to the intro marker. This button give the user an option to skip the intro marker duration and seek to the endOffset
of the intro marker, if clicked.
Similarly, a marker of type CHAPTER will trigger PlayerEvents of either CHAPTER_START
or CHAPTER_END
. However, these events are not presented to the endusers as a button but are merely there as a convenience for third party skins to take action on.
If present, marker of type CHAPTER does however get listed in the Content Marker Menu, next to Settings, where if clicked will seek the user to the starttime, i.e. offset
of said Chapter. In this list, whatever title is given to the content marker is presented next to the time of the content marker offset
.
A marker of type POINT, does not have an endOffset
. These are simply a point of interest in time. i.e a goal in a fotball game. These markers are, similarly to markers of type CHAPTER, presented in the Content Marker Menu of the video element and, if clicked, will seek the user to that point in time. Whatever title is given to the content marker is presented next to the time of the content marker offset. Marker of type POINT triggers a PlayerEvent of type MARKER
so that third party skins can take action on it.
Lastly, a marker of type CREDITS does not, like POINT, hold an endOffset
. They are also simply a point of interest in time, but can be used to trigger events like "Push Next Content" or "Watch Next" suggestions. They are also available on PlayerEvents.Marker
but are not presented in the list of Content Markers in the Content Marker Menu.
On all PlayerEvents
, the actual content marker is available so that developers can do additional checks of type, offset etc.
enum MarkerType {
INTRO = "INTRO",
CREDITS = "CREDITS",
POINT = "POINT",
CHAPTER = "CHAPTER"
}
class MarkerPoint extends WithLocalized {
offset: number; //start point in millisecond
endOffset?: number; //end point in milliseconds, omitted in MarkerType "POINT" and "CREDITS"
type: MarkerType;
}
If you do not want to listen to the different PlayerEvents, or need the markers up front to show an index or mark on the timeline, all available content markers are exposed on playerState.contentMarkers
. If there are no content markers on the specific asset, playerState.contentMarkers will return an empty array.
As you may have multiple intros, for example one being recap and the other being the actual intro, a state of the active intro marker is exposed on metadata.activeIntro
. This will default to null if there is no active Intro at that point in time.
the skip intro button is visible for 2.5 times the time set for settings.hideControlsTimer
. If omitted, the button gets hidden after 7 seconds.
Chromecast¶
Chromecast support is enabled by default using the default unbranded RBM receiver.
Note
The player will include the Google Cast API library if needed, do not manually include that script on your site.
Custom skin¶
To implement chromecast support in your custom skin please use the google-cast-launcher
webcomponent, more information is available here.
If you want to build a custom cast button please contact your RBM representative.
Custom receiver¶
To build a custom receiver follow the instruction here
Subtitles¶
Do you want to customize the subtitle style? You can do this by overriding the CSS for the subtitle cues with .redbee-player-subtitle-cue
as of as of v0.65.0. We recommend not using an older player version than 0.65.0 for subtitle styling, but if you do, you can style cues with .redbee-player-subtitle-container span
.
Example CSS
.redbee-player-subtitle-cue {
background: rgba(0, 0, 0, 0.5);
border-radius: 0.5em;
padding: 0.5em;
}
The subtitle cue container element by default covers the whole screen. If you want to change that, then you can override the css for .redbee-player-subtitle-container
. Note that as of v0.65.0 the default RedBeePlayer skin will regularly try to set the margin-bottom
property of this container to avoid rendering over the subtitles.
Note
The WebVTT spec is a living standard, and therefore will have partial support in browsers and player engines. We try to work around this and support as much of the spec as we can, but it's not possible for us to support all subfeatures of styling and positioning for all engines and browsers.
Error handling¶
Error can thrown, and catched, either from the asynchronous initiation process or during playback.
The first one can be catched through a async await, e.g.
const player = new RedBeePlayer(options);
try {
await player.load();
// player is loaded
} catch (e) {
console.error(e);
}
or as a promise chain
const player = new RedBeePlayer(options);
player.load().catch((e) => {
console.error(e);
});
The latter can be catched on the error event mentioned above The data object in such scenario is structured in the following way
class PlayerError {
error: string;
code?: number;
originalError?: string;
message: string;
};
Where the error property will be a concatenation of error group and error type according to the pattern ErrorGroup [ErrorType]
from respective exported enums.
export enum ErrorGroups {
INIT = "INIT",
USER = "USER",
API = "API",
PLAYER = "PLAYER",
}
export enum ErrorTypes {
GENERIC = "generic",
OPTIONS = "init_options",
API_AUTH = "auth_failed",
API_AUTH_ANON = "auth_anon_failed",
API_PLAY_REQUEST = "play_request_failed",
API_ASSET = "asset_request_failed",
DRM = "drm_error",
NETWORK = "network_error",
STREAM_NOT_AVAILABLE = "stream_not_available",
STREAM_LIMIT = "stream_limit_reached",
NOT_AUTHENTICATED = "session_not_authenticated",
NOT_AUTHORIZED = "unauthorized",
GEO_LOCATION = "geolocation",
MANIFEST = "manifest_error",
SEGMENT = "segment_error",
MEDIA = "media_error",
CODEC = "codec",
PLAYER_ENGINE = "generic_playerengine_error",
UNSUPPORTED_DEVICE = "unsupported_device",
UNSUPPORTED_SCREEN = "unsupported_screen",
OTHER = "other_error",
}