Chain play / Up Next
What you learn​
You're instantiating DIVA Player in your web front-end and relying on third party video streaming source.
The goal of this article is to build the simplest front-end to stream a video from third party video production with, at the end, the activation of up-next in combination with end of play.
Before starting​
- Ensure the your video production you rely on is up and running.
- Set the videoId and the related setting configuration.
- Ensure the VideoMetadata contains the upNext property.
- Ensure the VideoMetadata contains the countdownToAutoplay property.
- Ensure the settings contains the timeToDisableAutoplay property.
Instantiation​
Write the Basic instantiation code. There's no additional code to write, unless you need to overwrite the autoplay behavior that the VideoMetadata contains.
Up next configuration​
Write the App() function to read the VideoMetadataMap as in the following example
Set the upNext
property:
null
default value if not set and up next not shown- This is the only mandatory value to set to show up next:
"upNext":{
"itemId":"<videoId>",
}
- These are the complete fields that can be set:
"upNext":{
"itemId":"<videoId>",
"title":"<title>",
"caption":"<caption>",
"imageUrl":"<imageUrl>"
}
Autoplay configuration​
Set the countdownToAutoplay
property:
10000
default value if not set0
to set no autoplay- A positive integer that specifies the number of milliseconds before UpNext start automatically(Without user interaction). (eg: with
10000
the UpNext video starts automatically after 10 seconds).
"behaviour": {
"endOfPlay": {
"countdownToAutoplay":10000 //milliseconds, default 10000, 0 or negative means disabled
},
}
Set the timeToDisableAutoplay
property in the settings
file:
-
5400000
default value if not set -
A positive integer that specifies the number of milliseconds of user interaction before Autoplay to be disabled. (eg: with
5400000
the Autoplay is disabled after 90 minutes of user not interactions.
"general": {
"timeToDisableAutoplay": 5400000, //milliseconds, default 5400000
},
The autoplay will start if countdownToAutoplay
has set. In this case the countdown will start.
countdownToAutoplay
will enable or disable the autoplay at the end of the milliseconds set ()timeToDisableAutoplay
will disable the autoplay at the end of the milliseconds set with no interactions
Working sample code (.tsx)​
- RW
- WebTV
// DIVA Player SDK
import { DivaWebComponent } from "@deltatre-vxp/diva-sdk/diva-web-sdk";
import type { DivaConfiguration, VideoMetadata, VideoMetadataClean } from "@deltatre-vxp/diva-sdk/diva-web-sdk";
// Import SDK style
import "@deltatre-vxp/diva-sdk/diva-web-sdk/index.min.css";
const libs = {
mux: "https://cdnjs.cloudflare.com/ajax/libs/mux.js/6.2.0/mux.min.js",
shaka: "https://cdnjs.cloudflare.com/ajax/libs/shaka-player/4.11.2/shaka-player.compiled.js",
hlsJs: "https://cdn.jsdelivr.net/npm/hls.js@1.5.7",
googleIMA: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',
googleDAI: 'https://imasdk.googleapis.com/js/sdkloader/ima3_dai.js',
googleCast: 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1',
threeJs: 'https://cdnjs.cloudflare.com/ajax/libs/three.js/0.148.0/three.min.js',
};
const config: DivaConfiguration = {
videoId: "<video id>",
libs: libs,
setting: {
general: {
culture: 'en-GB',
timeToDisableAutoplay: 5400000,
}
},
dictionary: {
messages: {},
},
videoMetadataProvider: async (
videoId: string,
currentVideoMetadata?: VideoMetadataClean,
playbackState?: {
chromecast?: boolean | undefined;
}): Promise<VideoMetadata> => {
return {
"title": "Video Title",
"sources": [
{
"uri": "<stream URL>",
"format": "HLS"
}
],
"videoId": "<video id>",
"upNext": {
"videoId": "500080_minimal",
"title": "Juventus vs Inter",
"caption": "Final match of the season",
"imageUrl": "https://www.example.com/image.jpg",
},
"behavior": {
"endOfPlay": {
"countdownToAutoplay": 10000
}
}
}
},
};
export const App = () => {
return <DivaWebComponent config={config} />;
};
// DIVA Standalone SDK
import { DivaWebTV } from "@deltatre-vxp/diva-sdk/diva-webtv-sdk";
import type {
DivaWebTVInitType,
DivaWebTVProps,
VideoMetadata,
VideoMetadataClean
} from "@deltatre-vxp/diva-sdk/diva-webtv-sdk";
// Import SDK style
import "@deltatre-vxp/diva-sdk/diva-webtv-sdk/index.min.css";
const init: DivaWebTVInitType = {
setting: {
general: {
culture: "en-GB",
timeToDisableAutoplay: 5400000,
}
},
videoId: "<video id>"
};
const libs = {
mux: "https://cdnjs.cloudflare.com/ajax/libs/mux.js/6.2.0/mux.min.js",
shaka: "https://cdnjs.cloudflare.com/ajax/libs/shaka-player/4.11.2/shaka-player.compiled.js",
hlsJs: "https://cdn.jsdelivr.net/npm/hls.js@1.5.7",
googleIMA: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',
googleDAI: 'https://imasdk.googleapis.com/js/sdkloader/ima3_dai.js',
};
const props: DivaWebTVProps = {
init,
libs,
dictionary: {
messages: {},
},
videoMetadataProvider: async (
videoId: string,
currentVideoMetadata?: VideoMetadataClean,
playbackState?: {
chromecast?: boolean | undefined;
}): Promise<VideoMetadata> => {
return {
"title": "Video Title",
"sources": [
{
"uri": "<stream URL>",
"format": "HLS"
}
],
"videoId": "<video id>",
"upNext": {
"videoId": "500080_minimal",
"title": "Juventus vs Inter",
"caption": "Final match of the season",
"imageUrl": "https://www.example.com/image.jpg",
},
"behavior": {
"endOfPlay": {
"countdownToAutoplay": 10000
}
}
}
},
};
export const App = () => {
return <DivaWebTV {...props} />;
}
Override the Up Next component​
To override the Up Next component, you can use the ChainPlayComponent
property in the renderCustomization
object.
This property allows you to pass a custom component to the Up Next screen.
const config = {
// ...other configuration
renderCustomization: {
ChainPlayComponent: (props) => React.ReactElement // CustomChainPlayComponent,
},
};
Props​
There are several props provided by Diva and passed to your component that may be useful for you.
type Props = {
/**
* The metadata of the video that is currently playing/ending.
*/
videoMetadata: VideoMetadata | undefined;
/**
* Function to switch the video to the next one.
* @param videoId The ID of the video to switch to.
*/
switchVideo: (videoId: string) => void;
/**
* Information whether the component should be focused. Default: false
* Passed only on webtv platforms.
*/
focused?: boolean;
};
Focus Handling on WebTV platforms​
The component should not focus itself on render. Rather, the focus should be
based on the focused
prop.
- When this prop becomes
true
, the component should focus itself visually and make sure that it will be able to receive keydown events. - When this prop becomes
false
, the component should only remove visual focus representation and make sure not to react to any events. Any change inactiveElement
will be handled by Diva.
Events handling​
If the component handles keydown events, it should stop the propagation of the event if the event was handled by the component. Events that do not result in any action by the component should be propagated to Diva. This allows handling the focus back to Diva in case of direction keys not being processed by the component.
Dynamic fallback to default component​
It is possible to fallback back to the default component provided by Diva
dynamically from your custom component. To do this, simply throw
CustomComponentRenderDefault
error during the render phase.
import { CustomComponentRenderDefault } from '@deltatre-vxp/diva-webtv-sdk';
const MyCustomComponent = ({ focused }: Props) => {
const [dataError, setDataError] = useState(false);
useEffect(() => {
(async () => {
try {
// Fetch data
} catch (error) {
setDataError(true);
}
})();
}, [])
if (dataError) {
throw new CustomComponentRenderDefault();
}
return (
// Your component
)
};
Empty render​
Sometimes you might wish not to render anything. In such case, it is not
possible to just return null
. The null render result is not detectable easily
by the parent component. Because of focus handling, Diva would still try to
focus this empty component. To avoid this, you can throw
CustomComponentRenderNothing
error. This will be handled by Diva, nothing will
be rendered and the focus will not be sent to the component.
import { CustomComponentRenderNothing } from '@deltatre-vxp/diva-webtv-sdk';
const MyCustomComponent = ({ focused }: Props) => {
const data = useDataProvider();
if (data.length === 0) {
throw new CustomComponentRenderNothing();
}
return (
// Your component
)
};
Error handling​
Your custom component is wrapped by ErrorBoundary. If an error is thrown during
the render phase, the component will be unmounted and the default component will
be rendered instead. The error will be logged. In case of
CustomComponentRenderDefault
or CustomComponentRenderNothing
error, the
errors are not logged as errors.
In development mode, the error message will always be displayed and it may trigger error overlays for dev servers. However, in production mode these errors should be handled gracefully without interrupting the user experience.
Dictionary​
Ensure the dictionary file contains the relevant keys.
Analytics events​
Find here the available analytics events for the Chain play / Up Next.
Behaviour​
- During the end screen, ChainPlay elements will be shown on the bottom left, including Next Episode Information and countdown to autoplay.
- When casting to Chromecast, ChainPlay is disabled on the receiver device, meaning the next episode prompt and countdown will not be shown on the receiver.
Countdown Activation​
- The countdown starts only when the Squeeze Back feature is triggered or at the end of playback (if Squeeze Back is not enabled).
- The countdown timer will display the remaining seconds as per the design specifications. If no countdown value is set, the timer will not appear.
- When the countdown finishes, the next episode will automatically start unless the user interacts with the Endboard.
Countdown Cancellation​
- If the user interacts with the Endboard, the countdown timer is canceled, and the automatic transition to the next episode is halted. The specific interactions that cancel the countdown vary by platform:
- WebTV: Any change in focus, or pressing any directional key, even if it does not result in a focus shift.
- Responsive Web: Any mouse movement will cancel the countdown.
Countdown to Up-Next​
- When the countdown finishes without user interaction, the next episode will automatically load using the supplied video ID and begin playback.
- When the user selects the "Next Episode" item by clicking or tapping on it, the next episode will launch immediately, overriding the countdown.
Autoplay Limitations​
- To prevent continuous autoplay during inactive sessions, a ChainPlay timeout will be applied:
- The system will pause autoplay after a set number of episodes (set by the platform or session) if there is no user interaction.
- A session-based timer will track user inactivity. If the user does not interact with the device for a specified period, autoplay will be paused.
- Any user interaction with the device (e.g., pressing buttons, moving the cursor, or tapping on the screen) will reset the inactivity timer, allowing autoplay to continue.