使用Dash.js播放器播放自适应内容
以下步骤介绍如何将Dash.js播放器用于MSE模式,以播放自适应流媒体内容。
尽管亚马逊提供的Dash.js播放器补丁针对的是特定版本的播放器,但可以将它们移植到您想使用的任何版本的Dash.js播放器上。我们没有规定您必须使用的任何特定Dash.js播放器版本。您可以决定哪个版本的Dash.js播放器最适合您的要求。有关Dash.js播放器处理您内容的能力的问题,请洽询开源社区。
有关Dash.js播放器及其支持的不同配置的更多详细信息,请参阅Dash.js播放器(仅提供英文版)。
先决条件
在开始修改代码以在Dash.js播放器上播放自适应内容之前,请先满足以下先决条件以设置您的应用程序和播放器:
- 将您的应用设置成使用W3C媒体播放器。有关更多信息,请参阅媒体播放器设置。
配置适用于Vega的Dash.js播放器
-
将适用于Vega的Dash.js播放器下载到已知位置。
-
展开Dash.js播放器程序包。
tar -xzf dash-rel-v<x.y.z>-r<a.b>.tar.gz`例如:
tar -xzf dash-rel-v5.0.0-r1.3.tar.gz - 导航到/dash-rel/scripts目录。
- 运行setup.sh帮助程序脚本。
./setup.sh
setup.sh脚本执行构建,生成一个名为dash.js的目录。
- 从生成的dash.js目录中,将dash-rel/src/*目录中的内容复制到<应用根目录>/src/*。
- 从生成的dash.js目录中,将dist目录复制到<应用根目录>/src/dashjsplayer/dis。
播放自适应内容
完成以下步骤,在安装Video组件后加载Dash.js播放器。
使用Dash.js播放器播放自适应内容
-
打开您的src/App.tsx并用以下代码替换内容。
/* * 版权所有 (c) 2024 Amazon.com, Inc.或其关联公司。 保留所有权利。 * * 专有/机密信息。 相关使用受许可条款的约束。 */ 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'; // 导入polyfill 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'; // 安装polyfill Document.install(); Element.install(); TextDecoderPolyfill.install(); W3CMediaPolyfill.install(); MiscPolyfill.install(); // 如果应用需要手动在视频上调用播放API,则设置为false 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: 使用安全视频缓冲区。false: 使用不安全的视频缓冲区。 uri: 'https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd', drm_scheme: '', // com.microsoft.playready, com.widevine.alpha drm_license_uri: '', // DRM许可证获取服务器URL:仅当内容受DRM保护时才需要 }, ]; 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 } // 跟踪nextContent状态以进行重新呈现 const nextContentRef = useRef<number>(0); // 以全屏分辨率呈现 const {width: deviceWidth, height: deviceHeight} = useWindowDimensions(); useEffect(() => { if (nextContent.index !== nextContentRef.current) { nextContentRef.current = nextContent.index; // 强制重新渲染<Video>组件。 initializeVideoPlayer(); setNextContent((prev) => { return {...prev}; }); } }, [nextContent]); useEffect(() => { console.log('app:启动AppPreBuffering v13.0'); initializeVideoPlayer(); }, []); const onEnded = async () => { console.log('app:已收到onEnded'); 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:调用了错误事件侦听器`); }; const setUpEventListeners = (): void => { console.log('app:设置事件侦听器'); videoPlayer.current?.addEventListener('ended', onEnded); videoPlayer.current?.addEventListener('error', onError); }; const removeEventListeners = (): void => { console.log('app:删除事件侦听器'); videoPlayer.current?.removeEventListener('ended', onEnded); videoPlayer.current?.removeEventListener('error', onError); }; const initializeVideoPlayer = async () => { console.log('app:将调用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:已创建表面'); videoPlayer.current?.setSurfaceHandle(surfaceHandle); videoPlayer.current?.play(); }; const onSurfaceViewDestroyed = (surfaceHandle: string): void => { videoPlayer.current?.clearSurfaceHandle(surfaceHandle); }; const onCaptionViewCreated = (captionsHandle: string): void => { console.log('app:已创建字幕视图'); 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}>按下以播放视频</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, } }); -
使用Vega SDK来构建应用,在设备或模拟器上运行它并收集日志。有关在模拟器或设备上构建和运行应用的更多详细信息,请参阅创建Vega应用、Vega虚拟设备和在Fire TV Stick上运行应用。
手动集成Dash.js播放器
- 从https://github.com/Dash-Industry-Forum/dash.js克隆Dash.js程序包。
cd <根目录> git clone https://github.com/Dash-Industry-Forum/dash.js.git - 硬重置为特定的提交。
cd dash.js git reset --hard ca4c7aa0227d001bb31801faa61a2d57c4e14da4 - 将基于v5.0.0的git分支签出到名为v5.0.0-kepler的本地分支:
git checkout -b amz_5.0.0 - 将VegaDash.js播放器程序包下载到已知位置,您将在此处解压该文件。
- 展开文件。
tar -xzf dash-rel-v[x.y.z]-r[x.y].tar.gz - 应用Dash.js补丁:
git apply dash-rel/dash-patch/*.patch -3 - 通过运行npm install安装Dash.js依赖项。
npm install - 通过运行npm run build来构建Dash.js播放器。
npm run build
注意: 如果您收到错误消息,指出内部版本无法解析base-64和xmldom节点模块,请运行以下命令进行安装。
npm install --save base-64
npm install --save xmldom
相关主题
Last updated: 2025年9月30日

