Web端集成

本文介绍了使用标准集成(无UI)方式接入Web端的方法。适用于互动直播、互动课堂等场景产品。

重要
  • 旧版低代码方案(原低代码音视频工厂,以下简称低代码1.0)计划于2023年9月30日下线,在此之前低代码1.0的客户可继续使用旧版互动直播或互动课堂的功能直至2023/9/30停服,请您尽快切换至低代码2.0或视频直播。

  • 升级说明请参见低代码方案升级说明。升级咨询可加钉钉群10570030108(仅限升级咨询,如您有售后问题请提交工单)。

  • 新旧方案计费规则不同,资源包不可互通使用。低代码音视频工厂未消费的资源包可以申请按比例退款。

引入SDK

重要

SDK分两个版本,互动直播版本不支持RTC、白板、文档(gziped size 26kb),完全版全部支持(gziped size 300kb),注意引入合适的版本。

  1. 在script标签中引入SDK,并在URL中指定版本号,之后在JS中引入。

    <!-- 完全版 -->
    <script src='https://g.alicdn.com/code/npm/@ali/room-paas-web-engine/1.8.1/RoomPaasSdk.web.min.js'></script>
    
    <!-- 互动直播版 -->
    <script src='https://g.alicdn.com/code/npm/@ali/room-paas-web-engine/1.8.1/RoomPaasInteractionSdk.web.min.js'></script>
    // 按需解构赋值
    const { RoomEngine, EventNameEnum } = window.RoomPaasSdk;
  2. 如需使用白板功能,请参照互动白板Web端集成与使用文档完成白板SDK接入(互动课堂场景建议接入)。白板的方法直接使用白板SDK的实例进行调用。白板的docKey通过roomChannel上的白板插件实例wbService.getWhiteboardId().then(docKey => {})获取,跟业务逻辑相关的白板录制功能也在白板插件实例上调用。

工程接入

RoomEngine鉴权

  1. 获取RoomEngine实例。

    // 获取RoomEngine实例
    const roomEngine = RoomEngine.getInstance();
  2. 为RoomEngine配置参数。

    // 获取设备号deviceId,唯一标识当前设备
    // 在web端,不同的tab页代表不同设备
    const deviceId = roomEngine.getDeviceId();
    // 如果场景确保一个设备只有一个页面,需要使用getSingleDeviceId
    const deviceId = roomEngine.getSingleDeviceId();
    
    // 配置参数
    const config = {
      appKey, // 创建应用时分配的appKey
      appId, // 创建应用时分配的appId
      deviceId, // 设备号
      authTokenCallback, // 获取登录token的回调函数,需要返回Promise
    }
    // 传入配置
    roomEngine.init(config);
    重要

    获取deviceId时,如果是移动端设备这类,一个设备同一时间只会有一个页面的场景,请使用getSingleDeviceId,否则可能会出现数据不准确的情况。

  3. 其中authTokenCallback是一个返回Promise的函数,可以用以下的方式编写:

    • 可以使用任何能返回Promise的请求库或API(如axios或fetch等)。

    • 可以自己构造Promise,在resolve里返回结果。

    • 可以使用async函数,直接return结果。

    下面使用fetch API举例:

    const authTokenCallback = () => {
      const origin = 'xxx.xxx.com'; // 客户的域名
      const path = 'api/getToken'; // 客户服务端接口
      // fetch API返回一个Promise
      return fetch(`${origin}/${path}?userId=123&foo=bar`) // 您可以自己定义接口需要的数据
        .then((res) => res.json())
        .then((res) => {
          if (res) {
            // 需要保证数据结构符合AuthToken,其定义在下面
            const authToken = res.result; // 这里需要根据您服务端返回的数据结构来决定返回什么属性
            return authToken;
          }
          throw new Error('没有获取到Token');
        })
        .catch((err) => {
          console.error(err);
        });
    }

    resolve的值来源于客户服务端SDK的接入回调,数据结构为:

    interface AuthToken {
      accessToken: string;
      refreshToken: string;
      accessTokenExpiredTime: number;
    }
  4. RoomEngine鉴权,建立WebSocket长连接。

    // uid即用户ID,标识用户身份,返回promise代表auth结果
    // 需要在.then里进行或者使用await后进行房间操作,如进入房间等
    roomEngine.auth(uid).then(() => {
      // 在这里获取RoomChannel实例进行房间操作
    });
    
    // 或者使用await
    await roomEngine.auth(uid);
    // 在这里获取RoomChannel实例进行房间操作
  5. 在退出登录时需要调用logout,确保一个auth对应一个logout。

    await roomEngine.logout(); // 返回promise

