引言

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

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

前期准备

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

image

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

image
image

在项目发布时,可以参考文档官方仓库编写对应的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();

效果如图:

image

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视频通话已经完成了!

image

通话质量监测

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

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

image

小拓展

多个音频轨道

上文中有提到,一个客户端对象可以发布多个音频轨道,没有先后顺序,可以多次通过调用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]);
};

image

结尾

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

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


Aiwass
1 声望1 粉丝