七牛实时音视频云视频连线demo(web部分)
官方文档:
步骤
1.申请七牛云账号;
2.服务器上做token验证接口
3.web demo开发
注意事项
- 因为屏幕和摄像头采集只能在 localhost 或者 https 下完成;
- 因为项目涉及到和客户端视频连线,一开始客户端取不到web发布的视频流,后面仔细查看文档才知道需要把客户端打不得track流设置Master为true(默认false)
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>视频连线</title>
</head>
<link rel="stylesheet" href="src/css/index.css">
<link rel="stylesheet" href="src/layui/css/layui.css">
<body>
<div class="title">演播室</div>
<div id="localtracks"></div>
<div class="title">远方记者</div>
<div id="subtracks"></div>
<div class="button">
<button class="layui-btn layui-btn-normal" onclick="page.joinRoom()">加入房间</button>
<button class="layui-btn layui-btn-normal" onclick="page.leaveRoom()">离开房间</button>
</div>
</body>
<script src="src/js/public/pili-rtc-web.js"></script>
<script src="src/js/public/jquery-3.3.1.min.js"></script>
<script src="src/layui/layui.all.js"></script>
<script>
var page = {};
page.uid = 6;
page.roomname = '123456';
page.token = '';
myRoom = null;
page.getToken = async function () {
await $.ajax({
url: '/QiuNiu/getToken',
type: 'POST',
data: {
uid: page.uid,
roomname: page.roomname
},
success: function (res) {
res = JSON.parse(res)
if (res.code == 200) {
page.token = res.data.token
} else {
console.log(res.msg)
layer.msg(res.msg,{icon:2})
}
}
});
}
page.joinRoom = function () {
layer.prompt({title: '请输入房间号', value: page.roomname, maxlength: 64}, function(pass, index){
const roomReg = /[a-zA-Z0-9_-]{3,64}/;
if(roomReg.exec(pass)){
page.roomname = pass
layer.close(index);
page.startConnect();
} else {
layer.msg('房间号必须为3位以上字母和数字组成!',{icon:2})
}
});
}
page.startConnect = async function () {
await page.leaveRoom();
await page.getToken();
// 这里替换成刚刚生成的 RoomToken
await myRoom.joinRoomWithToken(page.token);
await page.publish();
page.autoSubscribe();
}
page.leaveRoom = async function () {
myRoom.leaveRoom();
$('#localtracks').html('');
const tracks = await QNRTC.deviceManager.getLocalTracks({
audio: {enabled: true, tag: "audio"},
video: {enabled: true, tag: "video"},
});
// 遍历 tracks,逐个销毁释放
for (const track of tracks) {
track.release();
}
}
page.publish = async function () {
// 我们打开了 3 个参数,即采集音频,采集视频,采集屏幕共享。
// 这个函数会返回一个列表,列表中每一项就是一个音视频轨对象
const localTracks = await QNRTC.deviceManager.getLocalTracks({
audio: {enabled: true, tag: "audio"},
video: {enabled: true, tag: "video"},
});
for (const localTrack of localTracks) {
localTrack.setMaster(true);
}
// 将刚刚的 Track 列表发布到房间中
await myRoom.publish(localTracks);
console.log("publish success!");
const localElement = document.getElementById("localtracks");
// 遍历本地采集的 Track 对象
for (const localTrack of localTracks) {
localTrack.setMaster(true);
// 如果这是麦克风采集的音频 Track,我们就不播放它。
if (localTrack.info.tag === "audio") continue;
// 调用 Track 对象的 play 方法在这个元素下播放视频轨
localTrack.play(localElement, true);
}
}
// 这里的参数 myRoom 是指刚刚加入房间时初始化的 Session 对象, 同上
// trackInfoList 是一个 trackInfo 的列表,订阅支持多个 track 同时订阅。
page.subscribe = async function (trackInfoList) {
// 通过传入 trackId 调用订阅方法发起订阅,成功会返回相应的 Track 对象,也就是远端的 Track 列表了
const remoteTracks = await myRoom.subscribe(trackInfoList.map(info => info.trackId));
// 选择页面上的一个元素作为父元素,播放远端的音视频轨
const remoteElement = document.getElementById("subtracks");
// 遍历返回的远端 Track,调用 play 方法完成在页面上的播放
for (const remoteTrack of remoteTracks) {
remoteTrack.play(remoteElement);
}
}
page.autoSubscribe = function () {
const trackInfoList = myRoom.trackInfoList;
// 调用我们刚刚编写的 subscribe 方法
// 注意这里我们没有使用 async/await,而是使用了 Promise,大家可以思考一下为什么
page.subscribe(trackInfoList)
.then(() => console.log("subscribe success!"))
.catch(e => console.error("subscribe error", e));
// 添加事件监听,当房间中出现新的 Track 时就会触发,参数是 trackInfo 列表
myRoom.on("track-add", (trackInfoList) => {
page.subscribe(trackInfoList)
.then(() => console.log("subscribe success!"))
.catch(e => console.error("subscribe error", e));
});
// 就是这样,就像监听 DOM 事件一样通过 on 方法监听相应的事件并给出处理函数即可
}
page.initRoom = async function () {
myRoom = new QNRTC.TrackModeSession();
}
$(function () {
page.initRoom();
});
// localhost 或者 127.0.0.1 访问刚刚那 2 个页面(因为屏幕和摄像头采集只能在 localhost 或者 https 下完成),
</script>
</html>