微信小程序使用腾讯云直播(用户端观看)聊天

1,757 阅读9分钟

仅需6步7分钟,用原生 js 接入腾讯云即时通信 IM


  1. 命令行打开项目文件根目录,`npm init -y` 快速生成 package.json
  2. 下载腾讯云即时通信 IMSDK:`npm install tim-wx-sdk@latest --production`
  3. 构建 npm


  4. 构建成功后能在项目目录看到 miniprogram_npm 和 tim-wx-sdk


  5. 详情-》本地设置-》使用 npm 模块


  6. 引入 TIM 模块

    import TIM from 'tim-wx-sdk'
    
    //app.js
    App({
      onLaunch: function () {
        // 创建 SDK 实例,TIM.create() 方法对于同一个 SDKAppID 只会返回同一份实例
        let options = {
          SDKAppID: 0 // 接入时需要将0替换为您的即时通信应用的 SDKAppID
        };
        let tim = TIM.create(options); // SDK 实例通常用 tim 表示
        // 设置 SDK 日志输出级别,详细分级请参见 setLogLevel 接口的说明
        tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用
      },
      globalData: {
        userInfo: null
      }
    })

  7. 控制台如果能看到 TIM.VERSION: 2.6.1 的日志,表示接入成功。
  8. 相关文档
  1. 更新日志
  2. SDK 接口文档
  3. AVChatRoom 使用指南
  4. Web Demo
========================================================================================================================我工作中deom

常看文档

cloud.tencent.com/document/pr…


  1. 新建im.js

