看我如何在 React 中使用 aliPlayer
今天接到一个需要播放视频的需求,公司采用了阿里云视频点播的方案。准确的说是阿里云视频点播中的“web播放器”。
当时心想,不就是调用一下API吗,so easy~当真正开发起来之后,果然不出意外的打脸了。
传送门:官方文档
官方文档的介绍可以说是“相当简洁”,再加上全是原生js的示例,一时间我竟不知该如何入手。
当我看完这份“一览无余”的文档后,我开始动手了~
引入
首先根据官方文档将播放器接入
首先是引入Web播放器SDK,这里我使用的是npm方式引入
。
- 安装npm包。
npm i aliyun-aliplayer
- 导出aliplayer和样式。
//导出aliplayer
import 'aliyun-aliplayer'
// 导出样式
import 'aliyun-aliplayer/dist/skins/default/aliplayer-min.css'
然后将元素挂载到页面,元素放在哪里都可以,保证能获取到即可。
<div id="J_prismPlayer"></div>
踩坑+爬坑
当完成前两步后,只剩下实例化播放器。当我认为会一切顺利的时候,爬坑之旅开始了。
我司采用的是“VID+PlayAuth播放”方式,其他播放方式大致相同,就不在此多做介绍了。
下面是官方文档的示例:
var player = new Aliplayer({
id: 'J_prismPlayer',
width: '100%',
vid : '<your video ID>',//必选参数。音视频ID。示例:1e067a2831b641db90d570b6480f****。
playauth : '<your PlayAuth>',//必选参数。音视频播放凭证。
},function(player){
console.log('The player is created.')
});
在我跟这段代码深入交流一番后,得到结论:创建实例时必须传递正确的vid
和playauth
,传空值或者错误值都不行。都会展示类似下图所示的内容。
![image-20230518175533915](/Users/mac/Library/Application Support/typora-user-images/image-20230518175533915.png)
在我略加思索后,得出了如下代码:
// 播放器
const [player, setPlayer] = useState<any>(null);
// 当前播放视频
const [curPlayVideo, setCurPlayVideo] = useState<any>(null);
// 初始化播放器
useEffect(()=>{
if(!curPlayVideo) return; // 如果播放视频不存在,不创建实例
var instance = new Aliplayer({
id: 'J_prismPlayer',
width: '100%',
vid : curPlayVideo.vid,
playauth : curPlayVideo.playauth,
});
setPlayer(instance);
},[curPlayVideo])
这里通过监听curPalyVideo
对象,对播放器进行实例化。
当程序设置curPlayVideo
对象后,播放器进行实例化,代码运行正常。效果如下图所示。
![image-20230518180025078](/Users/mac/Library/Application Support/typora-user-images/image-20230518180025078.png)
但是凭我多年的爬坑经验告诉我,事情绝不会这么简单。
我化身测试一通乱点,果然发现了问题:每点击一个视频进行播放时,都会创建一个视频播放的实例。
这会导致播放器出现各种问题,比如多个视频重叠、暂停按钮无效等。效果如下图所示。
![image-20230519095118433](/Users/mac/Library/Application Support/typora-user-images/image-20230519095118433.png)
鲁迅曾经说过:发现问题就等于问题解决了一半。
相信各位读者老爷也能看出来,解决这个问题的核心就是让视频播放器只存在一个实例。
我这里有两种实现思路:
第一种:只创建一个实例,通过操作该实例的vid
和playauth
参数,实现视频的切换。
第二种:保持只存在一个实例,当创建实例时,将之前已存在的实例进行销毁,实现视频的切换。
刚开始我采用了第一种方案进行实现,通过翻阅官方文档,我找到了下面这个方法。
![image-20230518182409476](/Users/mac/Library/Application Support/typora-user-images/image-20230518182409476.png)
使用播放器实例调用此方法。
player.replayByVidAndPlayAuth(vedio?.vid, vedio?.playauth)
结果浏览器报错,找不到这个方法。
自认为使用方法并没有问题,所以第一种实现思路就被我pass了,如果有大佬对这方面有了解,再次感谢指正!
最终我采用了第二种实现思路:每当创建一个播放器实例,就把之前存在的实例销毁。
代码最终效果如下:
// 播放器
const [player, setPlayer] = useState<any>(null);
// 当前播放视频
const [curPlayVideo, setCurPlayVideo] = useState<any>(null);
// 初始化播放器
useEffect(()=>{
if(!curPlayVideo) return; // 如果播放视频不存在,不创建实例
var instance = new Aliplayer({
id: 'J_prismPlayer',
width: '100%',
vid : curPlayVideo.vid,
playauth : curPlayVideo.playauth,
});
setPlayer(instance);
return () => {
instance.dispose(); // 销毁实例
}
},[curPlayVideo])
当用户改变curPlayVideo
对象时,程序会先将已存在的实例销毁,然后重新创建新的实例。
经过我严谨的测试后,程序运行一切正常。效果如下图所示。
![image-20230519094845006](/Users/mac/Library/Application Support/typora-user-images/image-20230519094845006.png)
代码优化
当我以为万事大吉的时候,又出现问题啦!😭
在 web 端来看,代码一切正常,但是在 appCloud 中使用时,出现一些了bug。
在 appCloud 中,当视频全屏,然后还原后。播放器会直接销毁然后重新创建,之前的观看进度也不会保留。
经过分析后得出结论,这是 appCloud 本身产生的问题,当视频全屏切换时,h5 页面会重新加载,进而导致播放器销毁然后重新创建。
这里针对这个特殊情况进行优化:对实例进行判断,如果实例已存在,则不创建实例。不再对播放器进行销毁。
另外发现在某些场景下视频播放会自动进入全屏模块,需要设置一下播放器类型。这部分内容参考了 CSDN的某篇文章
最终版代码如下:
// 播放器
const [player, setPlayer] = useState<any>(null);
// 当前播放视频
const [curPlayVideo, setCurPlayVideo] = useState<any>(null);
// 初始化播放器
useEffect(()=>{
if(!curPlayVideo) return; // 如果播放视频不存在,不创建实例
if (player) { // 如果实例已存在,不创建实例
player.replayByVidAndPlayAuth(
curPlayVideo?.play_info?.vid,
curPlayVideo?.play_info?.playauth
);
return;
}
var instance = new Aliplayer({
id: 'J_prismPlayer',
width: '100%',
vid : curPlayVideo.vid,
playauth : curPlayVideo.playauth,
},
function (instance: any) {
instance.on("ready", () => {
const ua = navigator.userAgent.toLocaleLowerCase();
const video = document.querySelector("video");
if (!video) return;
// x5内核
if (
ua.match(/tencenttraveler/) != null ||
ua.match(/qqbrowse/) != null
) {
video.removeAttribute("x5-playsinline"); // x5内核 启用同层H5播放器(会有黑屏缓冲问题)
video.setAttribute("x5-video-player-type", "h5-page");
} else {
// ios端
video.setAttribute("webkit-playsinline", true);
video.setAttribute("playsinline", true);
}
});
});
setPlayer(instance);
},[curPlayVideo])
扩展
在我的不懈努力下,视频已经可以正常的切换和播放了。
但是一个成熟的播放器只能播放视频是不够的,还应该有各种配置。
幸运的是,aliplayer已经为我们考虑到了很多场景。
具体的配置项都在这里面:播放器接口说明
通过对这些属性、方法和事件的处理,完全可以实现个性化配置的播放器,相信各位观众老爷都是有这个实力的,我就不在这废话了。
总结
踩坑之时无人为我指路,爬坑之后得此文章,希望能帮助到有需要的人。