• 《保姆级教程》基于Agora SDK实现音视频通话及屏幕共享


    😄作者简介:
    小曾同学.com,一个致力于测试开发的博主⛽️,主要职责:测试开发、CI/CD
    如果文章知识点有错误的地方,还请大家指正,让我们一起学习,一起进步。😊
    座右铭:不想当开发的测试,不是一个好测试✌️。
    如果感觉博主的文章还不错的话,还请点赞、收藏哦!👍

    如果你想实现一对一音视频通话和屏幕共享功能,不妨来看看这篇文章,保姆级教程,不需要从零实现,直接集成Agora SDK 即可轻松上手。


    一 前言

    Agora 提供了各端丰富的音视频SDK,本文将要使用的是Web端SDK。本篇文章主要给小伙伴们分享如何使用Agora SDK实现Web端音视频通话及屏幕共享功能,其中也会涵盖在实践过程中遇到的一些问题,以此记录防止小伙伴们踩坑,同时也希望通过从0到1实战的分享,能够帮助更多的小伙伴。

    二 前期准备

    在实战之前,需要有以下准备条件:

    • Npm & Node.js
    • 前端开发基础,如 html & CSS & JavaScript
    • 注册声网账号,申请声网APPID、临时Token ,详见开始使用声网平台

    如果你还没有声网账号,可以通过**这里**免费注册,每个账户每月都有10000分钟免费额度。如果是个人学习/调试,时长完全够用。

    我个人的开发环境,具体信息如下:

    • MacBook Pro
    • Visual Studio Code:v1.75.1
    • Npm:v8.19.3
    • Node.js:v16.19.0
    • Agora SDK:v4.2.1 ,sdk的下载可查看**这里**。
    • Google Chrome :v110.0.5481.177

    三 实战

    通过[前期准备],我们已经完成了相关配置,已经拥有了*App ID、Channel、临时Token、声网SDK,*在本次实战中,主要详细讲解两个demo,分别是音视频通话及屏幕共享连麦。

    3.1 实现音视频通话

    在开始实战之前,先声明下Demo组成架构,

    创建一个文件夹名为Agora_VideoCall,文件夹中包含五个文件,分别是

    • index.html:用于设计Web应用的用户界面
    • index.css:用于设计网页样式
    • basicVideoCall.js:实现音视频通话逻辑代码,主要通过AgoraRTCClient实现
    • AgoraRTC_N-4.2.1.js:声网音视频SDK
    • assets:第三方库,主要用于设计用户界面

    在 index.html 文件中导入声网SDK,具体内容可查看详细代码,接下来主要详细讲解音视频通话及屏幕共享实现逻辑。

    <script src="./AgoraRTC-N-4.2.1.js"></script>
    
    • 1

    3.1.1 实现音视频通话逻辑

    以下代码均在 basicVideoCall.js 文本中写入

    1)首先调用 AgoraRTC.createClient方法创建一个client对象,也就是创建客户端对象

    var client = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });
    
    • 1

    2)定义变量 App ID,Token、Channel、User ID,并使用箭头函数实现当页面被调用时用于加入音视频通话通道。

    var options = {
      appid: null,
      channel: null,
      uid: null,
      token: null
    };
    
    $(() => {
      var urlParams = new URL(location.href).searchParams;
      options.appid = urlParams.get("appid");
      options.channel = urlParams.get("channel");
      options.token = urlParams.get("token");
      options.uid = urlParams.get("uid");
      if (options.appid && options.channel) {
        $("#uid").val(options.uid);
        $("#appid").val(options.appid);
        $("#token").val(options.token);
        $("#channel").val(options.channel);
        $("#join-form").submit();
      }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3)加入频道

    定义 join 函数主要是将本地音视频 track 加入一个RTC频道,此时需要在函数中传入App ID,Token、Channel、User ID。加入房间后,需要发布音视频track,所以还需要创建音视频 track,并调用 publish 方法将这些本地音视频track对象当作参数发布到频道中。

    注意注意,在创建音视频track时需要先调用 createMicrophoneAudioTrack :通过麦克风采集的音频创建本地音频轨道对象;再调用 createCameraVideoTrack :通过摄像头采集的视频创建本地视频轨道对象。(如果先调用createCameraVideoTrack 那么页面中将不会显示本地视频预览画面)

    创建之后即可调用play方法展示本地预览,并调用publish方法发布到RTC频道中。注意play和publish方法的使用没有先后顺序,谁在前在后没有什么影响。

    async function join() {
      
      [ options.uid, localTracks.audioTrack, localTracks.videoTrack ] = await Promise.all([
        // 加入频道
        client.join(options.appid, options.channel, options.token || null, options.uid || null),
        // 创建本地音视频track
        //AgoraRTC.createCameraVideoTrack(),
        AgoraRTC.createMicrophoneAudioTrack(),
        AgoraRTC.createCameraVideoTrack()
      ]);
    
      localTracks.videoTrack.play("local-player");
      $("#local-player-name").text(`localVideo(${options.uid})`);
    
      await client.publish(Object.values(localTracks));
      console.log("publish success");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4)在频道中添加或移除远端用户逻辑

    实现将同频道的远端用户添加到本地接口,当远端用户取消发布时,则从本地将用户移除。

    function handleUserPublished(user, mediaType) {
      const id = user.uid;
      remoteUsers[id] = user;
      subscribe(user, mediaType);
    }
    
    function handleUserUnpublished(user, mediaType) {
      if (mediaType === 'video') {
        const id = user.uid;
        delete remoteUsers[id];
        $(`#player-wrapper-${id}`).remove();
    
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    5)订阅远端音视频逻辑

    当远端用户发布音视频时,本地用户需要对其订阅,从而实现音视频通话,在subscribe函数中需要传入两个参数,分别是同频道远端用户user id和远端mediaType,并调用play方法,播放远端用户音视频,从而实现一对一连麦。

    async function subscribe(user, mediaType) {
      const uid = user.uid;
      // 订阅远端用户
      await client.subscribe(user, mediaType);
      console.log("subscribe success");
      if (mediaType === 'video') {
        const player = $(`
          
    ${uid}">

    remoteUser(${uid})

    ${uid}" class="player">
    `
    ); $("#remote-playerlist").append(player); user.videoTrack.play(`player-${uid}`); } if (mediaType === 'audio') { user.audioTrack.play(); } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    6)监听事件

    当远端用户发布或者取消发布音视频track时,本地还需要对其监听,在 join 函数中,监听client.on(“user-published”, handleUserPublished)事件和client.on(“user-unpublished”, handleUserUnpublished)事件,具体如下

    client.on("user-published", handleUserPublished);
    client.on("user-unpublished", handleUserUnpublished);
    
    • 1
    • 2

    在这里插入图片描述

    7)离开频道

    当用户点击 leave 按钮时,则将stop本地和远端音视频track。

    async function leave() {
      for (trackName in localTracks) {
        var track = localTracks[trackName];
        if(track) {
          track.stop();
          track.close();
          localTracks[trackName] = undefined;
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.1.2 Demo展示

    接下来可以运行我们的Demo啦,输入APPID、Token、Channel、Userid,点击join,即可看到自己本地的画面,如果想和别人连麦,可以再复制一下网址,输入相同的APPID、Token、Channel,即可实现连麦,赶快试试吧。

    在这里插入图片描述

    3.2 屏幕共享连麦

    屏幕共享就是将本地用户的屏幕内容,以视频画面的方式分享给其他远端用户观看。其工作原理实际上是通过createScreenVideoTrack创建一个屏幕共享的视频轨道对象来实现。采集屏幕的过程中浏览器会询问需要共享哪些屏幕,根据终端用户的选择去获取屏幕信息。

    在上述音视频demo的基础上实现屏幕共享功能。

    3.2.1 添加屏幕共享UI

    在 index.html 页面中添加屏幕共享(ScreenShare)button

    在这里插入图片描述

    3.2.2 屏幕共享实现逻辑

    以下代码均在basicVideoCall.js文本中写入

    1)实现 share 函数

    和上述join函数功能类似,主要用于开启屏幕共享,使用createScreenVideoTrack创建屏幕共享的视频轨道对象,同时也可以对视频编码进行一些简单的配置。函数中同样也需要添加监听事件。

    async function share() {
    
      client.on("user-published", handleUserPublished);
      client.on("user-unpublished", handleUserUnpublished);
      let screenTrack;
    
          [options.uid, localTracks.audioTrack, screenTrack] = await Promise.all([
        
        client.join(options.appid, options.channel, options.token || null, options.uid || null),
        AgoraRTC.createMicrophoneAudioTrack(),
        AgoraRTC.createScreenVideoTrack({
          encoderConfig: {
            framerate: 15,
            height: 720,
            width: 1280
          }
        }, "auto")
      ]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2)添加屏幕共享音视频轨道,并调用play方法播放本地屏幕共享的视频。

    if(screenTrack instanceof Array){
        localTracks.screenVideoTrack = screenTrack[0]
        localTracks.screenAudioTrack = screenTrack[1]
      }
      else{
        localTracks.screenVideoTrack = screenTrack
      }
    
      localTracks.screenVideoTrack.play("local-player");
      $("#local-player-name").text(`localVideo(${options.uid})`);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3)发布屏幕共享

    发布本地音频和屏幕共享画面至RTC频道中。

    if(localTracks.screenAudioTrack == null){
        await client.publish([localTracks.screenVideoTrack, localTracks.audioTrack]);
      }
      else{
        await client.publish([localTracks.screenVideoTrack, localTracks.audioTrack, localTracks.screenAudioTrack]);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4)在share函数实现逻辑中需要绑定"track-ended"事件,当屏幕共享停止时,会有一个警报通知最终用户。

    localTracks.screenVideoTrack.on("track-ended", () => {
        alert(`Screen-share track ended, stop sharing screen ` + localTracks.screenVideoTrack.getTrackId());
        localTracks.screenVideoTrack && localTracks.screenVideoTrack.close();
        localTracks.screenAudioTrack && localTracks.screenAudioTrack.close();
        localTracks.audioTrack && localTracks.audioTrack.close();
      });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.2.3 Demo 展示

    当点击ScreenShare时,会提示用户选择哪一个page进行分享,同时也有一个默认音频选项,点击分享之后,即可发布屏幕共享。

    在这里插入图片描述

    三、小结

    如果你想实现音视频和屏幕共享的Web应用,完全可以借鉴本篇文章+声网SDK,如果不是很熟悉的话,可以先看Agora给出的快速开始音视频。在实践过程中需要注意的是:在创建音视频track时需要先调用 createMicrophoneAudioTrack ,再调用 createCameraVideoTrack ,如果先调用createCameraVideoTrack 那么页面中将不会显示本地视频预览画面。Generally,本篇文章给出的demo比较简单,如果想要添加其他的功能比如,虚拟背景、AI降噪等,可以在此基础上继续添加功能。

  • 相关阅读:
    Python命令行可以用下划线_代表上一次计算的结果
    如何用webgl(three.js)搭建一个3D库房,3D仓库3D码头,3D集装箱,车辆定位,叉车定位可视化孪生系统——第十五课
    Himall类型帮助类将string类型转换成decimal类型
    什么是幂等性?四种接口幂等性方案详解!
    js简写技巧
    Netty Review - 探究Netty优雅退出原理和源码解读
    自然算法 - AI面试基础补全
    linux安装并配置git连接github
    python mysql语句中有单引号执行的报错处理方式
    食之无味?App Startup 可能比你想象中要简单
  • 原文地址:https://blog.csdn.net/weixin_42182599/article/details/131178790