【愚公系列】2022年09月 微信小程序-实现直播功能

2022-09-28 12:42:28 浏览数 (1)

  • 1.前提准备
  • 2.live-player代码封装
  • 3.live-pusher代码封装

前言

目前短视频直播在当下是非常好的一个职业,而且对应的直播平台也很多,比如抖音,微视,虎牙等等,因为疫情现在很多人无法办工,在家里如果有这个直播系统的帮助能很好地运用做好短视频内容后就要做好粉丝互动这一块,因为点赞评论的数量越多,给我们带来的流量肯定也不会少,还可以把自己的短视频作品转发给朋友,让其点赞评论给自己增加气氛,这样还能带来一些精准的粉丝流量,给自己增加额外的收入。

小程序直播相关API文档可以参照以下两个:

  • 实时播放live-player:https://cloud.tencent.com/developer/article/1973457
  • 实时录制live-pusher:https://cloud.tencent.com/developer/article/1973456

一、实现直播功能

1.前提准备

实现直播功能需要准备以下东西:

  • 云直播入口:https://cloud.tencent.com/product/css
  • 资源包文档:https://cloud.tencent.com/document/product/267/49247
  • 域名管理文档:https://cloud.tencent.com/document/product/267/40935

腾讯云直播平台主界面

资源包界面

域名管理界面

小程序安装包:npm install blueimp-md5

2.live-player代码封装

代码语言:javascript复制
var md5 = require('blueimp-md5/index')

// https://www.ffmpeg.org/
// ffplay `url`

// rtmp://live.rixingyike.com/live/StreamName?txSecret=Md5(key StreamName hex(time))&txTime=hex(time)
function generatePlayUrl(domain, streamName, key, time = null){
  if (!time){
    // one day more
    time = Math.round( Date.now()/1000 ) // get Unix时间戳(Unix timestamp)
    time  = 24 * 60 * 60 * 1000
  } 
  var txTime = time.toString(16).toUpperCase()
  var txSecret = md5(key streamName txTime);
  var ext_str = `?txSecret=${txSecret}&txTime=${txTime}`
  return `http://${domain}/live/${streamName}.flv${ext_str}`
}

Page({
  data:{
    // 开发者工具暂不支持 rtmp 协议,请到客户端调试。
    // http://live.rixingyike.com/live/default.flv
    // livePlayUrl:'rtmp://live.rixingyike.com/live/default',
    // flv也需要在手机端预览
    // rtmp://live.rixingyike.com/live/default?txSecret=f0ddef58264f943d6d648db5e9b33eac&txTime=5ED3D47F
    livePlayUrl:'',
    videoHeight:220,
    showFullScreenExitButton:false
  },
  exitFullScreen(){
    if (this.ctx) this.ctx.exitFullScreen({
      success: res => {
        this.setData({
          showFullScreenExitButton:false
        })
        console.log('exitFullScreen success')
      },
      fail: res => {
        console.log('exitFullScreen fail',res)
      }
    })
  },
  // 全屏
  requestFullScreen(){
    if (this.ctx) this.ctx.requestFullScreen({
      success: res => {
        this.setData({
          showFullScreenExitButton:true
        })
        console.log('requestFullScreen success')
      },
      fail: res => {
        // operateLivePlayer:fail 开发者工具暂时不支持此 API 调试,请使用真机进行开发
        console.log('requestFullScreen fail',res)
      }
    })
  },
  onReady(res) {
    var videoHeight = wx.getSystemInfoSync().windowHeight
    this.setData({videoHeight})

    let url = generatePlayUrl('live.rixingyike.com','default','dc5f17d4089d60cd1591c96860d2f1b7')
    console.log('url',url);
    this.setData({
      livePlayUrl:url
    })

    this.ctx = wx.createLivePlayerContext('player')
  },
  statechange(e) {
    console.log('live-player code:', e.detail.code)
  },
  error(e) {
    console.error('live-player error:', e.detail.errMsg)
  },
  bindPlay() {
    this.ctx.play({
      success: res => {
        console.log('play success')
      },
      fail: res => {
        console.log('play fail')
      }
    })
  },
  bindPause() {
    this.ctx.pause({
      success: res => {
        console.log('pause success')
      },
      fail: res => {
        console.log('pause fail')
      }
    })
  },
  bindStop() {
    this.ctx.stop({
      success: res => {
        console.log('stop success')
      },
      fail: res => {
        console.log('stop fail')
      }
    })
  },
  bindResume() {
    this.ctx.resume({
      success: res => {
        console.log('resume success')
      },
      fail: res => {
        console.log('resume fail')
      }
    })
  },
  bindMute() {
    this.ctx.mute({
      success: res => {
        console.log('mute success')
      },
      fail: res => {
        console.log('mute fail')
      }
    })
  }
})
代码语言:javascript复制
<view class="page-body">
<live-player id="player" object-fit="fillCrop" min-cache="0.2" max-cache="0.8" picture-in-picture-mode="{{['pop','push']}}" style="z-index:-1;height:{{videoHeight}}px;position: fixed;width: 100%;" autoplay src="{{livePlayUrl}}" mode="live" bindstatechange="statechange" binderror="error">
<!-- 全屏之后显示的内容,要写在live-player容器内 -->
<button wx:if="{{showFullScreenExitButton}}" class="page-body-button"  bindtap="exitFullScreen" type="primary">退出全屏</button>
</live-player>
  <view class="page-section tc">
    <view class="btn-area">
    <button bindtap="requestFullScreen" class="page-body-button" type="primary">全屏</button>
      <button bindtap="bindPlay" class="page-body-button" type="primary">播放</button>
      <button bindtap="bindPause" class="page-body-button" type="primary">暂停</button>
      <button bindtap="bindStop" class="page-body-button" type="primary">停止</button>
      <button bindtap="bindResume" class="page-body-button" type="primary">恢复</button>
      <button bindtap="bindMute" class="page-body-button" type="primary">静音</button>
    </view>
  </view>
