旁路推流 RESTful API

最近更新时间:2025-03-19 10:44:09

本文介绍如何通过 RESTful API 实现旁路推流

开通服务

第一次使用旁路推流,需要开通服务,步骤如下:

1、登录控制台,在项目管理页面,选择需要开通旁路推流服务的项目,点击编辑按钮进入编辑项目页面。 2、在编辑项目页面的功能模块找到旁路推流,点击前往开启旁路推流。 3、点击开启旁路推流。 4、点击确定。

开通成功后你可以在用量页面看到旁路推流的使用情况。

认证

anyRTC RESTful API 要求 Basic HTTP 认证。每次发送 HTTP 请求时,都必须在请求头部填入 Authorization 字段。关于如何生成该字段的值,请参考 HTTP 基本认证

原理

你可以使用推流 RESTful API 订阅 anyRTC 频道内的音视频流,将音视频流转码后(或选择不转码),通过标准协议(如 RTMP)推送到 CDN(Content Delivery Network)。这个过程相当于 anyRTC 通过一个 Converter 将音视频流处理后输出并推到 CDN。你可以通过如下方法控制 Converter:

  • Create:为指定的项目创建一个 Converter,设置转码(或不转码)和推流的相关参数。频道内用户音视频流会按照指定的配置经过 Converter 处理后输出推到 CDN。

  • Delete:销毁指定的 Converter。销毁该 Converter 后,此频道内用户音视频流将不再经过 Converter 处理并输出推到 CDN。

  • Update:更新指定的 Converter 配置。

  • Get: 获取指定 Converter 的推流状态。

Create:创建一个 Converter

HTTP 请求

POST https://api.agrtc.cn/{region}/v1/projects/{appId}/rtmp-converters

路径参数

  • appId:String 型必填参数。anyRTC 为每个开发者提供的 App ID。在 anyRTC 控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。
  • region: String 型必填参数。创建 Converter 的区域。anyRTC 支持分区域创建 Converter,目前支持以下区域:
    • cn:中国大陆
    • ap:除中国大陆以外的亚洲区域
    • na:北美
    • eu:欧洲
  • 请保证设置的 region 与你的 CDN 源站在同一个区域。
  • 请保证传入 region 的值为小写。

查询参数

regionHintIp: String 型可选参数。CDN 源站 IP 地址,必须为有效的 IPv4 地址。该参数可以保障 RTMP 流的稳定性。

POST https://api.agrtc.cn/{region}/v1/projects/{appId}/rtmp-converters?regionHintIp={regionHintIp}

请求头

  • Content-Type : application/json

  • Authorization :该字段的值需参考认证说明

  • X-Request-ID:UUID(通用唯一识别码),标识本次请求。传入该字段后,anyRTC 服务器会在响应 header 中返回该字段。

anyRTC 推荐用户对 X-Request-ID 赋值。如果用户不赋值,anyRTC 服务器会自动生成一个 UUID 传入。

转码推流

包含如下字段:

