# Livery Video Docs
> Livery offers a complete, end-to-end interactive live streaming solution.
---
# Portal
Source: https://docs.livery.live/video-portal.md
# Video
The Livery customers portal allows our customers to manage their streams. The portal comes with default settings, and if requested the Livery team is able to customize the setup according to the specific needs of the customer(s), making more features available.
The core video features are accessible via a direct API implementation. Allowing our customers to merge the Livery Video solution in their own platform. More information about the API implementation can be found in the [API section.](customer-video-api.md 'api-calls')
## Create a stream
Additional streams can be added via the “+Stream” button in the top right corner of the portal. The required information needs to be added in the panel.
| Field | Description |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Name | The stream "Name" is used as reference in the system. |
| Type | Determines if the stream will use the cloud or on-prem encoder.|
| Region | Optimises the stream settings according to the main region of the viewers. When a required region is not included, select the second best location and/or contact the Livery team for support.|
| Orientation | The Livery encoder has dedicated optimizations for landscape and portrait streams, which help to maximize the video quality delivered to viewers. |
| Video Quality | Livery works with 3 quality presets; Basic (1.0mbps 720p), Premium (1.0mbps 720p, 3.0mbps 1080p) and Ultra (1.0mbps 720p, 3.0mbps 1080p, 5.0mbps 1080p). The cost associated with a configuration can be found on [liveryvideo.com](https://www.liveryvideo.com/pricing/)|
### Stream Quality and ABR
The predefined video configurations in the Livery platform contain multiple video qualities to support ABR (Adaptive Bitrate). ABR is a technology used in Livery players that provides a smooth viewing experience by dynamically adjusting the video quality based on the user's available network bandwidth and device capabilities.
Due to the small video buffer associated with low-latency streams, Livery's ABR algorithm has to be fairly aggressive. The logic will switch to a lower quality when it detects a negative change in network conditions or when the buffer is draining. The players will start with the lowest or preferred video quality and move up when possible. This approach minimizes the time-to-first frame. The algorithm takes the segment size and position of the I-frames into consideration to determine the best possible moment to switch without stalling.
The Custom quality feature enables our customers to customize their own ABR configuration, without being limited to three preset qualities. With the custom configuration setting, our customers can configure a 4K stream with high bitrates ranging from 10-20 Mbps. However, it is important to note that a custom configuration will have an impact on the user-hour price, which Livery calculates based on the usage of its service.
## Stream Overview
All streams connected to the account are listed in the stream overview. The basic information is listed in the row of a stream. Additional information and settings can be found in the menu on the right side of the row.
The StreamID is used to link a stream to a player implementation. More information about the players and the integration of the player SDK’s can be found on [docs.livery.live](index.md 'Main page')
The ID of the linked encoders is visible in the row. The cloud encoder ID only shows while streaming. The on-prem encoders, when linked, are always visible. An on-prem encoder, when available, can be linked to a stream via the “Add Encoder to Stream” option in the stream menu.
The Livery Console shows information about a cloud stream. For example the ingest url (SRT or RTMP) can be copied and pasted in your streaming program (OBS/Wirecast/etc). Please see [Mixer Soft- and Hardware section](encoder.md 'Main page') for more info. Once you start streaming from there a cloud instance will be provisioned for your stream. This can take some time 20-30 seconds when no cloud available cloud encoders are active. Once the encoder is provisioned and streaming, a red bubble with the text Streaming will appear which indicates the stream is live.
When the ingest to the cloud encoder has been stopped, the cloud encoder shuts down.
The Livery platform knows 3 stream phases; Pre, Live and Post broadcast. The selected phase determines the behaviour of the integrated player.
| Phase | Description |
| ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Pre | The player does not actively check if the stream is active, the viewers will not see a loading indicator and no stream data is collected. The players will show the Pre-Stream-Poster Image when set. |
| Live | The player actively checks if a stream is active, the viewers might see a loading indicator when the player checks for the stream. The players collect stream data, when in the Live phase. The players will show the Live-Stream-Poster Image when set. |
| Post | The player does not actively check if the stream is active, the viewers will not see a loading indicator and no stream data is collected. The players will show the Post-Stream-Poster Image when set. |
The Stream Phases dropdown allows you to change the phase of the stream. Please contact the Livery team if you want to use the Stream Phase feature and the option is not listed in the portal.
?> A phase change takes about 20-60 seconds to become effective for all viewers.
## Encoder Overview
One or more encoders can be linked to a customer account. The encoders are listed in the encoder overview. Encoders can be linked or unlinked to a stream, this allows the customer to rotate a single on-prem encoder between multiple streams.
One or more Encoders can be linked to a stream to create a redundant setup. The proper role needs to be defined for each encoder. The Livery Platform works with 3 encoder roles.
| Role | Description |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| Main | The main encoder for the stream, the majority of users will be connected with the main encoder. |
| Backup | The backup encoder for the stream. When the player(s) detects a possible issue it will switch to the backup encoder. |
| Standby | The players will not connect to an encoder in “Standby”. It is important to prevent a situation where a standby encoders is linked to a stream. |
## Stream settings
The settings linked to a stream are managed in the stream settings. Any change in the stream settings are automatically picked up by the players. It might take up-to 60 seconds before a change becomes available for all viewers.
| Field | Description |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Name | The stream "Name" is used as reference in the system. |
| Target Latency | The Livery Platform adjusts glass-to-glass latency based on the set target latency. |
| Poster image | Each phase can have it's own poster image, shown when the stream loads or when no stream is active. The poster image can be set by uploading an image or adding an image URL. An image with the same ratio as the stream settings is recommended. |
| Interactive | The interactive URL load a HTML/JavaScript element in the interactive layer of the player. |
| Pre-roll | The preroll is a short video clip loaded before the player loads the live stream. A MPEG-4 video file with the following specifications is recommended: 15 seconds video clip, 1080p, 4Mbps video and 128Kbps audio. |
| Fit | The Fit value determines how the video object fits the container:
- Contain, The content is scaled to maintain its aspect ratio while fitting within the container.
- Cover, The content is sized to maintain its aspect ratio while filling the entire container.
- Fill, The content is sized to fill the container. The entire object will completely fill the container. |
| Domain Whitelisting | One or more domains can be whitelisted when domain whitelisting is enabled. Only players hosted on these domains will be able to watch the stream. If this field is empty, any player can watch the stream. |
| Player configuration | The player settings determine the availability of the different player functions. Each of the settings can be turned ON or OFF. The following settings are available;
- Unbranded, determines if the Livery branding is shown in the players.
- Casting determines if the Google Cast and Apple Airplay features are accessible to the end-user.
- Error determines if the errors are shown in the players.
- Fullscreen, determines if the fullscreen button is shown in the players.
- Mute determines if the mute/unmute button is shown in the players.
- Pip determines if the picture-in-picture mode is allowed.
- Quality determines if the quality selection is shown in the players.
- Autoplay determines if the video automatically starts when the player is loaded. It is not always possible to Autoplay unmuted, due to browser restrictions. |
## Encoder settings
The settings linked to one or more Encoders are managed in the encoder settings. The encoder settings determine how the incoming video is encoded and transcoded. A stream needs to be stopped before any of the encoder settings can be changed.
| Field | Description |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Video Quality | The Video quality can be set by selecting one or multiple video bitrates. The name of the bitrates contains the information about the configuration of the video quality. The players will use the ABR algorithm when multiple bitrates have been selected. |
| Audio Quality | The Audio quality can be set by selecting one audio bitrate. |
| Segment Size | Determines the size in seconds of the video segments. |
| Crop Method | The "Crop Method" determines how the encoder is allowed to crop the video content to meet the set resolution. This is especially used when the ingest is in landscape and the stream in portrait. When manual is selected an X/Y offset is to be entered, calculated for the top left corner. |
## Stream History
The stream history, which can be accessed via the top right menu, contains a list of all streaming moments. The overview contains a basic list with details to provide insights in each of the streaming moments. When a redundant setup with multiple encoders is configured, each encoder is listed as a separate streaming moment.
## Statistics Dashboard
The statistics dashboard contains an overview of basic statistics, which are updated every 60 seconds. A customer is able to see his statistics for the past 14 days. Please contact the Livery team for specific stats, which are not listed in the dashboard.
Besides the dashboard, customers can also access the statistics via an API integration. Please see the GetAnalytics section in the [API section](customer-video-api.md 'GetAnalytics') for more info.
# Revision History
| Version | Description |
| ------- | ----------------------------------- |
| 1.0.43 | - Map improvements stats dashboard. |
# Q&A
**How to link an on-prem Encoder to a different stream?**
_One or more on-prem encoders could be linked to a stream. To unlink an encoder from a stream you need to select “Remove Encoder” from the stream menu (accessible via the 3 dotted button on the right side of the stream). When the encoder is successfully removed the encoder ID is no longer listed in the Encoders column. You can now add the removed encoder to a different stream, by clicking “Add Encoder to stream” from the stream menu. You need to select the specific encoder from the dropdown menu. All encoders (linked or unlinked) are listed in the encoder overview tab._
**The player buttons are not visible?**
_The player buttons are controlled by the Management tool in the stream settings._
**I don't see the interactive elements on top of the video stream?**
_The interactive layer of the Livery video player loads the interactive URL. You can find the input field in the [Stream Settings](portals.md 'stream-settings') . It takes 10-60 seconds before the URL becomes active in the interactive layer._
_When the Livery Interactive powers the interactie layer, an URL similar to the following: ...interactive.livery.live, is set in the Interactive URL field of the stream settings. The interaction list/schedule can be managed via the Livery Interactive portal. The interactions only show when the broadcast is set to LIVE, in the Livery Interactive portal._
---
# Ingest
Source: https://docs.livery.live/video-ingest.md
# Livery Video Ingest
Video can be ingested via an encoder. Livery provides reliable encoder technology fully integrated in the Livery ecosystem. The Livery encoder is built from the ground up to provide the highest video quality with the lowest possible latency, all in perfect sync. Based on the needs and preferences, encoding can be handled an on-premise hardware encoder or our cloud encoder solution.
## Cloud encoder
### Input Signal
The Livery Cloud encoder is capable of receiving an input signal via RTMP or SRT. The URL that is used for the video ingest can be found in the Livery Portal under Stream Details. For more detailed instructions on configuring different tools, please refer to the Mixer Soft- and Hardware documentation. If your preferred streaming software is not included, please contact us for further assistance.
### Pass Through
In the context of video encoding, "pass-through" refers to a setting that allows a video source to be copied and passed through the encoder without any modifications. When a video encoder is set to "pass-through," it does not perform any video compression or encoding. Instead, it simply copies the input video and sends it through to the output without any modifications.
Pass Through can be enabled via the Encoder settings in the portal. It is important to know that when 'Pass Through' is enabled, the Livery encoder will no longer correct any incorrect ingest settings, increasing the importance of configuring the proper settings in your streaming tool. These settings should include:
- Disabling B-frames
- Enabling a fixed keyframe interval of 1 second
- Using the x264 codec
- Setting the rate control to CBR
- x264 Options "keyint=25 min-keyint=25 scenecut=0"
## On-prem encoder
The hardware encoder accepts a HDMI or SDI feed and uploads it to the CDN. The two most important benefits of this device over the cloud encoder are: The first is that the video only needs to be encoded once instead of twice. This means using the hardware encoder will result in better video quality. And the second is that the hardware encoder sends out metrics to our backend. This allows us to diagnose issues when they occur on the internet connection between the encoder and the CDN.
The hardware encoder needs to communicate over the internet so send out metrics and allow remote diagnosis. For this it’s required that the encoder can make outbound connections on port 443 and port 22. Please make sure to open up these 2 ports if the encoder is deployed in an environment with a firewall.
### Input signal
Livery provides hardware encoders with two types of input connectors. The input specifications for both encoders are as follows.
#### SDI
Integrated cable equalizer supporting cable lengths up to 230M for HD signals
Support for SD/HD/3Ga/3Gb/3Gb-DL/3Gb-DS standards
Support for RGB 444, YCbCr 444, YCbCr 422 color sampling
Support resolutions up to 1080P. Please contact us for information about higher resolutions on SDI.
Support for capture frame rates up to 144fps (Actual capture frame rate can be limited by the image resolution)
#### HDMI
- 297MHz HDMI receiver
- Adaptive HDMI equalizer
- Support for RGB/YUV 444 8-bit format signals with a pixel frequency of no more than 297MHz
- Support for YUV 422 12-bit format signals with a pixel frequency of no more than 297MHz
- Support for RGB/YUV 444 10/12-bit format signals with a pixel frequency of no more than 170MHz
- Support resolutions up to 4K (4096x2160).
- Support for capture frame rates up to 144fps (Actual capture frame rate can be limited by the image resolution)
There are some things to consider when using a hardware encoder in combination with video mixing software on a computer. The encoder will be assigned as an external monitor for the computer. The mixing software has to be setup in such a way that it outputs the video and audio to the external monitor.
## Multi audio output
Both Windows and Mac OS allow the play audio over multiple outputs at the same time, including audio received by a microphone.
On Windows this can be achieved by enabling “Stereo Mix” via the audio settings. Navigate to the audio icon in your system tray, right-click it, and select “Open Sound settings” and the “Sound Control Panel”.
Navigate to the “Recording” tab and make sure both “Show Disabled Devices” and “Show Disconnected Devices” options are checked. The “Stereo Mix” setting is now visible.
Right-click on “Stereo Mix” and click “Enable” to be able to use it and select “Properties”. In the “Listen” tab of the properties panel, the proper audio device can be selected.
On Mac OS this can be achieved by using the App "Audio MIDI Setup" in /Applications/Utilities. When opening the app, a list of all audio devices in the list to the left. With the "+" button at the bottom a new “Aggregate Device” or a “Multi-Output Device” can be added.
Check the required devices from the overview. The created device shows up as normal audio devices in the system preferences' "Sound" settings.
## Cropping
The livery encoder can crop the video that it is receiving before it encodes the video. This is useful when the video stream is used in a portrait mode app. If we would not crop the image the video player will receive the full landscape image and has to crop it in order to not show black bars above and below the video. While this will also work it means that a lot of the streamed pixels are discarded by the video player. This is a waste of bandwidth.
Cropping on the encoder works as follows. The encoder uses the output resolution aspect ratio to determine the size of the cropping area. We can provide a position from where to do the cropping. Usually this will be either at the complete left or exactly centered. This is an example for a portrait stream with a 9:16 aspect ratio. The input resolution is 1920x1080 and we have set the encoder to do centered cropping.
The yellow plane is the input image and the blue plane is the part of that image that the encoder will use. The encoder will use a plane of 603 pixels wide and 1072 pixels in height. It takes this weird nr of pixels to get a perfect aspect ratio of 9/16.
## Resolution and refresh rate
If a computer is used as the video source there are usually 2 places where we have to set the resolution and refresh rate. In order to achieve the best possible image quality these settings must match the encoder settings (or the other way around). The first place is the monitor settings and the second place is the mixing software settings. Let’s say we want to stream a landscape video in 16/9 format where the highest quality we want to stream is 1080P/30FPS. If possible the framerate should be 30FPS or exactly double the target framerate. So 60FPS in this case. On Windows we can change the display settings like this:
Make sure to also check the Advanced display settings to make sure Active signal resolution is set correctly.
On macOS open Displays to alter the settings. Use the Gather Windows button to see the settings window of both monitor outputs. For the 1080P/30FPS we could set it up like this:
## Network
It is recommended to use an internet connection which has at least twice the speed of the total bitrate that is going to be streamed as upload speed. For example if you have a 5Mbit and a 1Mbit video quality with a 96Kbit audio quality you would need an internet connection with an upload speed of at least 12.2Mbit. This extra internet speed is needed to be able to cope with fluctuations in the internet connection.
## Mixer Soft- and Hardware
A soft- and/or hardware mixer is often used to output one or more broadcast streams. All video sources are connected with the Mixer, from which the broadcast stream is ingested in either the Cloud or On-premis encoder.
The following overview contains an overview of the most common video mixing tools and the configuration needed live stream using Livery's cloud encoder. Please be aware of the additional requerement when Passthrough [Pass through](#pass-through)is used.
### OBS
?>
#### **RTMP**
| Menu | Item Property | Value |
| ------ | ----------------- | --------------------------------------------------------------------------------------------- |
| Stream | Service | Custom |
| | Server | rtmp://ingest.livery.live/live/app |
| | Stream Key | The Stream Key as shown under Stream Details in the Livery Portal |
| Output | Output Mode | Advanced |
| | Encoder | Hardware Encoding would be recommanded for low-end streaming devices |
| | Rate Control | CBR (Constant bit rate) |
| | Bitrate | A higher value than the max bitrate configured in the Livery Encoder settings |
| | Keyframe interval | The Keyframe interaval should not be set to 0. It is recommended to match the segment size set in the Livery Encoder settings (default is 1) |
| | CPU Usages Preset | Veryfast |
| | Tune | Zerolatency |
| Video | Output Resolution | Recommended resolution 1920x1080px |
| | Common FPS Values | It is strongly recommended to use the same FPS throughout the complete workflow, to prevent audio/video sync issues |
#### **SRT**
| Menu | Item Property | Value |
| ------ | ----------------- | ----------------------------------------------------------------------------------------------|
| Stream | Service | Custom |
| | Server | srt://ingest.livery.live:9998?pkt_size=131 |
| | Stream Key | The Stream Key as shown under Stream Details in the Livery Portal |
| Output | Output Mode | Advanced |
| | Encoder | Hardware Encoding would be recommanded for low-end streaming devices |
| | Rate Control | CBR (Constant bit rate) |
| | Bitrate | A higher value as the max bitrate configured in the Livery Encoder settings |
| | Keyframe interval | The Keyframe interaval should not be set to 0. It is recommended to match the segment size set in the Livery Encoder settings (default is 1) |
| | CPU Usages Preset | Veryfast |
| | Tune | Zerolatency |
| Video | Output Resolution | Recommended resolution 1920x1080px |
| | Common FPS Values | It is strongly recommended to use the same FPS throughout the complete workflow, to prevent audio/video sync issues |
#### **On-prem**
Assign the on-prem encoder as an external monitor of the computer. Set OBS to Studio Mode, and select the encoder as the “Fullscreen Projector”.
#### **Screenshots**
### vMixer
?>
#### **RTMP**
| Menu Item | Property | Value |
| ----------------- | ------------------ | ------------------------------------------------------------------------------------------------- |
| Destination | Service | Custom |
| | URL | rtmp://ingest.livery.live/live/app |
| | Stream Key | The Stream Key as shown under Stream Details in the Livery Portal |
| | Quality | Custom via the gear icon |
| Streaming Quality | Encode Size | Recommended resolution 1920x1080 |
| | Profile | Main |
| | Level | 3.1 |
| | Preset | Ultrafast |
| | Aspect Ratio/Crop | Original |
| | Keyframe Frequency | It is recommended to match the segment size set in the Livery Encoder settings (default is 1) |
| | Network Buffer | 5 Seconds |
| | Strict CBR | Checked |
### **On-prem**
| Destination | Service | Custom |
| ------------------------ | ----------------- | ---------------------------------------------------------------------------- |
| Windows Display settings | Multiple displays | Extend these displays |
| vMix Display settings | Output Size | Recommended resolution 1920x1080 |
| | Display | 2 (The display port used by the encoder) |
| vMix Main screen | Fullscreen | Press Fullscreen to start outputting the video to the selected display port |
### **Screenshots**
### Wirecast
?>
#### **RTMP**
| Menu | Item Property | Value |
| --------------- | ----------------- | --------------------------------------------------------------------------------------------- |
| Output Settings | Destination | RTMP Server |
| | Encoding | A higher value than the max bitrate configured in hte Livery encoder settgings |
| | Address | rtmp://ingest.livery.live/live/app |
| | Stream | The Stream Key as shown under Stream Details in the Livery Portal |
#### **SRT**
| Menu | Item Property | Value |
| --------------- | ----------------- | --------------------------------------------------------------------------------------------- |
| Output Settings | Destination | SRT: Secure Reliable Transport |
| | Encoding | A higher value than the max bitrate configured in hte Livery encoder settgings |
| | Address | srt://ingest.livery.live |
| | Stream ID | The Stream Key as shown under Stream Details in the Livery Portal |
#### **Screenshots**
### StreamYard
?>
?> A Professional Streamyard account is required to make the required changes to stream using the Livery platform.
?> SRT is not supported
#### **RTMP**
| Menu Item | Property | Value |
| ----------- | ----------------- | ------------------------------------------------------------------ |
| Destination | Service | Custom |
| | RTMP Server URL | rtmp://ingest.livery.live/app |
| | Stream Key | The Stream Key as shown under Stream Details in the Livery Portal |
| Settings | Broadcast Quality | Recommended resolution 1080p |
#### **Screenshots**
### Streamaxia (iOS and Android SDK)
?>
?> SRT is not supported
?> On-Prem is not supported
#### **RTMP**
| Menu Item | Property | Value |
| --------- | --------------------- | ----------------------------------------------------------------------------- |
| Settings | Server URL | rtmp://ingest.livery.live/live/app |
| | Server Authentication | Add the Stream Key as it is listed under Stream Details in the Livery Portal |
| | Resolution | Recommended resolution 1920x1080 |
#### **Screenshots**
### Softvelum (iOS and Android SDK)
?>
?> On-Prem is not supported
#### **RTMP**
| Menu Item | Property | Value |
| ----------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Destination | URL | rtmp://ingest.livery.live/live/app |
| | Stream Key | Add the Stream Key as it is listed under Stream Details in the Livery Portal to the ingest URL. For example rtmp://ingest.livery.live/live/app/12345 |
| | Resolution | Recommended resolution 1920x1080 |
| | Keyframe frequency | The Keyframe interaval should not be set to 0. It is recommended to match the segment size set in the Livery Encoder settings (default is 1) |
| | Codec | H264 |
#### **SRT**
| Menu Item | Property | Value |
| ----------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Destination | URL | Larix requires the ingest URL and stream key to be separated. The stream ID should as well as the 'pkt_size=1316&streamid=' be removed from the Ingest URL srt://ingest.livery.live:9998 |
| | Stream Key | Add the Stream Key as it is listed under Stream Details in the Livery Portal. If the stream does not contain a Stream Key, the last part of the URL, the stream ID, can be added as Stream Key; 12a34b56c78d90e |
| | Resolution | Recommended resolution 1920x1080 |
| | Keyframe frequency | 2 seconds |
| | Codec | H264 |
#### **Screenshots**
### LiveU
?>
?> Go to to change any settings
#### **RTMP**
Select a custom RTMP source
| Menu Item | Property | Value |
| ----------- | ---------- | ----------------------------------------------------------------------------------|
| Destination | URL | rtmp://ingest.livery.live/live/app |
| | Stream Key | The Stream Key as shown under Stream Details in the Livery Portal |
#### **Screenshots**
### Magewell Ultra Stream
?>
#### **RTMP**
Select a custom RTMP source
| Menu Item | Property | Value |
| ---------------- | ----------------- | --------------------------------------------------------------------------------- |
| Streaming Server | URL | rtmp://ingest.livery.live/live/app |
| | Stream Key | The Stream Key as shown under Stream Details in the Livery Portal |
| | Keyframe Interval | The Keyframe interaval should not be set to 0. It is recommended to match the segment size set in the Livery Encoder settings (default is 1) |
| | Codec type | H264 |
#### **Screenshots**
### Magewell Ultra Encode
?>
#### **RTMP**
Select a custom RTMP source
| Menu Item | Property | Value |
| --------------------- | ----------------- | -----------------------------------------------------------------------------|
| Streaming Server | URL | rtmp://ingest.livery.live/live/app |
| | Stream Key | The Stream Key as shown under Stream Details in the Livery Portal |
| Encodering Parameters | Keyframe Interval | The Keyframe interaval should not be set to 0. It is recommended to match the segment size set in the Livery Encoder settings (default is 1) |
| | Codec type | H264 |
#### **SRT**
Select a custom Caller source
| Menu Item | Property | Value |
| --------------------- | ------------------ | ----------------------------------------------------------------------------|
| Streaming Server | address | srt://ingest.livery.live |
| | Port | 9998 |
| | Latency | 30ms (as low as possible) |
| | Stream ID | The Stream Key as shown under Stream Details in the Livery Portal |
| Encodering Parameters | Keyframe frequency | The Keyframe interaval should not be set to 0. It is recommended to match the segment size set in the Livery Encoder settings (default is 1) |
| | Codec | H264 |
#### **Screenshots**
### Teradek Vidiu
?>
#### **RTMP**
Select a custom RTMP source
| Menu Item | Property | Value |
| --------- | ---------------------- | --------------------------------------------------------------------------------- |
| Broadcast | Mode | RTMP/RTMPS |
| | CRTMP/RTMPS Server URL | rtmp://ingest.livery.live/live/app |
| | Stream | The Stream Key as shown under Stream Details in the Livery Portal |
#### **Screenshots**
### Black Magic Web Presenter
?>
?> The stream settings need to be set via the XML. The following generator can be used to create the proper XML file.
#### **RTMP**
Open the Back Magic Presenter Setup app on your desktop and select Livery as a RTMP destination. It is also possible to select the Livery RTMP destination directly from the device.
| Menu Item | Property | |
| ----------- | ------------ | ------------------------------------------------------------------------------------- |
| Live Stream | Video Output | Select a standard that matches the stream quality or higher. Recommanded 1080p 25fps |
| | Platform | Select the Livery platform as specified in the XML |
| | Server | Select the Livery stream as specified in the XML |
| | Key | Add the Stream Key as it is listed under Stream Details in the Livery Portal |
#### **Screenshots**
## Revision History
| Version | Description |
| ---------- | -------------------------------------------------------------------------------- |
| 2023-03-13 | Added SRT streamKey information |
| 2022-12-28 | Ingest info added for Black Magic Web Presenter |
| 2022-01-21 | Ingest info added for LiveU, Magewell Ultra & Teradek Vidiu |
| 2021-04-30 | Secure ingest
Use audio delay setting from the backend |
| 2021-02-18 | Added the ability to automatically update the encoder from the Management Portal |
## Q&A
**I see the video but I'm not able to get audio via the output of the computer?**
_Make sure the audio is sent along with the video single via the HDMI or SDI cable. This can be achieved via the audio output settings._
**I can hear the audio in the stream, but I’m no longer able to hear the audio via my studio headphone/speakers.**
Configure the audio settings, so the audio is played on both audio outputs. See Multi Audio output for more information.
**The cloud encoder keeps on restarting.**
_Make sure a 1080p video is ingested via the RTMP or SRT URL._
**The stream is unstable or the video buffer is low.**
_Check your internet connection; make sure the upload speed is double the combined total of the different qualities and you don't have any package loss.
If possible set the encoder/mixer to “Zero Latency” in the encoder settings._
**I want to ingest in 4k to the cloud encoder (3840x2160px).**
_Please contact the Livery team to make the additional changes._
**How long does it take for a cloud stream to stop?**
Every minute the system checks if a stream is still active.
If no data has been received for a minute the stream will be stopped.
This means that a stream will stop somewhere between 1 and 2 minutes after the RTMP/SRT signal has stopped.
---
# Android SDK
Source: https://docs.livery.live/android-sdk.md
# Livery Video Android SDK
[](android-sdk-changelog.md)
More information can be found at: [liveryvideo.com](https://liveryvideo.com).
## Installation
### Compatibility
Livery Android SDK is compatible with Android 6.0 (API level 23) or higher.
### Configure Gradle
From version 2.0.0 onwards Livery SDK is published via [jitpack.io](https://jitpack.io).
To install Livery SDK into your project, follow these steps below.
#### Resolve Repositories
For new projects created with Android Studio Arctic Fox 2020.3.1 go to settings.gradle and add:
```groovy
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
.....
maven {
url "https://jitpack.io"
credentials { username authToken }
}
}
}
```
For existing projects go to your project level build.gradle file, add these closures to **allprojects** > **repositories**.
```groovy
allprojects {
repositories {
//...
google()
jcenter()
maven {
url 'https://jitpack.io'
credentials { username '' }
}
}
}
```
To retrieve your access token log into with your GitHub account and go to .
Your GitHub account has to be granted access to the packages.
If you are unable to access the packages please ask your support contact to grant you access.
#### Add Implementations
Add these implementations inside **dependencies** to your app-level build.gradle.
```groovy
dependencies {
//...
implementation "com.liveryvideo:livery-sdk-android:4.5.0"
//...
}
```
#### Set Java Version of Project
Then add this compileOptions inside **android** closure on your app level build.gradle, like shown below.
```groovy
android {
//...
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
```
## Usage
For basic usage of the SDK following minimal steps are needed:
### Configure SDK streamId
Add `livery_stream_id` to your strings and pass the streamId as the value.
```xml
insert_stream_id_here
```
The `LiverySDK` will initialize itself using the string resource `livery_stream_id` when the application starts.
It is possible to know the LiverySDK State by calling:
```java
LiverySDK.State state = LiverySDK.getInstance().getState();
```
### Add LiveryPlayerView
Add the player view into the layout that your activity or fragment is using.
Please note that **keepScreenOn** attribute is optional and it defines whether
screen can turn off after an amount of time or not.
```xml
```
Due to the Cast feature the Player's Activity Theme needs to have a `colorPrimary` defined without opacity.
### Setup LiveryPlayerView
Bind LiveryPlayerView to your layout file, then call `createPlayer` to setup the LiveryPlayerView.
```java
LiveryPlayerView playerView;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
playerView = view.findViewById(R.id.liveryPlayer);
playerView.createPlayer();
}
```
The player might not be initializaed right after `createPlayer` call. For example, it may be defer to after `LiverySDK`
initialization finishes. [LiveryPlayerView.CreatePlayerListener and LiveryPlayerView.CreatePlayerErrorListener](#createplayer-feedback)
provide more information if the player was initialized or there was an error during initialization.
### Register in a LifecycleOwner
`LiveryPlayerView` implements `DefaultLifecycleObserver` and is must be registered in a `LifecycleOwner`, for example when using a `Fragment`:
```java
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
...
LiveryPlayerView playerView = view.findViewById(R.id.livery_player_view);
getLifecycle().addObserver(playerView);
...
}
```
#### 🎉 Done
Congratulations! You have implemented Livery SDK successfully.
To have more control over Livery SDK, next sections should provide you more knowledge.
## Advanced configuration
### Manual SDK Configuration
Defining the `streamId` via the resource string `livery_stream_id` as it is in [Configure SDK streamId](#configure-sdk-streamid)
automatically initializes the SDK when the application starts.
It is possible defer this initialization to a later point by doing it manually by defining the boolean
resource `livery_sdk_auto_init` with `false` instead of `livery_stream_id`:
```xml
false
```
and then use the `LiverySDK.initialize` method that allows to define a desied `streamId` and to have some feedback
about the SDK initization process:
```java
String streamId = ...
LiverySDK.getInstance().initialize(streamId, new LiverySDK.StateListener() {
@Override
public void stateChanged(LiverySDK.State state) {
}
@Override
public Lifecycle getListenerLifecycle() {
return getLifecycle();
}
});
```
When choosing the manual initialization neither LiverySDK nor LiveryPlayerView will automatically retry to initialize in
case or errors. Error handling and retry needs to be done manually.
```java
void initializeSdk(String streamId) {
LiverySDK.getInstance().initialize(streamId, new LiverySDK.StateListener() {
@Override
public void stateChanged(LiverySDK.State state) {
if (LiverySDK.State.INITIALIZED.equals(state)) {
// continue
} else {
// handle error
Exception error = state.error;
// retry
requireView().post(() -> initializeSdk(streamId));
}
}
@Override
public Lifecycle getListenerLifecycle() {
return getLifecycle();
}
});
}
```
LiveryPlayerView `createPlayer` should only be called after LiverySDK is initialized, otherwise this method will fail.
### Configure LiveryPlayerView
#### CreatePlayer feedback
It is possible to have more control of the LiveryPlayerView initialization. There are 2 interfaces in
`LiveryPlayerView` that allow to know when the player was configured or if there was an error during configuration:
```java
LiveryPlayerView playerView = ...
playerView.createPlayer(new LiveryPlayerView.CreatePlayerListener() {
@Override
public void finished() {
}
}, new LiveryPlayerView.CreatePlayerErrorListener() {
@Override
public void onError(Exception error) {
}
});
```
#### LiveryPlayerView options
The LiveryPlayerView can be configured with either remote or local configurations. When local configurations are set
they will override the corresponding remote configurations.
```java
LiveryPlayerView playerView = ...
LiveryPlayerOptions playerOptions = new LiveryPlayerOptions.Builder()
.setAutoPlay(true)
.setAudioOnly(true)
.setResizeMode(LiveryResizeMode.DEFAULT)
.setPrePoster("prePoster url")
.setPoster("poster url")
.setPostPoster("postPoster url")
.setAkamaiLongToken("akamai_token")
.build();
playerView.createPlayer(playerOptions);
// or
playerView.createPlayer(playerOptions, this::onPlayerCreated, this::onCreatePlayerError);
```
#### LiveryPlayerView controls options
The LiveryPlayerView controls can also be configured with either remote or local configurations. When local configurations are set
```java
LiveryPlayerView playerView = ...
LiveryControlsOptions controlsOptions = new LiveryControlsOptions.Builder()
.showFullscreen(true)
.showMute(true)
.showQuality(true)
.showPlay(true)
.showScrubber(true)
.showCast(true)
.showError(true)
.build();
playerView.setControlsOptions(controlsOptions);
```
## SDK Methods
> To access the SDK class, ‘LiverySDK’ should be used.
### SDK Instance
In order to call some methods, instance of the SDK must be used.
You can get the instance with the line below:
```java
LiverySDK.getInstance();
```
### Livery Endpoint ID
In some cases, getting the endpoint ID can be useful to look at user specific analytics. To do so, here is how to get the endpoint ID:
```java
String endpointId = LiverySDK.getInstance().getEndpointId();
```
## Player Methods
> To access these methods, use the reference to your LiveryPlayerView from your fragment or activity.
### Create Player
By calling `createPlayer()` on LiveryPlayerView reference, a player instance will be created and initialized.
### Current Time
#### Get Current playback time since the stream has started
```java
long currentTime = playerView.getCurrentTime();
```
### Duration
#### Get the duration of the stream. For Live streams returns the duration since the start of the stream
```java
long duration = playerView.getDuration();
```
### Mute/Unmute
#### Set Muted/Unmuted State
```java
boolean shouldMute = true;
playerView.setMuted(shouldMute);
```
#### Get Muted/Unmuted State
```java
boolean isMuted = playerView.isMuted();
```
### Latency
#### Set Target Latency
```java
int targetLatencyInMilliseconds = 5000;
playerView.setTargetLatency(targetLatencyInMilliseconds);
```
#### Get Target Latency
```java
long currentLatency = playerView.getLatency();
```
### Media Quality
#### Get Available Qualities
```java
List qualities = playerView.getQualities();
```
#### Get Active Quality
```java
LiveryQuality activeQuality = playerView.getActiveQuality();
```
#### Set Quality
```java
playerView.setQuality(liveryQuality.qualityId);
```
When you want to set quality to **automatic** mode or **audio-only** mode,
you need to make a call with a specific id that does not return in getQuality method.
For that, you can use the methods below.
```java
//Sets the quality automatically for the rest of the media,
//until a quality id is specified.
playerView.setQuality(LiveryQuality.AUTO_ID);
//Sets the quality to audio only.
playerView.setQuality(LiveryQuality.AUDIO_ONLY_ID);
```
### Audio Only Mode
Audio Only mode can be enabled when creating the player via `LiveryPlayerOptions`:
```java
LiveryPlayerView playerView = ...
LiveryPlayerOptions playerOptions = new LiveryPlayerOptions.Builder()
...
.setAudioOnly(true)
...
.build();
playerView.createPlayer(playerOptions);
```
### Akamai long token
Defines a access token to use to be able to see a stream that uses Akamai’s Token Auth feature.
```java
playerView.setAkamaiLongToken("akamai_token");
```
### Debug Mode
#### Set Debug Mode Status
This will create an info dialog on the top right corner of the player and output all logs of SDK.
```java
boolean isDebugMode = true;
playerView.setDebugModeEnabled(isDebugMode);
```
#### Get Debug Mode Status
```java
boolean isDebugModeEnabled = playerView.isDebugModeEnabled();
```
## Classes
### LiverySDK State
LiverySDK.State is used to provide LiverySDK state feedback either with [automatic initalization](#configure-sdk-streamid)
or [manual initialization](#manual-sdk-configuration).
LiverySDK.State can be one of 3 values:
- `LiverySDK.State.NOT_INITIALIZED`
- `LiverySDK.State.INITIALIZED`
- `LiverySDK.State.ERROR` where you can access the inner Exception via `LiverySDK.State.error` member.
### Player Options
LiveryPlayerOptions has these properties listed on the table below. These options take effect only after [createPlayer](#liveryplayerview-options) is called.
Each of these properties can be defined individually via LiveryPlayerOptions.Builder.
class **_LiveryPlayerOptions_**
| Name | Type | Default | Description |
| ----------------- | --------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `autoPlay` | `Boolean` | `true` | Determines whether video shall play immediately after [createPlayer](#create-player). |
| `setAudioOnly` | `Boolean` | `false` | Determines whether is enabled or not. |
| `fit` | `LiveryResizeMode` | `CONTAIN` | Provides access to LiveryResizeMode. Video size inside the player view can be changed from here. |
| `prePoster` | `String` | null | Represents URL to poster image. When this property is not empty, the player will show a poster on creation. |
| `poster` | `String` | null | Represents URL to poster image. When this property is not empty, the player will show a poster on creation. |
| `postPoster` | `String` | null | Represents URL to poster image. When this property is not empty, the player will show a poster on creation. |
| `akamaiLongToken` | `String` | null | Access token to use to be able to see a stream that uses Akamai’s Token Auth feature. |
| `sources` | `String` or `Array` | None | Defines the sources URLs. |
### Player Resize Mode
Player resize mode is passed on [Player Options](#player-options) to indicate video size.
enum **_LiveryResizeMode_**
| Name | Description |
| --------- | ----------------------------------------------------------------------------------------------------------------- |
| `CONTAIN` | Shows the full video in the view box no matter what, without breaking the aspect ratio. |
| `COVER` | Fills the view box, however, zooms the video if video dimensions are too big for the view. Keep the aspect ratio. |
| `FILL` | Fits the video into the view box, by ignoring aspect ratio rules. |
### Player Controls
You can edit LiveryControlsOptions from controls property of LiveryPlayerOptions.
Each of these properties can be defined individually via LiveryControlsOptions.Builder.
Available controls are listed on the table below.
class **_LiveryControlsOptions_**
| Name | Type | Default | Description |
| ------------ | --------- | ------- | --------------------------------------------- |
| `fullscreen` | `Boolean` | `false` | Sets the visibility of the fullscreen button. |
| `mute` | `Boolean` | `false` | Sets the visibility of the mute button. |
| `quality` | `Boolean` | `false` | Sets the visibility of the quality button. |
| `play` | `Boolean` | `false` | Sets the visibility of the play button. |
| `scrubber` | `Boolean` | `false` | Sets the visibility of the scrubber button. |
| `contact` | `Boolean` | `false` | Sets the visibility of the contact button. |
| `cast` | `Boolean` | `false` | Sets the visibility of the cast button. |
| `error` | `Boolean` | `false` | Sets the visibility of the error overlay. |
### Player Events
It might be important in some cases to receive player events and process the data for your needs. In order to receive player events, a LiveryPlayerListener must be registered to the player.
class **_LiveryPlayerListener_**
| Name | Description |
| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `onActiveQualityChanged(@NonNull LiveryQuality quality, boolean auto)` | Called when the active quality of the media being played has changed. |
| `onPlayerError(Exception e)` | Called when the player encounters an error. |
| `onPlayerStateChanged(@NonNull LiveryPlayerState playerState)` | Called when the playback state of the player has changed. |
| `onProgressChanged(long buffer, long latency)` | Called in short intervals while playing, buffer and latency values in milliseconds can be actively retrieved from here. |
| `onQualitiesChanged(@NonNull List qualities)` | Called when available qualities of media have changed. |
| `onPlaybackRateChanged(float rate)` | Called when the playback rate of current media has changed. |
| `onRecovered()` | Called when an error is recovered. |
| `onTimeUpdate(long currentTime)` | Called when the current time of media has changed. |
| `onSourceChanged(@NonNull String source)` | Called when the media source URL of the player has changed. |
#### Registering Player Event Listener
By calling `registerListener(LiveryPlayerListener)` method on LiveryPlayerView, a player event listener can be registered.
```java
playerView.registerListener(new LiveryPlayerListener() {
//...
});
```
### Player Media Quality
class **_LiveryQuality_**
| Name | Type | Description |
| ----------- | --------- | ------------------------------- |
| `bitrate` | `Integer` | Bitrate of the quality. |
| `codecs` | `String` | Codec of the media. |
| `frameRate` | `Float` | Frame rate of the media. |
| `height` | `Integer` | Height of the media. |
| `label` | `String` | Human readable name of quality. |
| `qualityId` | `String` | ID of quality. |
| `width` | `Integer` | Width of the media. |
## Handle Orientation Changes
There are situations when you need to handle screen orientation changes so that the player won’t re-initialize after changing orientation. To prevent it, add this line to the manifest in the activity scopes which you want to handle orientation changes.
```xml
```
## Interactive Bridge
It is possible to interact with LiveryPlayerView and the Interactive Layer using the [Interactive Bridge](/interactive-bridge).
The interactive URL can be defined with:
```java
LiveryPlayerView playerView = ...
String url = ...
playerView.setInteractiveUrl(url);
```
Besides the [methods](/interactive-bridge?id=methods) already definied on the Interactive Bridge to get values like the player **latency**, **quality**, etc. you can authenticate and get and send custom messages.
Any messages sent from the interactive layer through the bridge will be received on the player side via `LiveryInteractiveBridgeListener`.
```java
playerView.setInteractiveListener(new LiveryInteractiveBridgeListener() {
@Override
public void onAuthError(String error) {
}
@Override
public void onCustomMessage(@NonNull String name, @Nullable Object arg, @Nullable LiveryInteractiveBridge.CustomCommandResultCallback callback) {
}
});
```
**Note**: The LiveryPlayerView `setInteractiveBridgeCustomCommandListener` and `LiveryInteractiveBridge.CustomCommandListener` are marked as deprecated and will be removed in future versions. Please use `LiveryInteractiveBridgeListener` instead.
### Authentication
- It is possible to authenticate either with a `token` or with a map of `claims`:
```java
playerView.setInteractiveAuth("token");
```
or
```java
playerView.setInteractiveAuth(Collections.singletonMap("sub", "userId"));
```
- As well as clear any previous authentication.
```java
playerView.clearInteractiveAuth();
```
Any authentication errors will be received via `LiveryInteractiveBridgeListener.onAuthError` method.
### Custom commands
From the Android LiveryPlayerView it is possible to send and receive custom command to/from the interactive layer.
A custom command with a specific `name` and `argument` can be sent with the `sendInteractiveBridgeCustomCommand` method:
```java
String name = ...
Object argument = ...
playerView.sendInteractiveBridgeCustomCommand(name, argument, new LiveryInteractiveBridge.CustomCommandResponseCallback() {
@Override
public void result(@Nullable Object response, @Nullable String error) {
}
});
```
To receive callbacks from the interactive layer use the `LiveryInteractiveBridgeListener.onCustomMessage`.
The commands are received on `onCustomMessage` with the `name`, `argument` and a `callback`
that allows to sent back to the interactive layer a result Object:
```java
playerView.setInteractiveListener(new LiveryInteractiveBridgeListener() {
@Override
public void onAuthError(String error) {
}
@Override
public void onCustomMessage(@NonNull String name, @Nullable Object arg, @Nullable LiveryInteractiveBridge.CustomCommandResultCallback callback) {
...
Object result = ...
callback.result(result);
}
});
```
## Sentry Integration
Livery uses Sentry for error reporting. In order to setup sentry.io with the correct DNS LiverySDK forces its initialization to manual
by setting `false` to [io.sentry.auto-init](https://docs.sentry.io/platforms/android/configuration/manual-init/) meta-data key.
Sentry can be used in the host application along side with LiverySDK Sentry integration.
To prevent LiverySDK from using static methods define `livery_sentry_use_static_methods` resource boolean variable to false:
```xml
false
```
To enable sentry.io auto initialization please add the following to the Application AndroidManifest.xml
```xml
```
Sentry usage by LIverySDK can be disabled by setting `livery_enable_sentry` resource boolean variable to false, default is true:
```xml
false
```
## Migration Guide
#### [Migration from 3.2 to 4.0](/android-migration-4#migration-from-32-to-40)
---
# iOS SDK
Source: https://docs.livery.live/ios-sdk.md
# Livery Video iOS SDK
[](ios-sdk-changelog.md)
Livery Video iOS SDK, published via CocoaPods and Swift Package Manager. For CocoaPods see [livery-sdk-ios-podspec](https://github.com/liveryvideo/livery-sdk-ios-podspec) and for Swift Package Manager see [livery-sdk-ios-spm](https://github.com/liveryvideo/livery-sdk-ios-spm).
Documentation can be found at: [docs.livery.live/ios-sdk](ios-sdk.md).
More information can be found at: [liveryvideo.com](https://liveryvideo.com).
## Installation
### Compatibility
The Livery iOS SDK is compatible with iOS 14 or higher.
### Configuration
To install Livery SDK into your project, follow these steps below.
You should request credentials from Livery, then place them in your ~/.netrc as follows: (create if necessary)
```
machine sdk-ios-binaries.livery.live
login YOUR_USERNAME
password YOUR_PASSWORD
```
#### About Livery and its dependencies
Livery uses Sentry, Kronos, Lottie and GoogleCast SDKs as dependencies.
Sentry, Kronos and Lottie are linked dynamically in the CocoaPods xcframework and statically in the Swift Package Manager xcframework.
However GoogleCast is linked statically, along with its dependency Protobuf. This has to be with the fact that GoogleCast SDK is not available via Swift Package Manager and the only oficial way to use it is via CocoaPods using Google's static xcframework.
If your application uses one of Sentry, Kronos or Lottie we advise to use the CocoaPods installation method to avoid duplicated symbols issues.
Livery and its dependencies such as Sentry, Kronos are Lottie are built with `BUILD_LIBRARY_FOR_DISTRIBUTION=YES` flag and if you are using coocapods please enabled this flag to this dependencies as well, see [CocoaPods](#cocoapods).
#### CocoaPods
[CocoaPods](https://cocoapods.org/) is a dependency manager for Swift and Objective-C Cocoa projects. You can install it with the following command:
```
$ gem install cocoapods
```
To integrate Livery SDK into your Xcode project using CocoaPods, specify it in your Podfile, as follows:
```ruby
source 'https://cdn.cocoapods.org/'
source 'https://github.com/liveryvideo/livery-sdk-ios-podspec.git'
target 'MyProject' do
pod "Livery", "3.4.0"
end
```
Please also add the following to your Podfile to enable the `BUILD_LIBRARY_FOR_DISTRIBUTION` flag for Sentry, Kronos and Lottie:
```ruby
post_install do |installer|
installer.generated_projects.each do |project|
project.targets.each do |target|
if ['Kronos', 'lottie-ios', 'Sentry'].include? target.name
target.build_configurations.each do |config|
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end
end
end
```
Then run
```
$ pod install
```
**Note:** you may need to run `pod install --repo-update` to update the cocoapods repository.
#### Swift Package Manager
Swift Package Manager is distributed with Xcode. To add the Livery SDK to your iOS project, do as follows:
1. Open your project in Xcode and select File > Add Packages
2. Enter the URL for the Swift Package Manager Livery SDK repo () into the search bar and click "Add Package"
3. Then on the Dependency Rule menu select the "Exact Version" - 3.1.0 or "Branch" - main to have the latest release
## Usage
The `LiveryPlayerView` can be created either manually in code or by using Interface Builder. In both cases, the `LiverySDK.initialize()` method needs to be called before calling `LiveryPlayerView.createPlayer()`.
The following code snippet shows the minimal steps to start a stream with the Livery iOS SDK:
```swift
import Livery
let playerView: LiveryPlayerView
func start(streamId: String = "yourStreamId") async {
// 1. Initialize the SDK
// (See LiverySDK initialize() method below for more options)
do {
try await LiverySDK.initialize(streamId: streamId)
} catch {
// deal with the initialization error here
return
}
// 2. Create a player object
// (See LiveryPlayerView createPlayer() method below for a full list of supported options)
do {
try playerView.createPlayer()
} catch {
// deal with the initialization error here
return
}
// 3. The player is now ready to play
playerView.play()
}
```
At this point, the player will fetch the DASH manifest, start rendering by automatically synching to the targetLatency set in the remote config or the LiveryPlayerOptions (3 seconds default).
For more information about options, properties and methods please see relevant sections below.
For a sample application code utilizing these minimal steps see the LiveryExample sample application section.
The player can be stopped by calling the `stop()` method:
```swift
playerView.stop()
```
## Livery SDK
### Methods
| Name | Returns | Description |
| --------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
| `initialize(streamId, configType, completionQueue, completion)` | `void` | Livery SDK initialization method. |
| `initialize(completionQueue, completion)` | `void` | Livery SDK initialization method that uses `LIVERY_STREAM_ID` and `LIVERY_CONFIG_TYPE` values from your app's Info.plist. |
| `initialize(streamId, configType) async throws` | `void` | Livery SDK async initialization method. |
| `initialize() async throws` | `void` | Livery SDK async initialization method that uses `LIVERY_STREAM_ID` and `LIVERY_CONFIG_TYPE` values from your app's Info.plist. |
### SDK Initialize
The SDK `initialize()` method must be called before calling `LiveryPlayerView.createPlayer()`.
```swift
LiverySDK.initialize(
streamId: String,
configType: String = LiverySDK.defaultConfigType,
completionQueue: DispatchQueue = .main,
completion: (LiveryErrors) -> Void
)
// or
try await LiverySDK.initialize(
streamId: String,
configType: String = LiverySDK.defaultConfigType
)
```
It is also possible to define `LIVERY_STREAM_ID` and `LIVERY_CONFIG_TYPE` in your's app `Info.plist` file and use `LiverySDK.initialize()` without passing the `streamId` parameter.
```swift
LiverySDK.initialize(
completionQueue: DispatchQueue = .main,
completion: (LiveryErrors) -> Void
)
// or
try await LiverySDK.initialize()
```
----
The `streamId` is used to determine the remote configuration url and is fetched from it. If the remote configuration fails to be fetched the SDK will fail to initialize.
The `configType` defines the type of the remote configuration that would be requested. The `LiverySDK.defaultConfigType` is `IOS`.
The `completionQueue` defines the `DispatchQueue` in which the `completion` callback is called.
The `completion` callback is a block that receives a `LiveryErrors?` with the SDK initialization eror in case of any.
#### SDK Initialization Errors
```swift
enum LiveryErrors: LocalizedError {
case sdkNotInitialized
case invalidStreamId
case invalidURL
case invalidServerTime
case downloadError(_ error: Error)
case missingData
case missingConfig
case invalidConfig(_ error: Error)
case notEnoughSpace
}
```
### SDK Properties
| Name | Type | Default | Description |
| -------------------------------------- | ---------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------ |
| `sdkVersion` | `String` | | A getter to retrieve the SDK version. |
| `disableSentry` | `Bool` | `false` | A Bool which disabled `SentrySDK` usage. |
| `disableSentryStaticMethodsUsage` | `Bool` | `false` | A Bool which disabled `SentrySDK` static methos usage. A SentryHub is still created. |
| `audioSessionSettings` | [`LivertAudioSessionSettings`](#audio-session) | `LivertAudioSessionSettings()` | Property to store the `AVAudioSession` settings. |
| `minimumDeviceSpace` | `Int` | `20000000` | Minimum device space in bytes required for the SDK to work properly. |
| `endpointId` | `String` | | A getter to retrieve the endpoint ID. |
#### disableSentry
By default Livery will use the `SentrySDK` to track events, handled errors and crashes.
This integration can be disabled by setting this property to **true**.
This property needs to be set before calling the `initialize()` method.
#### disableSentryStaticMethodsUsage
By default Livery will use the `SentrySDK` to track events, handled errors and crashes.
**Warning**: If your application uses Sentry too you can disable Livery's Sentry usage by setting this property to **true**.
If set to **true** Livery will setup a custom `SentryHub` object that will only track events and handled errors.
This will not override your Sentry configuration.
#### audioSessionSettings
Property used to configure `AVAudioSession` by `LiverySDK` in its initialization process.
Default settings are:
```swift
category = .playback
mode = .spokenAudio
options = []
```
**Important:**
If `audioSessionSettings` is **nil** `LiverySDK` won't setup `AVAudioSession` and your application is responsible to call `AVAudioSession.sharedInstance().setCategory`.
`LiverySDK.audioSessionSettings` can be set after the `LiverySDK.initialize()` method is called, however `LiverySDK.audioSessionSettings` has no effect on `AVAudioSession` is set to **nil**.
If your application wants to play another audio, besides the one from the live stream, without stopping the live stream, you should set the `options` property to `[.mixWithOthers]`, as below:
```swift
LiverySDK.audioSessionSettings?.options = [.mixWithOthers]
```
#### Livery endpoint ID
In some cases, getting the endpoint ID can be useful to look at user specific analytics. To do so, here is how to get the endpoint ID:
```swift
let endpointId = LiverySDK.endpointId
```
## LiveryPlayerView
`LiveryPlayerView` is a `UIView` subclass that can be used to play a stream and can be placed in the view hierarchy.
It is possible to customize which controls are visible either via Remote Configuration or by calling [`LiveryPlayerView.setControlsOptions(controlsOptions:)`](#controls-options).
### Create Player
| Name | Description |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `createPlayer()` | Create a Livery internal Player. This method can receive specified options if you need to override the remote configurations. |
The LiveryPlayerView `createPlayer()` method must be called after calling `LiverySDK.initialize()`.
```swift
let playerView = LiveryPlayerView()
....
/* Create the player */
let options = LiveryPlayerOptions()
try playerView.createPlayer(with: options)
```
If you need to override the remote configurations of the player you can call `createPlayer(options: LiveryPlayerOptions)` with a `LiveryPlayerOptions` object.
For more information about [`LiveryPlayerOptions`](#player-options) properties please see the corresponding section.
### Player Options
These are the `LiveryPlayerOptions` to be passed to when creating the LiveryPlayerView [internal player](#create-player):
| Name | Type | Default | Description |
| ------------------------ | -------------------------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `akamaiLongToken` | `String` | `nil` | Access token to use to be able to see a stream that uses Akamai’s Token Auth feature |
| `autoplay` | `Bool` | `false` | Determines whether video shall play immediately after [`createPlayer`](#create-player). |
| `enablePictureInPicture` | `Bool` | `false` | Determines whether the Picture in Picture feature should be enabled or not. It is available only on iOS 15 or higher. |
| `fit` | [`LiveryPlayerFit`](#livery-player-fit)| `.contain` | Determines how the video will be scaled and cropped. See: [`LiveryPlayerFit`](#livery-player-fit) |
| `prePoster` | `String` | `nil` | URL for an image to be shown when in PRE streamPhase. |
| `poster` | `String` | `nil` | URL for an image to be shown while the video is loading. |
| `postPoster` | `String` | `nil` | URL for an image to be shown while in POST streamPhase. |
| `sources` | `String[]` | `[]` | Array of media source URLs from which the first that can be played will be selected. |
| `targetLatency` | `Integer` | `3` | Target live latency in seconds. If 0 then syncing is disabled. |
| `audioOnly` | `Bool` | `false` | Enabled [Audio Only Mode](#audio-only-mode). |
### Controls Options
These are the `LiveryControlsOptions` properties to control the controls visibility:
| Name | Type | Default | Description |
| ------------ | ------ | ------- | -------------------------------------------------------------------------------------------------------------------|
| `play` | `Bool` | `false` | Determines whether play button should be displayed or not. |
| `quality` | `Bool` | `false` | Determines whether select quality button should be displayed or not. |
| `scrubber` | `Bool` | `false` | Determines whether scrubber / progress bar view should be displayed or not. |
| `error` | `Bool` | `false` | Determines whether Error Overlay should be displayed or not. |
| `fullscreen` | `Bool` | `false` | Determines whether full screen button should be displayed or not. |
| `mute` | `Bool` | `false` | Determines whether mute button should be displayed or not. |
| `pip` | `Bool` | `false` | Determines whether Picture in Picture button should be displayed or not. It is available only on iOS 15 or higher. |
| `contact` | `Bool` | `false` | Determines whether contact button should be displayed or not. |
| `cast` | `Bool` | `false` | Determines whether cast button should be displayed or not. |
### Properties :id=player-properties
The following properties are exposed by LiveryPlayerView:
| Name | Type | Write | Description |
| --------------------------- | ----------------------------------------------------------------------------------------------- | ----- | ------------------------------------------------------------------------------------------------- |
| `activeQuality` | [`LiveryQuality`](#player-media-quality) | No | Active Media Quality. Emits: `activeQualityDidChange` |
| `akamaiLongToken` | `String` | Yes | Defines an access token to use to be able to see a stream that uses Akamai’s Token Auth feature |
| `buffer` | `Int64` | No | Size of buffer, ahead of current position, in milliseconds. Emits: `progressDidChange` |
| `currentSource` | `URL` | No | Current media source. Emits: `sourceDidChange` URL. |
| `currentTime` | `Int64` | No | Current playback time position in milliseconds. Emits: `timeDidUpdate` |
| `delegate` | [`LiveryPlayerDelegate`](#player-events) | Yes | Protocol to implement to get player events |
| `error` | `Error` | No | Most recent unrecovered error. Emits: `playerDidFail`, `playerDidRecover` |
| `interactiveBridgeDelegate` | [`LiveryInteractiveBridgeCustomCommandDelegate`](#liveryinteractivebridgecustomcommanddelegate) | Yes | Protocol to implement to get custom messages from the interactive layer |
| `interactiveURL` | `URL` | Yes | The interactive layer URL |
| `latency` | `Int64` | No | End to end latency in milliseconds. Emits: `progressDidChange` |
| `muted` | `Bool` | Yes | If true then audio is muted. Emits: `volumeDidChange`. |
| `playbackState` | [`LiveryPlaybackState`](#player-types) | No | Playback state: .none / .buffering / .playing / .paused / .ended Emits: `playbackStateDidChange`. |
| `qualities` | `[LiveryQuality]` | No | Array of Available Media Qualities. Emits: `qualitiesChange`. |
| `selectedQuality` | [`LiveryQuality`](#player-media-quality) | Yes | Selected Media Quality. Emits: `selectedQualityDidChange` |
| `timeOffset` | `Int64` | No | Local device time offset in milliseconds. |
**Note**: LiveryPlayerView properties are optional and will return `nil` if called before `createPlayer`.
### Methods :id=player-methods
The following methods are exposed by LiveryPlayerView:
| Name | Description |
| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `play()` | Start/resume media playback. |
| `pause()` | Pause media |
| `stop()` | Stop media playback. |
| `reload()` | Reloads the player by stopping it, selecting the best available source and start playing again. |
| `sendInteractiveBridgeCustomCommand(name:arg:completionHandler:)` | Sends a custom message to the interactive bridge. |
### Events :id=player-events
It might be important in some cases to receive player events and process the data for your needs.
In order to receive player events, the LiveryPlayerDelegate can be implemented.
All methods have an empty default implementation so only the ones desired need to be implemented.
```swift
public protocol LiveryPlayerDelegate: class {
// Emitted when activeQuality has changed.
// Auto is 'true' when it was changed through the ABR and 'false' when it was changed manually
func activeQualityDidChange(activeQuality: LiveryQuality?, auto: Bool)
// Emitted when playbackState has changed
func playbackStateDidChange(playbackState: LiveryPlaybackState)
// Emitted when an error occurs
func playerDidFail(error: Error)
// Emitted when player has recovered from an error
func playerDidRecover()
// Emitted periodically to inform of progress downloading the media
func progressDidChange(buffer: Int64, latency: Int64)
// Emitted when qualities have changed
func qualitiesDidChange(qualities: [LiveryQuality])
// Emitted when currentSource has changed
func sourceDidChange(currentSource: URL?)
// Emitted periodically to inform of current playback time changing
func timeDidUpdate(currentTime: Int64)
// Emitted when volume or muted has changed
func volumeDidChange()
}
```
To implement the `LiveryPlayerDelegate` you should do as follows:
```swift
playerView.delegate = // your class that implements the LiveryPlayerDelegate protocol
```
See [Livery iOS SDK Example App](#example-app) to see how playback state change events are received via the `LiveryPlayerDelegate` implementation.
## Types :id=player-types
```swift
enum LiveryPlaybackState : String {
case none = ""
case buffering = "Buffering"
case playing = "Playing"
case paused = "Paused"
case ended = "Ended"
}
```
### LiveryQuality :id=player-media-quality
```swift
struct LiveryQuality {
let qualityId: String
let label: String
let shortLabel: String
let bitrate: UInt32
let width: UInt32
let height: UInt32
let codecs: String
let frameRate: Float
}
```
| Name | Type | Description |
| ----------- | -------- | ----------------------------------------------- |
| `qualityId` | `String` | ID of quality. |
| `label` | `String` | Human readable name of quality. |
| `shortLabel` | `String` | Human readable shortname of quality: SD/HD/UHD. |
| `bitrate` | `UInt32` | Bitrate of the quality. |
| `width` | `UInt32` | Width of the media. |
| `height` | `UInt32` | Height of the media. |
| `codecs` | `String` | Codec of the media. |
| `frameRate` | `Float` | Frame rate of the media. |
### LiveryPlayerFit :id=livery-player-fit
The SDK provides fitting methods to scale and crop the video according to the specified fit option value.
```swift
public enum LiveryPlayerFit {
case contain
case cover
case fill
case scaledown
}
```
| Name | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `.contain` | The video will be scaled to fit in the view while maintaining the aspect ratio.(equivalent to `swift videoGravity = .resizeAspect`) |
| `.cover` | The video will be scaled to fill the entire view while maintaining the aspect ratio. If the object's aspect ratio does not match the aspect ratio of its box, then the object will be cropped to fit. (equivalent to `swift videoGravity = .resizeAspectFill`) |
| `.fill` | The video will be scaled to fill the entire view. The aspect ratio is ignored so the video will be stretched to the size of the view.(equivalent to `swift videoGravity = .resize` ) |
| `.scaledown` | Same as .contain for now |
## Playback Synchronization
The player will receive the millisecond precision server time from the time urls (Default is ) and start the Audio and Video decoder clocks timebase as
`currentTime - targetLatency`
In other words, IOS SDK players behave always in sync once initialized, meaning if audio packages or video frames are received later then their presentation timestamps due the network connections, they will be ignored or played back in a faster rate by the player.
## Audio Session
class **_AudioSessionSettings_**
| Name | Type | Default | Description |
| ---------- | -------------------------------- | ------------- | ---------------------------------------------------------------------------------- |
| `category` | `AVAudioSession.Category` | `playback` | Audio session category identifiers. |
| `mode` | `AVAudioSession.Mode` | `spokenAudio` | An object that communicates to the system how you intend to use audio in your app. |
| `options` | `AVAudioSession.CategoryOptions` | `[]` | Constants that specify optional audio behaviors. |
## Audio Only Mode
When you want users to not watch the video but hear it you can allow them to select audio-only mode.
To enable Audio Only mode you need to set the `audioOnly` property to `true` on [`PlayerOptions`](#player-options). With this option enabled a new "Audio Only" quality appears on quality list and ABR will switch to Audio Only when the network conditions are not good enough to play the video.
## Cast
Our SDK is able to cast to AirPlay and Google Chromecast.
### Google Chromecast
**Note:** Google Chromecast does not have support for Swift Package Manager or the simulator on the M1, so as a consequence, Livery SDK does not include Google Chromecast in any of those cases.
To cast to Google Chromecast you need to add two items in your app's `Info.plist`:
- Add `NSBonjourServices`
Specify `NSBonjourServices`, like is shown below, in your `Info.plist` to allow local network discovery to succeed.
```
NSBonjourServices
_googlecast._tcp
_93EB8FEA._googlecast._tcp
```
- Add `NSLocalNetworkUsageDescription`
We recommend that you customize the message shown in the Local Network prompt by adding an app-specific permission string in your app's `Info.plist` file for the `NSLocalNetworkUsageDescription`, as show below.
```
NSLocalNetworkUsageDescription
${PRODUCT_NAME} uses the local network to discover Cast-enabled devices on your WiFi network.
```
This message will appear as part of the iOS Local Network Access dialog when the user taps on the cast button.
## Interactive Bridge
On the interactive layer you can use the [Interactive Bridge](/interactive-bridge) to communicate with the Livery Player. Please see the [Interactive Bridge](/interactive-bridge) documentation for more details on how to use it on the interactive layer side.
Besides the [methods](/interactive-bridge?id=methods) already definied on the Interactive Bridge to get values like the player **latency**, device **orientation**, etc. you can authenticate and get and send custom messages.
Any messages sent from the interactive layer through the bridge will be received on the player side by implementing the `LiveryInteractiveBridgeDelegate` protocol.
```swift
playerView.interactiveDelegate = self
```
**Note**: The LiveryPlayerView `interactiveBridgeDelegate` and the protocol `LiveryInteractiveBridgeCustomCommandDelegate` are marked as deprecated and will be removed in future versions. Please implement the `LiveryInteractiveBridgeDelegate` protocol instead.
### Authentication
- It is possible to authenticate either with a `token` or with a list of `claims`:
```swift
playerView.setInteractiveAuth(token: "token")
```
or
```swift
playerView.setInteractiveAuth(claims: ["sub": "userId"])
```
- As well as clear any previous authentication.
```swift
playerView.clearInteractiveAuth()
```
Any authentication errors will be received on the protocol `LiveryInteractiveBridgeDelegate` method `interactiveBridgeAuthError`.
### Custom Messages
- To **SEND** custom messages you should call:
```swift
playerView.sendInteractiveBridgeCustomCommand(name: String, arg: Any?, completionHandler: @escaping (LiveryInteractiveBridgeCustomCommandResult) -> Void)
```
Those messages will be send to the interactive layer through the bridge. To get them on the interactive layer side you should first call the `registerCustomCommand(name, handler)` with the `name` matching the one used on the player. Please see Interactive Bridge [methods](/interactive-bridge?id=methods) section for more details.
```swift
public enum LiveryInteractiveBridgeCustomCommandResult {
case success(value: Any?)
case failure(error: String)
}
```
- To **GET** and **RESPONSE** to custom messages you should implement the `LiveryInteractiveBridgeDelegate` protocol method `interactiveBridgeCustomMessage`.
#### LiveryInteractiveBridgeDelegate
```swift
public protocol LiveryInteractiveBridgeDelegate: class {
func interactiveBridgeAuthError(_ error: String)
func interactiveBridgeCustomMessage(message name: String, arg: Any?, completionHandler: @escaping (_ value: Any?) -> Void)
}
```
Any authentication errors will be received on the `interactiveBridgeAuthError` method.
In the `interactiveBridgeCustomMessage` method you will get the custom messages you sent through the bridge on the interactive layer. You can use the name and the arg paramenters to better recognize the message itself and act on it by calling the `completionHandler` with a value that will be send back to the interactive layer.
## Picture in Picture
Please note that this feature is only available on iOS 15 or higher.
To enable the Picture in Picture feature you need to set the `enablePictureInPicture` property to `true` on [`PlayerOptions`](#player-options) and enable the “Audio, AirPlay, and Picture in Picture” option under background modes in Xcode.
The simplest way to configure it is by selecting your app’s target in Xcode and select the Signing & Capabilities tab. Under the Capabilities tab, add the Background Modes capability and select the “Audio, AirPlay, and Picture in Picture” option under its list of background modes, as exemplified on the image below:
## Migration Guide
#### [Migration from 1.4.1 to 2.0.0](/ios-migration-guide-2#migration-from-141-to-200)
#### [Migration from 2.1.0 to 3.0.0](/ios-migration-guide-3#migration-from-210-to-300)
## Example App
Example iOS application which demonstrates how to use the Livery iOS SDK.
You can find it on the following git repositories:
- Cocoapods: [Livery iOS Example App](https://github.com/liveryvideo/player-ios-example-cocoapods)
- Swift Package Manager: [Livery iOS Example App](https://github.com/liveryvideo/player-ios-example-spm)
Notes:
- Built using XCode 15.1 (15C65) (Swift 5.9)
### How to run the app
1. Clone this repo
2. Go to the repo directory on the terminal and run `pod install`
3. Open **livery-sdk-ios-example.xcworkspace**
4. You will need to change the **Bundle Identifier** and the **Team** to your own team in order to build and run the app
5. Run the project on selected device or simulator
## Q&A
---
# Web Player
Source: https://docs.livery.live/web-player.md
# Livery Video Web Player
[](https://www.npmjs.com/package/@liveryvideo/player)
[](/npm/player/CHANGELOG)
[](/npm/player/dist/)
[](https://lit.dev/)
[](https://cdn.jsdelivr.net/npm/@liveryvideo/player/LICENSE)
Livery video player for use in web browsers.
?> Links: [Product demo](https://liveryvideo.com/demo), [Test page](https://test.livery.live/)
Please refer to the [Livery Video Portal](video-portal.md) for stream configuration options.
## Basic Usage
If you're not bundling your own JS you can just use an HTML snippet like this:
```html
```
?> Replace the player version and stream id by your own, see: [CDN](#cdn), [HTML](#html) and [CSS](#css) for details below.
?> If this does not work you can fall back to embedding the player in an iframe instead, see: [Livery Video Embed](embed.md).
## Support
This package exports two bundles.
The ES `module` bundle is targetted at modern browsers and tools supporting `ES2022` since v7.20.0 (`ES2019` before that).
The UMD `main` bundle (as used by jsdelivr [CDN](#cdn)) supports the last 2 major versions of: Chrome, Safari, Edge, Firefox, Android Chrome, iOS Safari and Samsung Internet.
## Installation
### CDN
The player can be loaded from [jsdelivr](https://jsdelivr.com):
```html
```
?> Replace the version (`x.y.z`) above by the player version that you wish to use. E.g: update to latest stable release periodically. Please see the [CHANGELOG](/npm/player/CHANGELOG) for details.
### NPM
Or the player can be installed using NPM:
```bash
npm install @liveryvideo/player
```
And then loaded in your JavaScript and bundled as you like:
```js
import '@liveryvideo/player';
```
## Usage
### HTML
```html
```
?> Replace the Livery Demo stream id (`6613d164e4b0bf3ad645f3c6`) above by your own.
Please see the [LiveryPlayer](/npm/player/dist/classes/LiveryPlayer) API documentation for additional attributes etc.
### CSS
The livery-player element is displayed as a `block`, i.e: using the full width available by default.
If no height is specified it will use the video aspect ratio (default `16:9`) to determine the height intrinsically.
Alternatively you can specify the size extrinsically, to prevent it from changing as the stream is loaded, e.g:
```css
livery-player {
height: 50vh;
}
```
See also: [MDN Sizing items in CSS](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS)
When you use a fixed height like this the video contents of the player will be fitted inside the available space based on the `Fit` mode configured in the Livery Portal for this stream (e.g: `CONTAIN` or `COVER` or ..).
See also: [MDN object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit)
## [API](/npm/player/dist/)
Detailed documentation of the exported API is generated and included in the NPM package and can be viewed here: [API](/npm/player/dist/)
## [CHANGELOG](/npm/player/CHANGELOG)
A detailed changelog of the package is generated and included in the NPM package and can be viewed here: [CHANGELOG](/npm/player/CHANGELOG)
## Guides
### Frictionless Login
To have the interactive layer authenticate you can change the [LiveryPlayer interactiveAuth property](/npm/player/dist/classes/LiveryPlayer?id=interactiveauth) to a JWT token `string` or claims `object` value. Inversely you can change it to an `undefined` value to have the interactive layer logout.
When this is used the interactive layer should specify a callback to the [InteractiveBridge option](/npm/interactive-bridge/dist/classes/InteractiveBridge?id=parameters) `{ handleAuth }`. That will then be called with the value of the `LiveryPlayer` `interactiveAuth` property whenever that changes. And in turn should take care of corresponding authentication within the interactive layer.
### Custom Controls
The default player controls can be disabled by changing the [LiveryPlayer controlsDisabled attribute](/npm/player/dist/classes/LiveryPlayer?id=controlsdisabled) to `true` or by specifying [InteractiveBridge option](/npm/interactive-bridge/dist/classes/InteractiveBridge?id=parameters) `{ controlsDisabled: true }`.
You can subsequently implement custom controls using the [LiveryPlayer](/npm/player/dist/) or [InteractiveBridge](/npm/interactive-bridge/dist/) API.
General guidelines based on the `LiveryPlayer` API (the `InteractiveBridge` API is similar):
- Wait for loading to finish (e.g: for `config` to be defined)
- Only show playback controls when video is available (i.e: `config?.streamPhase === 'LIVE'`)
- Only use supported `features`
- Respect which `config?.controls` are enabled and disabled
- Show controls when active and hide them again after a timeout of around 1.8s
- Besides actively using controls (e.g: showing quality selection dialog)
- Consider hovering as activity with pointer devices and keyboard focus with keyboard inputs
- In addition to tapping or clicking anywhere in your preferred controls area
- Immediately hide controls when pointer hover or keyboard focus leaves the player
- Unless `performanceMode` is `'HIGH'` limit resource usage to enable the browser to remain or become responsive, e.g: disable costly graphical effects
More specifically, depending on the following criteria select one (or no) overlay to show (from highest to lowest priority):
1. If `!(online || playing)` then select the `offline` overlay
2. Else if `(config?.controls.error ?? true) && !!error && !playing` then select the `error` overlay
- Note: Not just when `controls.error`, but also when config has not loaded yet
- In that case the default player controls will show this unless `controlsDisabled`
3. Else if `config?.streamPhase === 'LIVE' && playbackState === 'ENDED'` then select the stream `unavailable` overlay
4. Else if `playbackState === 'PAUSED' && config?.controls.play === false || userPaused !== 'PAUSED'` then select the `play` overlay
- Where `userPaused: 'UNSPECIFIED' | 'PAUSED' | 'UNPAUSED'` corresponding to your use of `pause()` and `play()`
5. Else if `!config || stalled` then select the `loading` overlay
6. Else if `muted && (config?.controls.mute === false || userMuted !== 'MUTED')` then select the `unmute` overlay
- Where `userMuted: 'UNSPECIFIED' | 'MUTED' | 'UNMUTED'` corresponding to your use of `setMuted()`
- The player persists this to storage and so should you
Then show the following layers/controls from bottom to top on the video player:
- While selected, overlay `loading` with some loading indicator
- Interactive layer as shown by the interactive element/page or by the page using a video only stream
- While selected, one of the other overlays:
- Overlay `unmute` with a button bound to `setMuted(false)`
- Overlay `play` with a button bound to `play()`
- Overlay `unavailable` with a button bound to `reload()`
- Overlay `error` with `error.message` and a button bound to `reload()`
- While `features.contact && controls.contact` also link to the info dialog contact form (see below)
- Overlay `offline` with a button bound to `reload()`
- Controls bar with:
- While `features.scrubber && config?.streamPhase === 'LIVE' && config.controls.scrubber` a scrubber:
- _(to be specified, e.g: using playback details and `seek()`)_
- While `config?.streamPhase === 'LIVE' && config.controls.play` a pause toggle button using `paused` and `play()` or `pause()`
- While `config?.controls.mute` a mute toggle button using `muted` and `setMuted()`
- While `features.volume && config?.controls.mute` a volume slider using `volume`
- While `config?.streamPhase === 'LIVE' && config.controls.quality` a `qualities.list` toggle:
- Highlighting the `qualities.active`, `qualities.selected` and `qualities.forced` qualities
- Enabling selecting one of those or the automatic quality selection (`-1`) using `selectQuality()`
- If a quality is actively being forced (`qualities.forced !== -1`), disable user selection of a quality
- While `features.pip && config?.controls.pip` a picture-in-picture toggle button using `display` and `setDisplay('PIP' | 'DEFAULT')`
- While `features.fullscreen && config?.controls.fullscreen` a fullscreen toggle button using `display` and `setDisplay('FULLSCREEN' | 'DEFAULT')`
- While `features.airplay && config?.controls.airplay` an Airplay toggle button using `display` and `setDisplay('AIRPLAY' | 'DEFAULT')`
- While `features.chromecast && config?.controls.chromecast` a Chromecast toggle button using `display` and `setDisplay('CHROMECAST' | 'DEFAULT')`
- Enable showing an info dialog (currently shown on player/controls right click) with:
- Livery player `version` from package
- While `features.contact && config?.controls.contact` a contact form bound to `submitUserFeedback()`
### Next.js
Next.js makes use of server side rendering, which the Livery Web SDK does not currently support. However, users of Next.js can still use the SDK by making use of Next.js’s support for [dynamic imports](https://nextjs.org/docs/advanced-features/dynamic-import) inside a [React Effect Hook](https://reactjs.org/docs/hooks-effect.html) or in a [React class component's `componentDidMount` lifecycle method](https://reactjs.org/docs/react-component.html#componentdidmount). When used in combination, this ensures the module being imported is evaluated at runtime on the client.
Note that many of the examples that Next.js provides use a statement of the form `dynamic( import(...) )`. The `dynamic()` function is used for importing React components and should not be used for importing `@liveryvideo/player`. The code below illustrates basic usage with Next.js.
```js
// do not import('@liveryvideo/player') here
function MyComponent() {
useEffect(
() => {
import('@liveryvideo/player');
},
[], // tell react to only use this effect on mount
);
return ;
}
```
## FAQ
### Autoplay
**_Why doesn't the player automatically start (unmuted)?_**
Browsers keep track of user engagement with video players on pages, scoring higher when the video is shown clearly and when it is allowed to play unmuted by the user.
In Chrome you can check this on the [Media Engagement](chrome://media-engagement/) page; when the player page has a `Score` which is marked as `Is High` `Yes` then unmuted autoplay is allowed.
Our player attempts to automatically start playback unmuted, but if for example the engagement score is too low that will not be allowed by the browser. In that case the player attempts to automatically start playback _muted_ instead and show a dialog to manually unmute.
In some cases a browser (p.e: Safari in low-power mode) or user (using browser configuration) might not allow autoplay at all (not even muted) in which case a dialog will be shown to manually start playback.
---
# Embed
Source: https://docs.livery.live/embed.md
# Livery Video Embed
You can embed Livery in your website using an iframe like so:
?> Replace the Livery Demo stream `id` iframe `src` query parameter below by your own.
```html
```
!> Note: Embedding with an iframe like this will result in fullscreen support being unavailable in some browsers and is generally _not_ recommended.
You should be able to embed the [Livery Video Web Player](web-player.md) in your page directly just as easily (e.g: using a few lines of HTML).
In addition to the `id` query parameter you can also specify a `v` query parameter to specify the version of `@liveryvideo/player` to load (defaults to `latest`).
E.g: `https://embed.livery.live?id=6613d164e4b0bf3ad645f3c6&v=beta`.
## Example
[embed](https://embed.livery.live?id=6613d164e4b0bf3ad645f3c6 ':include :type=iframe width=100% height=315 frameborder=0 allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen')
## Interactive
Our Livery Interactive element can also be embedded from URL: `https://embed.livery.live/interactive/`.
This supports the following query parameters:
| Name | Description |
| ---------- | ------------------------------------------------------------------------------------------------- |
| `bridge` | Version of `@liveryvideo/interactive-bridge` to load for `test` and/or `mock`. |
| `mock` | Use a `@liveryvideo/interactive-bridge` `MockPlayerBridge` as interactive element `playerBridge`. |
| `region` | Interactive element server `region` attribute value to specify. |
| `tenantid` | Interactive element server `tenantid` attribute value to specify. |
| `test` | Use `@liveryvideo/interactive-bridge` `` as interactive element. |
| `v` | Version of `@liveryvideo/interactive` to load and use `` element from. |
The `bridge` and `v` query parameters are NPM package version selector strings that default to: `latest`.
Parameter examples:
- [?v=1.0.0®ion=eu&tenantid=123abc](https://embed.livery.live/interactive/?v=1.0.0®ion=eu&tenantid=123abc) -- E.g. for use by native players in a WebView or third party players in an iframe
- [?test&bridge=1.9.0](https://embed.livery.live/interactive/?test&bridge=1.9.0) -- For native player devs to test with specified version of interactive bridge
- [?mock&v=1.0.0](https://embed.livery.live/interactive/?mock&v=1.0.0) -- For interactive devs to test specified version of their element without a player
- [?mock&test&bridge=1.9.0®ion=eu&tenantid=123abc](https://embed.livery.live/interactive/?mock&test&bridge=1.9.0®ion=eu&tenantid=123abc) -- For bridge devs to test a specified version
---
# Security
Source: https://docs.livery.live/security.md
# Security
Security is an essential aspect of live streaming, and Livery strives to ensure the utmost safety of your interactive live streams. In addition to our general security measures, Livery provides supplementary security features that can be configured through Livery's online portal(s).
## Domain whitelisting
By enabling domain-level privacy, customers can specify the websites that are authorized to integrate or embed the Livery video player. Any sites not included on the list will receive an error message when attempting to play the stream. The domain whitelisting feature can be accessed through the 'Stream Settings'.
This feature allows the whitelisting of one or more domains. If the domain list is empty, any player will be able to play the stream. Please note that changes made to the domain whitelisting can take up to 4 hours to become active.
When a viewer attempts to play the stream, the browser will verify if the underlying domain matches any of the domains on the list. Please be aware that subdomains must be added separately, as adding the main domain will not cover them. Additionally, the use of wildcard characters is supported
## Token Authentication
Secure session tokens are utilized to authenticate user sessions and prevent unauthorized sharing of the streaming URL. Token-based authentication mechanisms are widely used across the Internet to verify user rights and enhance security.
This feature employs tokens that are generated using a "trusted shared secret". This secret is shared between the customer and the CDN.
Token Authentication security ensures that the stream is delivered only to the authenticated user, thus preventing link sharing and player hijacking attacks.
### Enable Token Authentication
Token Authentication can be enabled via the checkbox in the ‘Stream Settings’. When enabled the Livery backend generates a Token Authentication Key for each stream, which is automatically added to the configuration of the CDN.
The ‘Token Authentication Key’ is listed on the ‘Stream Details’ accessible via the portal.
The customer backend determines which users, logged in to the customer website, have access to the video stream. The customer backend generates tokens for these users using one of [Akamai's Token Auth software development kits (SDKs)](https://techdocs.akamai.com/adaptive-media-delivery/docs/generate-a-token-and-apply-it-to-content). The Akamai documentation explains how they use long and short tokens. With Livery we use a advanced version of Token Authentication which only uses long tokens. This allows you to deny access to users without having to wait 24 hours, which would be the case when using the traditional setup.
To generate the tokens, the backend needs the Token Authentication Key, which can be copied from the ‘Stream Detail’ page in the Livery Portal. The customer's backend then forwards these tokens to the customer application or website. When using one of the SDK's to generate a token, make sure to use these settings.
| Parameter | Value |
| ---------- | ---------------------------------- |
| acl | \* |
| window | The time the token should be valid |
| token_name | 'hdntl' |
| payload | 'hdntl' |
| key | The Token Authentication Key |
The customer application or website opens the Livery native or web player, which has an attribute called 'akamailongtoken'. This attribute can be set to the token retrieved from the customer backend.
The Livery player forwards the token to CDN when fetching the video data. Once the token expires, a new token needs to be provided from the customer application or website for the Livery player to authenticate with CDN again.
```mermaid
%%{init: {'theme':'dark'}}%%
sequenceDiagram
Customer backend->>Customer application or website: Token
Customer application or website->>Livery Player: Token
Livery Player->>CDN: Request stream with token
CDN-->>Livery Player: Authorised stream
```
## Stream Key
The Livery platform utilizes an RTMP or SRT stream for the first mile delivery to the cloud encoder. To authenticate a live stream with the Livery Cloud encoder, a Stream Key is used. The key can be copied or regenerated via the ‘Stream Details’ page in the Livery portal.
The Stream Key in combination with the Stream URL (SRT/RTMP)can be copied to the prefered streaming tool. See [mixer soft- and hardware](video-ingest.md?id=mixer-soft-and-hardware) for more infomation about the tools.
## CDN Authentication
CDN authentication is utilized to secure the connection between the encoder (both cloud and on-premises) and the CDN. This prevents hackers from hijacking the stream. For each stream, unique credentials are used to upload videos to the CDN, and this is done automatically by the Livery platform without requiring any intervention from the user.
## Security Captions and Translation
Livery's captioning and subtitle pipeline uses Speechmatics Realtime for speech-to-text caption generation and Amazon Translate for multilingual subtitle translation.
In the Speechmatics step, the customer’s audio is processed through Speechmatics Realtime. Speechmatics documents that its Realtime SaaS service does not store audio files, transcripts, or configuration data. The generated captions are returned to our system for further processing. [Source](https://docs.speechmatics.com/speech-to-text/realtime/limits)
Livery then send the generated caption text to Amazon Translate to create translated subtitle versions. At this stage, AWS receives caption text only, not the original media or audio, unless separately provided by our system.
For AWS AI services, including Amazon Translate, we have AWS AI services opt-out enabled by default. This means our standard configuration instructs AWS not to use customer content processed through supported AWS AI services for service improvement. [Source](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_ai-opt-out.html)
Livery only store captions, subtitles, translations, and related caption/subtitle metadata on our own controlled infrastructure. This infrastructure is managed under our own access controls, retention rules, security measures, and privacy policies. Speechmatics and AWS are used as processing services in the pipeline, not as the long-term system of record for caption or subtitle data.
Data is protected in transit. Speechmatics states that data is encrypted in transit using TLS 1.2 or higher, and AWS documents that Amazon Translate uses TLS 1.2 for data in transit.[Source](https://www.speechmatics.com/security) [Source](https://docs.aws.amazon.com/translate/latest/dg/encryption-in-transit.html)
Access to caption and subtitle data within our own infrastructure is restricted according to least-privilege principles and governed by our internal security and privacy controls.
AWS publishes data-protection and privacy documentation explaining how customer content is handled within AWS services, including customer control over content and AWS’s shared responsibility model. Our use of Amazon Translate is configured in line with these AWS controls, including the AI services opt-out policy described above.
In summary, Speechmatics Realtime is used as a transient speech-to-text processor, Amazon Translate is used to translate caption text, AWS AI services opt-out is enabled by default, and any retained caption or subtitle data is stored only in our own controlled infrastructure under our privacy and security rules.
---
# Customer API
Source: https://docs.livery.live/customer-video-api.md
# Livery Video Customer API
This page describes the API calls that are available to customers. These calls can be used by application developers that are using the Livery streaming solution and want to control the stream from within their own software instead of relying on the Livery producer console.
The paths in this page should be concatenated to the domain name of a environment to make the full URL for a request.
The domain name for the production environment is `backend.video-encoder.playtotv.com`.
So if the streamId is 1234 and the documentation mentions this API call:
```
GET api/1/services/analytics/{streamId}/dimensions
```
The URL for the API call would be:
```
https://backend.video-encoder.playtotv.com/api/1/services/analytics/1234/dimensions`
```
## Authorization
Access to the API calls is restricted to authorized users only. Authorization is done with API Keys.
The API key should be added as a X-PlayToTV-ApiKey header to requests.
There are two types of API Keys: Customer API keys and Stream API keys.
| API Key Type | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| Customer | authorized to do all documented customer requests & all stream request for streams owned by the customer which the API key belongs to. |
| Stream | authorized to do all documented stream requests that involve a single stream. |
## Rate limits
These API's are not ment to be used directly in frontend applications.
Make sure a backend is put in between to cache the responses and prevent hitting the rate limits.
The API calls are rate limited to 30 calls per minute per customer.
This means that it combines the request count for all streams of a customer.
If this limit is exceded the server will return a response with a 429 HTTP status code.
## API Calls
### GetAnalytics
The Livery analytics API allows customers to get insights in the performance of their streams.
The API consist of a single REST call with a number of query parameters.
This section explains how this API can be used.
```
GET api/1/services/analytics/{streamId}/dimensions
```
| Parameter | Type | Mandatory | Description |
| --------------- | ----- | --------- | --------------------------------------------------------------------------------------------------------------------------------- |
| streamId | Path | Yes | The stream identifier |
| from | Query | Yes | Start date in milliseconds |
| until | Query | Yes | End date in milliseconds |
| metric | Query | No | Currently only accepts "viewers". Defaults to viewers |
| dimension | Query | No | Which type of data to query, see info below |
| minutesInterval | Query | No | Minute intervals to split the data into as integer (1-1440). **Cannot be used along with the points parameter** |
| points | Query | No | The amount of points to split the data into as positive integer (1+). **Cannot be used along with the minutesInterval parameter** |
The minimum range to fetch data for is one minute, the maximum range is currently one week.
These are the dimensions that are supported:
| Dimension | Description |
| --------------- | ------------------------------------------------------------------------------------------------------------------ |
| PLATFORM | The type of SDK that is being used. This will be either android, iOS or web |
| CONNECTION_TYPE | The type of internet connection that viewers used, only available with the Android or iOS SDK |
| VIDEO_QUALITY | The video quality that viewers watched |
| ENCODER_TYPE | Shows if viewers were watching the stream of the MAIN or the BACKUP encoder |
| PACKAGE_NAME | This is the package name of the native app or the domain name of the website that viewers used to watch the stream |
| DEVICE_MODEL | The type of device that viewers were using to watch the stream |
For example, to get viewer data per platform in a single point:
```
GET api/1/services/analytics/{streamId}/dimensions?from=1606246100000&until=1606247300000&dimension=PLATFORM&points=1
```
Response example:
```json
{
"data": [
{
"timestamp": 1606246100000,
"values": [
{
"dimension": "android",
"value": 4699
},
{
"dimension": "web",
"value": 707
},
{
"dimension": "ios",
"value": 12
}
]
}
]
}
```
Or to retrieve the ENCODER_TYPE dimension in 10 minute intervals:
```
GET api/1/services/analytics/{streamId}/dimensions?from=1606246100000&until=1606247300000&dimension=ENCODER_TYPE&minutesInterval=10
```
Response example:
```json
{
"data": [
{
"timestamp": 1606242000000,
"values": [
{
"dimension": "main",
"value": 1600
},
{
"dimension": "backup",
"value": 13
}
]
},
{
"timestamp": 1606242600000,
"values": [
{
"dimension": "main",
"value": 5309
},
{
"dimension": "backup",
"value": 400
}
]
},
{
"timestamp": 1606243200000,
"values": [
{
"dimension": "main",
"value": 4811
},
{
"dimension": "backup",
"value": 444
}
]
}
]
}
```
### Test data
There is a dev environment that allows you to test the analytics API calls before you have had any live streams.
| Field | Description |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| Domain name | backend.video-encoder-dev.playtotv.com |
| streamId | 5e7a10bee4b046f00ad17248 |
| API key | 1568285122117_c0fa8dc13a4c104b673b4b2aa664341200ef81fbde330b03404621f178f9e158eae47d1e9b071d20f7ddd8ae9ba4f1df858081f31b43b809bbef920c04459951 |
For example this API call can be used to retrieve a mocked version of the viewers per platform:
```
curl -H "X-PlayToTV-ApiKey: 1568285122117_c0fa8dc13a4c104b673b4b2aa664341200ef81fbde330b03404621f178f9e158eae47d1e9b071d20f7ddd8ae9ba4f1df858081f31b43b809bbef920c04459951" https://backend.video-encoder-dev.playtotv.com/api/1/services/analytics/5e7a10bee4b046f00ad17248/dimensions?dimension=PLATFORM&from=1606246100000&until=1606247300000&points=1
```
### GetCustomer
Returns the customer data that is available for a given customerId.
```
GET api/1/services/customers
```
Response example:
```json
[
{
"customerId": "5c5468158f087748c233194f",
"name": "ExampleCustomer",
"email": "info@example.com",
"encoderIds": ["5f438c8d2e8037d91adf780a", "5f438c9b09ab5a068b9f87e7"],
"pushUrl": "https://customerserveraddress"
}
]
```
### GetStreams
Returns a list of streams. This call can be used to retrieve streamIds which are needed to start and stop a stream.
This could be used to monitor the streams by polling this API call reading the `warnings` field of the stream object.
When the system detects a problem with the stream or the attached encoders a new line with a description will be added to that field.
Check the [Rate limits](#rate-limits) section for some considerations around the polling frequency.
```
GET api/1/services/streams?pageIndex=1&pageSize=100
```
| Query parameter | Description |
| --------------- | ------------------------------------------------------------------ |
| pageIndex | The page index of the pagination. The first index is 1. |
| pageSize | The number of streams on a page |
| streamIds | List of streamIds to be found, ignored when using a stream API key |
Response:
[filename](_customer-video-api/_example-multiple-StreamResponseDTO.md ':include')
### StartStream
Starts the video stream. Once the response of this call is available the application can start the video player with the video urls from the response.
The urls are defined in the streamUrls field in the output.\
The value of streamingState should be _STARTED_
```
PUT api/1/services/streams/start?id=5f2022df27b35d1ebfe17b78
```
| Query parameter | Description |
| --------------- | --------------------------------------------------------------- |
| id | The stream identifier. Required when not using a Stream API Key |
Response example:
[filename](_customer-video-api/_example-StreamResponseDTO.md ':include')
### StopStream
Stops the video stream.
The value of streamingState should be _STOPPED_
```
PUT api/1/services/streams/stop?id=5f2022df27b35d1ebfe17b78
```
| Query parameter | Description |
| --------------- | --------------------------------------------------------------- |
| id | The stream identifier. Required when not using a Stream API Key |
Response example:
[filename](_customer-video-api/_example-stopped-StreamResponseDTO.md ':include')
### CreateStream
Create a new stream
```
POST api/1/services/streams
```
Request body:
```json
{
"name": "streamName",
"cdnRegionId": "6062e72ca1b0d8e93af985f9",
"posterUrl": "streamName.com/poster.png",
"prePosterUrl": "streamName.com/poster-pre.png",
"postPosterUrl": "streamName.com/poster-post.png",
"interactiveLayerUrl": "streamName.com/poster.png",
"videoStreamQualities": [
"6062e81716bcd84ab3562cc1",
"6062e81716bcd84ab3562cc1"
],
"audioStreamQualities": [
"6062e823f8cea49a7e2036f7",
"6062e82e40b0aaf95d6c634f"
],
"settings": {
"targetLatency": 3.0,
"segmentSizeInSeconds": 2.0
},
"player": {
"fit": "COVER",
"preRoll": "streamName.com/preroll.mp4"
},
"controls": {
"cast": false,
"error": false,
"fullscreen": false,
"mute": false,
"quality": false,
"pip": false
},
"cdn": {
"domainWhiteList": [
"https://streamName.com",
"https://video.streamName.com"
]
}
}
```
Response example:
[filename](_customer-video-api/_example-StreamResponseDTO.md ':include')
### UpdateStream
Update the settings of a stream.
```
PUT api/1/services/streams?id=5f2022df27b35d1ebfe17b78
```
| Query parameter | Description |
| --------------- | --------------------------------------------------------------- |
| id | The stream identifier. Required when not using a Stream API Key |
Request body:
```json
{
"name": "streamName",
"posterUrl": "streamName.com/poster.png",
"prePosterUrl": "streamName.com/poster-pre.png",
"postPosterUrl": "streamName.com/poster-post.png",
"interactiveLayerUrl": "streamName.com/poster.png",
"streamPhase": "PRE",
"settings": {
"targetLatency": 3.0,
"segmentSizeInSeconds": 2.0
},
"player": {
"fit": "COVER",
"preRoll": "streamName.com/preroll.mp4"
},
"controls": {
"cast": false,
"error": false,
"fullscreen": false,
"mute": false,
"quality": false,
"pip": false
},
"cdn": {
"domainWhiteList": [
"https://streamName.com",
"https://video.streamName.com"
]
}
}
```
Response example:
[filename](_customer-video-api/_example-StreamResponseDTO.md ':include')
### RemoveStream
Remove a stream.
```
DELETE api/1/services/streams?id=5f2022df27b35d1ebfe17b78
```
| Query parameter | Description |
| --------------- | --------------------------------------------------------------- |
| id | The stream identifier. Required when not using a Stream API Key |
### Re-generate Stream Key
Re-generate stream key for the specified customerId and streamId
```
PUT api/1/services/streams/{streamId}/streamkey
```
| Parameter | Type | Mandatory | Description |
| ---------- | ---- | --------- | ----------------------- |
| streamId | Path | Yes | The stream identifier |
Response example:
[filename](_customer-video-api/_example-key-re-generate-StreamResponseDTO.md ':include')
### Get stream history
Returns a list of StreamTime objects. These contain information about the stream when it was online.
```
GET api/1/services/streamtimes
```
| Parameter | Type | Mandatory | Description |
| ---------- | ----- | --------- | ------------------------------------------------------- |
| start | Query | Yes | Start timestamp of search query, in milliseconds. |
| end | Query | Yes | End timestamp of search query, in milliseconds. |
| pageIndex | Query | Yes | The page index of the pagination. The first index is 1. |
| pageSize | Query | Yes | The number of streams on a page |
Response example:
[filename](_customer-video-api/_example-StreamTimeDTO.md ':include')
## Push API
Livery has a push API available which can directly inform the customer server when the streaming state of a stream has changed.
For this the customer needs to configure a push url.
The Livery server will do an HTTP POST request to that url with the streamId and the streaming state.
The state can be either `STARTED` or `STOPPED`.
Request body:
```json
{
"streamId" : "5e7a10bee4b046f00ad17248",
"streamingState" : "STARTED"
}
```
---
# Portal
Source: https://docs.livery.live/interactive-portal.md
# Interactive Portal
Livery Interactive is a cloud based solution which brings true, interactive video within everyone’s reach on web, iOS and android devices. The responsive design ensures that on all devices you can enjoy the same experience.
With our product we provide you a fun and interactive way to enrich your broadcast event and at the same time create engaging experiences that are in perfect sync with the video.
Livery Interactive and Livery Video offered together but both parts of our product can be used separately as well.
On top of the video player sits the interactive layer, this is where your audience will see all interactions when they join your live broadcast event. You can plan, build and play all interactions in an intuitive web-based management system, designed to ensure that even one person can easily manage the elements of your broadcast but it is also supported to let multiple operators work together.
All important video management features are available within the web-based management system to provide an interface where both parts of the Livery product can be managed together.
Within Livery interactive the broadcast is the grouping entity of all the settings and interactions that you’d like to display to your audience during your broadcast event.
The interactions can have the following phases, all managed by the operators in the web-based management system:
- New: a new interaction in the timeline, still editable, not visible for the audience
- Open: the interaction has been played and showed to the audience, the end-users can interact
- Pending: the interaction is stopped, end-users can no longer interact with it but the results are not yet published
- Result: the results are published for the end-users
- Closed: the interaction is closed, the end-users can no longer see them in the interaction list
#### Poll and Vote
The poll interaction is meant to prepare poll or vote questions with one question and multiple answers. Points are not added to these questions.
Key features:
- Up to 4 answers in vertical, 6 answers in grid or 20 answers in a dropdown layout
- Grid layout supports text, image or emoji answer options
- Custom background colour on answers
- Optional time limit for answers
- Optional hiding of the question text
- Optional forcing of the interaction to the foreground
#### Trivia
The trivia interaction is meant to prepare trivia questions with one question and multiple answers where the correct answer(s) are marked. Eventual points will be calculated based on the player’s answers and optionally the time of answer or odds or waged amount, and these points will affect their position in the leaderboard.
Key features:
- Up to 4 answers in vertical, 6 answers in grid or 20 answers in a dropdown layout
- Grid layout supports text, image or emoji answer options
- Custom background colour on answers
- Optional time limit for answers
- Optionally attached points
- Leaderboard results
- Showing percentage of provided answers
- Optional time-based scoring
- Optional odds can be added
- Optional betting can be configured
- Optional hiding of the question text
- Optional forcing of the interaction to the foreground
- Show/hide the percentage of the results
#### Estimation poll
The estimation poll interaction is meant to prepare questions with answers within an interval. Scores are not added, this interaction provides the poll/vote result on a column chart including the average of given answers.
Key features:
- Slider or free value input
- Line diagram of result
- Optional time limit for answers
- Optional hiding of the question text
- Optional forcing of the interaction to the foreground
- Show/hide the percentage of the results
#### Rating
When you’d like to ask the opinion of your audience about a certain topic, you can set up a rating interaction.
Key features:
- Attached image
- Rating result override
- Link to product items
- Optional time limit for answers
- Optional hiding of the question text
- Optional forcing of the interaction to the foreground
#### Announcement
The announcement interaction is meant to prepare quick announcements with title and subtitle. This is shown only one time in the front-end, later the interaction disappears and can't be rewatched.
Key features:
- Quick announcement
- Option for auto or manual closing
- Image upload
- Button with external url
##### Picture in picture
When an announcement, product item or shopify product item has a button which opens an external link, picture in picture mode of the video can be configured.
#### Live reaction
To offer the option to express feelings during the broadcast, live reaction emojis can be shown.
Key features:
- Up to 5 emojis can be added in the selector from a standard list of emojis
- Unlimited sent reactions during broadcast
#### Countdown
The countdown indicates how much time is left before the broadcast event is starting. It shows days, hours, minutes and seconds.
Key features:
- Date and time selector in the web-based management system
- Audience can already interact before the time is up
- Configurable title
- Configurable message for the last 60 seconds
#### Chat
The audience can chat with each other via the chat module.
Key features:
- Rate limit to avoid spamming
- Enable/disable chat in the web-based management system
#### Q&A
When the Q&A session is open the audience has the option to raise questions which the operator can manage in the web-based management system.
Key features:
- Approve, answer options of questions
- Show/hide in Client and/or Presenter view
- Rate limit on question submission (avoid spamming)
- Enable/disable q&a in the web-based management system
- Pinning
- Filtering
- Search
#### Estimation
The estimation interaction is meant to prepare questions with answers within an interval. Points will be calculated based on the player’s answers and these points will affect their position in the leaderboard.
Key features:
- Slider or free value input
- Score deduction per steps
- Optional time-based scoring or no-points setup
#### Prediction
The prediction interaction is meant to prepare questions with one question and multiple answers where the correct answer(s) are not yet known. Points will be calculated based on the player’s answers and these points will affect their position in the Leaderboard.
Key features:
- Up to 4 answers in vertical, 6 answers in grid or 20 answers in a dropdown layout
- Grid layout supports text, image or emoji answer options
- Custom background colour on answers
- Optional time limit for answers
- Optionally attached points
- Leaderboard results
- Showing percentage of provided answers
- Optional time-based scoring
- Optional odds can be added
- Optional betting can be configured
- Optional hiding of the question text
- Optional forcing of the interaction to the foreground
- Show/hide the percentage of the results
#### Estimation prediction
The estimation prediction interaction is meant to prepare questions with answers within an interval where the correct answer is not yet known. Points will be calculated based on the player’s answers and these points will affect their position in the leaderboard.
Key features:
- Slider or free value input
- Score deduction per steps
- Optional time-based scoring
- Optional hiding of the question text
- Optional forcing of the interaction to the foreground
- Show/hide the percentage of the results
#### Leaderboard
The Leaderboard shows the earned points of the players during the broadcast.
Key features:
- Actual user is always in the top
- Top positions are highlighted
#### Product item
For product promotions the product item interaction can be used.
Key features:
- Discount price
- Attached rating
- Multiple attributes (size, color, etc.)
- Copy change of the Buy button
#### Shopify product item
To inlcude a product out of your shopify store the Shopify product item interaction can be used.
Key features:
- easy integration on plugin page
- available product data is pulled in automatically
- optional notification can be added
#### Webclip
With the webclip interaction external content can be embed in the interactive client
Key features:
- Custom size and position
- Optional hiding of the close button
- Optional dragging and resizing options
- Optional permission configuration for features. I.e. microphone, camera
#### Word guessing
The word guessing interaction is meant to prepare questions with one question and multiple answers where the correct answer(s) are defined. Eventual points will be calculated based on the player’s answers and these points will affect their position in the leaderboard.
Key features:
- Up to 8 correct answers
- For each answer up to 10 synonyms
- Synonyms can be AI generated
- Fuzzy loginc for typos or misspelled answers
- Optional time limit for answers
- Optional attached points per answer
- Leaderboard results
- Optional hiding of the question text
- Optional forcing of the interaction to the foreground
#### Captions and subtitles
AI generated captions can be added to the stream.
Key features:
- easy integration on plugin page
- integration with Rev.ai or Speechmatics
- subtitles can be shown/hidden by the end-user
- language selector in client
#### Social share (coming soon)
### Management features
These powerful management features give you the opportunity to configure your broadcast, target it for your audience and provide you data and analytics to make your broadcast event even better.
The features are Broadcast management, Account management, Currency handling, Theming, Show/Hide pages or features, Presenter view and Data export. All these management features, real-time interaction results and analytics are provided by our web-based management system.
#### Broadcast management
Broadcast is the main grouping element within our system.
For every broadcast event you set up a broadcast within the web-based management system where you define the details above..
Once you have a broadcast defined, you can start to add interactions to it to fill up your timeline.
| Field | Description |
| ------------------- | ------------------------------------------------------------------------------------ |
| Name | The name of the broadcast |
| Start date and time | The planned “Date” and “Time” of the broadcast |
| Stream | The list of available stream in case Livery Video is configured |
| Theme | The selected branding of the interactive layer |
| Locale | The locale which defines how the currencies, amounts and date/time will be formatted |
| Starting points | The points which every user will start with when they join the broadcast |
| Enabled features | All the features and pages which you’d like to show to your audience |
The web-based management system allows you to manage your broadcasts and get an overview of your previous items.
Key features:
- Use default authentication method
- Select your locale
- Define starting points
- Start/stop your broadcast anytime you want
- Select a theme for your branding
- Show/Hide features and pages
- Video Stream selection
#### Account management
To use the interactive features the players need to log in or set up a guest user.
Key features:
- Verification code for logging in
- Users can be removed
- Leaderboard results are attached to users
- Show/Hide live reactions
- Disclaimers based on the authentication template
#### Currency handling
The Broadcast’s locale can be selected on the Broadcast's form. This will define how currencies, amounts, date/time format and language will be shown on the front-end.
Key features:
- Predefined list (easy adjustment)
- Preview of values
#### Theming
The look and feel of the interactive features can be defined via Themes. The web-based management system offers an easy to use way to change colours and logos easily.
Key features:
- 10 colors generates a new look
- Default theme setup (on customer level)
- Theme definition on broadcast level
#### Show/Hide pages or features
You can select which pages and features you’d like to add to your broadcast out of the list of:
- Chat
- Q&A
- Interactions
- Leaderboard
- Highlights (product items)
- Showing percentage of provided answers
- User counter
#### Authentication
The following login methods are supported:
- Log in as Guest
- Email verified
- Phone number verified
- Unverified frictionless login
- Verified frictionless login via JWT token
On all login fields non-latin characters are also accepted.
#### Presenter view
During the broadcast event the Presenter can check the interaction results, live reaction activity or the raised Q&A questions on this dedicated page.
Key features:
- Without clicking the content can be seen
- Automated timer for scrolling the content
- Flipping screen horizontally or vertically
- Full screen option
- Font size setup
- Leaderboard top 10
#### Q&A overview
In the management portal all submitted questions can be approved, answered and shown to the users or the presenter.
#### Interaction forcing
Forcing to the foreground can be set on interaction level in the management portal. Default tenant setting can be added.
#### Interaction and Broadcast scheduling
Every broadcast and interaction can be scheduled by setting start- and end-time to their phases in the management portal.
#### Data export
During the broadcast event we collect information about user’s reactions and actions,. This data can be downloaded via the web-based management system, structured into the following reports:
- Broadcast data
- User information including leaderboard ranking and earned points
- Chat messages
- Q&A questions and answers
- Poll, Trivia, Prediction interaction data
- Estimate interaction data
- Rating results
#### Livery Video Integration - Video Stream Control
The most important Video stream settings and management is available via the web-based management system, so everything can be set up in one place end to end.
#### Interaction API
When you’d like to access the statistics of the interactive layer, you can use our Interaction API and with the available data build your overview.
---
# Bridge
Source: https://docs.livery.live/interactive-bridge.md
# Livery Interactive Bridge
[](https://www.npmjs.com/package/@liveryvideo/interactive-bridge)
[](/npm/interactive-bridge/CHANGELOG)
[](/npm/interactive-bridge/dist/)
[](https://lit.dev/)
[](https://cdn.jsdelivr.net/npm/@liveryvideo/interactive-bridge/LICENSE)
Bridge for communicating between a Livery Video Player and the interactive layer shown within that.
## Demo
- [Test page for use by Livery Video Players](https://interactive-bridge.liveryvideo.com)
- [Test with a mock player bridge and interactive element](https://interactive-bridge.liveryvideo.com/?mock)
- [Test with a mock player bridge and interactive iframe](https://interactive-bridge.liveryvideo.com/?mock=iframe)
## Support
This package exports two bundles.
The ES `module` bundle is targetted at modern browsers and tools supporting `ES2019`.
The UMD `main` bundle (as used by jsdelivr [CDN](#cdn)) supports the last 2 major versions of: Chrome, Safari, Edge, Firefox, Android Chrome, iOS Safari and Samsung Internet.
## Installation
### NPM
Install using NPM:
```bash
npm install @liveryvideo/interactive-bridge
```
### CDN
Or load from [jsdelivr](https://jsdelivr.com):
```html
```
?> Replace the version (`x.y.z`) above by the version of the SDK that you wish to use. E.g: update to latest stable release periodically. Please see the [CHANGELOG](/npm/interactive-bridge/CHANGELOG) for details.
## Usage
The main class to be used from this package is the InteractiveBridge:
```js
import { InteractiveBridge } from '@liveryvideo/interactive-bridge';
// The playerBridge will be provided to you as interactive element as interactive webview or iframe
const bridge = new InteractiveBridge(playerBridge || '*');
// To prevent cross site security issues:
// https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#security_concerns
// replace the `'*'` origin above with the origin of the page that the Livery Player is on
bridge.getAppName().then(appName => window.alert(`appName: ${appName}`));
```
## [API](/npm/interactive-bridge/dist/)
Detailed documentation of the exported API is generated and included in the NPM package and can be viewed here: [API](/npm/interactive-bridge/dist/)
## [CHANGELOG](/npm/interactive-bridge/CHANGELOG)
A detailed changelog of the package is generated and included in the NPM package and can be viewed here: [CHANGELOG](/npm/interactive-bridge/CHANGELOG)
---
# Customer API
Source: https://docs.livery.live/customer-interactive-api.md
# Livery Video Interactive API
This page describes the API calls that are available to customers.
These calls can be used by application administrators or developers to retrieve restricted data.
For more information regarding domain & paths, ask for the URL from Livery support.
## Rate limits
These API's are not ment to be used directly in frontend applications.
Make sure a backend is put in between to cache the responses and prevent hitting the rate limits.
The API calls are rate limited to 30 calls per minute per customer.
This means that it combines the request count for all streams of a customer.
If this limit is exceded the server will return a response with a 429 HTTP status code.
## Pull API
Authorized customers are allowed to access Livery interactive restricted API calls.
Authorization will be done via an API key that can be retrieved from the Livery interactive portal.
The value of the added key must be included in header `x-livery-api-key`
Unless an API key is added, the customer will not be able to retrieve broadcast data.
Page numbers start at 0 on paginated API calls
### Get current broadcast data
This API call can be used to retrieve information about the broadcast that is currently live.
A use case is to poll this API to react on the broadcast being closed.
```
curl -H "x-livery-api-key: value" https://www.example.com/services/broadcasts/current
```
Response example:
[filename](_customer-interactive-api/_example-BroadcastCurrent.md ':include')
#### List of supported interactions:
announcement
[announcement](_customer-interactive-api/interactions/announcement.md ':include')
countdown
[countdown](_customer-interactive-api/interactions/countdown.md ':include')
estimate
[estimate](_customer-interactive-api/interactions/estimate.md ':include')
estimationPoll
[estimationPoll](_customer-interactive-api/interactions/estimationpoll.md ':include')
estimationPrediction
[estimationPrediction](_customer-interactive-api/interactions/estimationprediction.md ':include')
liveReaction
[liveReaction](_customer-interactive-api/interactions/livereaction.md ':include')
poll
[poll](_customer-interactive-api/interactions/poll.md ':include')
prediction
[prediction](_customer-interactive-api/interactions/prediction.md ':include')
productItem
[productItem](_customer-interactive-api/interactions/productitem.md ':include')
rating
[rating](_customer-interactive-api/interactions/rating.md ':include')
shopifyProductItem
[shopifyProductItem](_customer-interactive-api/interactions/shopifyproductitem.md ':include')
trivia
[trivia](_customer-interactive-api/interactions/trivia.md ':include')
webclip
[webclip](_customer-interactive-api/interactions/webclip.md ':include')
wordGuessing
[wordGuessing](_customer-interactive-api/interactions/wordGuessing.md ':include')
### Get broadcast data
This API call can be used to retrieve information about any created broadcast.
```
curl -H "x-livery-api-key: value" https://www.example.com/services/broadcasts/{broadcastId}
```
Response example:
[filename](_customer-interactive-api/_example-Broadcast.md ':include')
### Get interaction
This API call can be used to retrieve information about interaction.
```
curl -H "x-livery-api-key: value" https://www.example.com/services/broadcasts/{broadcastId}/interactions/{interactionId}
```
Response example:
[estimationPoll](_customer-interactive-api/interactions/estimationpoll.md ':include')
This response is specific to the `estimationPoll` interaction type. [Here](#List-of-supported-interactions) is the full list of supported interactions.
### Get user data
This API call can be used to retrieve a list of users in a broadcast.
```
curl -H "x-livery-api-key: value" https://www.example.com/services/broadcasts/{broadcastId}/users/pagenumbers/{pagenumber}
```
Response example:
[filename](_customer-interactive-api/_example-Users.md ':include')
### Get leaderboard data
This API call can be used to retrieve game data on a broadcast.
The `isUpdating` field serves as an indicator of the leaderboard’s current processing status.
When `isUpdating` is set to `true`, it signifies that the leaderboard is actively undergoing updates,
such as recalculating player rankings or processing new scores.
Conversely, when `isUpdating` is `false`, it indicates that the leaderboard has completed all processing tasks and reflects the most recent data.
```
curl -H "x-livery-api-key: value" https://www.example.com/services/broadcasts/{broadcastId}/leaderboard/pagenumbers/{pageNumber}
```
Response example:
[filename](_customer-interactive-api/_example-Leaderboard.md ':include')
### Get audit log
The audit log records who performed what action, on which entity, and when inside the Livery Interactive system.
Customers can query audit logs for their own tenant using the Audit Log API endpoint described below.
The audit log search endpoint supports an optional free-text search filter.
When provided, the filter is applied as a substring match across the following fields: actorId (e.g. admin ID), category (derived from the controller or explicitly set), entityId (the affected entity identifier)
```
curl -G \
-H "x-livery-api-key: value" \
--data-urlencode "startTimestamp=1700000000000" \
--data-urlencode "endTimestamp=1700003600000" \
--data-urlencode "search=broadcast" \
https://www.example.com/services/auditlog/search
```
Example response:
[auditLog](_customer-interactive-api/_example-AuditLogRecords.md ':include')
## Push API
Next to the Pull API's a limited set of Push API's exist.
These API's work the other way around where the Livery server's will do a call to a server of the customer.
For each of the Push API's you can configure a push URL.
The Livery server will do a HTTP POST request to the configured url with a request body as specified below.
The push URL's can be configured in the `Services API settings` in the `Settings` page.
The server will retry each API call maximum 5 times, with a delay of 20 seconds after each retry.
The requests will come from one of these IP addresses, so you could use this list for IP firewal rules:
eu-west
- 52.215.179.168
- 52.31.232.94
- 54.247.174.208
us-east
- 100.27.160.183
- 18.208.29.208
- 98.82.209.116
me-south
- 16.24.189.67
- 157.241.88.51
- 157.241.36.141
### Broadcast push API
The broadcast push API call will be invoked when a broadcast is opened or closed.
This could be used to trigger the retrieval of exports for example.
Example request body:
[broadcast](_customer-interactive-api/_example-Broadcast.md ':include')
### Leaderboard push API
The leaderboard push API call will be invoked on several leaderboard related events.
This can be at the start or end of the update process or when the persisting state changes.
Leaderboards are updated in passes.
This is done to be able to time the leaderboard updates precicely.
For example we don't want to update user score's when the interaction results are not yet shown in the frontend.
When we start such a leaderboard pass, this push API will be invoked with the `updatingForTriggeredByIds` array containing the id of the interaction that caused the leaderboard update.
When the update process is done another call is done, and now the interaction id has been moved to the `updatedForTriggeredByIds` array.
So you can see which interactions have contributed to the current leaderboard.
Leaderboards also have a `state` field which can have one of the following values:
- LIVE: the leaderboard is in a stable state but can change at any time
- UPDATING: the leaderboard is currently being updated
- FINALIZED: the leaderboard is finalized, meaning scores will not be updated anymore
- PERSISTING: the leaderboard is being written to slower long term storage
- PERSISTED: the leaderboard persisting process has finished
Example request body:
[leaderboard push](_customer-interactive-api/_example-LeaderboardPush.md ':include')
---
# Frictionless Login
Source: https://docs.livery.live/frictionless-login.md
# Frictionless Authentication
Frictionless authentication is a feature that allows users to be granted authorization without requiring them to manually interact with the Livery Interactive Client. For instance, if a user is logged into a customer's platform and there is a Livery Video Player on a web page within that platform, the page can pass a set of credentials to the Livery Video Player, and the Interactive Client will automatically log the user into the Livery system. As a result, the end user doesn't need to log in to the Livery system separately from the surrounding platform, making the authentication process `Frictionless`. This feature also supports including profile fields together with the authentication token. Please note that when a user edits their information within the Livery system, the surrounding context won`t be informed.
Livery accommodates Verified and Unverified Frictionless authentication. The delivery mechanisms are almost the same for both variants. A JWT token can be provided that contains the user profile and authentication information. In case of `Verified` frictionless the provided JWT token is signed with either the RS256 or HS256 algorithm. With HS256 the secret is shared between the identity provider and Livery, which requires the least amount of effort but is less secure. With RS256 the identity provider generates the JWTs with a private key and only shares the public key with Livery. `Unverified` frictionless allows the customer to provide the profile fields directly, without the need of a token. Or alternatively it can provide the details via an unsigned JWT token. This approach requires less effort but does not allow account recovery or login on multiple devices and it's not secure.
## Generating tokens
Livery follows the OpenId Connect specification supporting all default and some additional claims. The supported claims are listed under `Profile configuration` in Livery's Interactive Portal. Please contact the Livery team if you require any specific claims. The `sub` claim is the only mandatory claim that always needs to be provided.
The following tool can be used to create signed JWT token for testing purposes:
The examples of this page assume you are using this tool, but any other JWT generator can be used.
This is an example of what a payload might look like when only the `sub` and `preferred_username` claim are supplied.
```json
{
"sub": "1234567890",
"preferred_username": "John Doe"
}
```
In order to generate a HS256 token you can fill in the secret and the JWT token is ready to use.
In order to generate a RS256 token you first need to create a public/private key pair.
One of the ways you can do this is by using the ssh-keygen command line tool:
```bash
ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key
```
__*Don't add passphrase*__
```bash
openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub
cat jwtRS256.key
cat jwtRS256.key.pub
```
Copy the public and private key in the corresponding fields of jwt.io and the JWT token is ready to use.
## Enabling Frictionless Authentication
To use Verified Frictionless Authentication, you must first configure a secret before setting up the authentication method. Configure either an HS256 secret or an RS256 public key in the portal under `Settings` → `Authentication Settings`.
To use Verified or Unverified Frictionless Authentication, add the method to `Authentication methods` within an `Authentication Templates`, located in the `Authentication requirements` section of the Livery Interactive Portal. Verified and Unverified methods cannot be used simultaneously.
The profile fields (user claims) configured in the authentication template must match those provided during frictionless login. If any required claims are missing from the token or query parameters, the Livery Interactive Client will display a “missing data” screen.
Some profile fields, such as phone number or email address, can be verified. Verification flags are only applied through verified tokens. Updating these fields without verification flags will reset their status to unverified.
## Authenticating
### Using the Livery video player
#### **Web Player**
The web player allows providing the token or auth claims via the [interactiveAuth](/npm/player/dist/classes/LiveryPlayer?id=interactiveauth) property.
JavaScript example of setting the token:
```js
player.interactiveAuth = 'eyJhbG...';
```
JavaScript example of setting the auth claims:
```js
player.interactiveAuth = {sub: '1234', preferred_username: 'Livery'};
```
It also allows providing the token or auth claims via the query parameters of the page on which the player is loaded.
This is useful to support personalized mailings from which the user links directly to the Livery experience with its username or other claims already prefilled.
Query parameter example with auth claims:
```
...&livery_sub=12345&livery_preferred_username=Livery
```
Query parameter example with a token:
```
...&livery_token=eyJhbG...
```
#### **Android Player**
The Android player allows providing the token or auth claims via the [setInteractiveAuth](/android-sdk?id=authentication) method.
Java example of setting the token:
```java
playerView.setInteractiveAuth("eyJhbG...");
```
Java example of setting the auth claims:
```java
playerView.setInteractiveAuth(Map.of("sub", "1234", "preferred_username", "Livery"));
```
#### **iOS Player**
The iOS player allows providing the token or auth claims via the [setInteractiveAuth](/ios-sdk?id=authentication) method.
Swift example of setting the token:
```swift
playerView.setInteractiveAuth(token: "eyJhbG...")
```
Swift example of setting the auth claims:
```swift
playerView.setInteractiveAuth(claims: ["sub": "1234", "preferred_username": "Livery"])
```
The token or claims can be used to create new users or to update the existing user-data. To update individual fields, the data is merged with the existing user data (as long as the `sub` field remains unchanged). If the value of a field is undefined, it indicates that the value shouldn't change.
If the `sub` value is different from the previous call or is null, the client will log the user out and create a new user. This allows end-users to switch accounts on a customer's platform without overwriting user data in the Livery system. This means that when using Unverified frictionless, every account switch will create a new user on the Livery system and it will not be possible to log back in on the previously created account.
---
# Livery Guides
Source: https://docs.livery.live/guides.md
# Welcome to the Livery Video Guides
Our comprehensive guides are designed to help you get the most out of the Livery platform. Whether you're just getting started or looking to optimize your streaming experience, you'll find step-by-step instructions, best practices, and tips to enhance your use of Livery’s powerful features.
Explore our guides to learn how to set up and manage your account, integrate with third-party tools like Shopify, customize your streaming experience, and more. Each guide is crafted to ensure you have all the information you need to successfully leverage Livery's capabilities for your interactive live streaming needs.
---
## Debugging Live Stream Stalls with OBS
Stalls can occur during live streams, and identifying their root cause is often challenging. While OBS Studio provides basic statistics, these insights are limited—especially for low-latency streaming. When metrics are collected at intervals longer than one second, short network or performance hiccups may go unnoticed.
To properly diagnose stalls, more granular data is required.
***Monitoring OBS with a Third-Party Utility***
The following utility allows you to monitor an OBS Studio instance via its WebSocket connection.
https://github.com/joepadmiraal/metrics-for-obs/releases
It collects detailed metrics such as network conditions and other performance-related data at a configurable interval. The recommended interval is **one second (default)**, which provides sufficient resolution to capture brief issues.
All collected data can be exported as a **CSV file**, making it easy to analyze and share.
Whenever you encounter issues with the utility tool, please report them on the OBS forum: https://obsproject.com/forum/threads/metrics-for-obs.193539/
***macOS Security Notice***
By default, macOS may prevent the downloaded utility from opening. If this happens:
1. Go to **System Settings → Privacy & Security**
2. Allow the **metrics-for-OBS** file to be opened
3. Retry launching the application
***Connecting to OBS***
When the tool starts, it will prompt you for the OBS WebSocket password.
- This password is configured in OBS
- The easiest approach is to set your own WebSocket password in OBS and click **Apply** or **OK**
- Enter the same password when prompted by the utility
Once connected, the tool will begin collecting metrics automatically.
***Exporting and Sharing Data***
When you stop the tool by pressing **Ctrl + C**, a CSV file is generated in the same directory where the utility is located.
This CSV file can be shared with the **Livery team**, enabling them to gain deeper insights into what occurred during the live streaming session and to more effectively diagnose potential stalls.
---
## Connecting Shopify and Livery
The Livery platform allows customers to connect their Shopify store directly to their Livery account.
This integration enables the **Shopify Product Interaction** feature, which allows customers to:
- Search for products directly from their Shopify store
- Automatically pull product data into Livery
- Eliminate the need to manually enter product details
When using Shopify Product Interaction:
- Viewers are directed to a specific product page in your store.
- The live stream continues in **Picture-in-Picture mode**, ensuring viewers don’t miss any content.
- All information collected via **Livery’s SSO** is automatically added to the Shopify purchase form, minimizing transaction effort.
**Connecting Your Shopify Account**
Follow the steps below to connect your Shopify store to Livery.
***Step 1: Create the App in the Shopify Dev Dashboard***
1. Go to the Shopify Developer Dashboard:
https://dev.shopify.com/dashboard/
2. Click **Create App**
4. Give your app a name.
6. Configure the following **Admin API scopes**: read_product_listings, read_products, unauthenticated_read_product_inventory, unauthenticated_read_product_listings
8. Save the app.
9. Install the app directly from the Developer Dashboard.
***Step 2: Install the App (Internal / Single-Store Integration)***
If this is an internal or single-store integration:
1. Open the app in the Dev Dashboard.
2. Click **Install App**.
4. Choose or create a new shop.
6. Approve the requested permissions.
***Step 3: Configure Credentials in the Livery Plugin***
1. Open the app in the Dev Dashboard.
2. Go to **Settings**.
3. Retrieve:
- `client_id`
- `client_secret`
4. Open the Shopify plugin inside the **Livery Portal**.
5. Configure:
- Client ID
- Client Secret
- Store domain
⚠️ **Important:**
Use the shop’s `*.myshopify.com` domain (not a custom domain).
---
## Add streaming support (SRT)
Third-party tools are required to ingest a live stream via SRT or RTMP into the Livery platform. While Livery does not provide a mobile streaming library to enable live transmission from mobile devices via RTMP or SRT, there are multiple alternatives available. The following guide explains how to add a transmission library to your application, enabling your customers to stream directly from their native application.
### Streaming support for iOS
To add a SRT ingest to your app you can use [SRTHaishinKit](https://github.com/shogo4405/SRTHaishinKit.swift#-installation) library, to do so:
Start by adding the library through Carthage or manually into your project (CocoaPods and Swift Package Manager are not available)
```groovy
github "shogo4405/SRTHaishinKit.swift" "main"
```
Install library prerequisites
```groovy
brew install cmake
```
Add camera and microphone permissions in your project’s `Info.plist`
```groovy
NSCameraUsageDescription
The app uses the camera to Live Stream
NSMicrophoneUsageDescription
The app uses the microphone to Live Stream
```
- Setup `AVAudioSession`
```groovy
import AVFoundation
let session: AVAudioSession = AVAudioSession.sharedInstance()
do {
try session.setPreferredSampleRate(44_100)
try session.setCategory(.playAndRecord, mode: .default, options: [.allowBluetooth])
try session.setMode(.default)
try session.setActive(true)
} catch {
// catch the error here
}
```
- Add a `HKView` or a `MTHKView` to your View Controller
```groovy
var hkView = HKView(frame: view.bounds)
view.addSubview(hkView)
```
- Create and setup the `SRTConnection` and the `SRTStream`
```groovy
let srtConnection = SRTConnection()
let srtStream = SRTStream(srtConnection)
// attach Camera and Audio sources in the stream
srtStream.attachCamera(DeviceUtil.device(withPosition: .back))
srtStream.attachAudio(AVCaptureDevice.default(for: .audio))
```
- Start streaming
```groovy
srtStream.publish("iOS app's stream")
srtConnection.connect("srt://host:port?option=foo") // yours srt ingest URL
```
- Stop streaming
```groovy
srtStream.close()
srtConnection.close()
```
For more details please check the [SRTHaishinKit](https://github.com/shogo4405/SRTHaishinKit.swift#-installation) installation and usage guide.
### Streaming support for Android
To add a SRT ingest to your app you can use [StreamPack](https://github.com/ThibaultBee/StreamPack) library.
Start by adding the library dependencies for SRT:
```groovy
dependencies {
def streampack_version = ...
implementation "io.github.thibaultbee:streampack:${streampack_version}"
implementation "io.github.thibaultbee:streampack-extension-srt:${streampack_version}"
}
```
- You need to add permissions to access the device's camera and microphone.
- Add a AutoFitSurfaceView to preview your stream:
```groovy
```
- Create and configure a streamer:
```groovy
streamer = CameraSrtLiveStreamer(
context,
enableAudio = true
).apply {
// (https://developer.android.com/reference/android/media/AudioRecord?hl=en#AudioRecord(int,%20int,%20int,%20int,%20int)): "44100Hz is currently the only rate that is guaranteed to work on all devices, but other rates such as 22050, 16000, and 11025 may work on some devices."
val audioConfig = AudioConfig(
startBitrate = 128000,
sampleRate = 44100,
channelConfig = AudioFormat.CHANNEL_IN_STEREO
)
configure(audioConfig)
val videoConfig = VideoConfig(
startBitrate = ,
resolution = ,
fps = 30
)
configure(videoConfig)
}
```
- To start the preview just call:
```groovy
streamer.startPreview(preview)
```
- To start streaming using an URL just use:
```groovy
streamer.connect()
streamer.startStream()
```
- At the end don't forget to stop and release the stream and preview:
```groovy
streamer.stopStream()
streamer.disconnect()
streamer.stopPreview()
streamer.release()
```
For more details check [StreamPack](https://github.com/ThibaultBee/StreamPack) quick start guide.
---
## Use the Frictionless login in combination with MailChimp
Livery's [Unverified Frictionless Auth](frictionless-login.md) (based on OpenId), in combination with its Query Parameter support, is a perfect tool for a smooth transition from personal marketing messages, such as emails, to active participation in an Interactive Live Broadcast. The user is automatically logged in once they navigate to the Livery interactive client via the URL, and with the use of Livery's Custom Dimensions, additional data can be passed along and stored on the user's profile. The following 5 steps explain how to set this up in combination with [MailChimp](https://mailchimp.com/).
**Step 1:**
Choose which extra user details you want to gather and store in the users broadcast profile. To guarantee that each user has a unique personal URL, it's crucial to add a unique `livery_sub` value parameter alongside other relevant details. A `livery_sub` value that is not known by the backend generates a new user, while a `livery_sub` value that is already known by the backend updates or extends the user's profile with the additional details provided via the parameters. These parameters can include the user's email address and name, as well as other information like their company, location, and phone number.
**Step 2:**
Upload your audience to Mailchimp either by uploading a file or entering them manually. When uploading your contacts, make sure to include all the parameters (contact information) that you'd like to add to the users broadcast profile. Also, make sure to match the correct labels to each column of information. These labels will be used in the unique user URLs.
**Step 3:**
Create the URL code that will be included in your email campaign.
An example URL is:
```groovy
https://embed.livery.live/?id=64382097e4b07f0e2af767a5&&livery_sub=*|EMAIL|*&livery_preferred_username=*|FNAME|*&livery_cd1=day1&livery_cd2=email
```
For this example, Livery's embed page is being used, with the specific stream ID contained in the '?id=...' part of the URL. The `livery_sub` parameter is used to determine who the user is. If an unknown value is used, a new user is created. If the 'sub' value is already known, the user's profile is updated. In the example above, the email address is used from each user to make the URL unique, and the first name is used as the preferred username in Livery. Next to the parameters used for the Frictionless login, 2 Custom Dimensions (`livery_cd`) are used to store general information about the campaign.
To ensure that Mailchimp recognizes which email address or name to include in the user URL for each specific user when you send out an email, it is important to use the correct merge tag. Mailchimp offers merge tags for various dynamic information. By inserting a merge tag into your email campaign, you can send personalized content to your subscribers. For instance, to include a user's email address, you should use the merge tag `*|EMAIL|*`. To get a comprehensive overview of Mailchimp's merge tags, please visit
**Step 4:**
Create a template email for your email campaign. You can include your URL in multiple ways;
- Add the URL code as text to the template
- Add the URL code as a link to written text (e.g. click here to watch the stream)
- Make a button and connect to URL code to that button
Both option 2 and 3 have an invisible link, so when your contacts receive the email the won’t see the URL with all the parameters.
**Step 5:**
Finalize your email and send out the campaign. Each contact will now receive an email with a unique and personalized URL. Clicking on this link will load the stream and automatically register the user, with a profile containing all the information included in the URL.
## How to live stream with Livery
1. For ingesting video into Livery, enter the Ingest URL and Stream Key in your preferred streaming tool (e.g. OBS, vMix, StreamYard)
2. Check our [recommended settings](video-ingest#mixer-soft-and-hardware) at docs.livery.live for recommended configurations
3. Click the “Start streaming” button in the streaming tool that you are using
4. Our cloud encoder automatically starts
5. After ~60 seconds start-up time, the video will be visible in the player. (The player URL is provided to you or can be specified by the stream ID =...)
---
## WebClip example list
The WebClip interaction is an integrated iframe within the interactive layer of our live-streaming solution, facilitating the seamless embedding of external web content directly into live streams. This feature enhances engagement by dynamically incorporating diverse content types, such as articles, videos, and collaborative documents, in real-time. Explore WebClip to elevate interactivity and audience engagement in your live-streaming sessions. For detailed instructions on how to utilize popular websites with the WebClip, refer to the table below.
| Website | Compatability | Web Clip Size | Description |
|:--------------|:------------------------------------|:----------------------------------------------------------------------------------------|:-------------|
| Amazon | Show a product | Custom size (Width: 80%, 27%). Positioning: Vertical bottom, Horizontal center.| 1. To embed an ad from these platforms, use Iframely: 2. Go to Iframely and create an account. 3. Paste the product link into Iframely. 4. Click “Make it a small card” and copy the link from the embed code. 5. Add “https://” to the beginning of the link if it’s missing. Click “Make it a small card” and copy the link from the embed code.|
| Apple Music | Share an album or playlist | Custom size (Width: 80%, Height: 60%).Positioning: Vertical bottom, Horizontal center. | 1. Click on the three dots next to the playlist or album. 2. Choose “Share” and then “Copy Embed code.” 3. Paste the code into a document and copy the link from it.|
| Apple Music | Share a song | Custom size (Width: 80%, Height: 30%). Positioning: Vertical bottom, Horizontal center.| 1. Click on the three dots next to the song. 2. Choose “Share” and then “Copy Embed code.” 3. Follow the same steps as for an album or playlist. |
| Bol.com | Show a product | Custom size (Width: 80%, 35%). Positioning: Vertical bottom, Horizontal center.| See Amazon description|
| Ebay | Show a product | Custom size (Width: 80%, 32%). Positioning: Vertical bottom, Horizontal center.| See Amazon description|
| Etsy | Show a product | Custom size (Width: 80%, 25%). Positioning: Vertical bottom, Horizontal center.| See Amazon description|
| Figma | Show a design | Full size | To share a Figma project, click on “Share” and then “Get embed code.” Copy the link from the embed code. |
| Google Docs | Work together on a document | Full size | For Google Docs, click on “Share” and then “Copy link.” Ensure that the people you’re sharing the document with have the appropriate rights to view or edit it, depending on your intentions. |
| Google Form | Fill in a form | Small size. Positioning: Vertical bottom, Horizontal center. | Click on “Send,” then select “Send with link,” shorten the URL if needed, and copy the link. |
| Google Slides | Presentation | Small size. Positioning: Vertical center, Horizontal center. | Click on “File,” then “Share,” and “Publish to web.” Ensure that viewers have the appropriate viewing rights. |
| Google Slides | Work together on a presentation | Full size | Click on “Share” and then “Copy link.” Make sure that the individuals you’re sharing the presentation with have the necessary rights to collaborate on it. |
| Instagram | Show a post | Full size | Click on the three dots on the right side of the Instagram post, select “Embed,” and copy the link from the embed code |
| Marktplaats | Show a product | Custom size (Width: 80%, 78%). Positioning: Vertical bottom, Horizontal center.| See Amazon description|
| Mentimeter | Host a quiz, presentation or survey | Full size | Click on “Share” and copy the invite link. |
| Spotify | Share an album or playlist | Custom size (Width: 80%, Height: 30%). Positioning: Vertical bottom, Horizontal center. | 1. Click on the three dots on the playlist or album. 2. Choose “Share” and then “Embed Playlist.” 3. Click “Show code” and copy the link from the generated iframe code.|
| Spotify | Share a song | Custom size (Width: 80%, Height: 30%). Positioning: Vertical bottom, Horizontal center. | 1. Click on the three dots next to the song. 2. Choose “Share” and then “Embed Track.” 3. Follow the same steps as for an album or playlist.|
| Sudoku | Make a Sudoku | Full size | For Sudoku, copy the link from the browser’s address bar. |
| Twitter | Show a tweet | Small size. Positioning: Vertical bottom, Horizontal center.| Click on the three dots on the right side of the tweet, select “Embed,” and copy the link from the embed code.|
| Vimeo | Play a video | Small size. Positioning: Vertical bottom, Horizontal center. | To share a Vimeo video, click on “Share” and copy the link from the “Embed” option. |
| Wikipedia | Browse pages | Full size | To share a Wikipedia page, simply copy the link from the browser’s address bar. |
| Youtube | Play video | Full size | To share a YouTube video, click on “Share” below the video, then select “Embed” and copy the link from the iframe code. |
| Zoom | Have an online meeting | Full size | To share a Zoom call, create a new meeting and copy the invite link. |
---
## How to create an interactive broadcast
1. You receive an email for account activation that enables you to access the Livery portal.
2. In the portal, press the button +CREATE in the middle of your screen or press the button +ADD in the top right corner to add a broadcast.
3. Configure the broadcast details and choose the features you would like to activate (can be changed later)
4. Click on ADD at the top right corner to proceed.
5. Press the +CREATE button in the center of your screen to configure your first interaction
6. Choose the interaction you would like to add from the dropdown menu.
7. Fill out the required fields marked with an asterisk (*).
8. Press the ADD button at the top right corner to add the interactive feature to the timeline.
9. Press the ADD INTERACTION button at the top of the timeline to add more interactions.
10. Click on START BROADCAST on the top right corner to display the interactive overlay in the player (interactions can be created at any time also during the live stream).
11. Broadcast Settings can be changed at any time by clicking on SETTINGS ICON on the top of the screen.
12. Press PLAY to show the interaction in the player, e.g. asking a trivia question to the users
13. You can find all OPEN interactions on the right side under ACTIVE INTERACTIONS
- you can manually STOP an interaction at any time or wait until the timer is up (if configured)
- click on the arrow to see real-time results
14. Additional features, such as Q&A overview and Presenter View, can be found next to the Broadcast Settings. Click on the THREE DOTS in the top right corner to open the menu.
15. Press STOP BROADCAST on the top right corner when you want to end the interactive broadcast (only the interactive overlay will be disabled, the ingested video will still be shown in the player).
# Wix site in combination with Livery
The Livery video player can be added to a [Wix](https://www.wix.com/) powered website. The following guide explains in 4 steps how to add the player.
Step 1: When editing a webpage, choose Add → Embed Code → Popular Embeds → Custom Element
Step 2: Click on "choose source" and add the server URL "https://cdn.jsdelivr.net/npm/@liveryvideo/player@X.Y.Z" as well as the tag name "livery-player". The latest player version is:
[](https://www.npmjs.com/package/@liveryvideo/player)
Step 3:Close the window and “add attributes”. Here you have to enter the “streamid” that you can find in the video portal or after request.
Step 4: Close the window and you can add additional attributes, such as the dimensions of the player, as well. More information can be found at official Wix guidelines:
---
## Livery IDs explained
The Livery solution uses multiple IDs to connect all of its elements together. The IDs referenced throughout our documentation and solution include:
- StreamId
- TenantId
- BroadcastId
- UserId
- Sub
### StreamId
The StreamId is used by the player SDK to load the correct configuration. This configuration specifies details such as which stream to play (m3u8 and MPD URLs), the interactive client URL, and other player-specific information.
For example, if the web player SDK is implemented on multiple websites using the same StreamId, it will behave consistently across those sites. If different StreamId values are used, you can display different configurations or information on each site.
### TenantId
The TenantId is a unique identifier within the Livery interactive solution, think of it as a customer ID. Each Livery customer is assigned a unique TenantId, which is included in the interactive client URL. This ensures that the interactions users see belong to the correct customer.
A single TenantId can be linked to one or more StreamId values. In other words, the interactive client URL (which contains the TenantId) is part of the player configuration and loads alongside its respective video URLs. This setup allows you to use the same interactive client across multiple StreamId values, such as for multiple camera angles of a single event or different languages, all while using the same interactive features.
It is also possible to load the interactive client URL directly, outside the video player SDKs. This is done to provide a second screen experience or for Hybrate events.
### BroadcastId
The BroadcastId is unique to a specific interactive broadcast, which has a defined start and end time. During the broadcast, the customer can collect and store interactive and game data. Each TenantId can only have one active (open) BroadcastId at a time, although multiple BroadcastId values can exist in different states (e.g., "new" or "closed").
### UserId and Sub
The UserId is a unique identifier generated by the Livery solution, scoped to a specific tenant. The same UserId can appear in multiple BroadcastId contexts if the user has participated in more than one broadcast.
The Sub is a user identifier provided by the customer, which must also be unique. Its primary purpose is to map Livery UserId values to user IDs from third-party login systems, ensuring consistent user identification across different platforms.