媒体播放器播放列表播放
本主题提供了示例,说明如何在onEnded
属性上实现JavaScript逻辑以在第一个视频完成后自动开始播放第二个视频。
先决条件
将您的应用设置成使用WC3媒体播放器。有关更多信息,请参阅媒体播放器设置。
整合播放列表
在App.tsx中,按照代码示例所示进行修改。它将内容转换为内容数组并添加另一个媒体项目条目。然后,它会注册onEnded
属性,卸载当前内容,并在触发onEnded
事件时开始播放下一个内容。以下重点介绍的步骤与播放内容播放列表有关
代码示例
以下代码示例显示了两种播放非自适应内容的方法:
VideoPlayer API
打开您的src/App.tsx并将其内容替换为以下代码块。
使用Vega SDK来构建应用,在设备或模拟器上运行它并收集日志。有关在模拟器上构建和运行应用的更多详细信息,请参阅创建Vega应用和Vega虚拟设备。
/*
* 版权所有 (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 {ShakaPlayer, ShakaPlayerSettings} from './shakaplayer/ShakaPlayer';
// 如果应用需要手动在视频上调用播放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 currShakaPlayerSettings = useRef<ShakaPlayerSettings>({
secure: false, // 通过安全或非安全模式进行播放
abrEnabled: true, // 启用自适应比特率 (ABR) 切换
abrMaxWidth: DEFAULT_ABR_WIDTH, // 对ABR允许的最大宽度
abrMaxHeight: DEFAULT_ABR_HEIGHT, // 对ABR允许的最大高度
});
const player = useRef<any>(null);
const videoPlayer = useRef<VideoPlayer | null>(null);
const timeoutHandler = useRef<ReturnType<typeof setTimeout> | null>(null);
const [playerSettings, setPlayerSettings] = useState<ShakaPlayerSettings>(
currShakaPlayerSettings.current,
);
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;
initializeShaka();
};
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 initializeShaka = () => {
console.log('app: in initializePlayer() index = ', nextContent.index);
if (videoPlayer.current !== null) {
player.current = new ShakaPlayer(videoPlayer.current, playerSettings);
}
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,
}
});
Video组件
打开您的src/App.tsx并将其内容替换为以下代码块。
使用Vega SDK来构建应用,在设备或模拟器上运行它并收集日志。有关在模拟器上构建和运行应用的更多详细信息,请参阅创建Vega应用和Vega虚拟设备。
/*
* 版权所有 (c) 2024 Amazon.com, Inc.或其关联公司。 保留所有权利。
*
* 专有/机密信息。 相关使用受许可条款的约束。
*/
import * as React from "react";
import { useRef } from "react";
import { useWindowDimensions, View, StyleSheet } from "react-native";
import { Video } from "@amazon-devices/react-native-w3cmedia";
// 如果应用需要手动在视频上调用播放API,则设置为false
const AUTOPLAY = true;
const content = {
uri: "https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd",
};
export const App = () => {
const video = useRef<Video | null>(null);
// 以全屏分辨率呈现
const { width: deviceWidth, height: deviceHeight } = useWindowDimensions();
console.log("AppNonAdaptiveVidoe v1.0");
return (
<View style={styles.videoContainer}>
<Video
autoplay={AUTOPLAY}
src={content.uri}
width={deviceWidth}
height={deviceHeight}
controls={true}
ref={(ref) => {
video.current = ref;
}}
/>
</View>
);
};
const styles = StyleSheet.create({
videoContainer: {
backgroundColor: "white",
alignItems: "stretch",
},
});
另请参阅
Last updated: 2025年9月30日