声网融合 CDN 直播提供 RESTful API,你可以通过你的业务服务器向声网服务器发送 HTTP 请求,在服务端配置和管理直播。
本文介绍融合 CDN 直播 RESTful API 的基础信息。
融合 CDN 直播 RESTful API 主要功能如下:
录制指定发布点下的全部直播流或单条直播流,可以设置录制文件的类型、第三方云存储服务厂商等。
封禁/取消封禁直播流,查询推流/播流信息。
使用标准录制时,支持从单个录制文件中截取片段和定点截图。
调用融合 CDN 直播 RESTful API 的主要流程如下:
融合 CDN 直播 RESTful API 使用 HTTP HMAC (Hash-based Message Authentication Code) 认证。
在发送 HTTP 请求时,你需要通过 HMAC-SHA256 算法生成一个签名,并在请求头部的 authorization
字段传入签名及相关信息。
在生成认证字段过程中,你需要用到以下声网账号的信息:
下面的 Python 代码(Python 3.7+)以获取域名列表的 API 为例,演示如何生成 authorization
字段的值:
import hmac
import base64
import datetime
from hashlib import sha256
# 你的声网项目的 App ID
appid = ''
#声网控制台 RESTful API 中获取的客户 ID
customer_username = ''
#声网控制台 RESTful API 中获取的客户密钥
customer_secret = ''
# 请求包体
data = ""
# 请求域名
host = "api.agora.io"
# 请求方法和 endpoint
req_metd = 'GET'
path = f'/v1/projects/{appid}/fls/domains'
body_sha256 = sha256(data.encode('utf-8')).digest()
body_sha256_base64 = base64.b64encode(body_sha256)
date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
request_line = "{} {} {}".format(req_metd, path, "HTTP/1.1")
digest = "SHA-256={}".format(body_sha256_base64.decode("utf-8"))
signing_string = "host: {}\ndate: {}\n{}\ndigest: {}".format(host, date, request_line, digest)
signature = base64.b64encode(
hmac.new(customer_secret.encode("utf-8"), signing_string.encode("utf-8"), sha256).digest())
authorization = 'hmac username="{}", algorithm="hmac-sha256", headers="host date request-line digest", signature="{}"'.format(
customer_username, signature.decode("utf-8"))
所有的请求均发送给域名:api.sd-rtn.com
。
为了保障通信安全,融合 CDN 直播 RESTful API 仅支持 HTTPS 协议。
所有的请求 URL 和请求包体内容都是区分大小写的。
融合 CDN 直播 RESTful API 调用频率上限为 50 次/秒。如果调用频率超出上限,请参考如何处理服务端 RESTful API 调用超出频率限制。
为保障 REST 服务的高可用,避免因区域网络故障造成的服务不可用,声网提供切换域名的方案。
主域名 | 区域域名 | 地理区域 |
---|---|---|
api.sd-rtn.com | api-us-west-1.sd-rtn.com | 美国西部 |
api-us-east-1.sd-rtn.com | 美国东部 | |
api-ap-southeast-1.sd-rtn.com | 亚太东南 | |
api-ap-northeast-1.sd-rtn.com | 亚太东北 | |
api-eu-west-1.sd-rtn.com | 欧洲西部 | |
api-eu-central-1.sd-rtn.com | 欧洲中部 | |
api-cn-east-1.sd-rtn.com | 中国华东 | |
api-cn-north-1.sd-rtn.com | 中国华北 | |
api.agora.io | api-us-west-1.agora.io | 美国西部 |
api-us-east-1.agora.io | 美国东部 | |
api-ap-southeast-1.agora.io | 亚太东南 | |
api-ap-northeast-1.agora.io | 亚太东北 | |
api-eu-west-1.agora.io | 欧洲西部 | |
api-eu-central-1.agora.io | 欧洲中部 | |
api-cn-east-1.agora.io | 中国华东 | |
api-cn-north-1.agora.io | 中国华北 |
本节提供调用融合 CDN 直播 RESTful API 的完整示例代码。
import hmac
import base64
import datetime
import requests
import json
from hashlib import sha256
# username
customer_username = "hmac_user_name"
# secret
customer_secret = "hmac_user_secret"
# appid
appid = "your_appid"
# streamName
stream_name = "stream_name"
# content
customer_data = json.dumps({"resumeTime":"2023-11-29T19:00:00+08:00"})
body_sha256 = sha256(customer_data.encode('utf-8')).digest()
body_sha256_base64 = base64.b64encode(body_sha256)
host = "api.agora.io"
path = "/v1/projects/%s/fls/entry_points/live/admin/banned_streams/%s" % (appid, stream_name)
date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
request_line = "{} {} {}".format("PATCH", path, "HTTP/1.1")
digest = "SHA-256={}".format(body_sha256_base64.decode("utf-8"))
signing_string = "host: {}\ndate: {}\n{}\ndigest: {}".format(host, date, request_line, digest)
signature = base64.b64encode(hmac.new(customer_secret.encode("utf-8"), signing_string.encode("utf-8"), sha256).digest())
authorization = 'hmac username="{}", algorithm="hmac-sha256", headers="host date request-line digest", signature="{}"'.format(customer_username, signature.decode("utf-8"))
print (authorization)
headers = {
"host": host,
"date": date,
"digest": digest,
"authorization": authorization,
}
print(signing_string)
response = requests.patch("https://{}{}".format(host, path), headers=headers, data=customer_data)
print(response.status_code, response.content.decode())
print(response.headers)
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
public class GatewayKey {
public static void main(String[] args) throws NoSuchAlgorithmException, IOException, InvalidKeyException {
String customerUsername = "hmac_user_name";
String customerSecret = "hmac_user_secret";
String customerData = "";
String appid = "your_appid";
String requestMethod = "GET";
MessageDigest messageDigest;
messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(customerData.getBytes("UTF-8"));
String base64encodedString = Base64.getEncoder().encodeToString(messageDigest.digest());
String digest = "SHA-256=" + base64encodedString;
String host = "api.agora.io";
String path = String.format("/v1/projects/%s/fls/entry_points/live/reports/online_streams", appid);
String requestLine = requestMethod + " " + path + " " + "HTTP/1.1";
final Date currentTime = new Date();
final SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = sdf.format(currentTime);
String signingString = String.format("host: %s\ndate: %s\n%s\ndigest: %s", host, date, requestLine, digest);
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(customerSecret.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secret_key);
String signature = Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(signingString.getBytes("UTF-8")));
String authorization = String.format("hmac username=\"%s\", algorithm=\"hmac-sha256\", headers=\"host date request-line digest\", signature=\"%s\"",
customerUsername, signature);
System.out.println(authorization);
System.out.println(signingString);
URL url = new URL("https://" + host + path);
HttpURLConnection http = (HttpURLConnection)url.openConnection();
http.setRequestMethod("GET");
http.setDoOutput(true);
http.setRequestProperty("host", host);
http.setRequestProperty("date", date);
http.setRequestProperty("digest", digest);
http.setRequestProperty("authorization", authorization);
InputStream stream = http.getInputStream();
System.out.println(http.getResponseCode() + " " + http.getResponseMessage());
BufferedReader br = null;
if (http.getResponseCode() == 200) {
br = new BufferedReader(new InputStreamReader(http.getInputStream()));
String strCurrentLine;
while ((strCurrentLine = br.readLine()) != null) {
System.out.println(strCurrentLine);
}
} else {
br = new BufferedReader(new InputStreamReader(http.getErrorStream()));
String strCurrentLine;
while ((strCurrentLine = br.readLine()) != null) {
System.out.println(strCurrentLine);
}
}
http.disconnect();
}
}
var crypto = require("crypto");
var request = require("request");
var customer_username = "{your_hmac_key}";
var customer_secret = "{your_hmac_secret}";
var host = "api.agora.io";
var path = "/v1/projects/{appid}/fls/entry_points/live/admin/banned_streams/{streamName}";
var method = "PATCH";
var content = {};
content.resumeTime = "2023-11-29T19:00:00+08:00";
var contentString = JSON.stringify(content);
gmt_date = new Date().toGMTString();
digest = "SHA-256=" + Buffer.from(crypto.createHash("sha256").update(contentString).digest()).toString("base64");
request_line = method + " " + path + " " + "HTTP/1.1";
signing_string = "host: " + host;
signing_string = signing_string + "\ndate: " + gmt_date;
signing_string = signing_string + "\n" + request_line;
signing_string = signing_string + "\ndigest: " + digest;
signature = crypto.createHmac("sha256", customer_secret).update(signing_string).digest();
signature = Buffer.from(signature).toString("base64");
authorization = 'hmac username="' + customer_username + '", ';
authorization = authorization + 'algorithm="hmac-sha256", headers="host date request-line digest", signature="';
authorization = authorization + signature + '"';
request.patch(
{
url: "https://" + host + path,
headers: {"content-type": "application/json", date: gmt_date, digest: digest, authorization: authorization},
body: contentString,
},
function (err, res, body) {
console.log("err:", err);
console.log("status:", res.statusCode);
console.log("body:", body);
},
);
<?php
#声网控制台 RESTful API 中获取的客户 ID
$customer_username = "{your username}";
#声网控制台 RESTful API 中获取的客户密钥
$customer_secret = "{your secret}";
# 你的声网项目的 App ID
$appid = "{your appid}";
# 请求方法
$request_method = "PATCH";
# 请求包体
$data = "";
# 请求域名
$host = "api.agora.io";
# 发布点
$entry_point = "live";
# 请求路径
$path = sprintf("/v1/projects/%s/fls/entry_points/%s/reports/online_streams", $appid, $entry_point);
# 日期
$date = gmDate("D, d M Y H:i:s ", time()) . "GMT";
$request_lint = sprintf("%s %s %s", $request_method, $path, "HTTP/1.1");
$data = trim($data);
$digest = 'SHA-256=' . base64_encode(pack("H*", hash("sha256", $data)));
$signing_string = sprintf("host: %s\ndate: %s\n%s\ndigest: %s", $host,$date,$request_lint,$digest);
$signature = base64_encode(pack('H*', hash_hmac('sha256', $signing_string, $customer_secret)));
$authorization = sprintf('hmac username="%s", algorithm="hmac-sha256", headers="host date request-line digest", signature="%s"', $customer_username, $signature);
$header = [
"host: $host",
"date: $date",
"digest: $digest",
"authorization: $authorization",
];
var_dump($header);
var_dump(getCurl("https://$host$path", $header, $request_method, $data));
function getCurl($url, $headerArray, $method, $data){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray);
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output,true);
return $output;
}
var customer_username = "hmac_user_name"
var customer_secret = "hmac_user_secret"
gmt_date = new Date().toGMTString()
digest = "SHA-256=" + CryptoJS.enc.Base64.stringify(CryptoJS.SHA256(pm.request.body.raw))
request_line = pm.request.method + " " + pm.request.url.getPath() + " " + "HTTP/1.1"
signing_string = "host: " + pm.request.url.getHost()
signing_string = signing_string + "\ndate: " + gmt_date
signing_string = signing_string + "\n" + request_line
signing_string = signing_string + "\ndigest: " + digest
signature = CryptoJS.HmacSHA256(signing_string, customer_secret)
signature = CryptoJS.enc.Base64.stringify(signature)
authorization = 'hmac username="' + customer_username + '", '
authorization = authorization + 'algorithm="hmac-sha256", headers="host date request-line digest", signature="'
authorization = authorization + signature + '"'
pm.request.headers.add({key: 'date', value: gmt_date})
pm.request.headers.add({key: 'digest', value: digest})
pm.request.headers.add({key: 'authorization', value: authorization})