小程序使用 移动直播SDK

2021-03-22 10:22:03 浏览数 (2)

在使用腾讯的 trtc 产品时,要是想在微信小程序实现直播的业务能力,首先需要指定 ‘主播’‘观众’ 角色,小程序的 <trtc-room> 中的标签属性和实例对象的方法都没有做直播状态时的角色区分;再就是想在主播端和观众端实现一些弹幕,点赞,连麦互动时需要使用到 custom 自定义面板,需要对页面进行设计,我也有对 custom 面板的简单使用写了两篇文章可供参考:微信小程序TRTC使用custom自定义面板(理解篇)、微信小程序TRTC使用custom自定义面板(实现篇)。为了方便开发者,腾讯云还有 移动直播SDK,其中集成了弹幕、点赞、美颜、连麦等一些功能的,微信小程序端的调用方式也是以组件形势进行调用。

腾讯 移动直播SDK 基于 RTMP SDK 的多平台直播开发工具,配合腾讯云直播云点播IM等云服务为客户提供了快速接入一体化 的直播方案,支持包括iOS、安卓、小程序等多种接入方式。配合腾讯云直播服务使用 RTMP over QUIC 快速推流至腾讯云,让直播更低卡顿、更低延迟。通过建立加速通道为双向传输的连麦降低音视频传输的延迟,保证直播连麦服务更加流畅。借助AI识别技术,对人脸进行识别定位。支持动销贴纸、手势互动、智能抠背、美颜美妆、高级滤镜等功能,满足客户的多样直播场景。

目前SDK的集成只支持iOS、安卓、微信小程序;摄像头推流的功能也是只有iOS、安卓、微信小程序;录屏推流功能只有iOS和安卓;拉流播放的功能是支持iOS、安卓、微信小程序和Web端;对于连麦互动的方案,微信小程序采用RTMP方案,安卓和iOS可以使用RTMP方案之外还可以采用RTC方案。

微信小程序集成的 移动直播SDK 版本是基础版本,版本功能可以到官方文档 SDK下载 进行查看。微信小程序的集成方法也可以上官网查看完成的流程。其中就是需要添加一个自己的域名来作为播放域名。

微信小程序使用 移动直播SDK 和使用trtc一样,直接引入组件,然后在需要直播的页面中写入 <mlvb-live-room> 组件,以下是代码说明:(参考官方Demo)

代码语言:javascript复制
const app = getApp()

