您可以阅读本文,了解视频互动直播服务端的集成操作。

前提条件

说明
  • 首次开通RTC服务后,系统会自动帮您创建一个应用项目,您可以直接使用自动创建好的应用项目,也可以在音视频通信控制台创建应用,详情请参见创建应用
  • 体验Demo可按照时长付费,暂时无需购买时长包。
  • 当您启用旁路转推服务且超过10个并发量时,您需要和客户经理沟通或提交工单(选择视频直播)。

操作步骤

说明 您在集成服务端时,如果遇到问题,请参见服务端运行常见问题
  1. 获取应用ID及其对应的AppKey。此处需要记录一下应用ID和AppKey,后续步骤中会用到。
    1. 登录RTC控制台
    2. 在左侧导航栏单击应用管理,进入应用管理页面。
    3. 获取应用ID和查询AppKey。
      • 应用ID:可在应用ID/名称列表下直接获取。
      • AppKey:单击查询AppKey获取AppKey。
      如果您还未有应用,您可以单击创建应用创建。获取AppKey和应用ID
  2. 获取AccessKey。
    说明 由于主账号AccessKey泄露会威胁您所有资源的安全,因此出于安全考虑,需要创建一个子账号(RAM用户)并获取子账号的AccessKey,用于访问您的云资源。
    1. 登录RAM控制台
    2. 在左侧导航栏选择人员管理 > 用户,进入用户页面。
    3. 单击创建用户,填写用户账号信息,选中编程访问创建用户。
      创建用户
    4. 重新返回用户页面。在用户登录名称/显示名称列表下,单击目标RAM子账户,进入管理页面。
      单击子RAM账户
    5. 单击权限管理,单击添加权限
      添加权限
    6. 分别输入RTC、Live、VOD进行搜索,选择AliyunRTCFullAccess(管理音视频通信的权限)、AliyunLiveFullAccess(管理视频直播的权限)和AliyunVODFullAccess(管理视频点播服务的权限),单击确定
      权限
    7. 单击认证管理,在用户AccessKey区域单击创建AccessKey
      说明
      • 首次创建时需填写手机验证码。
      • 如果AccessKey泄露或丢失,则需要创建新的AccessKey,最多可以创建2个AccessKey。
      创建AccessKey
    8. 获取AccessKey ID和AccessKey Secret。
      创建AccessKey完成后,会弹出创建AccessKey对话框,可以获取AccessKey ID和AccessKey Secret。
      注意 AccessKey ID和AccessKey Secret在后续开发中会使用,建议记录到本地文档妥善保存。AccessKey Secret只在创建时显示,不提供查询。
      获取AccessKey
  3. 获取推流地址和播放地址。详情请参见获取推流与播放地址
  4. 下载并解压Demo源码。
    解压目录
  5. 配置Demo工程。
    1. server/dist/videoliveRoom.zip文件解压到server/dist文件夹下。

      解压成功之后如下图所示。

      解压文件
      说明 解压成功后,可以看到BOOT-INF、META-INF及org文件夹,这三个文件夹需要和restart.sh保持在同一个目录下。
    2. 在MySQL中创建数据库并使用SQL文件/server/sql/appserver_create_table.sql建表。
      1. 启动MySQL服务。
        • Windows:net start MySQL服务名
        • Mac:sudo Mysql服务路径 start
        • Linux:service mysql start
      2. 重新打开终端,并定位到sql文件目录下,执行以下命令创建videoliveRoom数据库及channel表。

        mysqladmin -u root -p create videoliveroom

        mysql -u (输入用户名,如root) -p(输入密码) videoliveroom < ./appserver_create_table.sql

    3. 修改配置文件。
      打开BOOT-INF/classes/application.properties文件,修改配置。
      说明 使用文本编辑器打开即可,若找不到打开方式,推荐安装VSCode等轻量级代码编辑器打开。
      配置文件
      • 设置RTC应用AppId和AppKey,请参见步骤1获取。

        rtc.liveclass.appId = *

        rtc.liveclass.appKey = *

      • 设置AK,需要添加AliyunRTCFullAccess权限,请可参见步骤2获取。

        accessKeyID=*

        accessKeySecret=*

      • 设置播流地址和鉴权,请参见步骤3获取。

        live_play_domain = *

        live_play_domain_auth_key = *

      • 设置推流地址和鉴权,请参见步骤3获取。

        live_push_domain = *

        live_push_domain_auth_key = *

      • 修改数据库访问地址、用户名和密码。

        数据库访问地址:spring.datasource.url = jdbc:mysql://数据库IP地址(本地:127.0.0.1):3306/数据库名(videoliveroom)?useSSL=false&useUnicode=true&characterEncoding=UTF-8

        用户名:spring.datasource.username = *

        密码:spring.datasource.password = *

        说明 如果数据库和服务端都在本地运行,则数据库IP地址可以使用127.0.0.1。
  6. 运行服务,执行restart.sh文件。
    • Mac或Linux环境下请将终端定位至dist目录下,执行如下命令:

      sh restart.sh

      后台执行可以使用如下命令以确保退出终端时程序能够继续运行。

      nohup sh restart.sh >./run_log.log 2>&1 &

    • Windows环境需要打开CMD终端定位到server/dist文件夹下,执行如下命令:

      java org.springframework.boot.loader.JarLauncher

      若提示8080端口被占用,请尝试使用netstat命令查看占用8080端口的进程pid号,并使用taskkill关闭相关进程。

      netstat -ano | findstr 8080

      taskkill /pid 占用端口的进程pid号 /f

      终止8080端口

      终端成功运行后可以看到服务端启动成功的日志信息。

      日志
  7. 检查服务端是否已经启动。

    在浏览器中访问http://127.0.0.1:8080/videoliveRoom,如果如下图所示,表示服务端已经启动。

    验证