服务部分

  • 通过roomId获取或创建对应的roomChannel实例。

    // roomId标识房间号,方法调用结果获取当前房间roomChannel实例
    const roomChannel = roomEngine.getRoomChannel(roomId);
  • 调用enterRoom进入房间。必须先进入房间才能进行后续操作。

    // 必须保证enterRoom完成后才能进行后续操作,nick为用户名,例如示例为"jack"
    const nick = 'jack';
    await roomChannel.enterRoom(nick); // enterRoom返回Promise
  • 使用getPluginService(PluginId)来获取原子能力插件实例。

    // 获取Chat插件实例
    const chatService = roomChannel.getPluginService('chat');
    
    // 获取Live插件实例
    const liveService = roomChannel.getPluginService('live');
    
    // 获取Rtc插件实例
    const rtcService = roomChannel.getPluginService('rtc');
    
    // 获取Wb插件实例(白板)
    const wbService = roomChannel.getPluginService('wb');
    
    // 获取Doc插件实例
    const docService = roomChannel.getPluginService('doc');
  • 事件绑定。

    重要

    每个原子能力(包括roomChannel)都是通过插件实例来监听自身事件的,具体的事件列表可以查阅Web接口列表

    // 事件定义
    const enterRoomEventHandler = (data) => {
      console.log(data);
    }
    
    // 绑定Room事件
    roomChannel.on(EventNameEnum.PaaSRoomEnter, enterRoomEventHandler);
    
    // 解绑事件
    // SDK的事件系统允许绑定多个回调函数,如果需要解绑,请传入之前绑定时定义的函数
    roomChannel.remove(EventNameEnum.PaaSRoomEnter, enterRoomEventHandler);
    
    // 其他实例绑定方法是一样的
    // 绑定Chat事件,匿名函数
    chatService.on(EventNameEnum.PaaSChatReceiveComment, (data) => {
      console.log(data);
    });
    
    // 解绑事件
    // 如果在绑定时使用匿名函数,或者需要清空所有的绑定,可以不用传第二个参数
    chatService.remove(EventNameEnum.PaaSChatReceiveComment);
  • 退出房间。

    // 退出房间时必须调leaveRoom,不然可能会导致状态不正常
    roomChannel.leaveRoom();

API的使用

重要

在这里仅列出部分API的使用方法,完整API列表请参见Web接口列表

房间实例RoomChannel

在RoomChannel上可以调用房间的相关操作,比如进出房间、设置公告、查看房间内观众列表等。

// 进入房间
await roomChannel.enterRoom(nick);

// 异步获取房间信息
await roomChannel.getRoomDetailAsync();

// 分页获取房间用户在线列表
// pageIndex从1开始
await roomChannel.listUser(pageIndex, pageSize);

// 下面的方法需要房间所有者才可以调用

// 更新房间公告
await roomChannel.updateNotice(notice);

// 更新房间标题
await roomChannel.updateTitle(notice);

原子能力插件实例

