Play adaptive content using Dash.js Player
The following steps show you how to use Dash.js Player with MSE mode to play adaptive streaming content.
Even though the Dash.js Player patches provided by Amazon are for a specific version of the player, they can be ported to any version of Dash.js Player that you want to use. We don't prescribe any specific version of Dash.js Player that you must use. You can decide which version of Dash.js Player is most suitable for your requirement. For issues related to Dash.js Player's ability to handle your content, engage with the open source community.
For more details about the Dash.js Player and the different configurations it supports, see Dash.js Player.
Prerequisites
Before you begin to modify your code to play adaptive content on the Dash.js Player, complete the following prerequisites to set up your app and the player:
- Set up your app to use the W3C Media Player. For more information, see Media Player Setup.
Configure the Dash.js Player for Vega
-
Download the Dash.js Player for Vega to a known location.
-
Expand the Dash.js Player package.
tar -xzf dash-rel-v<x.y.z>-r<a.b>.tar.gz`
For example.
tar -xzf dash-rel-v5.0.0-r1.3.tar.gz
- Navigate to the /dash-rel/scripts directory.
- Run the setup.sh helper script.
./setup.sh
The setup.sh script performs a build which generates a directory named dash.js:
- From the generated dash.js directory, copy the contents of the dash-rel/src/* directory to <app root>/src/*.
- From the generated dash.js directory, copy the dist directory to <app root>/src/dashjsplayer/dist.
Play adaptive content
Complete the following steps to load the Dash.js Player when the Video component is mounted.
To play adaptive content with Dash.js Player
- Open your src/App.tsx and replace the contents with following code.
/*
* Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All rights reserved.
*
* PROPRIETARY/CONFIDENTIAL. USE IS SUBJECT TO LICENSE TERMS.
*/
import * as React from 'react';
import {useRef, useState, useEffect} from 'react';
import {
Platform,
useWindowDimensions,
View,
StyleSheet,
TouchableOpacity,
Text,
} from 'react-native';
import {
VideoPlayer,
VegaVideoSurfaceView,
VegaCaptionsView,
} from '@amazon-devices/react-native-w3cmedia';
import { DashJsPlayer } from './dashjsplayer/DashJsPlayer';
// import polyfills
import Document from './polyfills/DocumentPolyfill';
import Element from './polyfills/ElementPolyfill';
import TextDecoderPolyfill from './polyfills/TextDecoderPolyfill';
import W3CMediaPolyfill from './polyfills/W3CMediaPolyfill';
import MiscPolyfill from './polyfills/MiscPolyfill';
// install polyfills
Document.install();
Element.install();
TextDecoderPolyfill.install();
W3CMediaPolyfill.install();
MiscPolyfill.install();
// set to false if app wants to call play API on video manually
const AUTOPLAY = true;
const DEFAULT_ABR_WIDTH: number = Platform.isTV ? 3840 : 1919;
const DEFAULT_ABR_HEIGHT: number = Platform.isTV ? 2160 : 1079;
const content = [
{
secure: 'false', // true : Use Secure Video Buffers. false: Use Unsecure Video Buffers.
uri: 'https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd',
drm_scheme: '', // com.microsoft.playready, com.widevine.alpha
drm_license_uri: '', // DRM License acquisition server URL : needed only if the content is DRM protected
},
];
export const App = () => {
const player = useRef<any>(null);
const videoPlayer = useRef<VideoPlayer | null>(null);
const timeoutHandler = useRef<ReturnType<typeof setTimeout> | null>(null);
const [buttonPress, setButtonPress] = useState(false);
const [nextContent, setNextContent] = useState({index: 0}); // { index: number }
// Track the nextContent state for re-rendering
const nextContentRef = useRef<number>(0);
// Render in Full screen resolution
const {width: deviceWidth, height: deviceHeight} = useWindowDimensions();
useEffect(() => {
if (nextContent.index !== nextContentRef.current) {
nextContentRef.current = nextContent.index;
// Force Re-rendering of <Video> component.
initializeVideoPlayer();
setNextContent((prev) => {
return {...prev};
});
}
}, [nextContent]);
useEffect(() => {
console.log('app: start AppPreBuffering v13.0');
initializeVideoPlayer();
}, []);
const onEnded = async () => {
console.log('app: onEnded received');
player.current.unload();
player.current = null;
await videoPlayer.current?.deinitialize();
removeEventListeners();
onVideoUnMounted();
setNextContent({index: (nextContent.index + 1) % content.length});
};
const onError = () => {
console.log(`app: AppPreBuffering: error event listener called`);
};
const setUpEventListeners = (): void => {
console.log('app: setup event listeners');
videoPlayer.current?.addEventListener('ended', onEnded);
videoPlayer.current?.addEventListener('error', onError);
};
const removeEventListeners = (): void => {
console.log('app: remove event listeners');
videoPlayer.current?.removeEventListener('ended', onEnded);
videoPlayer.current?.removeEventListener('error', onError);
};
const initializeVideoPlayer = async () => {
console.log('app: calling initializeVideoPlayer');
videoPlayer.current = new VideoPlayer();
// @ts-ignore
global.gmedia = videoPlayer.current;
await videoPlayer.current.initialize();
setUpEventListeners();
videoPlayer.current!.autoplay = false;
initializeDash();
};
const onSurfaceViewCreated = (surfaceHandle: string): void => {
console.log('app: surface created');
videoPlayer.current?.setSurfaceHandle(surfaceHandle);
videoPlayer.current?.play();
};
const onSurfaceViewDestroyed = (surfaceHandle: string): void => {
videoPlayer.current?.clearSurfaceHandle(surfaceHandle);
};
const onCaptionViewCreated = (captionsHandle: string): void => {
console.log('app: caption view created');
videoPlayer.current?.setCaptionViewHandle(captionsHandle);
};
const initializeDash = () => {
console.log('app: in initializePlayer() index = ', nextContent.index);
if (videoPlayer.current !== null) {
player.current = new DashJsPlayer(videoPlayer.current);
}
if (player.current !== null) {
player.current.load(content[nextContent.index], AUTOPLAY);
}
};
const onVideoUnMounted = (): void => {
console.log('app: in onVideoUnMounted');
// @ts-ignore
global.gmedia = null;
videoPlayer.current = null;
};
if (!buttonPress) {
return (
<View style={styles.container}>
<TouchableOpacity
style={styles.button}
onPress={() => {
setButtonPress(true);
}}
hasTVPreferredFocus={true}
activeOpacity={1}>
<Text style={styles.buttonLabel}> Press to Play Video </Text>
</TouchableOpacity>
</View>
);
} else {
return nextContent.index === nextContentRef.current ? (
<View style={styles.videoContainer}>
<VegaVideoSurfaceView
style={styles.surfaceView}
onSurfaceViewCreated={onSurfaceViewCreated}
onSurfaceViewDestroyed={onSurfaceViewDestroyed}
/>
<VegaCaptionsView
onCaptionViewCreated={onCaptionViewCreated}
style={styles.captionView}
/>
</View>
) : (
<View style={styles.videoContainer}></View>
);
}
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: '#283593',
justifyContent: 'center',
alignItems: 'center',
},
button: {
alignItems: 'center',
backgroundColor: '#303030',
borderColor: 'navy',
borderRadius: 10,
borderWidth: 1,
paddingVertical: 12,
paddingHorizontal: 32,
},
buttonLabel: {
color: 'white',
fontSize: 22,
fontFamily: 'Amazon Ember',
},
videoContainer: {
backgroundColor: 'white',
alignItems: 'stretch',
},
surfaceView: {
zIndex: 0,
},
captionView: {
width: '100%',
height: '100%',
top: 0,
left: 0,
position: 'absolute',
backgroundColor: 'transparent',
flexDirection: 'column',
alignItems: 'center',
zIndex: 2,
}
});
- Use the Vega SDK to build the app, run it on device or simulator and collect logs. For more details about building and running apps on the simulator or device, see Create a Vega App, Vega Virtual Device, and Run your app on Fire TV Stick.
To integrate the Dash.js player manually
- Clone the Dash.js package from https://github.com/Dash-Industry-Forum/dash.js.
cd <root dir> git clone https://github.com/Dash-Industry-Forum/dash.js.git
- Reset hard to a specific commit.
cd dash.js git reset --hard ca4c7aa0227d001bb31801faa61a2d57c4e14da4
- Checkout the git branch based on v5.0.0 to a local branch named v5.0.0-kepler:.
git checkout -b amz_5.0.0
- Download the Vega Dash.js Player package to a known location where you will expand the file.
- Expand the file.
tar -xzf dash-rel-v[x.y.z]-r[x.y].tar.gz
- Apply the Dash.js patches:
git apply dash-rel/dash-patch/*.patch -3
- Installthe Dash.js dependencies by running npm install.
npm install
- Build the Dash.js Player by running npm run build.
npm run build
Note: If you recieve error in which the build is unable to resolve the base-64 and xmldom node modules, run the following commands to install them.
npm install --save base-64
npm install --save xmldom
Related topics
- W3C Media Player Overview
- Play adaptive content using Hls.js Player
- Play adaptive content (HLS/DASH) with Shaka Player
- Media Player playlist playback
Last updated: Sep 30, 2025