字段名类型描述
nameString(可选)Converter 的名字。长度必须在 64 个字符以内,支持的字符集范围为:
  • 所有小写英文字母(a-z)
  • 所有大写英文字母(A-Z)
  • 数字 0-9
  • "-", "_"

  • 不传值时该字段为空。
    transcodeOptionsJSON Object(必填)Converter 的转码配置。
    transcodeOptions.rtcChannelString(必填)anyRTC频道名称。即 Converter 处理的流所属的频道。字符串长度必须在 64 字节以内,支持以下字符集(共 89 个字符):
  • 所有小写英文字母(a-z)
  • 所有大写英文字母(A-Z)
  • 数字 0-9
  • 空格
  • "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "
  • transcodeOptions.audioOptionsJSON ObjectConverter 的音频转码配置。详见 audioOptions
  • 在纯视频流(无音频)场景中,无需设置 'audioOptions' 及其相关字段。
  • 在音视频场景中,audioOptions 为必填字段,若无字段要求,可以把 audioOptions 设置为空,例如:"audioOptions":{}
  • 当 converter.transcodeOptions.audioOptions 字段中无 rtcStreamUids 字段时,anyRTC会将频道内所有用户的音频流进行混音并通过 Converter 输出混音后的音频流
  • 当 converter.transcodeOptions.audioOptions 字段中有 rtcStreamUids 字段时,anyRTC会将指定用户的音频流进行混音并通过 Converter 输出混音后的音频流。
  • transcodeOptions.audioOptions.codecProfileString(可选)Converter 输出的音频编解码器。支持如下值:
  • LC-AAC(默认值): MPEG-4 AAC LC。
  • HE-AAC: High-Efficiency AAC。
  • transcodeOptions.videoOptionsJSON Object(可选)Converter 的视频转码配置。
  • 在纯音频流(无视频)场景中,无需设置 videoOptions 及其相关字段。
  • 在音视频场景中,videoOptions 为必填字段,且不能为空。
  • transcodeOptions.videoOptions.canvasJSON Object(必填)视频画布。详见 canvas
    transcodeOptions.videoOptions.layoutTypeNumber(可选输出视频的画面布局类型:
  • 0 或空:(默认)自定义布局,即通过 transcodeOptions.videoOptions.layout 设置布局信息。
  • 1:垂直布局。指定一个用户在屏幕左侧显示大视窗画面,其他用户以小视窗画面在屏幕右侧垂直排列,详见设置垂直布局。
  • transcodeOptions.videoOptions.layoutJSON Array(可选)画布上视频画面的内容描述。详见 layout。支持 RtcStreamView 和 ImageView 两种元素:
  • RtcStreamView 元素:画布上各用户的视频画面。
  • ImageView 元素:画布上的视频图片,可用于当水印。

  • 如果 layoutType 为0 或空,则该字段为必填。
    transcodeOptions.videoOptions.verticalJSON Object(可选)垂直布局的画面设置信息。当 layoutType 为 1 时必须设置该参数。详见 vertical
    transcodeOptions.videoOptions.defaultPlaceholderImageUrlString(可选)默认的用户画面背景图 URL 地址。支持 JPG、PNG 和 GIF 格式的图片。当频道内用户停止发布视频流:
  • 如果设置了该字段,用户的视频画面将切换为该背景图。
  • 如果未设置该字段,用户的视频画面先显示为该用户视频最后一帧,布局刷新后显示为画布背景色。
  • transcodeOptions.videoOptions.bitrateNumber(必填)输出视频的编码码率 (Kbps)。取值范围为 [1,10000]。详见常用视频属性
    transcodeOptions.videoOptions.frameRateNumber(可选)输出视频的编码帧率 (fps)。取值范围为 [1,30]。默认值为 15。详见常用视频属性
    transcodeOptions.videoOptions.gopNumber(可选)输出视频的 GOP。默认值为 frameRate * 2。
    transcodeOptions.videoOptions.codecString(可选)输出视频的编解码规格。不可设置为空。支持如下值:
  • H.264 (默认值)
  • H.265
  • transcodeOptions.videoOptions.codecProfileString(可选)输出视频的编码规格。支持如下值:
  • high(默认值): High 级别的视频编码规格,一般用于广播及视频碟片存储,高清电视。
  • baseline: Baseline 级别的视频编码规格,一般用于低阶或需要额外容错的应用,比如视频通话、手机视频等。
  • main: Main 级别的视频编码规格,一般用于主流消费类电子产品,如 mp4、便携的视频播放器、PSP 和 iPad 等。

  • 如果 codec 设置为 H.265,则 codecProfile 默认且必须为 main。
    transcodeOptions.videoOptions.seiOptionsJSON Object(可选)设置输出视频中携带的用户 SEI 信息。默认为空。不设置则表示不输出 SEI 信息。详见 seiOptions
    idleTimeoutNumber(可选)Converter 处于空闲状态的最大时长(秒)。空闲指 Converter 处理的音视频流所对应的所有用户均已离开频道。当 Converter 处于空闲状态时长大于 idleTimeout,Converter 自动销毁,推流停止。取值范围为 [5,86400]。如果设置值小于 5,则默认为 5;如果设置值大于 86400,则默认为 86400。默认值为 300。
    rtmpUrlString(必填)CDN 推流地址。必须为有效的 RTMP 地址,且长度在 1024 个字符以内。
    jitterBufferSizeMsInt(可选)音频接收端到网络抖动缓冲端的网络延迟 (ms)。默认值为 1000,取值范围 [0, 1000]。
  • 旁路推流服务会根据你设置的值,以 100 为单位向上取整。
  • 设置为 0 表示不使用抖动缓冲延迟。弱网情况下可能导致音画质量问题,anyRTC建议你不要将 jitterBufferSizeMs 设置为 0。
  • 不转码推流

    不转码推流的请求包体为 JSON Object 类型的 converter 字段,字段含义详见下表:

    字段名类型描述
    nameString(可选)Converter 的名字。长度必须在 64 个字符以内,支持的字符集范围为:
  • 所有小写英文字母(a-z)
  • 所有大写英文字母(A-Z)
  • 数字 0-9
  • "-", "_"

  • 不传值时该字段为空。
    rawOptionsJSON Object(必填)Converter 的推流配置。
    transcodeOptions.rtcChannelString(必填)anyRTC频道名称。即 Converter 处理的流所属的频道。字符串长度必须在 64 字节以内,支持以下字符集(共 89 个字符):
  • 所有小写英文字母(a-z)
  • 所有大写英文字母(A-Z)
  • 数字 0-9
  • 空格
  • "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "
  • transcodeOptions.rtcStreamUidNumber(必填)要推送的音视频流所属用户的 UID。
    rtmpUrlString(必填)CDN 推流地址。必须为有效的 RTMP 地址,且长度在 1024 个字符以内。
    idleTimeoutNumber(可选)Converter 处于空闲状态的最大时长(秒)。空闲指 Converter 处理的音视频流所对应的所有用户均已离开频道。当 Converter 处于空闲状态时长大于 idleTimeout,Converter 自动销毁,推流停止。取值范围为 [5,86400]。如果设置值小于 5,则默认为 5;如果设置值大于 86400,则默认为 86400。默认值为 300。
    jitterBufferSizeMsInt(可选)音频接收端到网络抖动缓冲端的网络延迟 (ms)。默认值为 1000,取值范围 [0, 1000]。
  • 旁路推流服务会根据你设置的值,以 100 为单位向上取整。
  • 设置为 0 表示不使用抖动缓冲延迟。弱网情况下可能导致音画质量问题,anyRTC建议你不要将 jitterBufferSizeMs 设置为 0。
  • HTTP 响应

    所有可能的响应状态码详见状态码汇总表

    响应头

    • X-Request-ID:UUID(通用唯一识别码),标识本次请求。该值为本次请求 header 中 X-Request-ID。如果请求出错,请在日志中打印出该值,排查问题。

    如果本次请求的响应状态码不是 2XX,那么响应 header 中可能无该字段。

    • X-Resource-ID:UUID(通用唯一识别码),标识本次请求创建的 Converter 的 ID。

    响应包体 如果状态码为 2XX,则请求成功。响应包体中包含字段含义详见下表:

    字段名类型描述
    converter.idStringConverter 的 ID。它是 anyRTC 服务器生成的一个 UUID(通用唯一识别码),标识一个已创建的 Converter。
    converter.createTsNumber创建 Converter 时的 Unix 时间戳(秒)。
    converter.updateTsNumber最近一次更新 Converter 配置时的 Unix 时间戳(秒)。
    converter.stateStringConverter 的运行状态:
  • connecting: 正在连接 anyRTC 推流服务器和 CDN 服务器。
  • running: 正在进行推流。
  • failed: 推流失败。
  • fieldsStringJSON 编码方式的字段掩码,详见谷歌 protobuf FieldMask 文档。用于描述返回的 converter 中包含的字段集合。在本示例中,fields 指定了anyRTC服务器返回 converter 字段中的 id,createTs,updateTs 和 state 字段子集。

    如果状态码不为 2XX,则请求失败。包体中包含 String 类型的 message 字段,描述失败的具体原因。

    {
        "message": "Invalid authentication credentials."
    }
    

    请求示例

    自定义布局的转码推流

    该示例展示将 show68 频道内指定的两个用户使用自定义布局进行合图后推到 CDN,将频道指定的两个用户音频进行混音,且分别指定两个用户的音量大小:

    {
        "converter": {
            "name": "show68_vertical",
            "transcodeOptions": {
                "rtcChannel": "show68",
                "audioOptions": {
                    "codecProfile": "HE-AAC",
                    "sampleRate": 48000,
                    "bitrate": 128,
                    "audioChannels": 1,
                    "rtcStreamUids": [
                        201,
                        202
                    ],
                    "volumes": [
                        {
                            "volume": 50,
                            "rtcStreamUid": 201
                        },
                        {
                            "volume": 150,
                            "rtcStreamUid": 202
                        }
                    ]
                },
                "videoOptions": {
                    "canvas": {
                        "width": 360,
                        "height": 640,
                        "color": 0
                    },
                    "layout": [
                        {
                            "rtcStreamUid": 201,
                            "region": {
                                "xPos": 0,
                                "yPos": 0,
                                "zIndex": 1,
                                "width": 360,
                                "height": 320
                            },
                            "fillMode": "fill",
                            "placeholderImageUrl": "http://example.anyrtc.io/host_placeholder.jpg"
                        },
                        {
                            "rtcStreamUid": 202,
                            "region": {
                                "xPos": 0,
                                "yPos": 320,
                                "zIndex": 1,
                                "width": 360,
                                "height": 320
                            }
                        },
                        {
                            "imageUrl": "http://example.anyrtc.io/watchmark.jpg",
                            "region": {
                                "xPos": 0,
                                "yPos": 0,
                                "zIndex": 2,
                                "width": 36,
                                "height": 64
                            },
                            "fillMode": "fit"
                        }
                    ],
                    "codec": "H.264",
                    "codecProfile": "high",
                    "frameRate": 15,
                    "gop": 30,
                    "bitrate": 400,
                    "seiOptions": {
                        "source": {
                            "metadata": true,
                            "datastream": true,
                            "customized": {
                                "payload": "example"
                            }
                        },
                        "sink": {
                            "type": 100
                        }
                    }
                }
            },
            "rtmpUrl": "rtmp://example/live/show68",
            "idleTimeout": 300
        }
    }
    

    垂直布局的转码推流

    该示例展示将 show68 频道内指定的两个用户使用垂直布局进行合图后推到 CDN,并且将频道内指定的两个用户的音频进行混音:

    {
        "converter": {
            "name": "show68_vertical",
            "transcodeOptions": {
                "rtcChannel": "show68",
                "audioOptions": {
                    "codecProfile": "HE-AAC",
                    "sampleRate": 48000,
                    "bitrate": 128,
                    "audioChannels": 1,
                    "rtcStreamUids": [
                        201,
                        202
                    ]
                },
                "videoOptions": {
                    "canvas": {
                        "width": 360,
                        "height": 640,
                        "color": 0
                    },
                    "layout": [
                        {
                            "rtcStreamUid": 201,
                            "region": {
                                "xPos": 0,
                                "yPos": 0,
                                "zIndex": 1,
                                "width": 360,
                                "height": 640
                            },
                            "fillMode": "fill",
                            "placeholderImageUrl": "http://example/host_placeholder.jpg"
                        },
                                         {
                            "rtcStreamUid": 202,
                            "region": {
                                "xPos": 0,
                                "yPos": 320,
                                "zIndex": 1,
                                "width": 360,
                                "height": 320
                            }
                        }
                    ],
                    "codec": "H.264",
                    "codecProfile": "high",
                    "frameRate": 15,
                    "gop": 30,
                    "bitrate": 400,
                    "layoutType": 1,
                    "vertical": {
                        "maxResolutionUid": 201,
                        "fillMode": "fill",
                        "refreshIntervalSec": 4
                    },
                    "defaultPlaceholderImageUrl": "http://example/host_placeholder.jpg",
                    "seiOptions": {
                        "source": {
                            "metadata": true,
                            "datastream": true,
                            "customized": {
                                "payload": "example"
                            }
                        },
                        "sink": {
                            "type": 100
                        }
                    }
                }
            },
            "rtmpUrl": "rtmp://example/live/show68",
            "idleTimeout": 300
        }
    }
    

    不转码推流

    该示例展示将 show68 频道内指定用户的音视频流推送到 CDN。

    {
        "converter": {
          "name": "show68_vertical",
          "rawOptions": {
            "rtcChannel": "show68",
            "rtcStreamUid": 201
          },
          "rtmpUrl": "rtmp://example/live/global"
        }
    }
    

    响应示例

    如果状态码为 2XX,则请求成功。示例如下:

    {
        "converter": {
            "id": "4c014467d647bb87b60b719f6fa57686",
            "createTs": 1591786766,
            "updateTs": 1591786766,
            "state": "connecting"
        },
        "fields": "id,createTs,updateTs,state"
    }
    

    Delete: 销毁指定的 Converter

    HTTP 请求

    DELETE https://api.agrtc.cn/{region}/v1/projects/{appId}/rtmp-converters/{converterId}
    

    路径参数

    • appId: String 型必填参数。anyRTC 为每个开发者提供的 App ID。在 anyRTC 控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。
    • converterId: String 型必填参数。Converter 的 ID。
    • region: String 型必填参数。Converter 所在的区域,必须与创建 Converter 设置的 region 一致。

    请求头

    • Content-Type : application/json

    • Authorization :该字段的值需参考认证说明

    • X-Request-ID:UUID(通用唯一识别码),标识本次请求。传入该字段后,anyRTC 服务器会在响应 header 中返回该字段。

    anyRTC 推荐用户对 X-Request-ID 赋值。如果用户不赋值,anyRTC 服务器会自动生成一个 UUID 传入。

    HTTP 响应

    所有可能的响应状态码详见状态码汇总表。

    响应头

    • X-Request-ID:UUID(通用唯一识别码),标识本次请求。该值为本次请求 header 中 X-Request-ID。如果请求出错,请在日志中打印出该值,排查问题。

    如果本次请求的响应状态码不是 2XX,那么响应 header 中可能无该字段。

    • X-Resource-ID:UUID(通用唯一识别码),标识本次请求删除的 Converter 的 ID。

    响应包体

    • 如果状态码为 2XX,则请求成功。Body 为空。
    • 如果状态码不为 2XX,请求失败。Body 中包含 String 类型的 message 字段,描述失败的具体原因。

    Update:更新指定的 Converter

    HTTP 请求

    PATCH https://api.agrtc.cn/{region}/v1/projects/{appId}/rtmp-converters/{converterId}
    

    路径参数

    • appId: String 型必填参数。anyRTC 为每个开发者提供的 App ID。在 anyRTC 控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。
    • converterId: String 型必填参数。Converter 的 ID。
    • region: String 型必填参数。Converter 所在的区域,必须与创建 Converter 设置的 region 一致。

    查询参数

    sequence:Number 型必填参数。Update 请求的序列号。取值需要大于或等于 0。请确保后一次 Update 请求的序列号大于前一次 Update 请求的序列号。序列号可以确保 anyRTC 服务器按照你指定的最新配置来更新 Converter。

    anyRTC 推荐你在第一次调用 Update 时,将 sequence 填 0。在第二次调用 Update 时,将 sequence 填 1。在第三次调用 Update 时,将 sequence 填 2。依次类推。anyRTC 服务器会按照最新 Update 请求(即最大的序列号)更新 Converter。

    PATCH https://api.agrtc.cn/{region}/v1/projects/{appId}/rtmp-converters/{converterId}?sequence={sequence}
    

    请求头

    • Content-Type: application/json
    • Authorization: 该字段的值需参考认证说明。
    • X-Request-ID: UUID(通用唯一识别码),标识本次请求。anyRTC 服务器会自动生成一个 UUID,并在响应 header 中返回 X-Request-ID 字段。

    anyRTC 推荐你对 X-Request-ID 赋值,anyRTC服务器会在响应 header 中返回一个 X-Custom-Request-ID 字段,以用于问题排查。

    请求包体

    你可以同时更新多个字段,字段含义详见 Create 请求 body。 Update 方法不支持更新 Converter 的如下配置:

    • name
    • idleTimeOut
    • transcodeOptions.rtcChannel
    • transcodeOptions.audioOptions.codecProfile
    • transcodeOptions.audioOptions.sampleRate
    • transcodeOptions.audioOptions.bitrate
    • transcodeOptions.audioOptions.audioChannels
    • transcodeOptions.videoOptions.codec
    • transcodeOptions.videoOptions.codecProfile

    调用 Create 方法创建一个只输出纯视频/音频流的 Converter 后,你无法通过 Update 方法将其更新为只输出纯音频/视频流的 Converter。

    当使用垂直布局(layoutType 为 1)时,仅支持更新 rtmpUrl 字段。

    HTTP 响应

    所有可能的响应状态码详见状态码汇总表。

    响应头

    • X-Request-ID:UUID(通用唯一识别码),标识本次请求。该值为本次请求 header 中 X-Request-ID。如果请求出错,请在日志中打印出该值,排查问题。

    如果本次请求的响应状态码不是 2XX,那么响应 header 中可能无该字段。

    • X-Resource-ID:UUID(通用唯一识别码),标识本次请求更新的 Converter 的 ID。

    响应包体 如果状态码为 2XX,则请求成功。响应包体中包含字段含义详见下表:

    字段名类型描述
    converter.idStringConverter 的 ID。它是 anyRTC 服务器生成的一个 UUID(通用唯一识别码),标识一个已创建的 Converter。
    converter.createTsNumber创建 Converter 时的 Unix 时间戳(秒)。
    converter.updateTsNumber最近一次更新 Converter 配置时的 Unix 时间戳(秒)。
    converter.stateStringConverter 的运行状态:
  • connecting: 正在连接anyRTC推流服务器和 CDN 服务器
  • running: 正在进行推流。
  • failed: 推流失败。
  • fieldsStringJSON 编码方式的字段掩码,详见谷歌 protobuf FieldMask 文档。用于描述返回的 converter 中包含的字段集合。在本示例中,fields 指定了 anyRTC 服务器返回 converter 字段中的 id,createTs,updateTs 和 state 字段子集。

    如果状态码不为 2XX,请求失败。Body 中包含 String 类型的 message 字段,描述失败的具体原因。

    请求示例

    更新多个字段

    更新 transcodeOptions.videoOptions.canvas 和 converter.transcodeOptions.videoOptions.layout 的示例代码如下:

    {
        "converter": {
            "transcodeOptions": {
                "videoOptions": {
                    "canvas": {
                        "width": 360,
                        "height": 640,
                        "color": 0
                    },
                    "layout": [
                        {
                            "rtcStreamUid": 201,
                            "region": {
                                "xPos": 0,
                                "yPos": 0,
                                "zIndex": 1,
                                "width": 360,
                                "height": 320
                            },
                            "fillMode": "fill",
                            "placeholderImageUrl": "http://example/host_placeholder.jpg"
                        }
                    ]
                }
            }
        },
        "fields": "transcodeOptions.videoOptions.canvas,transcodeOptions.videoOptions.layout"
    }
    

    调整混音用户的音量大小

    {
      "converter": {
        "transcodeOptions": {
          "audioOptions": {
            "volumes": [
              {
                "volume": 50,
                "rtcStreamUid": 201
              },
              {
                "volume": 150,
                "rtcStreamUid": 201
              }
            ]
          }
        }
      },
      "fields": "transcodeOptions.audioOptions.volumes"
    }
    

    调整混音用户的音量大小

    重置指定用户的音量大小,将其设为默认值:

    {
      "converter": {
        "transcodeOptions": {
          "audioOptions": {
            # 或不设置 volumes
            "volumes": null
          }
        }
      },
      "fields": "transcodeOptions.audioOptions.volumes"
    }
    

    响应示例

    如果状态码为 2XX,则请求成功。示例代码如下:

    {
        "converter": {
          "id": "4c014467d647bb87b60b719f6fa57686",
          "createTs": 1591786766,
          "updateTs": 1591788746,
          "state": "running"
       },
        "fields": "id,createTs,updateTs,state"
    }
    

    Get: 获取指定 Converter 的推流状态

    HTTP 请求

    GET https://api.agrtc.cn/{region}/v1/projects/{appId}/rtmp-converters/{converterId}
    

    路径参数

    • appId: String 型必填参数。anyRTC 为每个开发者提供的 App ID。在 anyRTC 控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。
    • converterId: String 型必填参数。Converter 的 ID。
    • region: String 型必填参数。Converter 所在的区域,必须与创建 Converter 设置的 region 一致。

    请求头

    • Content-Type: application/json
    • Authorization: 该字段的值需参考认证说明。
    • X-Request-ID: UUID(通用唯一识别码),标识本次请求。anyRTC 服务器会自动生成一个 UUID,并在响应 header 中返回 X-Request-ID 字段。

    anyRTC 推荐你对 X-Request-ID 赋值,anyRTC 服务器会在响应 header 中返回一个 X-Custom-Request-ID 字段,以用于问题排查。

    HTTP 响应

    所有可能的响应状态码详见状态码汇总表。

    响应头

    • X-Request-ID:UUID(通用唯一识别码),标识本次请求。该值为本次请求 header 中 X-Request-ID。如果请求出错,请在日志中打印出该值,排查问题。

    如果本次请求的响应状态码不是 2XX,那么响应 header 中可能无该字段。

    • X-Resource-ID:UUID(通用唯一识别码),标识本次请求更新的 Converter 的 ID。

    响应包体

    转码推流

    如果状态码为 2XX,则请求成功。转码推流响应包体中包含字段含义详见下表:

    字段名类型描述
    nameStringConverter 的名字。
    transcodeOptionsJSON ObjectConverter 的转码配置。
    transcodeOptions.rtcChannelStringanyRTC频道名称。
    transcodeOptions.audioOptionsJSON ObjectConverter 的音频转码配置。详见 audioOptions。
    transcodeOptions.videoOptionsJSON ObjectConverter 的视频转码配置。
    transcodeOptions.videoOptions.canvasJSON Object视频画布。详见 canvas。
    transcodeOptions.videoOptions.layoutJSON Object画布上视频画面的内容描述。支持 RtcStreamView 和 ImageView 两种元素:
  • RtcStreamView 元素:画布上各用户的视频画面。
  • ImageView 元素:画布上的视频图片,可用于当水印。详见 layout。
  • transcodeOptions.videoOptions.layoutTypeNumber输出视频的画面布局类型:
  • 0 或(默认)空:自定义布局,即通过 transcodeOptions.videoOptions.layout 设置布局信息。
  • 1:垂直布局。指定一个用户在屏幕左侧显示大视窗画面,其他用户以小视窗画面在屏幕右侧垂直排列,详见设置垂直布局。
  • transcodeOptions.videoOptions.verticalJSON Object垂直布局的画面设置信息。当 layoutType 为 1 时该参数必定存在。详见 vertical。
    transcodeOptions.videoOptions.defaultPlaceholderImageUrlStringString 默认的用户画面背景图 URL 地址。支持 JPG、PNG 和 GIF 格式的图片。当频道内用户停止发布视频流:
  • 如果设置了该字段,用户的视频画面将切换为该背景图。
  • 如果未设置该字段,用户的视频画面先显示为该用户视频最后一帧,布局刷新后显示为画布背景色。
  • transcodeOptions.videoOptions.bitrateNumber输出视频的编码码率 (Kbps)。
    transcodeOptions.videoOptions.frameRateNumber输出视频的编码帧率 (fps)。
    transcodeOptions.videoOptions.codecString输出视频的编解码规格。支持如下值:
  • H.264(默认值)
  • H.265
  • transcodeOptions.videoOptions.codecProfileString输出视频的编码规格。支持如下值:
  • high(默认值): High 级别的视频编码规格,一般用于广播及视频碟片存储,高清电视。
  • baseline: Baseline 级别的视频编码规格,一般用于低阶或需要额外容错的应用,比如视频通话、手机视频等。
  • main: Main 级别的视频编码规格,一般用于主流消费类电子产品,如 mp4、便携的视频播放器、PSP 和 iPad 等。。

  • 如果 codec 设置为 H.265,则 codecProfile 默认且必须为 main。
    transcodeOptions.videoOptions.seiOptionsString输出视频中携带的用户 SEI 信息。用于向 CDN 发送用户自定义的 SEI 信息。详见 seiOptions。
    rtmpUrlStringCDN 推流地址。
    idleTimeoutNumberConverter 处于空闲状态的最大时长(秒)。空闲指 Converter 处理的音视频流所对应的所有用户均已离开频道。当 Converter 处于空闲状态时长大于 idleTimeout,Converter 自动销毁,推流停止。
    createTsNumber创建 Converter 时的 Unix 时间戳(秒)。
    updateTsNumber最近一次更新 Converter 配置时的 Unix 时间戳(秒)。
    stateNumberConverter 的运行状态:
  • connecting: 正在连接anyRTC推流服务器和 CDN 服务器。
  • running: 正在进行推流。
  • failed: 推流失败。
  • 如果状态码不为 2XX,请求失败。Body 中包含 String 类型的 reason 字段,描述失败的具体原因。示例如下:

    {
       "reason": "Resource is not found and destroyed."
    }
    

    不转码推流

    如果状态码为 2XX,请求成功。不转码推流响应包体中包含字段含义详见下表:

    字段名类型描述
    nameStringConverter 的名字。
    rawOptionsJSON ObjectConverter 的推流配置。
    rawOptions.rtcChannelStringanyRTC 频道名称。即 Converter 处理的流所属的频道。
    rawOptions.rtcStreamUidNumber要推送的音视频流所属用户的 UID。
    rtmpUrlStringCDN 推流的地址。
    idleTimeoutNumberConverter 处于空闲状态的最大时长(秒)。空闲指 Converter 处理的音视频流所对应的所有用户均已离开频道。当 Converter 处于空闲状态时长大于 idleTimeout,Converter 自动销毁,推流停止。

    如果状态码不为 2XX,请求失败。Body 中包含 String 类型的 reason 字段,描述失败的具体原因。示例如下:

    {
       "reason": "Resource is not found and destroyed."
    }
    

    响应示例

    如果状态码为 2XX,请求成功。示例代码如下:

    转码推流且自定义布局

    {
        "name": "show68_vertical",
        "transcodeOptions": {
            "rtcChannel": "show68",
            "audioOptions": {
                "codecProfile": "HE-AAC",
                "sampleRate": 48000,
                "bitrate": 128,
                "audioChannels": 1,
                "rtcStreamUids": [
                    201
                ]
            },
            "videoOptions": {
                "canvas": {
                    "width": 360,
                    "height": 640,
                    "color": 0
                },
                "layout": [
                    {
                        "rtcStreamUid": 201,
                        "region": {
                            "xPos": 0,
                            "yPos": 0,
                            "zIndex": 1,
                            "width": 360,
                            "height": 320
                        },
                        "fillMode": "fill",
                        "placeholderImageUrl": "http://example.anyrtc.io/host_placeholder.jpg"
                    },
                    {
                        "rtcStreamUid": 202,
                        "region": {
                            "xPos": 0,
                            "yPos": 320,
                            "zIndex": 1,
                            "width": 360,
                            "height": 320
                        }
                    },
                    {
                        "imageUrl": "http://example.anyrtc.io/watchmark.jpg",
                        "region": {
                            "xPos": 0,
                            "yPos": 0,
                            "zIndex": 2,
                            "width": 36,
                            "height": 64
                        },
                        "fillMode": "fit"
                    }
                ],
                "codec": "H.264",
                "codecProfile": "High",
                "frameRate": 15,
                "gop": 30,
                "bitrate": 400,
                "seiOptions": {}
            }
        },
        "rtmpUrl": "rtmp://example.anyrtc.io/live/show68",
        "idleTimeout": 300,
        "createTs": 1616946970,
        "updateTs": 1783656785,
        "state": "running"
    }
    

    转码推流且垂直布局

    {
        "name": "show68_vertical",
        "transcodeOptions": {
            "rtcChannel": "show68",
            "audioOptions": {
                "codecProfile": "HE-AAC",
                "sampleRate": 48000,
                "bitrate": 128,
                "audioChannels": 1,
                "rtcStreamUids": [
                    201
                ]
            },
            "videoOptions": {
                "canvas": {
                    "width": 360,
                    "height": 640,
                    "color": 0
                },
                "layout": [
                    {
                        "rtcStreamUid": 201,
                        "region": {
                            "xPos": 0,
                            "yPos": 0,
                            "zIndex": 1,
                            "width": 360,
                            "height": 640
                        },
                        "fillMode": "fill",
                        "placeholderImageUrl": "http://example.anyrtc.io/host_placeholder.jpg"
                    }
                ],
                "codec": "H.264",
                "codecProfile": "high",
                "frameRate": 15,
                "gop": 30,
                "bitrate": 400,
                "layoutType": 1,
                "vertical": {
                    "maxResolutionUid": 201,
                    "fillMode": "fill",
                    "refreshIntervalSec": 4
                },
                "defaultPlaceholderImageUrl": "http://example.anyrtc.io/host_placeholder.jpg",
                "seiOptions": {
                    "source": {
                        "metadata": true,
                        "datastream": true,
                        "customized": {
                            "payload": "example"
                        }
                    },
                    "sink": {
                        "type": 100
                    }
                }
            }
        },
        "rtmpUrl": "rtmp://example.anyrtc.io/live/show68",
        "idleTimeout": 300
    }
    

    不转码推流

    {
        "converter": {
          "name": "wX8210Ce1VWVyGVHyaHA0W",
          "rawOptions": {
            "rtcChannel": "example",
            "rtcStreamUid": XXXX
          },
          "rtmpUrl": "rtmp://vid-218.push.chinanetcenter.broadcastapp.anyrtc.io/live/global",
          "idleTimeout": 120
        }
    }
    

    List:查询一个项目下所有或指定频道的 Converter

    HTTP 请求

    路径参数

    • appId: String 型必填参数。anyRTC为每个开发者提供的 App ID。在anyRTC控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。

    • cname:String 型必填参数。anyRTC频道名称。即 Converter 处理的流所属的频道。字符串长度必须在 64 字节以内,支持以下字符集(共 89 个字符):

      • 所有小写英文字母(a-z)
      • 所有大写英文字母(A-Z)
      • 数字 0-9
      • 空格
      • "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ","

      查询参数

      cursor:Number 型参数。游标,用于分页查询 Converter 信息列表。取值必须大于或等于 0。

      • 首次发起查询请求时无需设置 cursor,请求成功后返回第一页 Converter 列表。
      • 每次查询最多返回 500 个 Converter 的相关信息,如果项目下 Converter 数量超过 500,从响应 body 中获取 cursor,并在下一次请求的 URL 中传入该 cursor,直到响应 body 中 cursor 字段值为 0,则表示已查询到项目下或指定频道的所有 Converter。

      使用 Query Parameters 的 HTTP URL 如下:

      请求头

      • Content-Type: application/json
      • Authorization: 该字段的值需参考认证说明。
      • X-Request-ID: UUID(通用唯一识别码),标识本次请求。anyRTC服务器会自动生成一个 UUID,并在响应 header 中返回 X-Request-ID 字段。

      anyRTC推荐你对 X-Request-ID 赋值,anyRTC服务器会在响应 header 中返回一个 X-Custom-Request-ID 字段,以用于问题排查。

    HTTP 响应

    所有可能的响应状态码详见状态码汇总表。

    响应头

    X-Request-ID:UUID(通用唯一识别码),标识本次请求。该值为本次请求 header 中 X-Request-ID。如果请求出错,请在日志中打印出该值,排查问题。

    如果本次请求的响应状态码不是 2XX,那么响应 header 中可能无该字段。

    响应包体

    如果状态码为 2XX,则请求成功。响应包体中包含字段详见下表:

    字段名类型描述
    successBool请求成功。
    dataJSON Object返回数据详情。
    data.total_countString所查项目或频道下所有 Converter 的数量。
    data.cursorJSON游标,用于分页查询 Converter 信息列表。cursor为 0 表示已查询到项目下或指定频道的所有 Converter;否则需要继续查询。
    data.members.rtcChannelStringanyRTC频道名称。即 Converter 处理的流所属的频道。
    data.members.converterNameStringConverter 名称。
    data.members.updateTsNumber最近一次更新 Converter 配置时的 Unix 时间戳(秒)。
    data.members.appIdStringanyRTC为每个开发者提供的 App ID。在anyRTC控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。
    data.members.rtmpUrlStringCDN 推流地址。
    data.members.converterIdStringConverter 的 ID。Converter 的唯一标识。
    data.members.createNumber创建 Converter 时的 Unix 时间戳(秒)。
    data.members.idleTimeoutNumberConverter 处于空闲状态的最大时长(秒)。空闲指 Converter 处理的音视频流所对应的所有用户均已离开频道。当 Converter 处于空闲状态时长大于 idleTimeout,Converter 自动销毁,推流停止。
    data.members.stateStringConverter 的运行状态:
  • connecting: 正在连接anyRTC推流服务器和 CDN 服务器。
  • running: 正在进行推流。
  • failed: 推流失败。
  • 响应示例

    如果状态码为 2XX,则请求成功。示例代码如下:

    {
        "success": true,
        "data": {
            "total_count": 1,
            "cursor": 0,
            "members": [
                {
                    "rtcChannel": "testchannel",
                    "status": "200",
                    "converterName": "wX821XXXXVWVyGVHyaHA0W",
                    "updateTs": "1641267823",
                    "appId": "aab8b8f5aXXXX469a63042fcfafe7063",
                    "rtmpUrl": "rtmp://example/live/areu",
                    "ip": "183.131.160.244",
                    "converterId": "889B6D4BXXXXB62E68CCDA978BF21350",
                    "create": "1641267818",
                    "idleTimeout": "120",
                    "state": "running"
                }
            ]
        }
    }
    

    注意事项

    本节总结使用推流 RESTful API 的基础注意事项:

    • 请确保anyRTC频道场景为直播。
    • 请求出错时,请务必在日志中打印出响应 Header 中的 X-Request-ID 和 X-Resource-ID 字段值,以方便排查问题。
    • 如果你需要同一个频道内仅有一个 Converter,请你务必使用 name 参数,详见 name 参数解释。
    • 请确保将 region 设置为 CDN 源站所在区域,详见 region 参数解释。
    • 如果 Converter 因为服务故障等原因自动销毁,anyRTC推荐你重新创建一个 Converter。
    • 创建 Converter 后,如果 CDN 侧拉流异常。anyRTC推荐你 Delete 该 Converter,再重新创建一个 Converter。
    • 请确保对同一个 Converter 进行多次 Update 时,sequence 值递增,详见 sequence 参数解释。
    • anyRTC不支持你在一个 Converter 内同时进行转换转码推流和不转码推流。如要使用另一种方式的推流,你需要重新创建一个 Converter 并进行相关配置。
    • 在非转码模式下,Converter 只能将视频流进行 RTMP 转发,不能进行转码。为了保证 CDN 观众能正常观看视频,发流端需要使用符合 RTMP 标准协议的视频编解码规格,建议使用 H.264 或 H.265 格式以提高兼容性。如果发流端使用的是 VP8 编解码规格,则建议使用 Converter 的转码模式。
    • 针对网络故障,以及非anyRTC云,软件,设施和不可抗力因素等因素导致的推流中断,anyRTC旁路推流为了保证更好的用户体验,提供自动故障迁移服务,该服务会在尽量短的时间内完成迁移(预计 2 分钟内),迁移期间推流任务中断,可能导致部分数据丢失。
    • 如果对于频道内较多观众端的场景或关键性业务,你需要基于当前业务的重要性和anyRTC提供的自动迁移时效性来考虑是否采用更高的质量保障。

    参考信息

    数据类型定义

    本节介绍旁路推流 RESTful API 的相关数据类型定义。

    audioOptions

    Converter 的音频转码配置。

    字段名类型描述
    codecProfileString(可选)Converter 输出的音频编解码器。支持如下值:
  • LC-AAC(默认值): MPEG-4 AAC LC。
  • HE-AAC: High-Efficiency AAC。
  • sampleRateNumber(可选)Converter 输出的音频编码采样率 (Hz),可填 32000,44100 或 48000(默认值)。
    bitrateNumber(可选)Converter 输出的音频编码码率 (Kbps)取值范围为 [32,128]。默认值为 48。如果音频编解码器为 LC-AAC,推荐音频编码码率取值范围为 [32, 112]。如果音频编解码器为 HE-AAC,推荐音频编码码率取值范围为 [40, 96]。
    audioChannelsNumber(可选)Converter 输出的音频声道数,可填 1(默认值) 或 2。
    rtcStreamUidsJSON Array(可选)参与混音的用户 UID 数组。
  • 默认值为频道内所有用户 UID,代表anyRTC将频道内所有用户音频进行混音。
  • 如果数组为空,则不混合任何用户的音频流。
  • volumesJSON Array(可选)设置参与混音的用户音量。
  • 仅指定混音用户 UID (设置 rtcStreamUids)时该字段生效。
  • 你可以调用 Update 方法调整指定用户的音量,每一次 Update 请求成功会将本次指定用户以外的其他用户的音量恢复为默认值 100。
  • volumes.rtcStreamUidNumber待设置音量的混音用户 UID。
    volumes.volumeNumber指定的混音用户的音量。默认值为 100,取值范围 [0, 200]。

    videoOptions

    Converter 的视频转码配置。

    videoOptions.canvas

    视频画布配置。

    字段名类型描述
    widthNumber(必选)画布的宽度 (pixel)。取值范围为 [66,1920]。
    heightNumber(必选)画布的高度 (pixel)。取值范围为 [66,1920]。
    colorNumber(必选)画布的背景色。RGB 颜色值,以十进制数表示。如 255 代表蓝色。取值范围为 [0,16777215]。默认值为 0,即黑色。
    videoOptions.layout

    画布上视频画面的内容描述。

    videoOptions.layout.RtcStreamView

    用于配置画布上各用户的视频画面。

    字段名类型描述
    rtcStreamUidNumber(必选)视频流所属用户的 UID。
    regionJSON Object(必填)用户视频画面在画布上的显示区域。超出画布的视频画面会被裁剪,无法显示。
    region.xPosNumber(必选)画面在画布上的 x 坐标 (pixel)。以画布左上角为原点,x 坐标为画面左上角相对于原点的横向位移。
    region.yPosNumber(必选)画面在画布上的 y 坐标 (pixel)。以画布左上角为原点,y 坐标为画面左上角相对于原点的纵向位移。
    region.zIndexNumber(必选)画面的图层编号。取值范围为 [0,100]。0 代表最下层的图层。100 代表最上层的图层。
    region.widthNumber(必选)画面的宽度 (pixel)。
    region.heightNumber(必选)画面的高度 (pixel)。
    fillModeString(必选)画面的显示方式:
  • (默认)fill:在保持长宽比的前提下,缩放画面,使画面充满容器。
  • fit:在保持长宽比的前提下,缩放画面,使得画面在容器内完整显示出来。
  • placeholderImageUrlString(必选)用户画面的背景图 URL 地址。支持 JPG、PNG 和 GIF 格式的图片。当频道内用户停止发布视频流,如果设置了该字段,用户的视频画面将切换为该背景图,否则会显示为画布背景色。
    videoOptions.layout.ImageView

    配置画布上的视频图片,可用于当水印。

    字段名类型描述
    imageUrlString(必选)图片的 HTTP(S) URL。支持 JPG 和 PNG 格式的图片。
    regionJSON Object(必填)图片在画布上的显示区域。超出画布的图片会被裁剪,无法显示。
    region.xPosNumber(必填)图片在画布上的 x 坐标 (pixel)。以画布左上角为原点,x 坐标为图片左上角相对于原点的横向位移。
    region.yPosNumber(必填)图片在画布上的 y 坐标 (pixel)。以画布左上角为原点,y 坐标为图片左上角相对于原点的纵向位移。
    region.zIndexNumber(必填)图片的图层编号。取值范围为 [0,100]。0 代表最下层的图层。100 代表最上层的图层。
    region.widthNumber(必填)图片的宽度 (pixel)。
    region.heightNumber(必填)图片的高度 (pixel)。
    region.fillModeString图片的显示方式。
  • (默认)fill:在保持长宽比的前提下,缩放图片,使图片充满容器
  • fit:在保持长宽比的前提下,缩放图片,使得图片在容器内完整显示出来
  • videoOptions.layout.vertical

    配置垂直布局的视频画面。

    字段名类型描述
    maxResolutionUidNumber(可选)显示大视窗画面的用户 UID。如果未设置 maxResolutionUid,则布局刷新时音量最大的用户显示为大视窗画面。
  • Converter 会 3 秒刷新一次画面布局,如需调整刷新时间间隔。
  • 未设置 maxResolutionUid 可能会导致画面布局每隔 3 秒变化一次,如果需要布局稳定不变,请设置该参数。
  • fillModeString(可选)用户画面的显示方式。
  • fill:在保持长宽比的前提下,缩放画面,使画面充满容器。
  • fit:在保持长宽比的前提下,缩放画面,使得画面在容器内完整显示出来。
  • videoOptions.seiOptions

    设置输出视频中携带的用户 SEI 信息。

    字段名类型描述
    sourceJSON Object(可选)设置 SEI 信息的数据来源。默认为空。
    source.metadataBool(可选)设置是否传入 metadata 类型的 SEI 信息。
  • true:传入 metadata 类型的 SEI 信息。
  • (默认)false:不传入 metadata 类型的 SEI 信息。
  • source.datastreamBool(可选)设置是否传入anyRTC DataStream 类型的 SEI 信息 。
  • true:传入anyRTC DataStream 类型的 SEI 信息。
  • (默认)false:不传入anyRTC DataStream 类型的 SEI 信息。
  • source.customizedJSON Object(可选)自定义 SEI 信息。默认为空。
    source.customized.prefixForanyRTCSeiString(可选)设置 SEI 信息的 payload 前缀。长度必须在 32 个字符以内,默认为空。
    source.customized.payloadString(可选)设置 SEI 信息的 payload。长度必须在 4096 个字符以内,默认为空。
    sinkJSON Object(可选)设置输出 SEI 信息的属性。默认为空。
    sink.typeInt(可选)设置输出 SEI 信息的 payload type。默认为 100。

    API 限流说明

    anyRTC服务器限制用户 API 调用速率,超出限制速率时会返回状态码 429(Too Many Requests)。如果你有更高调用速率需求,请联系技术支持。

    API限流说明
    Create一个项目中,创建 Converter 的速率上限为 50 次/秒。
    Delete一个项目中,销毁 Converter 的速率上限为 50 次/秒。
    Update一个项目中,更新一个指定的 Converter 的速率上限为 50 次/秒。
    Get一个项目中,获取一个指定的 Converter 推流状态的速率上限为 50 次/秒。

    状态吗汇总表

    • 如果状态码为 2XX,则请求成功。
    • 如果状态码不为 2XX,则请求失败。请根据对应的响应 Body 中的 message 或 reason 字段内容排查问题。响应 Body 中具体字段可参考每个 API 请求响应的文档。
    状态码可能的 message 或 reason 字段内容
    200 OK/
    400 Bad Request
  • Invalid parameter: rtmpUrl. Replace it and retry.
  • Invalid parameter: idleTimeout. Replace it and retry.
  • 401 UnauthorizedInvalid authentication credentials.
    403 ForbiddenNo valid permission to use this function. Contact us.
    404 Not FoundResource is not found and destroyed.
    409 ConflictResource with the same name has already existed. Use the existing resource, otherwise delete it and create a new resource.
    429 Too Many Requests
  • Request rate limit exceeded.
  • Resource quota limit exceeded.
  • No available resources..
  • 500 UnknownInternal errors. Contact us for troubleshooting.
    501 Not ImplementedThe method requested has not been implemented.
    503 Service Unavailable
  • The server is temporarily overloading. Retry with a backoff strategy and contact us for troubleshooting.
  • The server is temporarily down. Retry with a backoff strategy.
  • 504 Gateway TimeoutGateway timeout. Check whether the resource is created, if not, re-create a new resource.

    常用视频属性

    设置转码输出媒体流的视频分辨率、帧率和码率时,anyRTC推荐你使用默认值。你也可以参考下表设值。如果设置的码率超出合理范围,anyRTC服务器会在合理区间内自动调整码率。

    分辨率帧率(fps)码率(Kbps)
    160 × 12015130
    120 × 12015100
    320 × 18015280
    180 × 18015200
    240 × 18015240
    320 × 24015400
    240 × 24015280
    424 × 24015440
    640 × 36015800
    360 × 36015520
    640 × 360301200
    360 × 36030800
    480 × 36015640
    480 × 36030980
    640 × 480151000
    480 × 48015800
    640 × 480301500
    480 × 480301200
    848 × 480151220
    848 × 480301860
    640 × 48010800
    1280 × 720152260
    1280 × 720303420
    960 × 720151820
    960 × 720302760