在SDK中,各个原子能力是以插件(Plugin)的形式提供的服务(Service)。所以,需要使用getPluginService(PluginId)获取到各个原子能力插件的实例,之后就可以使用实例上的方法了。根据原子能力的组合可以实现不同的业务场景。

  • 互动Chat:

    负责直播时的弹幕、点赞、自定义消息、禁言相关功能。

    // 发送弹幕
    // 第二个参数是extension字段,内容会透传给事件和弹幕列表
    await chatService.sendComment(content, { avatar: 'xxx.xxx.png' });
    
    // 异步获取房间信息
    // sortType 排序方式,0-时间递增顺序,1-时间递减顺序
    await chatService.listComment(sortType, pageIndex, pageSize);
    
    // 点赞,连续调用(用户连续点击)时在SDK内部合并请求
    // 连续点赞场景一般实现:每次用户点击前端+1点赞数并调用sendLike
    // 收到点赞事件后用事件里的点赞数覆盖前端点赞数
    chatService.sendLike();
    
    // 下面的方法需要房间所有者才可以调用
    
    // 禁言全体
    await chatService.banAllComment();
    
    // 禁言某个用户 muteSeconds 禁言时长(s)
    await chatService.banComment(userId, muteSeconds);
    
    // 取消禁言全体
    await chatService.cancelBanAllComment();
  • 直播Live:

    负责直播拉流相关功能,并在Web端封装了AliPlayer播放器。

    重要

    在liveService中,AliPlayer实例是单例的。

    // 播放器配置,在创建播放器之前必须调用,否则会报错
    liveService.setPlayerConfig({
        container:'#player', // DOM容器id
    });
    
    // 尝试播放直播流,会根据直播状态自动决定是否创建播放器
    liveService.tryPlayLive();
    
    // 切换播放源
    liveService.switchPlaySource(url);
    
    // 结束播放(会同时销毁播放器)
    liveService.stopPlay();
    
    // 销毁播放器
    liveService.destroy();
    
    // 获取m3u8里的录制时间戳
    liveService.getCurrentPDT();
  • 播放器的使用:

    setPlayerConfig中传入的参数列表是AliPlayer的参数和本SDK所需参数的并集,SDK所需参数如下:

    interface PlayerParams {
      protocal?: 'http' | 'https'; // 强制使用http或https协议的播放地址
      useArtc?: boolean; // 是否使用连麦
      // AliPlayer的参数可以任意添加到这里
    }
    重要

    • 如果需要开启连麦,应在控制台中为您的播流域名配置好HTTPS证书,之后在setPlayerConfig中增加useArtc: true即可。

    • 如果连麦出现播放失败,会自动降级到普通直播。

    如果封装的播放器功能不足以支撑业务逻辑,可以直接获取到AliPlayer的实例:

    // 在开始播放之后(创建播放器后)才能获取到
    const playerInstance = liveService.playerInstance;
    // 直接调用AliPlayer的方法
    playerInstance.play();

    AliPlayer的属性和接口说明参阅属性和接口说明

  • 播放器事件:

    播放器自身也会透出事件,这些事件被直播实例所捕获,可以按照下面的方法监听:

    // 绑定播放器事件
    liveService.on(EventNameEnum.PaaSPlayerEvent, (data) => {
      console.log(data.eventName); // 播放器事件名称
      console.log(data.eventData); // 播放器事件返回数据
    });

    有关播放器事件列表,请参阅播放器事件

  • 音视频通信Rtc:

    负责Rtc通信的入会、订阅、媒体操作(静音、屏幕分享等)、旁路推直播流等功能,封装了AliRtc。

    // 获取设备信息
    rtcService.getDeviceInfo();
    
    // 开始摄像头预览
    rtcService.startRtcPreview(videoDom);
    
    // 进入频道
    await rtcService.joinChannel();
    
    // 开始推流
    await rtcService.startPublish();
    
    // 开始旁路推流(开始直播)
    await rtcService.startRoadPublish();
    
    // 发布屏幕流(必须在推流状态下设置)
    await rtcService.startPublishScreen();
    
    // 获取会议成员列表
    await rtcService.listConfUser(pageIndex, pageSize);
  • AliRtc实例:

    如果封装的Rtc能力不足以支撑业务,可以通过以下方法获取AliRtc实例:

    // 获取AliRtc的实例
    const aliRtcInstance = rtcService.aliRtcInstance;

    有关AliRtc的接口参阅AliRtcEngine接口

  • AliRtc事件:

    除了SDK事件以外,rtcService也透出了AliRtc自身的事件,事件名也直接并集成EventNameEnum,可以直接在实例上监听:

    // 绑定onMedia事件
    rtcService.on(EventNameEnum.onMedia, (data) => {
      console.log(data);
    });

    AliRtc事件列表如下:

    enum AliRTCSdkEventNames {
      onPublisher = 'onPublisher',
      onUnPublisher = 'onUnPublisher',
      onMediaStream = 'onMediaStream',
      onJoin = 'onJoin',
      onLeave = 'onLeave',
      onError = 'onError',
      onBye = 'onBye',
      onUpdateRole = 'onUpdateRole',
      onNotify = 'onNotify',
      onAudioLevel = 'onAudioLevel',
      onMedia = 'onMedia',
      onSubscribeResult = 'onSubscribeResult'
    }
    说明

    可以发现RtcService和AliRtc的关系类似LiveService和AliPlayer的关系,但绑定事件方式不同,是因为SDK内部对AliRtc的事件需要做特殊处理和封装,之后可能会根据需要作出改动。

  • 文档Doc

    负责ppt/pdf/jpg/png等文档的操作,包括上传、下载、转码、查看等操作。

    // 上传文档,返回值为文档Id
    const docId = await docService.upload(file);
    
    // 下载文档,返回值为文档下载地址,有效期30分钟
    docService.download(docId);
    
    // 文档转码,targetType支持'jpg'
    await docService.convert(sourceDocId, targetType, targetName);
    
    // 获取文档链接
    const data = await docService.getUrlList(docId);
  • 白板Wb

    负责白板服务与RoomChannel的关联,包括获取白板的dockey、白板的录制相关接口。

    说明

    由于白板是一个较为完备的SDK,接入方式也有多种,所以本SDK只封装了白板与房间交互的部分,即获取白板的dockey、白板的录制,没有封装白板本身提供的方法。

    // 获取白板id,如果存在则返回,不存在则创建一个
    // 返回一个Promise,需要用await获取值或者在then里取值
    const dockey = await wbService.getWhiteboardId();
    
    // 开始白板录制,返回录制的recordId等信息
    await wbService.startWhiteboardRecording();
    
    // 根据recordId结束白板录制
    await wbService.stopWhiteboardRecording(recordId);
    
    // 暂停白板录制
    await wbService.pauseWhiteboardRecording(recordId);
    
    // 继续白板录制
    await wbService.resumeWhiteboardRecording(recordId);