Page({
  component: null,
  data: {
    userName: '',
    roomID: '',
    roomName: '',
    pureAudio: false,
    role: 'audience',
    showLiveRoom: false,
    rooms: [],
    comment: [],
    linked: false,
    debug: false,
    frontCamera: true,
    inputMsg: [],
    muted: false,
    toview: '',
    beauty: 5,
    shouldExit: false,
    phoneNum: '',
    headerHeight: app.globalData.headerHeight,
    statusBarHeight: app.globalData.statusBarHeight,
  },
  // 进入页面将上个页面收集的一些配置信息进行保存
  onLoad: function (options) {
    var self = this;
    console.log("--> onLoad: ", options)
    var role = options.type == 'create' ? 'anchor' : 'audience';

    if (role == 'audience') {
      self.setData({
        roomID: options.roomID,
        roomName: options.roomName,
        userName: options.userName,
        role: role,
        showLiveRoom: true
      }, function () {
        self.start();
      })
    } else {
      self.setData({
        roomName: options.roomName,
        userName: options.userName,
        pureAudio: JSON.parse(options.pureAudio),
        role: role,
        showLiveRoom: true
      }, function () {
        console.log('======> page data: ', self.data)
        self.start();
      })
    }
  },
  // 设置监听 mlvb-live-room 组件返回的事件
  onRoomEvent: function (e) {
    var self = this;
    var args = e.detail;
    console.log('onRoomEvent', args)
    switch (args.tag) {
      case 'roomClosed': {
        wx.showModal({
          content: `房间已解散`,
          showCancel: false, // 标识房间已经解散
          complete: () => {
            wx.navigateBack({ delta: 1 })
          }
        });
        break;
      }
      case 'error': {
        wx.showToast({
          title: `${args.detail}[${args.code}]`,
          icon: 'none',
          duration: 1500
        })
        if (args.code == 5000) {
          this.data.shouldExit = true;
        } else {
          console.error("收到error:", args)
          if (args.code != -9004) {
            setTimeout(() => {
              wx.navigateBack({ delta: 1 })
            }, 1500)
          } else {
            self.setData({
              linked: false, // 出错断开连麦标识
              phoneNum: ''
            })
          }
        }
        break;
      }
      case 'linkOn': { // 连麦连上
        self.setData({
          linked: true, // 标识连麦连上
          phoneNum: ''
        })
        break;
      }
      case 'linkOut': { //连麦断开
        self.setData({
          linked: false, // 标识断开连麦
          phoneNum: ''
        })
        break;
      }
      case 'recvTextMsg': {
        console.log('收到消息:', e.detail.detail);
        var msg = e.detail.detail;
        self.data.comment.push({
          content: msg.message,
          name: msg.userName,
          time: msg.time
        });
        self.setData({
          comment: self.data.comment,
          toview: ''
        });
        // 滚动条置底
        self.setData({
          toview: 'scroll-bottom'
        });
        break;
      }
      case 'requestJoinAnchor': { //收到连麦请求
        var jioner = args.detail;
        var showBeginTime = Math.round(Date.now());
        wx.showModal({
          content: `${jioner.userName} 请求连麦`,
          cancelText: '拒绝',
          confirmText: '接受',
          success: function (sm) {
            var timeLapse = Math.round(Date.now()) - showBeginTime;
            if (timeLapse < 10000) {
              if (sm.confirm) {
                console.log('用户点击同意')
                self.component && self.component.respondJoinAnchor(true, jioner);
              } else if (sm.cancel) {
                console.log('用户点击取消')
                self.component && self.component.respondJoinAnchor(false, jioner);
              }
            } else {
              wx.showToast({
                title: '连麦超时',
              })
            }
          }
        })
        break;
      }
      default: {
        console.log('onRoomEvent default: ', e)
        break;
      }
    }
  },
  // 开始直播或者播放直播
  start: function () {
    var self = this;
    // 选择<mlvb-live-demo>实例
    self.component = self.selectComponent("#id_liveroom")
    console.log('self.component: ', self.component)
    console.log('self:', self);
    // 启动
    self.component.start();
  },
  // 设置页面标签为房间名
  onReady: function () {
    var self = this;
    // 设置页面标签为房间名
    wx.setNavigationBarTitle({
      title: self.data.roomName
    })
  },
  // 检查房间是否还存在,存在恢复直播或播放
  onShow: function () {
    if (this.data.shouldExit) {
      wx.showModal({
        title: '提示',
        content: "收到退房通知",
        showCancel: false,
        complete: function () {
          wx.navigateBack({ delta: 1 });
        }
      });
    }
    var self = this;
    self.component && self.component.resume();
  },
  // 观众点击连麦请求
  onLinkClick: function () {
    var self = this;
    self.component && self.component.requestJoinAnchor();
    self.setData({
      phoneNum: 'phone-1'
    })
    self.setInternal();
  },
  // 接听动画
  setInternal: function () {
    var self = this;
    setTimeout(() => {
      if (!self.data.phoneNum) {
        return;
      }

      var curPhoneNum = '';
      switch (self.data.phoneNum) {
        case 'phone-1':
          curPhoneNum = 'phone-2';
          break;
        case 'phone-2':
          curPhoneNum = 'phone-3';
          break;
        case 'phone-3':
          curPhoneNum = 'phone-1';
          break;
        default:
          break;
      }
      self.setData({
        phoneNum: curPhoneNum
      })
      self.setInternal();
    }, 500);
  },
  // 退出页面后停止直播或播放
  onHide: function () {
    var self = this;
    self.component && self.component.pause();
  },
  // 调试模式开关
  showLog: function () {
    var self = this;
    self.setData({
      debug: !self.data.debug
    })
  },
  // 麦克风开关
  changeMute: function () {
    var self = this;
    self.setData({
      muted: !self.data.muted
    })
  },
  // 美颜开关
  setBeauty: function () {
    var self = this;
    self.setData({
      beauty: self.data.beauty == 5 ? 0 : 5
    })
  },
  // 切换摄像头
  changeCamera: function () {
    var self = this;
    self.component && self.component.switchCamera();
    self.setData({
      frontCamera: !self.data.frontCamera
    })
  },
  // 返回键
  onBack: function () {
    wx.navigateBack({
      delta: 1
    });
  },
})

