小程序直播相关

直播插件

因为小程序组件<live-player />需要直播相关主体,所以用了腾讯云直播插件<live-room-play />
相关文档
其中有个播放状态监控:

1
2
<!-- 这里有个小窗播放`picture-in-picture-mode`此插件1.3.0版本已经支持,但是没实现了,不知原因,查找中... -->
<live-room-play class="live-room" objectFit="contain" version="2" picture-in-picture-mode="['push', 'pop']" liveAppID="" autoplay="{{autoPlay}}" bindPlayEvent="playStatus" bindNetStatus="netStatus" autopause="true" bindError="error" playUrl="{{playUrl}}">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//播放状态变化事件回调
playStatus(e) {
let that = this;
console.log("播放状态", e.detail.detail)
if (e.detail.code == 2004) {
//视频播放开始
this.setData({
livePause: false
})
if (this.timer) {
clearInterval(this.timer)
}
}
if (e.detail.code == 2001) {
//已经连接服务器
}
if (e.detail.code == 2103) {
//网络断连, 启动自动重连
if (this.data.liveEnd) {
//直播结束不再请求
if (this.timer) {
clearInterval(this.timer)
}
}
}
if (e.detail.code == -2301) {
// -2301:网络断连且经多次重连抢救无效
this.setData({
autoPlay: false,
livePause: true
})
if (!this.timer) {
this.timer = setInterval(() => {
console.log("开始请求直播拉流")
that.setData({
playUrl: that.data.playUrl,
autoPlay: true
})
that.liveRoomComponent && that.liveRoomComponent.start();
}, 5000)
}
}
if (e.detail.code == 2006) {
//2006:视频播放结束;
this.setData({
liveEnd: true
})
}
},

即时通信IM

因为是直播,所以IM类型选择直播群

官方文档很详细

这里加几个注意的点:

1. IM设置头像昵称要在ready之后调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
tim.on(TIM.EVENT.SDK_READY, function (event) {
// SDK ready 后接入侧才可以调用 sendMessage 等需要鉴权的接口,否则会提示失败!
// event.name - TIM.EVENT.SDK_READY
console.log("SDK ready", event)
// 修改个人标配资料
tim.updateMyProfile({
nick: wx.getStorageSync('wxUserInfo').nickName,
avatar: wx.getStorageSync('wxUserInfo').avatarUrl
}).then(function (imResponse) {
console.log(imResponse.data); // 更新资料成功
}).catch(function (imError) {
console.warn('updateMyProfile error:', imError); // 更新资料失败的相关信息
});
})
2.有成员加群回调只有调用登录tim.login方法 再调用加群tim.joinGroup方法 才会触发

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//登录IM
tim.login({
userID: uid, //用户ID后台返回的用户ID
userSig: data.data.UserSig //后台返回的根据用户ID生成的加密串
}).then(function (imResponse) {
console.log("登录成功", imResponse.data); // 登录成功
tim.joinGroup({
groupID: that.data.groupID, //群ID
type: TIM.TYPES.GRP_AVCHATROOM //类型为直播群必填字段
}).then(function (imResponse) {
console.log("加群成功", imResponse)
switch (imResponse.data.status) {
case TIM.TYPES.JOIN_STATUS_SUCCESS: // 加群成功
// console.log(imResponse.data.group) // 加入的群组资料
break
case TIM.TYPES.JOIN_STATUS_ALREADY_IN_GROUP: // 已经在群中
break
default:
break
}
}).catch(function (imError) {
console.warn('加群失败', imError) // 申请加群失败的相关信息
});
resolve(imResponse)
}).catch(function (imError) {
console.warn('登录IM失败:', imError); // 登录失败的相关信息
reject(imError)
});
3.判断是否被禁言,调用发消息(包括各种类型的消息)前先判断是否被禁言,如果禁言调用发消息会报错(注意必须在SDK_READY之后调用)

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//判断是否被禁言
checkUserBanned() {
let that = this;
return new Promise((resolve, reject) => {
tim.getGroupMemberProfile({
groupID: that.data.groupID,
userIDList: [wx.getStorageSync('userInfo').uid] //用户ID,必须为数组
}).then(function (imResponse) {
// console.log(imResponse.data.memberList); // 群成员列表
resolve(imResponse.data.memberList)
}).catch(function (imError) {
// console.warn('getGroupMemberProfile error:', imError);
reject(imError)
});
})
},
//检查是否被禁言,这样调用还有个弊端,每次发消息都会请求禁言接口,导致发消息很慢,所以我优化成了调用login时判断此用户是否被禁言
that.checkUserBanned().then((res) => {
for (let groupMember of res) {
if (groupMember.muteUntil * 1000 > Date.now()) {
//禁言中
wx.showToast({
title: '您已被禁言',
icon: "none"
})
} else {
//未禁言
let message = tim.createCustomMessage({
to: that.data.groupID,
conversationType: TIM.TYPES.CONV_GROUP,
payload: {
data: '', // 用于标识该消息是什么类型自定义消息
description: that.liveId, // 直播ID
extension: number + "" //
}
});
// 3. 发送消息
let promise = tim.sendMessage(message);
promise.then(function (imResponse) {
// 发送成功
console.log(imResponse);
}).catch(function (imError) {
// 发送失败
console.warn('sendMessage error:', imError);
});
}
}
})
4.进场消息、购买消息等只显示一次,并且显示时间相同的消息实现
  • 基本原理就是onShow生命周期触发一个定时器方法,在收到进群消息或购买消息回调之后,把收到的消息push到一个相同的数组中,然后页面只展示第一条数组,因为动画是三秒一条消息,所以定时器三秒轮询一次,第一条三秒之后删除,这样不会导致数组内存过大,
    示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    onShow(){
    this.tipMsg()
    },
    buyMessage(message) {
    //收到购买消息回调之后,往tipsData数组push一条数据,定时器监测到有数据便会渲染出来
    let that = this;
    let res = {};
    res.avatar = message.avatar;
    res.nick = message.nick;
    res.type = 3;
    that.data.tipsData.push(res)
    },
    tipMsg() {
    let that = this;
    that.tipTimer = setInterval(() => {
    if (that.data.tipsData.length > 0) {
    that.setData({
    tipsDatas: that.data.tipsData[0] //这里的tipsData对象便是要渲染到页面中的单条数据
    })
    that.tipAnimation()
    }
    }, 3000);
    },
    tipAnimation() {
    let that = this;
    let animation = wx.createAnimation({
    duration: 300
    })
    animation.translateX(0).step()
    that.setData({
    animationData: animation.export()
    })
    setTimeout(() => {
    animation.translateX('-100%').step({
    duration: 0
    })
    that.setData({
    animationData: animation.export()
    })
    that.data.tipsData.shift()
    // console.log(that.data.tipsData)
    }, 2700);
    },