</view>

3.live-pusher代码封装

代码语言:javascript复制
var md5 = require('blueimp-md5/index')

// rtmp://64400.livepush.myzijiebao.com/live/default?txSecret=034f506211aca7002ceab7e33fada61c&txTime=5ED4C4BF
function generatePushUrl(domain, streamName, key, time = null){
  if (!time){
    // one day more
    time = Math.round( Date.now()/1000 )
    time  = 24 * 60 * 60 * 1000
  } 
  var txTime = time.toString(16).toUpperCase()
  var txSecret = md5(key streamName txTime);
  var ext_str = `?txSecret=${txSecret}&txTime=${txTime}`
  return `rtmp://${domain}/live/${streamName}${ext_str}`
}

Page({
  data:{
    // rtmp://64400.livepush.myzijiebao.com/live/default?txSecret=7ed234039073374299e49dd5d1d46e70&txTime=5ED3D47F
    livePushUrl:'',
    videoHeight:220
  },
  
  onReady(res) {
    //设置视频高度
    var videoHeight = wx.getSystemInfoSync().windowHeight
    this.setData({videoHeight})
    //生成腾讯直播推流地址
    let url = generatePushUrl('64400.livepush.myzijiebao.com','default','dc5f17d4089d60cd1591c96860d2f1b7')
    console.log('url',url);
    this.setData({
      livePushUrl:url
    })
    //创建视频推流
    this.ctx = wx.createLivePusherContext('pusher')
  },
  statechange(e) {
    console.log('live-pusher code:', e.detail.code)
  },
  bindStart() {
    this.ctx.start({
      success: res => {
        console.log('start success')
      },
      fail: res => {
        console.log('start fail')
      }
    })
  },
  bindPause() {
    this.ctx.pause({
      success: res => {
        console.log('pause success')
      },
      fail: res => {
        console.log('pause fail')
      }
    })
  },
  bindStop() {
    this.ctx.stop({
      success: res => {
        console.log('stop success')
      },
      fail: res => {
        console.log('stop fail')
      }
    })
  },
  bindResume() {
    this.ctx.resume({
      success: res => {
        console.log('resume success')
      },
      fail: res => {
        console.log('resume fail')
      }
    })
  },
  bindSwitchCamera() {
    this.ctx.switchCamera({
      success: res => {
        console.log('switchCamera success')
      },
      fail: res => {
        console.log('switchCamera fail')
      }
    })
  }
})
代码语言:javascript复制
<view class="page-body">
<live-pusher id="pusher" enable-ans min-bitrate="300" max-bitrate="800" beauty="5" whiteness="5" style="z-index:-1;height:{{videoHeight}}px;position: fixed;width: 100%;" url="{{livePushUrl}}" mode="RTC" autopush bindstatechange="statechange" />
  <view class="page-section tc">
    <view class="btn-area">
      <button bindtap="bindStart" class="page-body-button" type="primary">播放推流</button>
      <button bindtap="bindPause" class="page-body-button" type="primary">暂停推流</button>
      <button bindtap="bindStop" class="page-body-button" type="primary">停止推流</button>
      <button bindtap="bindResume" class="page-body-button" type="primary">恢复推流</button>
      <button bindtap="bindSwitchCamera" class="page-body-button" type="primary">切换前后摄像头</button>
    </view>
    <navigator style="color:white;text-align: center;width: 100%;" url="/pages/2.16/player/index" open-type="navigate">play</navigator>
  </view>
</view>

0 人点赞