Web音视频通话解决方案 —— Agora Web SDK NG 版接入教程

引言

随着社会的发展,人们对实时音视频的需求越来越多。在线会议,电商直播,在线教育等相关产品不断涌现。但是对于个人开发者或者小团队来说,自己实现一个实时音视频服务并且要保障服务稳定,满足低延时等要求,难度非常大。为此我们需要寻找一个合适的解决方案。功能强大且可靠的声网Agora就成为了极佳的选择。

今年声网推出了下一代 Agora Web SDK (Agora Web SDK NG),基于 TypeScript 开发,使用 Promise 来管理异步操作,灵活易用。今天我就来分享一下如何快速接入该SDK并实现一些简单的实时音视频通话。

前期准备

首先我们需要注册一个声网账号(注册地址),注册成功后会进入控制台,完成实名认证,在左侧进入项目管理页面,开始创建项目:

创建项目

输入项目名称,选择鉴权机制。为了项目安全性考虑,这里推荐使用安全模式。提交后进入项目信息页面,记录一下AppID和证书我们之后在代码中会用到。由于我们选择了安全模式,在使用SDK时我们需要生成token,在本地开发调试时可以在项目信息页面下方点击生成临时token,然后拷贝到代码中使用。

生成临时token入口
生成临时token

在项目发布时,可以参考文档官方仓库编写对应的token生成代码,部署到自己的服务器上通过调用接口的形式来获取token。

新建项目并集成SDK

前期准备工作已经完成,大家根据自己的实际情况来新建一个web项目,完成后,我们开始通过npm安装SDK。

npm install agora-rtc-sdk-ng --save

你也可以通过script标签的形式引入SDK。

<script src="https://download.agora.io/sdk/web/AgoraRTC_N-4.1.0.js"></script>
<!-- or -->
<script src="./AgoraRTC_N-4.1.0.js"></script>

之后我们只需要在项目代码中引入agora-rtc-sdk-ng就可以直接使用了。

import AgoraRTC from "agora-rtc-sdk-ng";

实现基础的1对1视频通话

现在我们开始来按步骤实现基础的1对1视频通话。

1. 创建本地客户端对象

首先我们需要创建一个本地客户端对象,由于我们不是直播,mode我们选择rtc,编码有H.264和VP8两种,我这里没有兼容性要求,所以选用推荐的VP8,参考官方文档

const rtcClient = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });

2. 加入频道

加入频道这里需要传入4个参数:声网的项目appid,频道名称,如果鉴权开启了安全模式需要传入token,最后传入uid,uid为null时SDK会自动生成一个uid返回给你。

如果你是用app证书通过自己的代码生成token,需要保证频道名称和uid与生成token时保持一致,否则加入频道会失败。

const uid = await rtcClient.join(<appid>, <channel name>, <token>, <uid>);

3. 创建本地音视频轨道

加入完频道我们开始创建本地音视频轨道,调用createMicrophoneAudioTrack()通过本地麦克风采集的音频创建音频轨道对象,调用
createCameraVideoTrack()通过本地摄像头采集的视频创建视频轨道对象。你也可以在调用时传入参数来调整编码、前置\后置摄像头等配置。同时这里还需要注意浏览器提示或相关的设置,允许浏览器访问摄像头、麦克风等设备,必要时对用户进行引导和提示。

const localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
const localVideoTrack = await AgoraRTC.createCameraVideoTrack();

4. 播放本地音视频轨道

创建完本地音视频轨道对象后,我们可以调用play()进行播放,预览一下音频和视频。播放音频轨道时不需要传入任何参数,播放视频轨道时需要指定一个DOM元素,你可以传入一个元素对象,也可以传入元素的id值。之后SDK会自动在该元素内部生成一个video元素播放视频轨道。

<div id="video-container"></div>
// 播放视频轨道
localVideoTrack.play(document.getElementById('video-container'));
// or
localVideoTrack.play('video-container');

// 播放音频轨道
localAudioTrack.play();

效果如图:

本地预览

5. 发布本地音视频轨道

现在我们需要调用publish()将我们本地的音视频轨道发布到频道中,一个本地客户端对象可以发布多个音频轨道,比如:背景音乐、麦克风声音等,SDK会自动将其合并为一个音频轨道发布到频道中去,但是一个本地客户端对象只能发布一个视频轨道,如果有发布多个视频轨道的需求,你可以创建多个本地客户端对象加入同一个频道,然后发布不同的视频轨道,但是需要注意区分2个client使用的uid,并在本地订阅时过滤掉,防止重复订阅,参考文档

await rtcClient.publish([
    localAudioTrack,
    localVideoTrack
]);

6. 订阅远端用户并播放远端音视频

现在我们需要监听user-published事件,当同一频道的其他用户调用publish()发布音视频轨道时,SDK会触发该事件,我们需要监听这个事件并在回调中订阅其他用户发布的音视频轨道,并调用play()进行播放