主要功能说明

  • 获取正在直播的房间列表。

    访问地址:/getChannelList

    List<Channel> channelList = channelService.getChannelList(lastChannelId, pageSize);
    
    String appId = ConfigMapUtil.getValueByKey("rtc.liveclass.appId");
    
    ResponseResult responseResult = new ResponseResult();
    Iterator<Channel> channelIterator = channelList.iterator();
    while (channelIterator.hasNext()) {
        Channel channel = channelIterator.next();
        String channelId = channel.getChannelId();
    
    
        DescribeChannelUsersResponse response = RtcOpenAPI.describeChannelUsers(appId, channelId);
    
        if (CollectionUtils.isEmpty(response.getUserList())) {
            channelService.deleteChannel(channelId);
            channelIterator.remove();
        }
    
    }
    
    responseResult.setData(channelList);
  • 随机生成用户信息和客户端调用RTC SDK加入房间的Token信息。具体生成方式参考RTC帮助文档接入工具

    访问地址:/getRtcAuth

    JSONObject rtcToken = RtcOpenAPI.createToken(channelId, userId);
    
    responseResult.setData(rtcToken);
    
    String appId = ConfigMapUtil.getValueByKey("rtc.liveclass.appId");
  • 开启旁路直播。

    访问地址:/startMPUTask

    StartMPUTaskResponse response = RtcOpenAPI.startMPUTask(channelId, pushUrl, channelId, appId, userId);
    
    Channel channel = new Channel();
    channel.setChannelId(channelId);
    channel.setOwnerId(userId);
    channel.setCoverUrl(coverUrl);
    channel.setTitle(title);
    channel.setCreateDateTime(LocalDateTime.now());
    channelService.insertChannel(channel);
  • 根据房间ID获取播放地址。

    访问地址:/getPlayUrl

    String livePlayDomain = ConfigMapUtil.getValueByKey("live_play_domain");
    String livePlayDomainAuthKey = ConfigMapUtil.getValueByKey("live_play_domain_auth_key");
    
    String appStream = ConfigMapUtil.getValueByKey("live_app_stream_name");
    
    Long timestamp = System.currentTimeMillis() / 1000;
    String rand = UUID.randomUUID().toString().replace("-", "");
    
    ResponseResult responseResult = new ResponseResult();
    
    // 原画
    String playUrlRtmp = "rtmp://" + livePlayDomain + AuthKeyUrlUtil.getAuthedPath(appStream + channelId, livePlayDomainAuthKey, timestamp, rand);
    String playUrlFlv = "https://" + livePlayDomain + AuthKeyUrlUtil.getAuthedPath(appStream + channelId + ".flv", livePlayDomainAuthKey, timestamp, rand);
    String playUrlM3u8 = "https://" + livePlayDomain + AuthKeyUrlUtil.getAuthedPath(appStream + channelId + ".m3u8", livePlayDomainAuthKey, timestamp, rand);
    
    JSONObject playUrl = new JSONObject();
    playUrl.put("rtmp", playUrlRtmp);
    playUrl.put("flv", playUrlFlv);
    playUrl.put("m3u8", playUrlM3u8);
  • 房间人数变化时更新布局。

    访问地址:/updateMPULayout

    List<String> userList = getSortedUserList(channelId);
    
    UpdateMPULayoutRequest request = new UpdateMPULayoutRequest();
    
    String appId = ConfigMapUtil.getValueByKey("rtc.liveclass.appId");
    
    request.setAppId(appId);
    
    request.setTaskId(channelId);
    
    List<UpdateMPULayoutRequest.UserPanes> userPanesList = new LinkedList<>();
    for (int i = 0; i < userList.size(); i++) {
        UpdateMPULayoutRequest.UserPanes userPanes = new UpdateMPULayoutRequest.UserPanes();
        userPanes.setUserId(userList.get(i));
        userPanes.setPaneId(i);
        userPanes.setSourceType("camera");
        userPanesList.add(userPanes);
    }
    
    request.setUserPaness(userPanesList);
    
    String layout1Id = ConfigMapUtil.getValueByKey("layout_1");
    String layout2Id = ConfigMapUtil.getValueByKey("layout_2");
    String layout3Id = ConfigMapUtil.getValueByKey("layout_3");
    List layoutIdArr = new ArrayList();
    layoutIdArr.add(layout1Id);
    layoutIdArr.add(layout2Id);
    layoutIdArr.add(layout3Id);
    request.setLayoutIdss(layoutIdArr);
    
    UpdateMPULayoutResponse response = RtcOpenAPI.updateMPULayout(request);
    log.info(JSON.toJSONString(response));
  • 主播关闭直播后关闭旁路转推任务。

    访问地址:/stopMPUTask

    StopMPUTaskResponse response = RtcOpenAPI.stopMPUTaskRequest(request);
    RtcOpenAPI.deleteChannel(appId, channelId);
    
    channelService.endChannel(channelId, LocalDateTime.now());
    
    return responseResult;
  • 查询正在上麦的用户列表。

    访问地址:/getUserList

    ResponseResult responseResult = new ResponseResult();
    List<String> userList;
    userList = getSortedUserList(channelId);
  • 将指定终端用户从频道踢出。

    调用访问地址:/removeTerminals

    DescribeChannelUsersResponse response = RtcOpenAPI.describeChannelUsers(appId, channelId);
    
    List<String> userList = response.getUserList();
    userList.remove(operatorId);
    
    RtcOpenAPI.removeTerminals(appId, channelId, userList);