看我如何在 React 中使用 aliPlayer

2023-06-19 下午前端 70 次浏览暂无评论

今天接到一个需要播放视频的需求,公司采用了阿里云视频点播的方案。准确的说是阿里云视频点播中的“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.')
        });

在我跟这段代码深入交流一番后,得到结论:创建实例时必须传递正确的vidplayauth,传空值或者错误值都不行。都会展示类似下图所示的内容。

![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)

鲁迅曾经说过:发现问题就等于问题解决了一半。

相信各位读者老爷也能看出来,解决这个问题的核心就是让视频播放器只存在一个实例。

我这里有两种实现思路:

第一种:只创建一个实例,通过操作该实例的vidplayauth参数,实现视频的切换。

第二种:保持只存在一个实例,当创建实例时,将之前已存在的实例进行销毁,实现视频的切换。

刚开始我采用了第一种方案进行实现,通过翻阅官方文档,我找到了下面这个方法。

![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已经为我们考虑到了很多场景。

具体的配置项都在这里面:播放器接口说明

通过对这些属性、方法和事件的处理,完全可以实现个性化配置的播放器,相信各位观众老爷都是有这个实力的,我就不在这废话了。

总结

踩坑之时无人为我指路,爬坑之后得此文章,希望能帮助到有需要的人。


目录

踩坑+爬坑
代码优化
扩展
总结
ICP备案号:鲁ICP备2020040322号