<div id="remote-user"></div>
rtcClient.on("user-published", async (user, mediaType) => {
    await rtcClient.subscribe(user, mediaType);
    if (mediaType === "video") {
        console.log("subscribe video success", user);
        user.videoTrack.play(document.getElementById('remote-user'));
    }
    if (mediaType === "audio") {
        console.log("subscribe audio success");
        user.audioTrack.play();
    }
});

效果如下图,上方是我们本地的摄像头画面,下方为远端的摄像头画面,到这里为止一个基础的1对1视频通话已经完成了!

视频通话效果图

通话质量监测

对于实时音视频来说,保障通话质量是很重要的一环,在SDK中提供了相关的api供我们查询当前的通话质量,文档,通过使用这些api,客户端可以及时采取措施,给予用户及时的提示和反馈。避免影响用户的使用体验。

声网控制台还有水晶球面板,里面提供了丰富的通话质量数据查询功能,开发者可以使用这个工具更全面的掌握通话质量状况。

水晶球截图

小拓展

多个音频轨道

上文中有提到,一个客户端对象可以发布多个音频轨道,没有先后顺序,可以多次通过调用publish()进行发布,SDK会自动合并为一个音频轨道发布到频道中。下面我们就通过自定义音频采集以及MediaStreamTrack API往通话中播放一个本地音频文件作为背景音乐。

1. 创建HTMLAudioElement

我们在前面基础音视频通话代码的基础上进行修改,首先创建一个button确保用户,让用户点击后再播放音频文件,确保用户与页面有一个交互行为。并监听对应的点击事件。

<button id="addMusic">添加音乐</button>
document.getElementById("addMusic").addEventListener("click", () => {
    const audio = new Audio("./music.ogg");
    audio.play();
});

2. 获取音频轨道并发布

调用captureStream()获取MediaStream对象,监听addtrack事件,触发时调用getAudioTracks()获取MediaStreamTrack对象的集合,由于我的音频文件只有一个音轨,所以这里直接取第1个元素。使用createCustomAudioTrack()将获取到的MediaStreamTrack转换为一个可以用于SDK的音频轨道,最后使用客户端对象的publish()发布。结合之前的音视频通话,此时在远端已经能正常收听到2个音轨的声音了(麦克风和音乐文件)。

document.getElementById("addMusic").addEventListener("click", () => {
    const audio = new Audio("./music.ogg");
    audio.play();
    const musicStream = audio.captureStream();
    const musicStream.onaddtrack = async () => {
        const musicMediaStreamTrack = musicStream.getAudioTracks()[0];
        const musicCustomAudioTrack = AgoraRTC.createCustomAudioTrack({
            mediaStreamTrack: musicMediaStreamTrack
        });
        await rtClient.publish([musicCustomAudioTrack])        
    };
});

自定义视频采集

和音频一样,SDK也支持你使用自定义的视频轨道来实现如屏幕录制,播放本地视频文件等功能。屏幕录制在官方文档中有介绍,这里我分享一下如何获取并发布一个本地视频文件的视频轨道。

一个客户端对象只支持发布一个视频轨道,同时发布多个(比如录屏+摄像头画面)需要创建2个客户端对象分别进行发布。

1. 创建video元素

首先我们创建一个video元素用于播放视频文件,并获取到HTMLVideoElement对象。

<video id="videoFile" src="./video.mp4" control>
const video = document.getElementById('video');

2. 获取并发布视频文件的媒体流

这一步和获取音频文件媒体流类似,我们分别发布了视频和音频轨道后的效果如图。画面上方的A端播放的视频文件,画面下方是B端的摄像头画面

视频文件包含视频轨道和音频轨道,我们需要分别获取对应的轨道进行发布,如果只发布了视频轨道会导致远端没有视频声音

const stream = video.captureStream();
stream.onaddtrack = async () => {
    const videoMediaStreamTrack = stream.getVideoTracks()[0];
    const audioMediaStreamTrack = stream.getAudioTracks()[0];
    const videoTrack = AgoraRTC.createCustomVideoTrack({
        mediaStreamTrack: videoMediaStreamTrack
    });
    const audioTrack = AgoraRTC.createCustomAudioTrack({
        mediaStreamTrack: audioMediaStreamTrack
    });
    await this.rtc.client!.publish([videoTrack,audioTrack]);
};
自定义视频效果图

结尾

声网的Agora Web SDK NG 版接入是十分便捷的,简单易上手,功能强大,文档清晰。SDK也在github上开源。每个月还有10000分钟的免费额度,他们也会不定期举办一些套餐包优惠活动。通话质量也有可靠的保障。对于个人或小团队来说实现音视频通话不再是很困难的一件事了。总结一下就是:真香。如果你和你的团队有这方面的需求,不妨也来试试使用声网。

「本文为个人原创,首发于声网开发者社区

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容