import TIM from 'tim-wx-sdk';import {  genTestUserSig} from '../debug/GenerateTestUserSig.js';let tim;function initIM() {  // 创建 SDK 实例,TIM.create() 方法对于同一个 SDKAppID 只会返回同一份实例  let optionss = {    SDKAppID: 1400348947 // 接入时需要将0替换为您的即时通信应用的 SDKAppID  };  tim = TIM.create(optionss); // SDK 实例通常用 tim 表示  // 设置 SDK 日志输出级别,详细分级请参见 setLogLevel 接口的说明  tim.setLogLevel(1); // 普通级别,日志量较多,接入时建议使用 }//im登录function imLogin(uid) {  // onSdkReady()  // onMessageReceived()  return tim.login({    userID: uid,    userSig: genTestUserSig(uid).userSig  })}//自动登录function autoLogin() {  //获取本地用户信息  var nickName = wx.getStorageSync("nickName");  var uid = wx.getStorageSync("uid");  //本地有用户信息时自动登录  if (nickName != null && nickName != "" && uid != null && uid != "") {    let promise = imLogin(uid);    promise.then(function (imResponse) {      console.log("IM登录成功");      console.log(imResponse.data); //登录成功      wx.setStorageSync("isLogin", true);    }).catch(function (imError) {      console.warn('登录失败的相关信息error:', imError); // 登录失败的相关信息    });  }}//退出登录function imLogout() {  return tim.logout();}//查看登录状态function isLogin() {  return wx.getStorageSync("isLogin");}export {  initIM,  // imLogin,  autoLogin,  imLogout,  isLogin,  TIM,  tim}

2、在app.js引入并挂在全局

const IM = require("./api/im");
App({    onLaunch(options) {        //腾讯IM初始化        IM.initIM();    },    checkNewVersion: function () { // 检查版本更新        // 获取小程序更新机制兼容        if (wx.canIUse("getUpdateManager")) {            const updateManager = wx.getUpdateManager();            updateManager.onCheckForUpdate(function (res) {                // 请求完新版本信息的回调                if (res.hasUpdate) {                    updateManager.onUpdateReady(function () {                        wx.showModal({                            title: "更新提示",                            content: "新版本已经准备好,是否重启应用?",                            success: function (res) {                                if (res.confirm) {                                    // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启                                    updateManager.applyUpdate();                                }                            }                        });                    });                    updateManager.onUpdateFailed(function () {                        // 新的版本下载失败                        wx.showModal({                            title: "已经有新版本了哟~",                            content: "新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~"                        });                    });                }            });        } else {            // 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示            wx.showModal({                title: "提示",                content: "当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。"            });        }    },    globalData: {},    IM});

3、新建player文件夹

//player.wxml
<view class="player"><!-- 头部 -->   <scroll-view scroll-x  class="player_top">        <view class="player_title" wx:for="{{10}}">title税点</view>   </scroll-view><!-- 列表 -->    <scroll-view scroll-y enable-flex="{{true}}" class="player_item">      <view class="pl_child" wx:for="{{10}}" bindtap="entry">      </view>     </scroll-view> </view>

//player.wxss
/* pages/player/player.wxss */page{  height: 100%;}.player{  width: 100%;  height: 100%;  display: flex;  flex-direction: column;  justify-content: flex-start;}.player_item{  display: flex;  flex-direction: row;  justify-content:flex-start;  flex-wrap: wrap;  height: 100%;  width: 100%;}.player_top{  height: 80rpx;  width: 100%;  white-space:nowrap;}.player_title{  display: inline-block;  line-height: 80rpx;  padding: 0 30rpx;  border: 1rpx solid yellow;}.pl_child{  width: 350rpx;  border: 1rpx solid red;  height: 100px;  margin: 10rpx 0;  margin-left: 16rpx;}

player.js
// pages/player/player.jsconst app = getApp();Page({  /**   * 页面的初始数据   */  data: {     },  /**   * 生命周期函数--监听页面加载   */  onLoad: function (options) {  },  // 进入聊天室  entry: function () {    var self = this;    // 防止两次点击操作间隔太快    var nowTime = new Date();    if (nowTime - this.data.tapTime < 1000) {      return;    }    // let identifier = this.data.users[this.data.index].identifier||' '    // let userConfig = genTestUserSig(identifier)||' '// ?identifier=${identifier}&userSig=${userConfig.userSig}    //此处判断横竖屏 开启不同页面展示    var url = `/pages/player/template/fullscreen/fullscreen`;    wx.navigateTo({      url: url    });  },  /**   * 生命周期函数--监听页面初次渲染完成   */  onReady: function () {  },  /**   * 生命周期函数--监听页面显示   */  onShow: function () {  },  /**   * 生命周期函数--监听页面隐藏   */  onHide: function () {  },  /**   * 生命周期函数--监听页面卸载   */  onUnload: function () {  },  /**   * 页面相关事件处理函数--监听用户下拉动作   */  onPullDownRefresh: function () {  },  /**   * 页面上拉触底事件的处理函数   */  onReachBottom: function () {  },  /**   * 用户点击右上角分享   */  onShareAppMessage: function () {  }})

4、在player文件夹中新建templete=>子文件fullscreen

fullscreen.wxml
<live-player id="player" src="http://mlive.yunjinji.cn/live/202004111017Test.flv" bindstatechange="statechange" binderror="error">  <cover-view>    <cover-view class="btn-box">      <button bindtap="bindPlay" type="primary">播放</button>      <button bindtap="bindPause" type="warn">暂停</button>      <button bindtap="bindStop" type="warn">停止</button>      <button bindtap="bindResume" type="primary">恢复</button>      <button bindtap="bindMute" type="warn">静音</button>    </cover-view>  </cover-view></live-player><!-- 聊天信息 --><scroll-view scroll-y="{{true}}" scroll-top="{{scrollTop}}" class="msgs-wrapper">  <view class="msgs">    <!-- <view class="msgs" wx:for="{{msgs}}" wx:key="index"> -->    <!-- <text class="msg-item"><text class="nickname">{{item.fromAccountNick}}</text> : {{item.content}}</text> -->    <text class="msg-item" wx:key="{{item.time}}" wx:for="{{msgs}}"><text class="nickname">{{item.nickName}}</text>{{item.payload2==false?item.payload3==false?item.payload.text:'':':'+item.payload.text}}</text>  </view></scroll-view><!-- 底部 --><view class="input-section">  <input adjust-position="{{true}}" value="{{msgContent}}" confirm-type="send" placeholder="" bindinput="bindInput" bindconfirm="bindConfirm" />  <!-- <button class="love" bindtap="bindTap">  </button> -->  <button class="love" data-value="{{msgContent}}" bindtap="bindConfirm"></button></view><!-- rtmp://58.200.131.2:1935/livetv/hunantv -->

fullscreen.wxss
page{  height: 100%;  box-sizing: border-box;  overflow: hidden;}.btn-box{  display: flex;  margin-top:40rpx;} .btn-box button{  margin-bottom: 30rpx;  flex:1;  font-size: 24rpx;  padding: 0;  margin:0 20rpx;}live-player {  width: 100%;  height: 100%;  position:relative;}/* //聊天 */.msgs-wrapper {  position: absolute;  bottom: 100rpx;  left: 10rpx;  right: 10rpx;  height: 400rpx;  overflow: hidden;  overflow-y: auto;}.msgs {  max-width: 80%;  display: block;  padding: 5rpx;  color: #ffffff;  margin: 5rpx 0;  word-wrap: break-word;  width: 430rpx;}.msg-item {  padding: 8rpx 5rpx;  display: block;  font-size: 14px;  background:rgba(0,0,0,1);  opacity:0.4;  border-radius:10rpx;  margin: 10rpx 0;}.nickname {  color: #ff7906}.input-section {  position: absolute;  bottom: 10rpx;  left: 10rpx;  right: 10rpx;}.input-section input {  background: #fff;  margin-right: 100rpx;  padding: 10rpx;}.input-section .love {  background: url(http://avc.qcloud.com/demo/webim/biggroup/mobile/img/like_hover.png);  background-size: 100%;  width: 70rpx;  height: 70rpx;  display: block;  position: absolute;  right: 10rpx;  bottom: 0;  border: 0;  outline: 0;}.input-section .love:after {  border: 0}

fullscreen.js
import { autoLogin, isLogin} from '../../../../api/im.js'import { hudong, playerFn} from './method.js'var app = getApp()Page({  data: {    // identifier: '', // 当前用户身份标识,必选    // userSig: '', // 当前用户签名,必选    nickName: '', // 当前用户昵称,选填    // avChatRoomId: CONFIG.avChatRoomId, // 群ID, 必选    // motto: 'Hello World',    msgs: [],//消息数据    playerName:'LOL直播间',//直播间昵称    msgContent: "",//文本内容    uid:'',//自己id    scrollTop:100,    togroup:'@TGS#aXV66ILGG'//群聊id  },  onReady(res) {    this.ctx = wx.createLivePlayerContext('player')  },     // 聊天室  ...hudong,  //按钮  ...playerFn,  //加载  onLoad: function (options) {    var that=this    //加入群聊室    that.joinGroup(this.data.togroup).then(res => {      console.log('joinGroup')      console.log(res)      if(res.code===0){        //  + that.data.playerName        let msgobj = {          nickName: '欢迎来到直播间!直播内容和评论严禁包含政治,低俗色情,吸烟酗酒等内容,如若违反,将视情节严重程度给予禁播,永久禁播或封停账号处理!',//昵称           payload2: false //控制内容一级(:)是否显示        }        let msgarr = that.data.msgs        msgarr.push(msgobj)        that.setData({          msgs: msgarr        })        //滚动        that.scrollFn()      }      // let msg = '欢迎进入' + data.payload.groupProfile.name      // let msgobj = {      //   nickName: msg,//昵称      //   payload: false //控制内容一级(:)是否显示      // }      // let msgarr = that.data.msgs      // msgarr.push(msgobj)      // that.setData({      //   msgs: msgarr      // })    })    //监听群消息    app.IM.tim.on(app.IM.TIM.EVENT.MESSAGE_RECEIVED,that.onMessageReceived);     },  //显示  onShow:function(){    console.log('onShow')    // setTimeout(()=>{      // if (isLogin()) {//查看im是否登录        this.setData({          nickName: wx.getStorageSync("phone"),          uid: wx.getStorageSync("uid")        })      // }    // },2000)     },  //卸载  onUnload:function(){    app.IM.tim.off(app.IM.TIM.EVENT.MESSAGE_RECEIVED, this.onMessageReceived);    this.quitGroup(this.data.togroup)  }  })

5、新建method.js

import {  autoLogin,  isLogin} from '../../../../api/im.js'const IM = require('../../../../api/im.js')//播放function bindPlay() {  this.ctx.play({    success: res => {      console.log('播放成功')      console.log(res)    },    fail: res => {      console.log('播放失败,失败原因' + res.errMsg)    }  })}//暂停function bindPause() {  this.ctx.pause({    success: res => {      console.log('暂停成功')    },    fail: res => {      console.log('暂停失败,失败原因' + res.errMsg)    }  })}//停止function bindStop() {  this.ctx.stop({    success: res => {      console.log('停止成功')    },    fail: res => {      console.log('停止失败,失败原因' + res.errMsg)    }  })}//恢复function bindResume() {  this.ctx.resume({    success: res => {      console.log('恢复成功')    },    fail: res => {      console.log('恢复失败,失败原因' + res.errMsg)    }  })}//静音function bindMute() {  this.ctx.mute({    success: res => {      console.log('静音成功')    },    fail: res => {      console.log('静音失败,失败原因' + res.errMsg)    }  })}const hudong = {  //监听消息  onMessageReceived: function(event) {    console.log(event)    let data = event.data[0]    //判断是否刚刚进来聊天室    let names = data.payload.operatorID    let iD = data.ID    let froms = data.from //消息来自哪里  @TIM#SYSTEM(系统)    let isSystemMessage = data.isSystemMessage    let isower = (this.data.uid != names)    let groupJoinType = data.payload.groupJoinType //没有登陆时自己的groupJoinType为0,其他人登录进来为1    if (names != undefined && names != "" && !isSystemMessage && isower && froms == '@TIM#SYSTEM' && groupJoinType!=0) { //别人进直播间      console.log('11111111111111111111111111111111111111111')      let msgobj = {        nickName:names, //昵称        payload2:false,        payload3:false,        payload:{          text:'来了'        },      }      let msgarr = this.data.msgs      msgarr.push(msgobj)      this.setData({        msgs: msgarr      })      //滚动      this.scrollFn()    }    // if (isSystemMessage) { //自己刚进入聊天系统提示    //   console.log('2222222222222222222')    //   let playenmae = data.payload.groupProfile.name //直播间昵称    //   let msgobj = {    //     nickName: '欢迎进入' + playenmae + '直播间', //昵称    //     payload: false    //   }    //   let msgarr = this.data.msgs    //   msgarr.push(msgobj)    //   this.setData({    //     msgs: msgarr    //   })    // }    if (isower && froms != '@TIM#SYSTEM' && froms != this.data.uid) {      console.log('33333333333333')      let msgobj = {        nickName: event.data[0].from, //昵称        payload: event.data[0].payload //消息      }      let msgsarr = this.data.msgs      msgsarr.push(msgobj)      this.setData({        msgs: msgsarr      })      //滚动      this.scrollFn()    }  },  // 发送消息  bindConfirm: function(e) {    if (isLogin()) { //查看im是否登录      if (this.data.msgContent != '') {        let data = {          msg: this.data.msgContent,          togroup: this.data.togroup        }        this.textMessages(data).then(res => {          console.log(this.data.msgContent)          console.log(res)          if (res.code === 0) {            res.data.message.nickName = this.data.nickName //获取当前用户昵称            let list = res.data.message            let msgs = this.data.msgs            msgs.push(list)            this.setData({              msgs: msgs            })            this.cleartxFn()            //滚动            this.scrollFn()          }        })      }    }else{      wx.navigateTo({        url:'/pages/login/login'      })    }  },  //清除文本内容  cleartxFn: function() {    this.setData({      msgContent: ''    })  },  //初始化SDK功能  onSdkReady() {    // return new Promise((resolve, reject) => {    let onSdkReady = function(event) {      let message = tim.createTextMessage({        to: '@TGS#aXV66ILGG', //groupID        conversationType: TIM.TYPES.CONV_GROUP, //会话类型,取值TIM.TYPES.CONV_C2C(端到端会话) 或 TIM.TYPES.CONV_GROUP(群组会话)        payload: {          text: 'Hello world!' //消息        }      });      tim.sendMessage(message);    };    // })    tim.on(TIM.EVENT.SDK_READY, onSdkReady);  },  //发送群消息  /*   msg@@@===发送的内容消息   togroup@@@===直播间群组id  */  textMessages({    msg,    togroup  }) {    // 发送文本消息,Web 端与小程序端相同    // 1. 创建消息实例,接口返回的实例可以上屏    let message = IM.tim.createTextMessage({      to: togroup,      conversationType: IM.TIM.TYPES.CONV_GROUP,      // 消息优先级,用于群聊(v2.4.2起支持)。如果某个群的消息超过了频率限制,后台会优先下发高优先级的消息,详细请参考:https://cloud.tencent.com/document/product/269/3663#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)      // 支持的枚举值:TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL(默认), TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST      // priority: TIM.TYPES.MSG_PRIORITY_NORMAL,      payload: {        text: msg      }    });    // 2. 发送消息    return IM.tim.sendMessage(message);  },  //加入聊天室  /*   group@@@===直播间群组id  */  joinGroup(group) {    return IM.tim.joinGroup({      groupID: group,      type: IM.TIM.TYPES.GRP_AVCHATROOM    });  },  //退出群组  /*   group@@@===直播间群组id  */  quitGroup(group) {    let promise = IM.tim.quitGroup(group);    promise.then(function(imResponse) {      console.log(imResponse.data.groupID); // 退出成功的群 ID    }).catch(function(imError) {      console.warn('quitGroup error:', imError); // 退出群组失败的相关信息    });  },  //滚动  scrollFn(){    let msgs = this.data.msgs    let top=msgs.length*60    this.setData({      scrollTop: top    })  },  //监听输入框  bindInput(e){    this.setData({      msgContent:e.detail.value    })  }}const playerFn={  inputFocus(e) {    console.log(e, '键盘弹起')    var inputHeight = 0    if (e.detail.height) {      inputHeight = e.detail.height    }  },  inputBlur() {    console.log('键盘收起')  },  statechange(e) {    let types = {      '2001': '已经连接服务器',      '2002': '已经连接 RTMP 服务器,开始拉流',      '2003': '网络接收到首个视频数据包(IDR)',      '2004': '视频播放开始',      '2005': '视频播放进度',      '2006': '视频播放结束',      '2007': '视频播放Loading',      '2008': '解码器启动',      '2009': '视频分辨率改变',      '-2301': '网络断连,且经多次重连抢救无效,更多重试请自行重启播放',      '-2302': '获取加速拉流地址失败',      '2101': '当前视频帧解码失败',      '2102': '当前音频帧解码失败',      '2103': '网络断连, 已启动自动重连',      '2104': '网络来包不稳:可能是下行带宽不足,或由于主播端出流不均匀',      '2105': '当前视频播放出现卡顿',      '2106': '硬解启动失败,采用软解',      '2107': '当前视频帧不连续,可能丢帧',      '3001': 'RTMP -DNS解析失败',      '3002': 'RTMP服务器连接失败',      '3003': 'RTMP服务器握手失败',      '3005': 'RTMP 读/写失败'    }    console.log('live-player code:', e.detail.code, '==========', types[e.detail.code])  },  error(e) {    console.error('live-player error:', e)  },}export {  bindPlay,  bindPause,  bindStop,  bindResume,  bindMute,  hudong,  playerFn}