概述
一直好奇直播这个东东是如何实现的,譬如音视频流是如何采集的? 音视频流是如何推送到订阅方 ? 如何支撑上万级、百万级用户同时观看直播 ?
下面就基于声网 Agora SDK 开发一个简单的直播网站来体验一下吧。
功能设计
如上图所示为直播 Demo 实现的基本功能展示,包括:
主播端:
- 创建直播间
- 发布、取消发布视频
- 下播
- 浏览发送弹幕
访客端:
- 浏览直播间
- 观看直播
- 退出直播间
- 浏览发送弹幕
下面看下本次实现的简易架构图:
实现
在实现之前我们需要创建 Agora 账号并获取 App ID(参见声网的开发者中心)。
主播端
创建直播间
本次实现对于直播间的创建只是简单记录下直播间的名称
存储直播间名称
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取直播间名称
String room = req.getParameter("room");
// 新增直播间
RoomListHolder.addRoom(room);
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json");
resp.getWriter().write("true");
}
复制代码
Agora SDK 集成
// 创建 Agora Client
var client = AgoraRTC.createClient({mode: 'interop'});
// 初始化 client,并在初始化成功后执行加入直播间频道
client.init('APP ID', function () {
// 加入直播间频道
client.join(null, room, null, function (uid) {
console.log("用户 " + uid + "创建了直播间 " + room);
// 执行本地视频发布
});
});
复制代码
发布视频
主播在完成直播间的创建之后,基于 Agora SDK 实现本地视频的发布,这样当有订阅该直播间频道的用户将会获取视频流。
获取本地音频设备
在发布视频前,需要获取本地的音频设备,也即是麦克风,摄像头。
AgoraRTC.getDevices(function (devices) {
for (var i = 0; i !== devices.length; ++i) {
var device = devices[i];
if (device.kind === 'audioinput') {
// 获取麦克风设备
media.audio = device.deviceId;
} else if (device.kind === 'videoinput') {
// 获取摄像头设备
media.video = device.deviceId;
}
}
});
复制代码
发布视频
// 创建本地音视频流
var localStream = AgoraRTC.createStream({
streamID: uid, // Agora 分配的 uid
audio: true,
cameraId: camera,
microphoneId: microphone,
video: true,
screen: false
});
// 初始化音视频流
localStream.init(function () {
// 指定元素 ID 播放音视频流
localStream.play('video');
// 发布音视频流
client.publish(localStream, function (err) {
console.log("音视频发布失败: " + err);
});
// 监听音视频发布事件
client.on('stream-published', function (evt) {
console.log("音视频发布成功!");
});
}, function (err) {
console.log("", err);
});
复制代码
下播
下播对于 Agora SDK 来说即是离开频道,同时从直播间列表中移除当前直播间。
client.leave(function () {
// 主播执行时 会触发访客端事件 peer-leave
// 访客执行时 不会触发
console.log("下播成功");
// 将 room 从直播间列表中移除
$.post("/removeRoom?room=" + room, {}, function(data, textStatus, jqXHR) {
// do nothing
}, 'json');
}, function (err) {
console.log("下播失败");
});
复制代码
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取待移除的直播间
String room = req.getParameter("room");
// 移除直播间
RoomListHolder.removeRoom(room);
}
复制代码
访客端
访客通过浏览直播间列表,选择自己感兴趣的主播观看。
浏览直播间
// 获取直播间列表数据
$.get("/getRooms", function (data, status) {
var roomHtml = '';
if (data == null) {
roomHtml = '当前没有直播间';
} else {
$.each(data, function (i, room) {
roomHtml += '\n' +
' \n' +
' '+ room +'\n' +
' \n' +
' +
' 观看\n' +
' \n' +
' \n' +
' \n' +
' \n' +
' ';
});
}
// 渲染
$('#roomList').html(roomHtml);
});
复制代码
观看直播
访客观看直播,对于 Agora SDK 来说也就是加入直播间频道,并订阅频道视频流。
client.join(null, room, null, function (uid) {
console.log("用户 " + uid + " 来到直播间 " + room);
}, function (err) {
console.log("加入直播间失败")
});
client.on('stream-added', function (evt) {
// 主播发布视频时会触发 stream-added 事件
var stream = evt.stream;
// 访客订阅 stream 流
client.subscribe(stream, function (err) {
console.log("视频流订阅失败", err);
});
});
client.on('stream-subscribed', function (evt) {
// 主播端视频流订阅成功后触发 stram-subscribed 事件
var stream = evt.stream;
// 按指定元素 ID 播放视频流
stream.play('video_remote');
});
client.on('stream-removed', function (evt) {
// 主播端执行 unpublish 时会触发该事件
var stream = evt.stream;
// 停止视频播放
stream.stop();
});
client.on('peer-leave', function (evt) {
// 主播端执行 leave 下播操作时会触发该事件
var stream = evt.stream;
if (stream) {
// 停止视频流播放
stream.stop();
}
});
复制代码
弹幕
本次只是对直播的简单实现,弹幕的功能暂时忽略吧,o(╯□╰)o
效果
直播
观看直播
小结
在 Agora SDK 的使用过程中,可以感受到其有以下优点:
- 支持多种应用场景
- 完善的 API 文档,方便开发者查阅
- 提供开发者社区,便于开发者交流,反馈使用过程中的问题
- 针对各种场景提供了 DEMO
不过在官网提供的快速开始及 API 相关重要方法譬如client.publish中,最好能说明下调用了该方法会触发哪些事件;而不是只有在查阅了 event api 才会发现其是哪些操作触发的。
Agora SDK 使用体验征文大赛 | 掘金技术征文,征文活动正在进行中