wxml文件:

代码语言:html复制
<view class='container-box'>
  <!-- 直接调用 移动直播组件 -->
  <mlvb-live-room id="id_liveroom" wx:if="{{showLiveRoom}}" roomid="{{roomID}}" role="{{role}}" roomname="{{roomName}}" pureaudio="{{pureAudio}}" debug="{{debug}}" muted="{{muted}}" beauty="{{beauty}}" template="float" bindRoomEvent="onRoomEvent">

    <!-- 主播返回按钮 -->
    <cover-view slot="casterBackButton" style='position:absolute;left:0;height:10%;width:10%;top:{{(headerHeight   statusBarHeight) - 26}}rpx'>
        <cover-image class='close' src="/pages/Resources/back.png" bindtap="onBack"></cover-image>
    </cover-view>

    <!-- 观众返回按钮 -->
    <cover-view slot="audienceBackButton" style='position:absolute;left:0;height:10%;width:10%;top:{{(headerHeight   statusBarHeight) - 26}}rpx'>
        <cover-image class='close' src="/pages/Resources/back.png" bindtap="onBack"></cover-image>
    </cover-view>
      
    <!-- 主播推流界面上叠加的操作按钮 -->
    <cover-view slot="caster" style='position:absolute;bottom:0;height:10%;width:100%'>
      <cover-view class="operate">
        <!-- 切换(前后置)摄像头 -->
        <cover-view class='img-box'>
          <cover-image class='img-view' src='/pages/Resources/camera{{frontCamera?"":"-gray"}}.png' bindtap="changeCamera"></cover-image>
        </cover-view>
        <!-- 美颜按钮 -->
        <cover-view class='img-box'>
          <cover-image class='img-view' src='/pages/Resources/{{beauty > 0? "beauty" : "beauty-dis"}}.png' bindtap="setBeauty"></cover-image>
        </cover-view>
        <!-- 调试模式开关 -->
        <cover-view class='img-box'>
          <cover-image class='img-view' src='/pages/Resources/{{debug? "log" : "log2"}}.png' bindtap="showLog"></cover-image>
        </cover-view>
      </cover-view>
    </cover-view>

    <!-- 观众播放界面上叠加的操作按钮 -->
    <cover-view slot="audience" style='position:absolute;bottom:0;height:10%;width:100%'>
      <cover-view class='{{!linked? "operate-nolink" : "operate"}}'>
        <!-- 观众端连上麦后 切换摄像头按钮 -->
        <cover-view wx:if="{{linked}}" class='img-box'>
          <cover-image class='img-view' src='/pages/Resources/camera.png' bindtap="changeCamera"></cover-image>
        </cover-view>
        <!-- 观众端连上麦后 美颜开关 -->
        <cover-view wx:if="{{linked}}" class='img-box'>
          <cover-image class='img-view' src='/pages/Resources/{{beauty > 0? "beauty" : "beauty-dis"}}.png' bindtap="setBeauty"></cover-image>
        </cover-view>
        <!-- 没连上麦时 发起连麦请求的按钮 -->
        <cover-view wx:if="{{!linked}}" class='img-box-big'>
          <cover-image class='img-view-big' src='/pages/Resources/video-call.png' bindtap="onLinkClick"></cover-image>
        </cover-view>
        <!-- 调试模式开关 -->
        <cover-view class='{{!linked? "img-box-small" : "img-box"}}'>
          <cover-image class='{{!linked? "img-view-small" : "img-view"}}' src='/pages/Resources/{{debug? "log" : "log2"}}.png' bindtap="showLog"></cover-image>
        </cover-view>
      </cover-view>
      <!-- 请求连麦动画 -->
      <cover-image wx:if="{{phoneNum}}" class='center' src="/pages/Resources/{{phoneNum}}.png"></cover-image>
    </cover-view>
  </mlvb-live-room>
</view>

0 人点赞