Taro中小程序LivePlayer使用经验

匿名用户 分类:javascript

自疫情爆发以来,直播行业似乎越来越平凡的出现在各大APP、网页、小程序上,对于我们一个小开发仔来说,接触新兴行业也算是自我提升的一个很好的途径,恰巧公司最近在搞一个小程序关于直播课程的,于是乎顺利的成了我首战项目,接下来分享一下在项目中所遇到的问题,给各位小伙伴踩踩坑~

注意:直播组件优先开通实时音频和视频(小程序管理后台),并且申请对应的直播资质证书

基础直播

由于公司对接第三方推流使用rtmp格式,所以我们最开始使用最基本的直播组件LivePlayer

<LivePlayer
  id="liveVideo"
  ref={player}
  className={style.player}
  src={url}
  mode="RTC"
  autoplay
  onFullScreenChange={fullScreenChange}
  onStateChange={liveStaChange}
>
复制代码

常规使用,没有任何处理,也没有任何业务牵扯,基本可以满足大部分需求,但是,在一定情况下会出现一个bug!!!!

常见问题

(一)、如果用户是重新下载微信,此时的用户没有拨打过语音、视频,也没有授权系统的访问摄像头和麦克风,此时我们拉流rtmp会出现insertLivePlayer:fail:access denied (二)、产品定制需求,需要自定义封面,封面上有倒计时,并且横屏时候也需要~ 此时ios、android会有不同表现

如何解决

解决问题一,既然用户拒绝给微信授权麦克风和摄像头,那么首先想到看能不能在直播点击开始之前,做一个兼容处理,如果用户已经授权,正常播放,否则跳转系统授权页面(提示用户),巧了,在新版本中微信出了一个getAppAuthorizeSetting获取系统授权信息的api,并且还支持跳转,如下:

/**
 * 获取系统权限状态
 * 0 用户已开通对应权限
 * -1 获取系统权限失败
 * 1001 当前微信版本过低,部分功能无法使用~
 * 100 打开系统授权页成功
 * 101 打开系统授权页失败
 * 403 用户点击取消
 * 401 权限没打开
 * */
export const getSystemInfo = (keys: Tkey[], content = '') => {
  return new Promise((resolve) => {
  // 判断微信是否支持api
    const canUseSta = Taro.canIUse('getAppAuthorizeSetting');
    if (!canUseSta) {
      return resolve({ code: 1001, msg: '当前微信版本过低,部分功能无法使用~' });
    }

    // 会返回授权具体信息 https://developers.weixin.qq.com/miniprogram/dev/api/base/system/wx.getAppAuthorizeSetting.html
    // 获取系统授权信息 返回 [key]:undefined | denied | authorized(权限已打开)
    const systemInfo = wx.getAppAuthorizeSetting();
    
    if (!systemInfo) {
      return resolve({ code: -1, msg: '获取系统权限失败~' });
    }
    keys.forEach((item) => {
      if (systemInfo[item] !== 'authorized') {
        Taro.showModal({
          content,
          success: (res) => {
            if (res.confirm) {
              // 跳转系统授权页
              wx.openAppAuthorizeSetting({
                success: () => {
                  return resolve({ code: 100, msg: '打开系统授权页成功~' });
                },
                fail: () => {
                  return resolve({ code: 101, msg: '打开系统授权页失败~' });
                }
              });
            } else {
              return resolve({ code: 403, msg: '用户点击取消~' });
            }
          }
        });
        return resolve({ code: 401, msg: '权限没打开~' });
      }
    });
    return resolve({ code: 0, msg: '用户已开通对应权限~' });
  });
};

// 调用promise
// 获取系统权限
const res: any = await getSystemInfo(
  ['cameraAuthorized', 'microphoneAuthorized'],
  '检测到您没有打开麦克风和相机权限,部分功能将没法使用~'
);
复制代码

问题(二)如何解决ios和android定制化的封面和封面加入的倒计时呢? 既然是定制化,首先想到微信小程序现在加入的同层渲染,具有覆盖小程序原生组件的能力或者使用CoverView、CoverImage

同屏渲染问题在竖屏情况下,原生覆盖能力ios和android表现形式还是不错的,但是,如果在直播全屏横屏的情况下,此时android会出现覆盖不了的情况,因此建议还是用覆盖组件

<LivePlayer
  id="liveVideo"
  ref={player}
  className={style.player}
  src={url}
  mode="RTC"
  autoplay
  onFullScreenChange={fullScreenChange}
  onStateChange={liveStaChange}
>
  <CoverView className={style['cover-main']}>
    <CoverView className={style['cover-main']}>
      <CoverView className={style['live-control']} onClick={showTips}></CoverView>

      {/*水印*/}
      {url && teachStatus && startStatus && (
        <CoverView className={style['watermark']} style={waterP}>
          {waterMaskTxt}
        </CoverView>
      )}

      {fullScreenFlag && (
        <>
          {/*广告*/}
          <Curtain />

          {/* 封面*/}
          <CoverView className={style.cannot_see}>
            {livePostUrl && (
              <CoverImage
                className={style.cannot_see_img}
                src={livePostUrl}
              ></CoverImage>
            )}
            {liveLoading && startStatus && teachStatus && (
              <CoverView className={style.loading}>
                <CoverImage
                  src={LoadingIcon}
                  className={style['loading-icon']}
                ></CoverImage>
                <CoverView className={style['loading-txt']}>加载中...</CoverView>
              </CoverView>
            )}
          </CoverView>

          {/* 倒计时*/}
          {time >= 1800 ? <CountDown time={time} /> : null}
        </>
      )}

      {/*控制*/}
      <CoverView
        className={`${style.control} ${tips ? style['up-ani'] : style['down-ani']}`}
      >
        <CoverView className={style.info}>
          <CoverView>直播</CoverView>
        </CoverView>
        <CoverView className={style['full-screen']} onClick={handleFullScreen}>
          <CoverImage
            className={style.icon}
            src={fullScreenFlag ? tuichuquanping : quanping}
          ></CoverImage>
          <CoverView>{fullScreenFlag ? '小屏播放' : '全屏播放'}</CoverView>
        </CoverView>
      </CoverView>
      {/*顶部标题和返回*/}
      {fullScreenFlag && (
        <CoverView
          className={`${style.head} ${tips ? style['up-ani'] : style['down-ani']}`}
        >
          <CoverImage
            src={BackIcon}
            className={style['back-icon']}
            onClick={handleFullScreen}
          ></CoverImage>
          <CoverView className={style['title']}>
            {courseName || '书画院直播间'}
          </CoverView>
        </CoverView>
      )}
    </CoverView>
  </CoverView>
</LivePlayer>
复制代码

tips:在覆盖组件的情况下,如果是全屏还需要注意,在LivePlayer下的顶层容器和直接子节点需要设置 visiblity:visible;position:relative;z-index:99999;  必须得处理,不然android 的CoverView依然覆盖不了原生直播组件。

.cover-main{

    position: absolute;

    visibility: visible;

    z-index: 999999;

}

原文链接:https://juejin.cn/post/7054860337018830885

回复

我来回复
  • 暂无回复内容