我的项目须要一个列表循环播放视频的性能,应用的是阿里云公有加密,先说一下实现思路。
- 申请视频列表数据
- 首次默认第一条视频列表数据
- 自动播放第一条数据
- 播放完结自动更新索引值加载下一个视频。
因为播放器是须要dom构造加载的,所以须要应用componentDidMount
办法加载渲染播放器,
咱们页面加载的第一次申请将通过它实现。
阿里云播放器自定义组件
我给自定义播放组件提供了componentWillReceiveProps
办法,用于跟踪配置文件变动,重载播放器播放视频。
接下来是实现的代码
import React from 'react';import Router, {withRouter} from 'next/router'import styles from './index.module.scss'import Aliplayer from "@/components/aliplay";import Head from 'next/head'export default withRouter( class PlayList extends React.Component { constructor(props) { super(props); this.handleCoursePlayBtnClick = this.handleCoursePlayBtnClick.bind(this) this.videoPlayer = React.createRef(); } state = { showDataSource: [], showPlayer: false, instance: null, playNextStatus: true, selectedPlayIndex: 0, } componentDidMount() { this.init() } async init() { const response = await api.getList() try { var data = response.data || [] if (data.length > 0) { let firstVideo = data[0] this.setState({selectedPlayIndex: 0}) this.getInfo(firstVideo.vid) } this.setState({showDataSource: data}) } catch (e) { } } handleCoursePlayBtnClick(index, vid) { this.getInfo(vid) this.setState({selectedPlayIndex: index}) } async getInfo(vid) { var playerConfig = { vid: "", playauth: "", width: '100%', height: '100%', autoplay: true, // 自动播放 useH5Prism: true, // 播放器类型:html5 preload: true, } if (!vid) { throw Error("未提供vid") } var video = {} const responseVideo = await api.getAuth(video.videoSourceId) try { playerConfig.playauth = responseVideo.playAuth } catch (e) { delete playerConfig.playauth delete playerConfig.vid } this.setState({ video: video, playerConfig: playerConfig, }) // console.log("课程加载实现", playerConfig,this.state.showPlayer) } onGetInstance = (player) => { let that = this player.on('ended', async function (e) { if (that.state.playNextStatus) { that.setState({playNextStatus: false}) that.playNextVideo() } setTimeout(() => { that.setState({playNextStatus: true}) clearTimeout() }, 800) // console.log("播放器完结播放", e) }) player.on('playing', function (e) { console.log("播放中") }) player.on('ready', function (e) { console.log("视频准备就绪,行将播放") }); player.on('error', function (e) { console.log("呈现谬误", e) }); player.on('autoplay', function (data) { //能够自动播放 data.paramData }) } playNextVideo = () => { let that = this const dataSource = that.state.dataSource let index = (dataSource.length > that.state.selectedPlayIndex + 1) ? (that.state.selectedPlayIndex + 1) : 0; let id = dataSource[index] && dataSource[index].id that.getInfo(id) that.setState({selectedPlayIndex: index}) } render() { const {showDataSource, selectedPlayIndex, playerConfig, showPlayer} = this.state return ( <div className="match video-page"> <Head> <script src={'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js'} type={'text/javascript'}/> <link href={'https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css'} rel={'stylesheet'}/> </Head> <div className={styles.main + " row match content-start"}> <div className={styles.videoListBox + " h-match cell-scroll-y"}> <div className={styles.listBtn}> <img className={styles.listBtnIcon} alt="" src={"/logo_sign.png"}/> </div> <div className="col content-start match"> <ul className={styles.videoList}> {showDataSource && showDataSource.map((video, i) => { return ( <li className={styles.videoCard + " " + (selectedPlayIndex === i && styles.videoCardActived)} key={i}> <div className="w-match p-2 col"> <div className={styles.imageBox} onClick={() => this.handleCoursePlayBtnClick(i, video.id)}> <img className={styles.videoImage} alt="" src={video.videoCover}/> </div> <div className={styles.title} onClick={() => this.handleCoursePlayBtnClick(i, video.id)}>{video.title} </div> </div> </li> ) })} </ul> </div> </div> <div className={styles.playerContainer + " match bg-black"}> <div className={styles.videoContainer}> <div ref={this.videoPlayer} style={{height: this.state.height}} className={"col " + styles.videoBox}> {(showPlayer && playerConfig) && <Aliplayer config={playerConfig} onGetInstance={instance => this.onGetInstance(instance)} />} </div> </div> </div> </div> </div> ); } })
这里是开发过程中发现并解决的几个点:
1、播放器在完结播放并进行下一个视频播放时,会屡次触发ended
事件,其问题本源就是该播放器状态为完结时,我进行切换下个视频,此时ended
事件再次或屡次激活,导致跳过多个视频。
2、循环播放列表须要对index索引判断,进行播放视频内容更新;
目前的解决方案是做一个状态标记,通过计时器解决该问题;
这里是开发过程中发现未解决的几个点:
1、首次网页加载须要点击能力进行自动播放;