AppServer提供了登录服务和直播间管理服务等功能,通过与AUI Kits低代码集成工具互动直播场景SDK搭配使用可以快速实现互动直播应用,助力业务创新快速上线。

前提条件

  • 已完成前置准备相关操作。
  • 如果您需要通过容器镜像快速部署AppServer,请确保环境中已安装Docker,详情请参见Docker
  • 如果您需要通过源码构建并部署AppServer,请确保环境中已安装Golang,详情请参见Golang

通过函数计算(FC)快速部署

说明 更多AUI Kits问题咨询及使用说明,请搜索钉钉群(35685013712)加入AUI客户支持群联系我们。
  1. 进入创建互动直播应用配置界面
  2. 配置互动直播应用参数。
    参数描述
    部署类型部署AppServer的类型,本文以直接部署为例说明。
    • 通过代码仓库部署:表示将克隆一份代码到您授权的仓库下,后续可以进行源码定制。适用于正式业务发布。
    • 直接部署:表示无法自行定制源码,仅用于体验直播间AppServer功能。
    直播推流域名直播配置参数。具体配置,请参见前置准备
    直播推流鉴权Key
    直播拉流域名
    直播拉流鉴权Key
    连麦应用ID
    连麦AppKey
    IM的AppId(互动消息应用ID)
    存储类型AppServer数据存储类型,取值:
    • none:表示基于直播IM扩展能力实现,仅用于体验使用,请勿在线上使用。
    • mysql:表示通过ORM方式接入,请按规范填写地址。
    存储地址如果存储类型为none,存储地址可忽略;如果存储类型为mysql,存储地址示例:username:password@tcp(example.rds.aliyuncs.com:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local。
    说明 除表格以外其他参数保持模板中默认。
  3. 单击创建,开始部署直播间AppServer,部署时间大约为5分钟。
  4. 单击部署版本,获取访问域名。
    001002
    说明 如果提示因为合规无法直接访问,请进行域名绑定;如果用于生产环境,则必须绑定域名。具体操作,请参见配置自定义域名

通过源码构建及部署

根据源码的说明文档配置并执行,源码地址如下:

项目部署和体验

  1. 登录Serverless应用中心,一键部署应用。
    在创建应用页面,根据页面提示填写应用参数后,按需选择创建并部署默认环境只创建应用
  2. 通过Serverless Devs Cli进行部署。
    1. 安装Serverless Devs Cli开发者工具,并进行授权信息配置。详情请参见工具安装与升级配置阿里云密钥
    2. 初始化项目。
      s init ApsaraLiveDemo -d ApsaraLiveDemo
    3. 进入项目,并进行项目部署。
      cd ApsaraLiveDemo && s deploy -y

配置文件

配置文件说明
AUI Kits低代码集成工具使用YAML格式的配置文件,文件内容如下所示:
definitions:
  auth.authResponse:
    properties:
      expire:
        type: string
      token:
        type: string
    type: object
  auth.login:
    properties:
      password:
        type: string
      username:
        type: string
    required:
    - password
    - username
    type: object
  handler.CreateRequest:
    properties:
      anchor:
        description: 主播id
        example: 主播userId
        type: string
      anchor_nick:
        description: 主播Nick
        example: 主播nick
        type: string
      cover_url:
        description: 直播封面url
        example: 直播封面url
        type: string
      extends:
        description: 扩展字段,通常是JSON格式字符串
        example: 扩展字段,通常是JSON格式字符串
        type: string
      mode:
        default: 0
        description: 模式,默认0 普通直播,1 连麦直播
        example: 0
        type: integer
      notice:
        description: 直播公告
        example: 直播公告
        type: string
      title:
        description: 直播标题
        example: 直播标题
        type: string
    required:
    - anchor
    - title
    type: object
  handler.DeleteRequest:
    properties:
      id:
        description: 直播Id
        example: uuid,直播房间id
        type: string
      user_id:
        description: 当前用户Id
        example: 当前用户id
        type: string
    required:
    - id
    - user_id
    type: object
  handler.GetMeetingInfoRequest:
    properties:
      id:
        example: 直播Id
        type: string
    type: object
  handler.GetRequest:
    properties:
      id:
        description: 直播Id
        example: uuid,直播房间id
        type: string
      user_id:
        description: 用户Id
        example: 当前用户id
        type: string
    required:
    - id
    - user_id
    type: object
  handler.ListRequest:
    properties:
      page_num:
        description: PageNum
        example: 1
        type: integer
      page_size:
        description: PageSize
        example: 10
        type: integer
      status:
        description: 直播状态,不传为默认值-1 ,代表所有类型;0-准备中,1-已开始,2-已结束
        type: integer
      user_id:
        description: 用户id
        type: string
    required:
    - page_num
    - page_size
    - user_id
    type: object
  handler.LiveStatusRequest:
    properties:
      id:
        example: uuid,直播房间id
        type: string
      user_id:
        example: 当前用户id
        type: string
    required:
    - id
    - user_id
    type: object
  handler.MeetingActionRequest:
    properties:
      id:
        example: 直播Id
        type: string
      members:
        items:
          $ref: '#/definitions/models.MeetingMember'
        type: array
    type: object
  handler.TokenRequest:
    properties:
      device_id:
        description: 设备Id
        example: 设备id:DEVICE-ID
        type: string
      device_type:
        description: 设备类型:android/ios/web/win/mac ,H5接入请一定用web
        example: 设备类型:android/ios/web/win/mac
        type: string
      user_id:
        description: 用户Id
        example: 用户id:foo
        type: string
    required:
    - device_id
    - device_type
    - user_id
    type: object
  handler.TokenResponse:
    properties:
      access_token:
        type: string
      refresh_token:
        type: string
    type: object
  handler.UpdateRequest:
    properties:
      extends:
        description: 扩展字段,通常是JSON格式字符串
        example: 扩展字段,通常是JSON格式字符串
        type: string
      id:
        description: 直播Id
        example: 直播Id
        type: string
      notice:
        description: 直播公告
        example: 直播公告
        type: string
      title:
        description: 直播标题
        example: 直播标题
        type: string
    type: object
  live.PullLiveInfo:
    properties:
      flv_url:
        description: FLV协议拉流地址
        type: string
      hls_url:
        description: HLS协议拉流地址
        type: string
      rtmp_url:
        description: RTMP协议拉流地址
        type: string
      rts_url:
        description: RTS协议拉流地址
        type: string
    type: object
  models.LinkInfo:
    properties:
      cdn_pull_info:
        $ref: '#/definitions/live.PullLiveInfo'
        description: 普通观众CDN拉流地址
      rtc_pull_url:
        description: 拉流地址
        type: string
      rtc_push_url:
        description: 推流地址
        type: string
    type: object
  models.MeetingInfo:
    properties:
      members:
        items:
          $ref: '#/definitions/models.MeetingMember'
        type: array
    type: object
  models.MeetingMember:
    properties:
      camera_opened:
        description: 摄像头状态
        type: boolean
      mic_opened:
        description: 麦克风状态
        type: boolean
      rtc_pull_url:
        description: 连麦拉流地址
        type: string
      user_avatar:
        description: 用户头像
        type: string
      user_id:
        description: 用户Id
        type: string
      user_nick:
        description: 用户Nick
        type: string
    type: object
  models.Metrics:
    properties:
      like_count:
        description: 当前直播间点赞总量
        type: integer
      online_count:
        description: 当前直播间在线人数
        type: integer
      pv:
        description: 当前直播间访问人次
        type: integer
      uv:
        description: 当前直播间独立访问用户数,
        type: integer
    type: object
  models.PlayInfo:
    properties:
      bit_depth:
        description: 颜色位深。取值为整数。
        type: integer
      bit_rate:
        description: 媒体流码率。单位:Kbps。
        type: string
      creation_time:
        description: 创建时间 音/视频创建时间。格式为:yyyy-MM-ddTHH:mm:ssZ(UTC时间)。
        type: string
      definition:
        description: 视频流清晰度定义。取值: FD:流畅。 LD:标清。 SD:高清。 HD:超清 OD:原画。 2K:2K。 4K:4K。
          SQ:普通音质。 HQ:高音质。 AUTO:自适应码率。
        type: string
      duration:
        description: 媒体流长度。单位:秒。
        type: string
      encrypt:
        description: 媒体流是否加密流,取值:0:否。1 是。
        type: integer
      encrypt_type:
        description: '媒体流加密类型。取值: AliyunVoDEncryption:阿里云视频加密。AliyunVoDEncryption:阿里云视频加密。'
        type: string
      format:
        description: 媒体流格式。 若媒体文件为视频则取值: mp4、 m3u8。
        type: string
      fps:
        description: 媒体流帧率。单位:帧/每秒。
        type: string
      hdr_type:
        description: '媒体流HDR类型。取值: HDR,HDR10,HLG,DolbyVision,HDRVivid,HDRVivid'
        type: string
      height:
        description: 媒体流高度。单位:px。
        type: integer
      play_url:
        description: 媒体流宽度。单位:px。
        type: string
      size:
        description: 媒体流宽度。单位:px。
        type: integer
      status:
        description: 媒体流状态,Normal:正常状态,标记的是每种清晰度和格式的一路最新转码完成的流的状态。Invisible:不可见状态,当每种清晰度和格式有多路重复的转码流时,除了最新的一路流会被标记为正常状态,其他流会被标记为不可见状态。
        type: string
      stream_type:
        description: 媒体流类型。 若媒体流为视频则取值:video,若是纯音频则取值:audio。
        type: string
      watermark_id:
        description: 当前媒体流关联的水印ID。
        type: string
      width:
        description: 媒体流宽度。单位:px。
        type: integer
    type: object
  models.PushLiveInfo:
    properties:
      rtmp_url:
        description: RTMP协议地址
        type: string
      rts_url:
        description: RTS协议地址
        type: string
      srt_url:
        description: SRT协议地址
        type: string
    type: object
  models.RoomInfo:
    properties:
      anchor_id:
        description: 主播Id
        type: string
      anchor_nick:
        description: 主播Nick
        type: string
      chat_id:
        description: 群组Id
        type: string
      cover_url:
        description: 直播封面
        type: string
      created_at:
        description: 创建时间
        type: string
      extends:
        description: 扩展字段
        type: string
      id:
        description: 直播Id
        type: string
      link_info:
        $ref: '#/definitions/models.LinkInfo'
        description: 连麦PK 等信息, 动态生成
      meeting_id:
        description: 连麦Id
        type: string
      meeting_info:
        description: 连麦成员信息(json序列化)
        type: string
      metrics:
        $ref: '#/definitions/models.Metrics'
        description: 直播间统计
      mode:
        description: 直播模式 0-普通直播, 1-连麦直播,2-PK直播
        type: integer
      notice:
        description: 直播公告
        type: string
      pull_url_info:
        $ref: '#/definitions/live.PullLiveInfo'
        description: 拉流相关地址信息,动态生成
      push_url_info:
        $ref: '#/definitions/models.PushLiveInfo'
        description: 推流相关地址信息,动态生成
      started_at:
        description: 直播开始时间
        type: string
      status:
        description: 直播状态,0-准备中,1-已开始,2-已结束
        type: integer
      stopped_at:
        description: 直播结束时间
        type: string
      title:
        description: 直播标题
        type: string
      updated_at:
        description: 更新时间
        type: string
      user_status:
        $ref: '#/definitions/models.UserStatus'
        description: 用户状态
      vod_id:
        description: 点播Id
        type: string
      vod_info:
        $ref: '#/definitions/models.VodInfo'
        description: 直播转录制,点播信息
    type: object
  models.Status:
    properties:
      code:
        type: integer
      details: {}
      message:
        type: string
    type: object
  models.UserStatus:
    properties:
      mute:
        description: 用户设备是否静音
        type: boolean
      mute_source:
        description: 静音来源
        items:
          type: string
        type: array
    type: object
  models.VodInfo:
    properties:
      playlist:
        items:
          $ref: '#/definitions/models.PlayInfo'
        type: array
      status:
        description: 状态  0 准备中,1 成功,2 失败
        type: integer
    type: object
info:
  contact: {}
paths:
  /create:
    post:
      consumes:
      - application/json
      description: 创建直播房间
      operationId: create
      parameters:
      - description: Bearer your-token
        in: header
        name: Authorization
        required: true
        type: string
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/handler.CreateRequest'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            $ref: '#/definitions/models.RoomInfo'
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      security:
      - ApiKeyAuth: []
      summary: 创建直播房间
  /delete:
    post:
      consumes:
      - application/json
      description: 删除房间
      operationId: delete
      parameters:
      - description: Bearer your-token
        in: header
        name: Authorization
        required: true
        type: string
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/handler.DeleteRequest'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            $ref: '#/definitions/models.RoomInfo'
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      security:
      - ApiKeyAuth: []
      summary: 删除房间
  /get:
    post:
      consumes:
      - application/json
      description: 获取直播房间详情
      operationId: get
      parameters:
      - description: Bearer your-token
        in: header
        name: Authorization
        required: true
        type: string
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/handler.GetRequest'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            $ref: '#/definitions/models.RoomInfo'
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      security:
      - ApiKeyAuth: []
      summary: 获取直播房间详情
  /getMeetingInfo:
    post:
      consumes:
      - application/json
      description: 全量获取连麦信息
      operationId: GetMeetingInfo
      parameters:
      - description: Bearer your-token
        in: header
        name: Authorization
        required: true
        type: string
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/handler.GetMeetingInfoRequest'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            $ref: '#/definitions/models.MeetingInfo'
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      security:
      - ApiKeyAuth: []
      summary: 全量获取连麦信息
  /list:
    post:
      consumes:
      - application/json
      description: 获取直播房间列表
      operationId: list
      parameters:
      - description: Bearer your-token
        in: header
        name: Authorization
        required: true
        type: string
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/handler.ListRequest'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            items:
              $ref: '#/definitions/models.RoomInfo'
            type: array
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      security:
      - ApiKeyAuth: []
      summary: 获取直播房间列表
  /login:
    post:
      consumes:
      - application/json
      description: App用户登录
      operationId: login
      parameters:
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/auth.login'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            $ref: '#/definitions/auth.authResponse'
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      summary: App用户登录
  /pause:
    post:
      consumes:
      - application/json
      description: 暂停直播
      operationId: pause
      parameters:
      - description: Bearer your-token
        in: header
        name: Authorization
        required: true
        type: string
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/handler.LiveStatusRequest'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            $ref: '#/definitions/models.RoomInfo'
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      security:
      - ApiKeyAuth: []
      summary: 暂停直播
  /start:
    post:
      consumes:
      - application/json
      description: 开始直播
      operationId: start
      parameters:
      - description: Bearer your-token
        in: header
        name: Authorization
        required: true
        type: string
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/handler.LiveStatusRequest'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            $ref: '#/definitions/models.RoomInfo'
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      security:
      - ApiKeyAuth: []
      summary: 开始直播
  /stop:
    post:
      consumes:
      - application/json
      description: 停止直播
      operationId: stop
      parameters:
      - description: Bearer your-token
        in: header
        name: Authorization
        required: true
        type: string
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/handler.LiveStatusRequest'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            $ref: '#/definitions/models.RoomInfo'
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      security:
      - ApiKeyAuth: []
      summary: 停止直播
  /token:
    post:
      consumes:
      - application/json
      description: 获取token
      operationId: token
      parameters:
      - description: Bearer your-token
        in: header
        name: Authorization
        required: true
        type: string
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/handler.TokenRequest'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            $ref: '#/definitions/handler.TokenResponse'
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      security:
      - ApiKeyAuth: []
      summary: 获取TOKEN
  /update:
    post:
      consumes:
      - application/json
      description: 更新房间详情
      operationId: update
      parameters:
      - description: Bearer your-token
        in: header
        name: Authorization
        required: true
        type: string
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/handler.UpdateRequest'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            $ref: '#/definitions/models.RoomInfo'
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      security:
      - ApiKeyAuth: []
      summary: 更新房间详情
  /updateMeetingInfo:
    post:
      consumes:
      - application/json
      description: 全量更新直播连麦人员信息
      operationId: UpdateMeetingInfo
      parameters:
      - description: Bearer your-token
        in: header
        name: Authorization
        required: true
        type: string
      - description: 请求参数
        in: body
        name: request
        required: true
        schema:
          $ref: '#/definitions/handler.MeetingActionRequest'
      produces:
      - application/json
      responses:
        "200":
          description: ok
          schema:
            $ref: '#/definitions/models.MeetingInfo'
        "400":
          description: 4xx, 客户端错误
          schema:
            $ref: '#/definitions/models.Status'
        "500":
          description: 5xx, 请求失败
          schema:
            $ref: '#/definitions/models.Status'
      security:
      - ApiKeyAuth: []
      summary: 全量更新直播连麦人员信息
swagger: "2.0"
统一配置说明
  • 数据库配置
    当配置好DB后(请参见互动直播配置的存储类型存储地址参数),启动GO程序,如果DB中无表则会自动生成数据库表。如果不想使用程序自动生成,可以手工创建数据库表。以创建MySQL数据库表为例,建表语句如下所示:
    CREATE TABLE `room_infos` (
      `id` varchar(256) NOT NULL,
      `created_at` datetime DEFAULT NULL,
      `updated_at` datetime DEFAULT NULL,
      `title` varchar(256) DEFAULT NULL,
      `anchor` varchar(256) DEFAULT NULL,
      `extends` mediumtext,
      `status` bigint(20) DEFAULT NULL,
      `mode` bigint(20) DEFAULT NULL,
      `chat_id` varchar(256) DEFAULT NULL,
      `pk_id` varchar(256) DEFAULT NULL,
      `notice` varchar(256) DEFAULT NULL,
      `meeting_id` varchar(256) DEFAULT NULL,
      `cover_url` varchar(256) DEFAULT NULL,
      `anchor_id` varchar(256) DEFAULT NULL,
      `anchor_nick` varchar(256) DEFAULT NULL,
      `vod_id` varchar(256) DEFAULT NULL,
      `meeting_info` mediumtext,
      `started_at` datetime DEFAULT NULL,
      `stopped_at` datetime DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `idx_create_at` (`created_at`)
    );
  • 面向服务的鉴权配置
    需要先调用/login接口获取鉴权的token,将token放到请求头中,然后再调用其它接口。具体流程如下所示:服务端集成
    /login接口说明

    该接口您可以按自身业务需求实现,包括token的生成算法也可以自定义,但是需要确保生成以及检验token使用相同的算法。

    使用说明
    • 请求协议: HTTP/HTTPS
    • 请求Path:/login
    • 是否需要授权:否
    • 请求Method:POST
    • 请求ContentType:JSON
    请求参数
    名称类型是否必填示例值描述
    usernameStringusernamexxx用户名
    passwordStringpasswordxxxx密码
    返回数据
    名称类型示例值描述
    codeInteger200业务响应码。参考HTTP响应码
    expireString2023-02-28T14:38:06+08:00过期时间。使用UTC时间格式
    tokenStringeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9****授权凭证。默认使用jwt生成
    示例
    请求示例
    {
    "username":"usernamexxx",
    "password":"passwordxxxx"
    }
    正常返回示例
    {
    "code": 200,
    "expire": "2023-02-28T14:38:06+08:00",
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Nzc1NjYyODYsImlkIjoieXl5eSIsIm9yaWdfaWF0IjoxNjc3NDc5ODg2fQ.xxxxxx"
    }