tips:这样应该不是最优解,毕竟定时器触发还是有点耗性能的,loading…

这样做下来直播IM还是相对简单的,毕竟用的API还没有十分之一,很多API都是聊天群才用到的

小程序云点播功能需要插件并且需要买流量买插件,所以用了H5的播放器

1.自动播放:查了很多没实现,基本都说,微信浏览器必须有用户操作行为才会播放

1
2
3
4
5
6
7
<link href="https://imgcache.qq.com/open/qcloud/video/tcplayer/tcplayer.css" rel="stylesheet">
<!--如果需要在 Chrome 和 Firefox 等现代浏览器中通过 H5 播放 HLS 格式的视频,需要在 tcplayer.v4.1.min.js 之前引入 hls.min.0.13.2m.js。-->
<script src="https://imgcache.qq.com/open/qcloud/video/tcplayer/libs/hls.min.0.13.2m.js"></script>
<!--播放器脚本文件,不转码用下面这个js-->
<script src="https://imgcache.qq.com/open/qcloud/video/tcplayer/tcplayer.min.js"></script>
<!--播放器脚本文件,转码用下面这个js-->
<script src="https://imgcache.qq.com/open/qcloud/video/tcplayer/tcplayer.v4.1.min.js"></script>
1
2
<!-- 设置播放器容器 -->
<video id="player-container-id" preload="auto" width="100%" height="100%" autoplay="true" playsinline webkit-playsinline></video>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
this.player = TCPlayer("player-container-id", {
// player-container-id 为播放器容器 ID,必须与 html 中一致
fileID: data.data[0].file_id, // 请传入需要播放的视频 filID(必须)
appID: "1500001289", // 请传入点播账号的 appID(必须)
// autoplay: true,
// plugins: {
// ContinuePlay: {
// // 开启续播功能
// auto: true //[可选] 是否在视频播放后自动续播
// }
// }
});
// 切换播放视频
methods: {
chooseVideo(v) {
this.currentId = v.file_id;
this.player.loadVideoByID({
fileID: v.file_id, // 请传入需要播放的视频 filID(必须)
appID: "1500001289" // 请传入点播账号的 appID(必须)
});
}
}