本文主要通过介绍网页版群直播基础功能和实现流程来告诉大家TWebLive 能用来做什么,如何把TWebLive集成到项目中 。
一、网页版群直播效果
二、网页版群直播实现框架
三、网页版群直播基础功能介绍
3.1、在腾讯云即时通信IM Demo[2]中可以通过2种方式体验群直播功能。
(1)、通过全局群直播入口进入,此时不会向任何群组发送群直播开播/停播消息通知
(2)、在Demo中创建Public、Work、Meeting任意一个群组类型(不支持在AVChatRoom中开启群直播),打开会话窗口,点击群直播按钮开启群直播。
3.2、进入群直播界面后可以输入直播名称,底部操作区设置有开始直播/结束直播,摄像头和麦克风开关按钮。
3.3、开播时会给群组内所有成员推送开播通知,群组成员可以通过点击消息卡片进入直播间观看直播。
3.4、直播过程中主播端可以查看主播个人信息、直播在人数、直播时长,主播可以发送普通文本消息进行互动。
3.5、观众进入直播间可发送普通文本和礼物消息,暂停观看不影响与主播进行消息互动。
3.6、主播结束直播时会给群组内推送结束直播通知,直播结束后再点击卡片会提示直播已结束,不能再进入直播间。
3.7、网页版群直播与云通信IM APP群直播互通体验
四、实现群直播的核心技术—TWebLive
网页版群直播功能的实现依赖TWebLive SDK。TWebLive集成了腾讯云实时音视频TRTC[3]、腾讯云即时通信IM[4]、腾讯云超级播放器TcPlayer[5],覆盖了Web直播互动场景常见的功能,封装了简单易用的API[6]。
TWebLive主要提供了三大核心功能:主播端推流,观众端观看,直播互动。主播端推流基于实时音视频TRTC实现,观众端CDN观看基于TcPlayer实现,直播互动基于即时通信IM实现。
五、如何利用TWebLive实现群直播功能
5.1、接入TWebLive
在TRTC应用或者IM应用中均可接入TWebLive。这里主要介绍在IM应用中接入TWeblive的流程。接入前,需要在腾讯云即时通信IM控制台创建的IM应用中开通腾讯云实时音视频服务,开通音视频服务后,还需要在腾讯云直播控制台配置直播域名且域名需要配置HTTPs。
在项目中通过npm安装最新版本的tim-js-sdk、trtc-js-sdk、tweblive。如果项目已经集成有tim-js-sdk或trtc-js-sdk,直接将其升级到最新版本即可。
npm install tim-js-sdk --save
npm install trtc-js-sdk --save
npm install tweblive --save
在项目中引入tweblive
import TWebLive from 'tweblive'
Vue.prototype.TWebLive = TWebLive
如果需要通过script标签外链的方式引入,需要将tim-js.js、trtc.js、tweblive.js拷贝至项目中,按顺序引入。
<script src="./trtc.js"></script>
<script src="./tim-js.js"></script>
<script src="./tweblive.js"></script>
5.2、群直播主播端主要功能实现如下
// 初始化pusher
init() {
this.pusher = this.TWebLive.createPusher({
userID: this.user.userID
})
this.setRenderView()
this.pusher.on(this.TWebLive.EVENT.RTC_CONNECTION_STATE_CHANGED, this.onRTCConnectionStateChanged) this.pusher.on(this.TWebLive.EVENT.RTC_CLIENT_BANNED,this.onRTCClientBanned)
this.pusher.on(this.TWebLive.EVENT.RTC_CLIENT_ERROR,this.onRTCError)
},
// eslint-disable-next-line no-unused-vars
onRTCConnectionStateChanged(event) {},
// eslint-disable-next-line no-unused-vars
onRTCClientBanned(event) {},
// eslint-disable-next-line no-unused-vars
onRTCError(event) {},
//开启本地预览
setRenderView() {
this.pusher.setRenderView({
elementID: 'video-container',
audio: true,
video: true
}).then(() => {
// 设置背景
let el =document.getElementById('videocontainer').childNodes
el[0].style.backgroundColor = 'rgba(0,0,0,0)'
this.isStartCamera = false
}).catch(() => {})
},
// 打开摄像头
startCamera() {
this.pusher.startCamera().then(() => {
this.isStartCamera = false
}).catch(() => {})
},
// 关闭摄像头
stopCamera() {
this.pusher.stopCamera().then(() => {
this.isStartCamera = true
}).catch(() => {})
},
// 打开麦克风
startMicrophone() {
this.pusher.startMicrophone().then(() => {
this.isMute = false
}).catch(() => {})
},
// 关闭麦克风
stopMicrophone() {
this.pusher.stopMicrophone().then(() => {
this.isMute = true
}).catch(() => {})
},
// 通过业务服务器创建直播房间
async createRoom() {},
//开始推流
async startPushStream() {
await this.createRoom()
// streamID生成规则:sdkappid_roomid_userid_main
const streamID = `${this.user.sdkAppID}_${this.roomID}_${this.user.userID}_main`
// 对userSig进行encode,防止userSig中带有+时被浏览器解析为空格,导致trtc ws连接失败
const url = `room://livedomainname=xxx.xxx.com&sdkappid=${this.user.sdkAppID}&roomid=${this.roomID}&userid=${this.user.userID}&usersig=${encodeURIComponent
(this.user.userSig)}&streamid=${streamID}`
this.pusher.startPush(url).then(() => {
// 发送开播群通知
this.sendNoticeToGroup(1)
}).catch(() => {})
},
// 停止推流
async stopPush() {
await this.pusher.stopPush()
// 发送直播结束群通知
this.sendNoticeToGroup(0)
},
// 给群内发送开始直播、结束直播自定义消息
// roomStatus 1 开始直播 0 结束直播
sendNoticeToGroup(roomStatus) {
if (!this.groupLiveInfo.groupID) { return }
const { userID, nick, avatar } = this.user.currentUserProfile
// 自定义消息结构体,根据实际需要修改,以下结构体仅为Demo使用
const form = {
roomId: this.roomID,
roomName: this.roomName,
roomCover: avatar,
roomStatus: `${roomStatus}`,
anchorName: nick,
version: 4,
roomType: 'liveRoom',
anchorId: userID,
businessID: 'group_live'
}
const message = this.tim.createCustomMessage({
to: this.groupLiveInfo.groupID,
conversationType: this.TIM.TYPES.CONV_GROUP,
priority: this.TIM.TYPES.MSG_PRIORITY_NORMAL,
payload: {
data: JSON.stringify(form),
description: '',
extension: '',
},
})
this.tim.sendMessage(message).then(() => {}).catch(() => {})
}
5.3、群直播观众端主要功能实现如下
// 初始化player
init() {
this.player = this.TWebLive.createPlayer()
this.player.setCustomConfig({
autoplay: true,
poster: { style:'cover', src: poster },
pausePosterEnabled: false,
wording: {
1:'您观看的直播已结束哦~ ',
2:'您观看的直播已结束哦~ ',
4:'您观看的直播已结束哦~ ',
13:'您观看的直播已结束',
2032: '请求视频失败,请检查网络',
2048: '请求m3u8文件失败,可能是网络错误或者跨域问题'
}
})
// 监听播放事件
this.player.on(this.TWebLive.EVENT.PLAYER_PLAYING,this.onPlayerPlaying)
// 监听暂停事件
this.player.on(this.TWebLive.EVENT.PLAYER_PAUSE,this.onPlayerPause)
// 监听浏览器不允许自动播放事件
this.player.on(this.TWebLive.EVENT.PLAYER_AUTOPLAY_NOT_ALLOWED, this.onPlayerAutoPlayNotAllowed)
// 监听播放异常事件
this.player.on(this.TWebLive.EVENT.PLAYER_ERROR,this.onPlayerError)
this.setRenderView()
},
// eslint-disable-next-line no-unused-vars
onPlayerPlaying(event) {},
// eslint-disable-next-line no-unused-vars
onPlayerPause(event) {},
// eslint-disable-next-line no-unused-vars
onPlayerAutoPlayNotAllowed(event) {
this.$store.commit('showMessage', {
message: '不能自动播放',
type: 'info'
})
},
//开始播放
startPlay() {
const streamID = `${this.user.sdkAppID}_${this.roomID}_${this.anchorId}_main`
const flv = `https://xxx.xx.com/live/${streamID}.flv`
const hls = `https://xxx.xx.com/live/${streamID}.m3u8`
const url = `https://flv=${encodeURIComponent(flv)}&hls=${encodeURIComponent(hls)}`
this.player.startPlay(url).then(() => {
this.isPlaying = true
}).catch(() => {})
},
//暂停播放
pauseVideo() {
this.player.pauseVideo().then(() => {
this.isPlaying = false
}).catch(() => {})
},
// 恢复播放
resumeVideo() {
this.player.resumeVideo().then(() => {
this.isPlaying = true
}).catch(() => {})
},
// 调节播放器音量
setPlayoutVolume() {
this.player.setPlayoutVolume(this.volumeValue)
},
// 停止播放
stopPlay() {
this.player.stopPlay()
this.isPlaying = false
}
5.4、群直播互动功能实现
由于腾讯云即时通信IM Demo[2]中已经集成了IM应用,直播互动部分的功能通过IM SDK API实现。
// 创建直播互动群
async createGroupLiveAvChatRoom() {
await this.tim.createGroup({
name: this.roomName,
groupID: this.roomID,
type: this.TIM.TYPES.GRP_AVCHATROOM,
})
},
// 进入直播互动群
joinGroupLiveAvChatRoom() {
this.tim.joinGroup({
groupID: this.groupLiveInfo.roomID
}).then((imResponse) => {
const status = imResponse.data.status
if (status === this.TIM.TYPES.JOIN_STATUS_SUCCESS || status === this.TIM.TYPES.JOIN_STATUS_ALREADY_IN_GROUP) {
// 加群成功后才可以发消息
this.sendAvailable = true
}
}).catch(() => {})
},
// 发送普通文本消息
sendTextMessge() {
const message = this.tim.createTextMessage({
to: this.groupLiveInfo.roomID,
conversationType: this.TIM.TYPES.CONV_GROUP,
payload: { text: this.messageContent }
})
this.tim.sendMessage(message).catch(error => {})
this.messageContent = ''
}
// 发送礼物消息
sendGiftMessage() {
// data为礼物消息结构体,根据实际需要自己定义
const data = {}
const message = this.tim.createCustomMessage({
to: this.groupLiveInfo.roomID,
conversationType: this.TIM.TYPES.CONV_GROUP,
payload: {
data: JSON.stringify(data),
description: '',
extension: ''
}
})
this.tim.sendMessage(message).catch(error => {})
}
代码片段是在Vue框架下实现,代码中使用到的变量维护在Vuex 和组件data属性中。可以复制以上代码片段到Vue项目中,即可快速搭建一个网页版群直播功能。
六、TWebLive SDK体积优化
TWebLive SDK 1.0.0打包时将IM SDK、TRTC SDK、TcPlayer 集成输出,导致输出的包体积很大(接近1M),如果在已有IM或者TRTC应用中接入TWebLive时,存在重复引用的问题。为了提升接入体验,已发布TWebLive 1.1.0版本,主要是在1.0.0的基础上优化SDK的打包方式,把IM SDK和TRTC SDK作为外部依赖打包,SDK体积减少了78%。接入TWeblive时手动安装IM SDK和TRTC SDK即可。
七、注意事项
第一、接入TWebLive时,需要安装最新版本的tim-js-sdk、trtc-js-sdk,避免引起版本兼容性问题。
第二、Pusher和Player中使用到的SDKAppID必须与IM应用的SDKAppID保持一致。
第三、由于 H.264 版权限制,华为系统的 Chrome 浏览器和以 Chrome WebView 为内核的浏览器均不支持 TRTC 桌面浏览器端 SDK 的正常运行。
参考资料:
[1] TWebLive详情
[2] 腾讯云即时通信IM在线 Demo
[3] 腾讯云实时音视频 TRTC
[4] 腾讯云即时通信IM
[6] TWebLive接口手册
[7] 腾讯云即时通信接口手册
[8] TWebLive 使用
[9] 腾讯点播视频DEMO