你可以通过 RESTful API 创建推流密钥,使用该密钥将在线媒体流作为直播视频源流输入到声网频道内。同时,也可以通过 RESTful API 开启并配置在线流的转码能力。
第一次使用 RTMP 网关功能,需要联系声网技术支持开通服务。
以使用 OBS 推流软件输入 RTMP 协议的媒体流为例,工作原理及实现代码如下:
服务器:填写的值为推流域名后加 /live
。可以使用声网统一域名,也可以绑定用户自己的域名。
声网统一域名为 rtls-ingress-prod-{region}.agoramdn.com
,你需要根据实际区域填写 {region} 字段,支持的区域如下:
cn
:中国大陆ap
:除中国大陆以外的亚洲区域na
:北美eu
:欧洲使用用户自己的域名,请联系声网技术支持进行配置,配置成功后方可使用。
推流码:生成方式取决于你使用声网域名还是用户域名。
默认情况下,推流到 RTMP 网关之后,视频会不经转码直接被推送到声网频道。如果你需要转码,需要使用 RESTful API 设置相关参数,详见使用流配置模板。
在默认不开启转码的情况下,如果源流中包含 B 帧,Web 端的声网观众会有兼容性问题。
以 OBS 推流软件为例,可以通过以下两种方式确保源流中不会出现 B 帧。
添加 x264 编码参数
在设置 > 输出 > 直播页面的编码器设置中,将 x264 选项设置为 bframes=0
。
该设置作用为不编码 B 帧。
添加微调(Tune)参数
在设置 > 输出 > 直播页面的编码器设置中,将微调(Tune)设置 zerolatency
模式。
该设置作用为加速流编码,包含不编码 B 帧。
当使用用户自己的域名进行推流时,可以在用户本地生成推流码。
在生成推流码过程中,你需要用到以下信息:
channelName
。uid
。expiresAfter
(秒)。templateId
(可选,详见使用流配置模板)。以下的 Node.js 示例代码,演示了如何本地生成推流码:
const crypto = require("crypto");
const msgpack = require("msgpack-lite");
// 你的声网项目的 AppID 对应的App证书
appcert = "";
// 声网频道名称
channel = "";
// 声网频道内的主播uid
uid = "";
// 推流码的有效时长(秒)
expiresAfter = 86400;
// 关联的流配置模板,如果不确定有什么用,请保持注释状态
// templateId = "720p";
const expiresAt = Math.floor(Date.now() / 1000) + expiresAfter;
const rtcInfo = {
C: channel,
U: uid,
E: expiresAt,
// 如果不确定要不要用流配置模板,请保持注释状态
// T: templateId,
};
// 使用 msgpack 序列化
const data = msgpack.encode(rtcInfo);
// 随机生成一个初始化向量(IV)
const iv = crypto.randomBytes(16);
// 使用 App 证书作为加密密钥
const key = Buffer.from(appcert, "hex");
// 创建一个 AES-128 的 CTR 加密器
const encrypter = crypto.createCipheriv("aes-128-ctr", key, iv);
// 对数据进行加密
const encrypted = Buffer.concat([
iv,
encrypter.update(data),
encrypter.final(),
]);
// base64转换,并保证URL安全
const streamkey = encrypted
.toString("base64")
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/\=+$/, "");
console.log(`streamkey is ${streamkey}`);
以上示例代码依赖 msgpack-lite
模块。如果你还没有安装,在项目根目录执行执行 npm install msgpack-lite
后运行 node app.js
即可。
声网 RESTful API 要求通过安全认证,支持 Basic HTTP 认证和 HMAC HTTP 认证两种认证方式。其中,HMAC 认证安全性较高,为推荐认证方式;Bacsic 认证则更为易用,但安全性较弱。
每次发送 HTTP 请求时,你都必须在请求头部填入 Authorization
字段。关于如何生成该字段的值,请参考 RESTful API 要求 认证。
在发送 HTTP 请求时,你需要通过 HMAC-SHA256 算法生成一个签名,并在请求头部的 Authorization
字段传入签名及相关信息。
在生成认证字段过程中,你需要用到以下声网账号的信息:
下面的 Node.js 代码以获取服务配置信息的 API 为例,演示如何生成 Authorization
字段的值:
const crypto = require("crypto");
const http = require("http");
// 你的声网项目的 App ID
appid = "";
// 声网控制台 RESTful API 中获取的客户 ID
customer_username = "";
// 声网控制台 RESTful API 中获取的客户密钥
customer_secret = "";
// 请求包体
data = "";
function hashData(data) {
const hash = crypto.createHash("sha256");
hash.update(data);
return hash.digest("base64");
}
function signData(data) {
const hmac = crypto.createHmac("sha256", customer_secret);
hmac.update(data);
return hmac.digest("base64");
}
date = new Date().toUTCString();
reqpath = `/cn/v1/projects/${appid}/rtls/ingress/appconfig`;
reqline = `GET ${reqpath} HTTP/1.1`;
// 计算 Body 的 SHA-256 的哈希值
bodySign = hashData(args.data);
digest = `SHA-256=${bodySign}`;
// 生成签名
signingStr = `host: ${host}\ndate: ${date}\n${reqline}\ndigest: ${digest}`;
sign = signData(signingStr);
auth = `hmac username="${customer_username}", `;
auth += `algorithm="hmac-sha256", `;
auth += `headers="host date request-line digest", `;
auth += `signature="${sign}"`;
console.log(`Authorization: ${auth}`);
调用该接口创建一个推流码。
POST https://api.sd-rtn.com/{region}/v1/projects/{appId}/rtls/ingress/streamkeys
appId
:(必填)声网为每个开发者提供的 App ID,String 型。在声网控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。region
:(必填)创建推流码的区域,String 型。声网支持分区域创建推流码,目前支持以下区域:cn
:中国大陆ap
:除中国大陆以外的亚洲区域na
:北美eu
:欧洲region
与输入的源流在同一个区域。region
与推流使用的域名在同一个区域。region
的值为小写。Authorization
:该字段的值详见通过 HMAC HTTP 认证。X-Request-ID
:本次请求的 UUID(通用唯一识别码)。传入该字段后,声网服务器会在响应 header 中返回该字段。X-Request-ID
赋值。如果用户不赋值,声网服务器会自动生成一个 UUID 传入。请求包体为 JSON Object 类型的 settings
字段,包含如下字段:
channel
:(必填)声网频道名称,String 型。字符串长度必须在 64 字节以内,支持以下字符集(共 89 个字符):
uid
:(必填)RTMP 网关在声网频道内的主播用户 UID,String 型。可以为数字 ID 或字符串 ID。如果为数字 ID,取值范围为 1 到 232-1;如果为字符串 ID,不能超过 255 字节,也不能为空字符串。支持的字符集范围(共 89 个字符)如下:expiresAfter
:(选填)创建的推流码的有效时长,Number 型,单位为秒。从创建时开始计算。如果填 0
,则推流码永远有效。templateId
:(可选)String 类型。关联的流配置模板 ID,具体请见使用流配置模板。如果你不确定它的作用,请不要提供此字段。null
或 ""
。所有可能的响应状态码详见状态码汇总表。
X-Request-ID
:本次请求的 UUID(通用唯一识别码)。该值为本次请求 header 中的 X-Request-ID
。
401(Unauthorized)
,那么响应头部中无该字段。如果状态码为 2xx
,则请求成功。Body 中包含如下字段:
status
:请求状态,String 型,值为 success
。data
:JSON Object 型,包含以下字段:streamKey
:新创建的推流码,String 型。channel
:推流码绑定的声网频道名称,String 型。uid
:推流码绑定的声网频道内的用户 UID,String 型。expiresAfter
:推流码的有效时长,Number 型,从创建时开始计算,单位为秒。createdAt
:推流码创建的 Unix 间戳,String 型,单位为秒。如果状态码不为 2xx
,则请求失败。Body 中包含 String 型的 message
字段,描述失败的具体原因。
{
"settings": {
"channel": "shx001",
"uid": "1001",
"expiresAfter": 0
}
}
{
"status": "success",
"data": {
"streamKey": "2dfMTR****fys",
"channel": "shx001",
"uid": "1001",
"expiresAfter": 0,
"createdAt": "1686820170"
}
}
调用该接口,查询推流码的信息,如绑定的 UID,绑定的频道名,有效时长等。
GET https://api.sd-rtn.com/{region}/v1/projects/{appId}/rtls/ingress/streamkeys/{streamkey}
appId
:(必填)声网为每个开发者提供的 App ID,String 型。在声网控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。
region
:(必填)推流码的区域,String 型。目前支持以下区域:
cn
:中国大陆
ap
:除中国大陆以外的亚洲区域
na
:北美
eu
:欧洲
region
与创建推流码的区域一致。region
的值为小写。streamkey
:(必填)要查询的推流码,String 型。
Authorization
:该字段的值详见通过 HMAC HTTP 认证。X-Request-ID
:本次请求的 UUID(通用唯一识别码)。传入该字段后,声网服务器会在响应 header 中返回该字段。X-Request-ID
赋值。如果用户不赋值,声网服务器会自动生成一个 UUID 传入。所有可能的响应状态码详见状态码汇总表。
X-Request-ID
:本次请求的 UUID(通用唯一识别码)。该值为本次请求 header 中的 X-Request-ID
。
401(Unauthorized)
,那么响应头部中无该字段。如果状态码为 2xx
,则请求成功。Body 中包含如下字段:
status
:请求状态,String 型,值为 success
。data
:JSON Object 型,包含以下字段:streamKey
:要查询的推流码,String 型。channel
:推流码绑定的声网频道名称,String 型。uid
:推流码绑定的声网频道内的用户 UID,String 型。expiresAfter
:推流码的有效时长,Number 型,从创建时开始计算,单位为秒。createdAt
:推流码创建的 Unix 间戳,String 型,单位为秒。如果状态码不为 2xx
,则请求失败。Body 中包含 String 类型的 message
字段,描述失败的具体原因。
{
"status": "success",
"data": {
"streamKey": "2dfMTR****fys",
"channel": "shx001",
"uid": "1001",
"expiresAfter": 0,
"createdAt": "1686820170"
}
}
调用该接口销毁不再使用的推流码。
DELETE https://api.sd-rtn.com/{region}/v1/projects/{appId}/rtls/ingress/streamkeys/{streamkey}
appId
:(必填)声网为每个开发者提供的 App ID,String 型。在声网控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。
region
:(必填)推流码的区域,String 型。目前支持以下区域:
cn
:中国大陆
ap
:除中国大陆以外的亚洲区域
na
:北美
eu
:欧洲
region
与创建推流码的区域一致。region
的值为小写。streamkey
:(必填)要销毁的推流码,String 型。
Authorization
:该字段的值详见通过 HMAC HTTP 认证。X-Request-ID
:本次请求的 UUID(通用唯一识别码)。传入该字段后,声网服务器会在响应 header 中返回该字段。X-Request-ID
赋值。如果用户不赋值,声网服务器会自动生成一个 UUID 传入。所有可能的响应状态码详见状态码汇总表。
X-Request-ID
:本次请求的 UUID(通用唯一识别码)。该值为本次请求 header 中的 X-Request-ID
。
401(Unauthorized)
,那么响应头部中无该字段。如果状态码为 2xx
,则请求成功。Body 中包含如下字段:
status
:请求状态,String 型,值为 success
。如果状态码不为 2xx
,则请求失败。Body 中包含 String 类型的 message
字段,描述失败的具体原因。
{
"status": "success"
}
声网服务器限制用户 API 调用速率,超出限制速率时会返回状态码 429(Too Many Requests)
。参考下表了解各 API 的调用限制:
API | 限流说明 |
---|---|
Create |
一个项目中,创建推流码的速率上限为 50 次/秒。 |
Delete |
一个项目中,销毁推流码的速率上限为 50 次/秒。 |
Query |
一个项目中,单次查询速率上限为 100 次/秒 。 |
List |
一个项目中,批量查询速率上限为 2 次/秒 。 |
2xx
,则请求成功。2xx
,则请求失败。请根据对应的响应包体中的 message
字段内容排查问题。状态码 | 可能的 message 字段内容 |
错误原因 | 解决方案 |
---|---|---|---|
200 OK | / | 请求成功。 | / |
400 Bad Request |
|
请求参数错误。 | 根据 message 字段的具体内容进行排查。 |
401 Unauthorized | Invalid authentication credentials. | RESTful API 认证失败。 | 重新进行 HMAC 认证。 |
403 Forbidden |
|
|
|
404 Not Found | Resource is not found and destroyed. | 请求的资源不存在。 | 检查传入的 streamkey 是否正确。 |
409 Conflict | Resource with the same name already exists. | 并发请求过多。 | 采取退避策略重试。例如,第一次等待 1 秒后重试,第二次等待 3 秒后重试,第三次等待 6 秒后重试。 |
429 Too Many Requests |
|
服务端内部错误。 | 采取退避策略重试。 |
500 Unknown | Some internal error happened. Contact us to help fix it. | 服务端内部错误。 | 采取退避策略重试。 |
503 Service Unavailable |
|
服务端内部错误。 | 采取退避策略重试。 |
504 Gateway Timeout | Gateway timeout. Query to check whether the player has been created, or to create another one instead. | 服务端内部错误。 | 采取退避策略重试。 |
本节总结使用 RTMP 网关功能的基础注意事项:
uid
都是唯一的,详见 uid
参数说明。region
设置为媒体流源站所在区域,详见 region
参数说明。