From dfa33832b5a8dcd9dd1a6082e8d2b16afeae4445 Mon Sep 17 00:00:00 2001 From: kelzr Date: Fri, 14 Apr 2023 14:09:30 +0800 Subject: [PATCH 1/8] [CT] modify best practice --- ...00\344\275\263\345\256\236\350\267\265.md" | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 "markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" diff --git "a/markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" "b/markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" new file mode 100644 index 00000000000..661d62fe857 --- /dev/null +++ "b/markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" @@ -0,0 +1,96 @@ +为了保障云端合图服务的可靠性,声网建议你在集成云端合图 RESTful API 时注意以下几点: + +## 保障 REST 服务高可用 + + +为保障 REST 服务的高可用,避免因区域网络故障造成的服务不可用,声网提供故障迁移、多路备份、切换域名的方案。 + +### 故障迁移 + +针对网络故障,以及非声网云服务,非声网软件,基础设施和不可抗力等因素可能导致的风险,声网云端合图为提升用户体验,提供高可用自动任务迁移服务。当故障确认后,该服务会在尽量短的时间(预计 90 秒内)完成,在此期间会存在合图中断等风险。 + +对于频道内观众较多或对高可用有极高要求的场景,你需要根据业务需求判断能否接受高可用迁移的影响,决定是否要采用更高的质量保障措施。例如,对关键任务进行多路合图,即,使用多个不同的 `uid`(在输出频道内)发起多路合图任务,或通过[周期性频道查询](#monitor)和消息通知服务了解合图任务状态,以便在发生故障时及时使用备用 `uid` 重新发起新的合图任务,从而确保关键任务顺利完成。 + + +### 多路备份 + +如需比故障迁移更高的质量保障,你可以采用多路任务保障策略。每路合图转码任务单独计费。实现步骤如下: + +1. 同时发起主任务和备份任务,订阅相同的主播源流,向同一频道或不同频道推送合图转码流,观众端订阅主任务中的输出频道内的 `uid`。 + +2. 在客户端监听以下回调事件,可以及时通知观众端订阅备份任务中的输出频道内的 `uid`: + + - 主播掉线回调: [`onUserOffline`](hhttps://docs.agora.io/cn/live-streaming-premium-4.x/API%20Reference/java_ng/API/toc_core_method.html#callback_irtcengineeventhandler_onuseroffline) + - 主播音视频状态变化回调: [`onRemoteAudioStateChanged`](https://docs.agora.io/cn/live-streaming-premium-4.x/API%20Reference/java_ng/API/toc_audio_process.html#callback_irtcengineeventhandler_onremoteaudiostatechanged)/[`onRemoteVideoStateChanged`](https://docs.agora.io/cn/live-streaming-premium-4.x/API%20Reference/java_ng/API/toc_video_process.html#callback_irtcengineeventhandler_onremotevideostatechanged) + + + +### 切换域名 + +~45f50180-d902-11ed-8efe-b91caddc8ecb~ + +## 获取服务状态 + +你可以通过云端合图 RESTful API 来获取合图服务状态。相比于云端合图 RESTful API,[消息通知服务](https://docs.agora.io/cn/cloud-transcoding/ncs_transcoding?platform=All%20Platforms)更适合作为辅助手段。 + +以下是所有的服务状态(`services.cloudTranscoder.status`): + +|status |描述| +|------|-----| +|`"serviceIdle"` |子服务未开始。| +|`"serviceStarted"` |子服务已开始。| +|`"serviceReady"` |子服务已就绪。| +|`"serviceInProgress"` |子服务正在进行中。| +|`"serviceCompleted"` |订阅内容已全部上传至扩展服务。| //TODO +|`"servicePartialCompleted"` |订阅内容部分上传至扩展服务。| +|`"serviceValidationFailed"` |扩展服务验证失败。| +|`"serviceAbnormal"` |子模块状态异常。| + + +
+
  • 消息通知服务只能作为辅助手段来获取服务合图状态。不建议你的核心业务逻辑依赖消息通知服务。如果你的业务高度依赖消息通知服务,建议联系技术支持开通该服务的冗余消息功能,即接收双路消息通知,降低消息丢失的概率。开通冗余消息功能后,需要你基于 taskId对消息进行去重。冗余消息功能仍然不能保证 100% 的消息到达率。
  • +
  • 每个 App ID 每秒钟的请求数(QPS)限制默认为 10 次。请根据你的同时最大并发任务数(PCW)和查询间隔,预估所需的 QPS,并通过提交工单的方式申请调整 QPS 限制。
  • +
  • 国内 PCW 限制为 100,其他地区 PCW 限制为 30。如需提升 PCW 限制,请联系技术支持。
  • +
    + +### 检查合图服务已经成功启动 + +建议你通过如下步骤确认合图服务已成功启动: + +1. 确认 `start` 请求成功,即成功获得 `taskId` (合图 ID)。如果 `start` 请求返回 HTTP 状态码非 `200`,则需要根据状态码采取相应措施: + - 如果返回的 HTTP 状态码为 `201`,则表示合图任务已成功启动并在进行中。 + - 如果返回的 HTTP 状态码为 `206`,则表示请求超时,建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `start` 方法。 + - 如果返回的 HTTP 状态码为 `40x`,则表示请求参数错误,需要进行排查。 + - 如果返回的 HTTP 状态码为 `50x`,可使用相同的参数重试多次,直到成功返回 `taskId` 为止。建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `start` 方法。 + - 如果收到错误码 `65`,需要使用相同的参数再次调用 `start`。建议使用退避策略重试两次,如第一次等待 3 秒后重试、第二次等待 6 秒后重试。 +2. 获得 taskId 之后的 5 秒后,使用退避策略调用 `query` 方法,退避间隔建议小于 `start` 请求中的 idleTimeout (最长空闲频道时间)。如果 `query` 请求成功,且 `serverResponse` 中的 `status` 参数值为 `4` 或 `5`,则表示合图服务已成功启动。如果在获得 taskId 之后的 90 秒后 `status` 仍非 `4` 或 `5`, 则可以认为合图未启动或成功后超时退出。 + +
    建议你准备一个备份 UID,在重新启动合图时使用,以避免输出频道内两个相同 UID 互踢。主备 UID 可以交替使用。
    + +### 合图任务的状态监控 + +你可以通过周期性调用 `query` 方法来确认合图服务正在进行中且状态正常。相比于 `query`,消息通知服务更适合作为辅助手段。详见[消息通知服务和 query 方法的对比](https://docs.agora.io/cn/faq/ncs_vs_query)。 + + + +#### 周期性频道查询 + +如果你对状态查询的可靠性要求较高,声网强烈建议你使用 `query` 方法周期性查询频道内的合图状态,例如每隔 2 分钟调用一次 `query`,并根据返回的 HTTP 状态码采取相应措施。 + +- 如果返回的 HTTP 状态码一直为 `40x`,则表示请求参数错误,需要进行排查。 +- 如果返回的 HTTP 状态码为 `404`,且已经确认请求参数无误,则表示合图并未成功启动、或启动后中途退出。建议采用退避策略多次调用 `query` (例如间隔 5 秒、10 秒、15 秒)进行确认。 +- 如果返回的 HTTP 状态码为 `50x`,则表示 `query` 请求失败,但尚不明确合图是否已退出。出现 `50x` 错误的概率极小,建议使用退避策略 (5 秒, 10 秒, 15 秒,30 秒) 继续调用 `query`。 + +#### 冗余消息通知服务 + +开通冗余消息功能后,需要你基于 `taskId` 对消息进行去重。举例来说,如果你需要在合图超时退出后再次开启合图,流程为: + +1. 你的服务器收到 `111` 事件,表示合图服务已正常退出。 +2. 收到事件后,你的应用调用 `acquire`,重新开启合图服务。 +3. 在此期间你的服务器又收到了 `111` 事件。如果以上事件中的 taskId 与前一次的 `111` 事件一致,则可以作为冗余事件通知忽略。 +4. 如果你需要完全确保成功开启了合图服务,则仍然需要调用 `query` 进行查询。 + + +## 避免合图服务频繁退出 + +`start` 方法中的 `idleTimeout` 参数默认值为 300 秒。对于要求合图服务一直在频道中的场景,为避免合图服务因主播频繁上下线而频繁启动和退出,你需要在设置 `idleTimeout` 取值时权衡实际场景,避免取值过小。合适的取值可以保证合图服务在短时间无发流端时也能稳定运行,避免合图服务频繁退出。 From 754348dc0632699d3af44b4ea81b93c843d87df7 Mon Sep 17 00:00:00 2001 From: kelzr Date: Mon, 17 Apr 2023 16:43:06 +0800 Subject: [PATCH 2/8] [CT] modify best practice --- ...00\344\275\263\345\256\236\350\267\265.md" | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git "a/markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" "b/markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" index 661d62fe857..9b153154173 100644 --- "a/markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" +++ "b/markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" @@ -1,4 +1,4 @@ -为了保障云端合图服务的可靠性,声网建议你在集成云端合图 RESTful API 时注意以下几点: +本文介绍使用云端转码服务的最佳实践,包含保障高可用、检查服务状态并及时排查问题、避免服务频繁退出。通过采用这些措施,可以更好保障服务的可靠性和稳定性,从而为你提供更好的业务支持。 ## 保障 REST 服务高可用 @@ -7,16 +7,16 @@ ### 故障迁移 -针对网络故障,以及非声网云服务,非声网软件,基础设施和不可抗力等因素可能导致的风险,声网云端合图为提升用户体验,提供高可用自动任务迁移服务。当故障确认后,该服务会在尽量短的时间(预计 90 秒内)完成,在此期间会存在合图中断等风险。 +针对网络故障,以及非声网云服务,非声网软件,基础设施和不可抗力等因素可能导致的风险,声网云端转码服务为提升用户体验,提供高可用自动任务迁移服务。当故障确认后,该服务会在尽量短的时间(预计 90 秒内)完成,在此期间会存在合流中断等风险。 -对于频道内观众较多或对高可用有极高要求的场景,你需要根据业务需求判断能否接受高可用迁移的影响,决定是否要采用更高的质量保障措施。例如,对关键任务进行多路合图,即,使用多个不同的 `uid`(在输出频道内)发起多路合图任务,或通过[周期性频道查询](#monitor)和消息通知服务了解合图任务状态,以便在发生故障时及时使用备用 `uid` 重新发起新的合图任务,从而确保关键任务顺利完成。 +对于频道内观众较多或对高可用有极高要求的场景,你需要根据业务需求判断能否接受高可用迁移的影响,决定是否要采用更高的质量保障措施。例如,对关键任务进行多路合流,即,使用多个不同的 `uid`(在输出频道内)发起多路合流任务,或通过[周期性频道查询](#monitor)和消息通知服务了解合流任务状态,以便在发生故障时及时使用备用 `uid` 重新发起新的合流任务,从而确保关键任务顺利完成。 ### 多路备份 -如需比故障迁移更高的质量保障,你可以采用多路任务保障策略。每路合图转码任务单独计费。实现步骤如下: +如需比故障迁移更高的质量保障,你可以采用多路任务保障策略。每路合流转码任务单独计费。实现步骤如下: -1. 同时发起主任务和备份任务,订阅相同的主播源流,向同一频道或不同频道推送合图转码流,观众端订阅主任务中的输出频道内的 `uid`。 +1. 同时发起主任务和备份任务,订阅相同的主播源流,向同一频道或不同频道推送合流转码流,观众端订阅主任务中的输出频道内的 `uid`。 2. 在客户端监听以下回调事件,可以及时通知观众端订阅备份任务中的输出频道内的 `uid`: @@ -31,66 +31,66 @@ ## 获取服务状态 -你可以通过云端合图 RESTful API 来获取合图服务状态。相比于云端合图 RESTful API,[消息通知服务](https://docs.agora.io/cn/cloud-transcoding/ncs_transcoding?platform=All%20Platforms)更适合作为辅助手段。 +你可以通过云端转码 RESTful API 来获取合流服务状态。相比于云端转码 RESTful API,[消息通知服务](https://docs.agora.io/cn/cloud-transcoding/ncs_transcoding?platform=All%20Platforms)更适合作为辅助手段。 -以下是所有的服务状态(`services.cloudTranscoder.status`): +以下是所有的合流服务状态(`services.cloudTranscoder.status`): |status |描述| |------|-----| -|`"serviceIdle"` |子服务未开始。| -|`"serviceStarted"` |子服务已开始。| -|`"serviceReady"` |子服务已就绪。| -|`"serviceInProgress"` |子服务正在进行中。| -|`"serviceCompleted"` |订阅内容已全部上传至扩展服务。| //TODO -|`"servicePartialCompleted"` |订阅内容部分上传至扩展服务。| -|`"serviceValidationFailed"` |扩展服务验证失败。| -|`"serviceAbnormal"` |子模块状态异常。| - +|`"serviceIdle"` |服务未开始。| +|`"serviceStarted"` |服务已开始。| +|`"serviceReady"` |服务已就绪。| +|`"serviceInProgress"` |服务正在进行中。| +|`"serviceCompleted"` |服务已经停止,任务全部完成。| +|`"servicePartialCompleted"` |服务已经停止,任务部分完成。| +|`"serviceValidationFailed"` |服务参数验证失败。| +|`"serviceAbnormal"` |服务异常退出。| +|`"serviceUnknown"` |服务未知状态。|
    -
  • 消息通知服务只能作为辅助手段来获取服务合图状态。不建议你的核心业务逻辑依赖消息通知服务。如果你的业务高度依赖消息通知服务,建议联系技术支持开通该服务的冗余消息功能,即接收双路消息通知,降低消息丢失的概率。开通冗余消息功能后,需要你基于 taskId对消息进行去重。冗余消息功能仍然不能保证 100% 的消息到达率。
  • +
  • 消息通知服务只能作为辅助手段来获取服务合流状态。不建议你的核心业务逻辑依赖消息通知服务。如果你的业务高度依赖消息通知服务,建议联系技术支持开通该服务的冗余消息功能,即接收双路消息通知,降低消息丢失的概率。开通冗余消息功能后,需要你基于 taskId 对消息进行去重。冗余消息功能仍然不能保证 100% 的消息到达率。
  • 每个 App ID 每秒钟的请求数(QPS)限制默认为 10 次。请根据你的同时最大并发任务数(PCW)和查询间隔,预估所需的 QPS,并通过提交工单的方式申请调整 QPS 限制。
  • 国内 PCW 限制为 100,其他地区 PCW 限制为 30。如需提升 PCW 限制,请联系技术支持。
  • -### 检查合图服务已经成功启动 +### 检查合流服务已经成功启动 -建议你通过如下步骤确认合图服务已成功启动: +建议你通过如下步骤确认合流服务已成功启动: -1. 确认 `start` 请求成功,即成功获得 `taskId` (合图 ID)。如果 `start` 请求返回 HTTP 状态码非 `200`,则需要根据状态码采取相应措施: - - 如果返回的 HTTP 状态码为 `201`,则表示合图任务已成功启动并在进行中。 +1. 确认 `start` 请求成功,即成功获得 `taskId` (合流 ID)。如果 `start` 请求返回 HTTP 状态码非 `200`,则需要根据状态码采取相应措施: + - 如果返回的 HTTP 状态码为 `201`,则表示合流任务已成功启动并在进行中。 - 如果返回的 HTTP 状态码为 `206`,则表示请求超时,建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `start` 方法。 - 如果返回的 HTTP 状态码为 `40x`,则表示请求参数错误,需要进行排查。 - 如果返回的 HTTP 状态码为 `50x`,可使用相同的参数重试多次,直到成功返回 `taskId` 为止。建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `start` 方法。 - 如果收到错误码 `65`,需要使用相同的参数再次调用 `start`。建议使用退避策略重试两次,如第一次等待 3 秒后重试、第二次等待 6 秒后重试。 -2. 获得 taskId 之后的 5 秒后,使用退避策略调用 `query` 方法,退避间隔建议小于 `start` 请求中的 idleTimeout (最长空闲频道时间)。如果 `query` 请求成功,且 `serverResponse` 中的 `status` 参数值为 `4` 或 `5`,则表示合图服务已成功启动。如果在获得 taskId 之后的 90 秒后 `status` 仍非 `4` 或 `5`, 则可以认为合图未启动或成功后超时退出。 +2. 获得 taskId 之后的 5 秒后,使用退避策略调用 `query` 方法,退避间隔建议小于 `start` 请求中的 idleTimeout (最长空闲频道时间)。如果 `query` 请求成功,且 `serverResponse` 中的 `status` 参数值为 `4` 或 `5`,则表示合流服务已成功启动。如果在获得 taskId 之后的 90 秒后 `status` 仍非 `4` 或 `5`, 则可以认为合流未启动或成功后超时退出。 -
    建议你准备一个备份 UID,在重新启动合图时使用,以避免输出频道内两个相同 UID 互踢。主备 UID 可以交替使用。
    +
    建议你准备一个备份 UID,在重新启动合流时使用,以避免输出频道内两个相同 UID 互踢。主备 UID 可以交替使用。
    -### 合图任务的状态监控 +### 合流任务的状态监控 -你可以通过周期性调用 `query` 方法来确认合图服务正在进行中且状态正常。相比于 `query`,消息通知服务更适合作为辅助手段。详见[消息通知服务和 query 方法的对比](https://docs.agora.io/cn/faq/ncs_vs_query)。 +你可以通过周期性调用 `query` 方法来确认合流服务正在进行中且状态正常。相比于 `query`,消息通知服务更适合作为辅助手段。详见[消息通知服务和 query 方法的对比](https://docs.agora.io/cn/faq/ncs_vs_query)。 #### 周期性频道查询 -如果你对状态查询的可靠性要求较高,声网强烈建议你使用 `query` 方法周期性查询频道内的合图状态,例如每隔 2 分钟调用一次 `query`,并根据返回的 HTTP 状态码采取相应措施。 +如果你对状态查询的可靠性要求较高,声网强烈建议你使用 `query` 方法周期性查询频道内的合流状态,例如每隔 2 分钟调用一次 `query`,并根据返回的 HTTP 状态码采取相应措施。 - 如果返回的 HTTP 状态码一直为 `40x`,则表示请求参数错误,需要进行排查。 -- 如果返回的 HTTP 状态码为 `404`,且已经确认请求参数无误,则表示合图并未成功启动、或启动后中途退出。建议采用退避策略多次调用 `query` (例如间隔 5 秒、10 秒、15 秒)进行确认。 -- 如果返回的 HTTP 状态码为 `50x`,则表示 `query` 请求失败,但尚不明确合图是否已退出。出现 `50x` 错误的概率极小,建议使用退避策略 (5 秒, 10 秒, 15 秒,30 秒) 继续调用 `query`。 +- 如果返回的 HTTP 状态码为 `404`,且已经确认请求参数无误,则表示合流并未成功启动、或启动后中途退出。建议采用退避策略多次调用 `query` (例如间隔 5 秒、10 秒、15 秒)进行确认。 +- 如果返回的 HTTP 状态码为 `50x`,则表示 `query` 请求失败,但尚不明确合流是否已退出。出现 `50x` 错误的概率极小,建议使用退避策略 (5 秒, 10 秒, 15 秒,30 秒) 继续调用 `query`。 #### 冗余消息通知服务 -开通冗余消息功能后,需要你基于 `taskId` 对消息进行去重。举例来说,如果你需要在合图超时退出后再次开启合图,流程为: +开通冗余消息功能后,需要你基于 `taskId` 对消息进行去重。举例来说,如果你需要在合流超时退出后再次开启合流,流程为: -1. 你的服务器收到 `111` 事件,表示合图服务已正常退出。 -2. 收到事件后,你的应用调用 `acquire`,重新开启合图服务。 +1. 你的服务器收到 `111` 事件,表示合流服务已正常退出。 +2. 收到事件后,你的应用调用 `acquire`,重新开启合流服务。 3. 在此期间你的服务器又收到了 `111` 事件。如果以上事件中的 taskId 与前一次的 `111` 事件一致,则可以作为冗余事件通知忽略。 -4. 如果你需要完全确保成功开启了合图服务,则仍然需要调用 `query` 进行查询。 +4. 如果你需要完全确保成功开启了合流服务,则仍然需要调用 `query` 进行查询。 -## 避免合图服务频繁退出 +## 避免合流服务频繁退出 -`start` 方法中的 `idleTimeout` 参数默认值为 300 秒。对于要求合图服务一直在频道中的场景,为避免合图服务因主播频繁上下线而频繁启动和退出,你需要在设置 `idleTimeout` 取值时权衡实际场景,避免取值过小。合适的取值可以保证合图服务在短时间无发流端时也能稳定运行,避免合图服务频繁退出。 +`start` 方法中的 `idleTimeout` 参数默认值为 300 秒。对于要求合流服务一直在频道中的场景,为避免合流服务因主播频繁上下线而频繁启动和退出,你需要在设置 `idleTimeout` 取值时权衡实际场景,避免取值过小。合适的取值可以保证合流服务在短时间无发流端时也能稳定运行,避免合流服务频繁退出。 From 8b18d8278a5b283a4dd602c6da36e7b5d9f79759 Mon Sep 17 00:00:00 2001 From: kelzr Date: Wed, 19 Apr 2023 11:42:25 +0800 Subject: [PATCH 3/8] [CT] modify api name --- .../cloud-transcoder/best-practice.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) rename "markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" => markdown/cloud-transcoder/best-practice.md (76%) diff --git "a/markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" b/markdown/cloud-transcoder/best-practice.md similarity index 76% rename from "markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" rename to markdown/cloud-transcoder/best-practice.md index 9b153154173..a7133c3ac94 100644 --- "a/markdown/cloud-transcoder/CT \351\233\206\346\210\220\346\234\200\344\275\263\345\256\236\350\267\265.md" +++ b/markdown/cloud-transcoder/best-practice.md @@ -9,7 +9,7 @@ 针对网络故障,以及非声网云服务,非声网软件,基础设施和不可抗力等因素可能导致的风险,声网云端转码服务为提升用户体验,提供高可用自动任务迁移服务。当故障确认后,该服务会在尽量短的时间(预计 90 秒内)完成,在此期间会存在合流中断等风险。 -对于频道内观众较多或对高可用有极高要求的场景,你需要根据业务需求判断能否接受高可用迁移的影响,决定是否要采用更高的质量保障措施。例如,对关键任务进行多路合流,即,使用多个不同的 `uid`(在输出频道内)发起多路合流任务,或通过[周期性频道查询](#monitor)和消息通知服务了解合流任务状态,以便在发生故障时及时使用备用 `uid` 重新发起新的合流任务,从而确保关键任务顺利完成。 +对于频道内观众较多或对高可用有极高要求的场景,你需要根据业务需求判断能否接受高可用迁移的影响,决定是否要采用更高的质量保障措施。例如,对关键任务进行多路合流,即,使用多个不同的 `uid`(在输出频道内)发起多路合流任务,或通过[周期性频道查询](#monitor)和消息通知服务了解合流任务状态,以便在发生故障时及时使用备用 `uid` 重新发起新的合流任务,从而确保关键任务顺利完成。//TODO 合流 -> 转码 ### 多路备份 @@ -57,40 +57,40 @@ 建议你通过如下步骤确认合流服务已成功启动: -1. 确认 `start` 请求成功,即成功获得 `taskId` (合流 ID)。如果 `start` 请求返回 HTTP 状态码非 `200`,则需要根据状态码采取相应措施: +1. 确认 `Create` 请求成功,即成功获得 `taskId` (合流 ID)。如果 `Create` 请求返回 HTTP 状态码非 `200`,则需要根据状态码采取相应措施: - 如果返回的 HTTP 状态码为 `201`,则表示合流任务已成功启动并在进行中。 - - 如果返回的 HTTP 状态码为 `206`,则表示请求超时,建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `start` 方法。 + - 如果返回的 HTTP 状态码为 `206`,则表示请求超时,建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `Acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `Create` 方法。 - 如果返回的 HTTP 状态码为 `40x`,则表示请求参数错误,需要进行排查。 - - 如果返回的 HTTP 状态码为 `50x`,可使用相同的参数重试多次,直到成功返回 `taskId` 为止。建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `start` 方法。 - - 如果收到错误码 `65`,需要使用相同的参数再次调用 `start`。建议使用退避策略重试两次,如第一次等待 3 秒后重试、第二次等待 6 秒后重试。 -2. 获得 taskId 之后的 5 秒后,使用退避策略调用 `query` 方法,退避间隔建议小于 `start` 请求中的 idleTimeout (最长空闲频道时间)。如果 `query` 请求成功,且 `serverResponse` 中的 `status` 参数值为 `4` 或 `5`,则表示合流服务已成功启动。如果在获得 taskId 之后的 90 秒后 `status` 仍非 `4` 或 `5`, 则可以认为合流未启动或成功后超时退出。 + - 如果返回的 HTTP 状态码为 `50x`,可使用相同的参数重试多次,直到成功返回 `taskId` 为止。建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `Acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `Create` 方法。 + - 如果收到错误码 `65`,需要使用相同的参数再次调用 `Create`。建议使用退避策略重试两次,如第一次等待 3 秒后重试、第二次等待 6 秒后重试。 +2. 获得 taskId 之后的 5 秒后,使用退避策略调用 `Query` 方法,退避间隔建议小于 `Create` 请求中的 idleTimeout (最长空闲频道时间)。如果 `Query` 请求成功,且 `serverResponse` 中的 `status` 参数值为 `4` 或 `5`,则表示合流服务已成功启动。如果在获得 `taskId` 之后的 90 秒后 `status` 仍非 `4` 或 `5`, 则可以认为合流未启动或成功后超时退出。
    建议你准备一个备份 UID,在重新启动合流时使用,以避免输出频道内两个相同 UID 互踢。主备 UID 可以交替使用。
    ### 合流任务的状态监控 -你可以通过周期性调用 `query` 方法来确认合流服务正在进行中且状态正常。相比于 `query`,消息通知服务更适合作为辅助手段。详见[消息通知服务和 query 方法的对比](https://docs.agora.io/cn/faq/ncs_vs_query)。 +你可以通过周期性调用 `Query` 方法来确认合流服务正在进行中且状态正常。相比于 `Query`,消息通知服务更适合作为辅助手段。详见[消息通知服务和 query 方法的对比](https://docs.agora.io/cn/faq/ncs_vs_query)。 #### 周期性频道查询 -如果你对状态查询的可靠性要求较高,声网强烈建议你使用 `query` 方法周期性查询频道内的合流状态,例如每隔 2 分钟调用一次 `query`,并根据返回的 HTTP 状态码采取相应措施。 +如果你对状态查询的可靠性要求较高,声网强烈建议你使用 `Query` 方法周期性查询频道内的合流状态,例如每隔 2 分钟调用一次 `Query`,并根据返回的 HTTP 状态码采取相应措施。 - 如果返回的 HTTP 状态码一直为 `40x`,则表示请求参数错误,需要进行排查。 -- 如果返回的 HTTP 状态码为 `404`,且已经确认请求参数无误,则表示合流并未成功启动、或启动后中途退出。建议采用退避策略多次调用 `query` (例如间隔 5 秒、10 秒、15 秒)进行确认。 -- 如果返回的 HTTP 状态码为 `50x`,则表示 `query` 请求失败,但尚不明确合流是否已退出。出现 `50x` 错误的概率极小,建议使用退避策略 (5 秒, 10 秒, 15 秒,30 秒) 继续调用 `query`。 +- 如果返回的 HTTP 状态码为 `404`,且已经确认请求参数无误,则表示合流并未成功启动、或启动后中途退出。建议采用退避策略多次调用 `Query` (例如间隔 5 秒、10 秒、15 秒)进行确认。 +- 如果返回的 HTTP 状态码为 `50x`,则表示 `Query` 请求失败,但尚不明确合流是否已退出。出现 `50x` 错误的概率极小,建议使用退避策略 (5 秒, 10 秒, 15 秒,30 秒) 继续调用 `Query`。 #### 冗余消息通知服务 开通冗余消息功能后,需要你基于 `taskId` 对消息进行去重。举例来说,如果你需要在合流超时退出后再次开启合流,流程为: 1. 你的服务器收到 `111` 事件,表示合流服务已正常退出。 -2. 收到事件后,你的应用调用 `acquire`,重新开启合流服务。 -3. 在此期间你的服务器又收到了 `111` 事件。如果以上事件中的 taskId 与前一次的 `111` 事件一致,则可以作为冗余事件通知忽略。 -4. 如果你需要完全确保成功开启了合流服务,则仍然需要调用 `query` 进行查询。 +2. 收到事件后,你的应用调用 `Acquire`,重新开启合流服务。 +3. 在此期间你的服务器又收到了 `111` 事件。如果以上事件中的 `taskId` 与前一次的 `111` 事件一致,则可以作为冗余事件通知忽略。 +4. 如果你需要完全确保成功开启了合流服务,则仍然需要调用 `Query` 进行查询。 ## 避免合流服务频繁退出 -`start` 方法中的 `idleTimeout` 参数默认值为 300 秒。对于要求合流服务一直在频道中的场景,为避免合流服务因主播频繁上下线而频繁启动和退出,你需要在设置 `idleTimeout` 取值时权衡实际场景,避免取值过小。合适的取值可以保证合流服务在短时间无发流端时也能稳定运行,避免合流服务频繁退出。 +`Create` 方法中的 `idleTimeout` 参数默认值为 300 秒。对于要求合流服务一直在频道中的场景,为避免合流服务因主播频繁上下线而频繁启动和退出,你需要在设置 `idleTimeout` 取值时权衡实际场景,避免取值过小。合适的取值可以保证合流服务在短时间无发流端时也能稳定运行,避免合流服务频繁退出。 From 9d598db83ed97937c07e68cc98e2543b4d0ed43c Mon Sep 17 00:00:00 2001 From: kelzr Date: Thu, 20 Apr 2023 18:31:35 +0800 Subject: [PATCH 4/8] [CT] update after review --- ...ce.md => best-practice-for-integration.md} | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) rename markdown/cloud-transcoder/{best-practice.md => best-practice-for-integration.md} (59%) diff --git a/markdown/cloud-transcoder/best-practice.md b/markdown/cloud-transcoder/best-practice-for-integration.md similarity index 59% rename from markdown/cloud-transcoder/best-practice.md rename to markdown/cloud-transcoder/best-practice-for-integration.md index a7133c3ac94..39620c56e01 100644 --- a/markdown/cloud-transcoder/best-practice.md +++ b/markdown/cloud-transcoder/best-practice-for-integration.md @@ -2,21 +2,18 @@ ## 保障 REST 服务高可用 - 为保障 REST 服务的高可用,避免因区域网络故障造成的服务不可用,声网提供故障迁移、多路备份、切换域名的方案。 ### 故障迁移 -针对网络故障,以及非声网云服务,非声网软件,基础设施和不可抗力等因素可能导致的风险,声网云端转码服务为提升用户体验,提供高可用自动任务迁移服务。当故障确认后,该服务会在尽量短的时间(预计 90 秒内)完成,在此期间会存在合流中断等风险。 - -对于频道内观众较多或对高可用有极高要求的场景,你需要根据业务需求判断能否接受高可用迁移的影响,决定是否要采用更高的质量保障措施。例如,对关键任务进行多路合流,即,使用多个不同的 `uid`(在输出频道内)发起多路合流任务,或通过[周期性频道查询](#monitor)和消息通知服务了解合流任务状态,以便在发生故障时及时使用备用 `uid` 重新发起新的合流任务,从而确保关键任务顺利完成。//TODO 合流 -> 转码 +针对网络故障,以及非声网云服务,非声网软件,基础设施和不可抗力等因素可能导致的风险,声网云端转码服务为提升用户体验,提供高可用自动任务迁移服务。当故障确认后,该服务会在尽量短的时间(预计 90 秒内)完成迁移,在此期间会存在转码中断等风险。对于频道内观众较多或对高可用有极高要求的场景,你需要根据业务需求判断能否接受高可用迁移的影响,决定是否要采用更高的质量保障措施。例如,使用多个不同的 `uid`(在输出频道内)发起多路转码任务,或通过[周期性频道查询](#monitor)和消息通知服务了解转码任务状态,以便在发生故障时及时使用备用 `uid` 重新发起新的转码任务,从而确保关键任务顺利完成。 ### 多路备份 -如需比故障迁移更高的质量保障,你可以采用多路任务保障策略。每路合流转码任务单独计费。实现步骤如下: +如需比故障迁移更高的质量保障,你可以采用多路任务保障策略。每路转码任务单独计费。实现步骤如下: -1. 同时发起主任务和备份任务,订阅相同的主播源流,向同一频道或不同频道推送合流转码流,观众端订阅主任务中的输出频道内的 `uid`。 +1. 同时发起主任务和备份任务,订阅相同的主播源流,向同一频道或不同频道推送转码输出的流,观众端订阅主任务中的输出频道内的 `uid`。 2. 在客户端监听以下回调事件,可以及时通知观众端订阅备份任务中的输出频道内的 `uid`: @@ -31,11 +28,11 @@ ## 获取服务状态 -你可以通过云端转码 RESTful API 来获取合流服务状态。相比于云端转码 RESTful API,[消息通知服务](https://docs.agora.io/cn/cloud-transcoding/ncs_transcoding?platform=All%20Platforms)更适合作为辅助手段。 +你可以通过云端转码 RESTful API 来获取转码服务状态。相比于云端转码 RESTful API,[消息通知服务](https://docs.agora.io/cn/cloud-transcoding/ncs_transcoding?platform=All%20Platforms)更适合作为辅助手段。 -以下是所有的合流服务状态(`services.cloudTranscoder.status`): +以下是所有的转码服务状态(`services.cloudTranscoder.status`): -|status |描述| +|服务状态 |描述| |------|-----| |`"serviceIdle"` |服务未开始。| |`"serviceStarted"` |服务已开始。| @@ -48,49 +45,49 @@ |`"serviceUnknown"` |服务未知状态。|
    -
  • 消息通知服务只能作为辅助手段来获取服务合流状态。不建议你的核心业务逻辑依赖消息通知服务。如果你的业务高度依赖消息通知服务,建议联系技术支持开通该服务的冗余消息功能,即接收双路消息通知,降低消息丢失的概率。开通冗余消息功能后,需要你基于 taskId 对消息进行去重。冗余消息功能仍然不能保证 100% 的消息到达率。
  • -
  • 每个 App ID 每秒钟的请求数(QPS)限制默认为 10 次。请根据你的同时最大并发任务数(PCW)和查询间隔,预估所需的 QPS,并通过提交工单的方式申请调整 QPS 限制。
  • -
  • 国内 PCW 限制为 100,其他地区 PCW 限制为 30。如需提升 PCW 限制,请联系技术支持。
  • +
  • 消息通知服务只能作为辅助手段来获取服务转码状态。不建议你的核心业务逻辑依赖消息通知服务。如果你的业务高度依赖消息通知服务,建议联系技术支持开通该服务的冗余消息功能,即接收双路消息通知,降低消息丢失的概率。开通冗余消息功能后,需要你基于 taskId(任务 ID)对消息进行去重。冗余消息功能仍然不能保证 100% 的消息到达率。
  • +
  • 每个 App ID 每秒钟的请求数(QPS)限制默认为 10 次。请根据你的同时最大并发任务数(PCW)和查询间隔,预估所需的 QPS,并通过提交工单的方式申请调整 QPS 限制。
  • +
  • 国内 PCW 限制为 100,其他地区 PCW 限制为 30。如需提升 PCW 限制,请联系技术支持
  • -### 检查合流服务已经成功启动 +### 检查转码服务是否已经成功启动 //TODO 任务启动 vs 服务开始? -建议你通过如下步骤确认合流服务已成功启动: +建议你通过如下步骤确认转码服务已成功启动: -1. 确认 `Create` 请求成功,即成功获得 `taskId` (合流 ID)。如果 `Create` 请求返回 HTTP 状态码非 `200`,则需要根据状态码采取相应措施: - - 如果返回的 HTTP 状态码为 `201`,则表示合流任务已成功启动并在进行中。 +1. 确认 `Create` 请求成功,即成功获得 `taskId`。如果 `Create` 请求返回 HTTP 状态码非 `200`,则需要根据状态码采取相应措施: + - 如果返回的 HTTP 状态码为 `201`,则表示转码任务已成功启动并在进行中。 - 如果返回的 HTTP 状态码为 `206`,则表示请求超时,建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `Acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `Create` 方法。 - 如果返回的 HTTP 状态码为 `40x`,则表示请求参数错误,需要进行排查。 - 如果返回的 HTTP 状态码为 `50x`,可使用相同的参数重试多次,直到成功返回 `taskId` 为止。建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `Acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `Create` 方法。 - 如果收到错误码 `65`,需要使用相同的参数再次调用 `Create`。建议使用退避策略重试两次,如第一次等待 3 秒后重试、第二次等待 6 秒后重试。 -2. 获得 taskId 之后的 5 秒后,使用退避策略调用 `Query` 方法,退避间隔建议小于 `Create` 请求中的 idleTimeout (最长空闲频道时间)。如果 `Query` 请求成功,且 `serverResponse` 中的 `status` 参数值为 `4` 或 `5`,则表示合流服务已成功启动。如果在获得 `taskId` 之后的 90 秒后 `status` 仍非 `4` 或 `5`, 则可以认为合流未启动或成功后超时退出。 +2. 获得 `taskId` 之后的 5 秒后,使用退避策略调用 `Query` 方法,退避间隔建议小于 `Create` 请求中的 `idleTimeout` (最长空闲频道时间)。如果 `Query` 请求成功,且 `serverResponse` 中的 `status` 参数值为 `4` 或 `5`,则表示转码服务已成功启动。如果在获得 `taskId` 之后的 90 秒后 `status` 仍非 `4` 或 `5`, 则可以认为转码未启动或成功后超时退出。 -
    建议你准备一个备份 UID,在重新启动合流时使用,以避免输出频道内两个相同 UID 互踢。主备 UID 可以交替使用。
    +
    建议你准备一个备份 UID,在重新启动转码时使用,以避免输出频道内两个相同 UID 互踢。主备 UID 可以交替使用。
    -### 合流任务的状态监控 +### 转码任务的状态监控 -你可以通过周期性调用 `Query` 方法来确认合流服务正在进行中且状态正常。相比于 `Query`,消息通知服务更适合作为辅助手段。详见[消息通知服务和 query 方法的对比](https://docs.agora.io/cn/faq/ncs_vs_query)。 +你可以通过周期性调用 `Query` 方法来确认转码服务正在进行中且状态正常。相比于 `Query`,消息通知服务更适合作为辅助手段。详见[消息通知服务和 query 方法的对比](https://docs.agora.io/cn/faq/ncs_vs_query)。 #### 周期性频道查询 -如果你对状态查询的可靠性要求较高,声网强烈建议你使用 `Query` 方法周期性查询频道内的合流状态,例如每隔 2 分钟调用一次 `Query`,并根据返回的 HTTP 状态码采取相应措施。 +如果你对状态查询的可靠性要求较高,声网强烈建议你使用 `Query` 方法周期性查询频道内的转码状态,例如每隔 2 分钟调用一次 `Query`,并根据返回的 HTTP 状态码采取相应措施。 - 如果返回的 HTTP 状态码一直为 `40x`,则表示请求参数错误,需要进行排查。 -- 如果返回的 HTTP 状态码为 `404`,且已经确认请求参数无误,则表示合流并未成功启动、或启动后中途退出。建议采用退避策略多次调用 `Query` (例如间隔 5 秒、10 秒、15 秒)进行确认。 -- 如果返回的 HTTP 状态码为 `50x`,则表示 `Query` 请求失败,但尚不明确合流是否已退出。出现 `50x` 错误的概率极小,建议使用退避策略 (5 秒, 10 秒, 15 秒,30 秒) 继续调用 `Query`。 +- 如果返回的 HTTP 状态码为 `404`,且已经确认请求参数无误,则表示 cloud transcoder 并未成功启动、或启动后中途退出。建议采用退避策略多次调用 `Query` (例如间隔 5 秒、10 秒、15 秒)进行确认。 +- 如果返回的 HTTP 状态码为 `50x`,则表示 `Query` 请求失败,但尚不明确 cloud transcoder 是否已退出。出现 `50x` 错误的概率极小,建议使用退避策略 (5 秒,10 秒,15 秒,30 秒) 继续调用 `Query`。 #### 冗余消息通知服务 -开通冗余消息功能后,需要你基于 `taskId` 对消息进行去重。举例来说,如果你需要在合流超时退出后再次开启合流,流程为: +开通冗余消息功能后,需要你基于 `taskId` 对消息进行去重。举例来说,如果你需要在 cloud transcoder 超时退出后再次开启,流程为: -1. 你的服务器收到 `111` 事件,表示合流服务已正常退出。 -2. 收到事件后,你的应用调用 `Acquire`,重新开启合流服务。 +1. 你的服务器收到 `111` 事件,表示转码服务已正常退出。 +2. 收到事件后,你的应用调用 `Acquire`,重新开启转码服务。 3. 在此期间你的服务器又收到了 `111` 事件。如果以上事件中的 `taskId` 与前一次的 `111` 事件一致,则可以作为冗余事件通知忽略。 -4. 如果你需要完全确保成功开启了合流服务,则仍然需要调用 `Query` 进行查询。 +4. 如果你需要完全确保成功开启了转码服务,则仍然需要调用 `Query` 进行查询。 -## 避免合流服务频繁退出 +## 避免转码服务频繁退出 -`Create` 方法中的 `idleTimeout` 参数默认值为 300 秒。对于要求合流服务一直在频道中的场景,为避免合流服务因主播频繁上下线而频繁启动和退出,你需要在设置 `idleTimeout` 取值时权衡实际场景,避免取值过小。合适的取值可以保证合流服务在短时间无发流端时也能稳定运行,避免合流服务频繁退出。 +`Create` 方法中的 `idleTimeout` 参数默认值为 300 秒。对于要求 cloud transcoder 一直在频道中的场景,为避免 cloud transcoder 因主播频繁上下线而频繁启动和退出,你需要在设置 `idleTimeout` 取值时权衡实际场景,避免取值过小。合适的取值可以保证转码服务在短时间无发流端时也能稳定运行,避免转码服务频繁退出。 From a2afae7d65edd2f7cb64f1783c18b1c0402e6ec9 Mon Sep 17 00:00:00 2001 From: kelzr Date: Fri, 21 Apr 2023 12:07:11 +0800 Subject: [PATCH 5/8] [CT] update after review --- .../best-practice-for-integration.md | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/markdown/cloud-transcoder/best-practice-for-integration.md b/markdown/cloud-transcoder/best-practice-for-integration.md index 39620c56e01..3a7e3eca1b0 100644 --- a/markdown/cloud-transcoder/best-practice-for-integration.md +++ b/markdown/cloud-transcoder/best-practice-for-integration.md @@ -1,5 +1,6 @@ 本文介绍使用云端转码服务的最佳实践,包含保障高可用、检查服务状态并及时排查问题、避免服务频繁退出。通过采用这些措施,可以更好保障服务的可靠性和稳定性,从而为你提供更好的业务支持。 +[TOC] ## 保障 REST 服务高可用 为保障 REST 服务的高可用,避免因区域网络故障造成的服务不可用,声网提供故障迁移、多路备份、切换域名的方案。 @@ -45,24 +46,28 @@ |`"serviceUnknown"` |服务未知状态。|
    -
  • 消息通知服务只能作为辅助手段来获取服务转码状态。不建议你的核心业务逻辑依赖消息通知服务。如果你的业务高度依赖消息通知服务,建议联系技术支持开通该服务的冗余消息功能,即接收双路消息通知,降低消息丢失的概率。开通冗余消息功能后,需要你基于 taskId(任务 ID)对消息进行去重。冗余消息功能仍然不能保证 100% 的消息到达率。
  • 每个 App ID 每秒钟的请求数(QPS)限制默认为 10 次。请根据你的同时最大并发任务数(PCW)和查询间隔,预估所需的 QPS,并通过提交工单的方式申请调整 QPS 限制。
  • 国内 PCW 限制为 100,其他地区 PCW 限制为 30。如需提升 PCW 限制,请联系技术支持
  • -### 检查转码服务是否已经成功启动 //TODO 任务启动 vs 服务开始? +### 检查转码服务是否已经成功启动 -建议你通过如下步骤确认转码服务已成功启动: +建议你通过如下步骤检查转码服务是否已成功启动: -1. 确认 `Create` 请求成功,即成功获得 `taskId`。如果 `Create` 请求返回 HTTP 状态码非 `200`,则需要根据状态码采取相应措施: - - 如果返回的 HTTP 状态码为 `201`,则表示转码任务已成功启动并在进行中。 - - 如果返回的 HTTP 状态码为 `206`,则表示请求超时,建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `Acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `Create` 方法。 - - 如果返回的 HTTP 状态码为 `40x`,则表示请求参数错误,需要进行排查。 - - 如果返回的 HTTP 状态码为 `50x`,可使用相同的参数重试多次,直到成功返回 `taskId` 为止。建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `Acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `Create` 方法。 - - 如果收到错误码 `65`,需要使用相同的参数再次调用 `Create`。建议使用退避策略重试两次,如第一次等待 3 秒后重试、第二次等待 6 秒后重试。 -2. 获得 `taskId` 之后的 5 秒后,使用退避策略调用 `Query` 方法,退避间隔建议小于 `Create` 请求中的 `idleTimeout` (最长空闲频道时间)。如果 `Query` 请求成功,且 `serverResponse` 中的 `status` 参数值为 `4` 或 `5`,则表示转码服务已成功启动。如果在获得 `taskId` 之后的 90 秒后 `status` 仍非 `4` 或 `5`, 则可以认为转码未启动或成功后超时退出。 +#### 1. 检查 Create 请求是否成功 -
    建议你准备一个备份 UID,在重新启动转码时使用,以避免输出频道内两个相同 UID 互踢。主备 UID 可以交替使用。
    +如果 `Create` 请求返回 HTTP 状态码为 `200`,则请求成功。如果 `Create` 请求返回 HTTP 状态码非 `200`,则需要根据状态码采取相应措施: +- 如果返回的 HTTP 状态码为 `201`,则表示转码任务已成功启动并在进行中。 +- 如果返回的 HTTP 状态码为 `206`,则表示请求超时,建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `Acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `Create` 方法。 +- 如果返回的 HTTP 状态码为 `40x`,则表示请求参数错误,需要进行排查。 +- 如果返回的 HTTP 状态码为 `50x`,可使用相同的参数重试多次,直到成功返回 `taskId` 为止。建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `Acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `Create` 方法。 +- 如果收到错误码 `65`,需要使用相同的参数再次调用 `Create`。建议使用退避策略重试两次,如第一次等待 3 秒后重试、第二次等待 6 秒后重试。 + +#### 2. 检查 cloud transcoder 是否成功启动 + +`Create` 请求成功后,你会获得 `taskId`。获得 `taskId` 之后的 5 秒后,使用退避策略调用 `Query` 方法,退避间隔建议小于 `Create` 请求中的 `idleTimeout` (最长空闲频道时间)。如果 `Query` 请求成功,且 `serverResponse` 中的 `status` 参数值为 `4` 或 `5`,则表示 cloud transcoder 已成功启动。如果在获得 `taskId` 之后的 90 秒后 `status` 仍非 `4` 或 `5`, 则可以认为 cloud transcoder 在创建后未成功启动,超时退出。 + +
    考虑到频道内用户 UID 不能冲突,因此建议你为 cloud transcoder 准备一个备用 UID,以便在重新发起新的转码任务时使用。主用 UID 和备用 UID 可以交替使用。
    ### 转码任务的状态监控 @@ -76,17 +81,22 @@ - 如果返回的 HTTP 状态码一直为 `40x`,则表示请求参数错误,需要进行排查。 - 如果返回的 HTTP 状态码为 `404`,且已经确认请求参数无误,则表示 cloud transcoder 并未成功启动、或启动后中途退出。建议采用退避策略多次调用 `Query` (例如间隔 5 秒、10 秒、15 秒)进行确认。 -- 如果返回的 HTTP 状态码为 `50x`,则表示 `Query` 请求失败,但尚不明确 cloud transcoder 是否已退出。出现 `50x` 错误的概率极小,建议使用退避策略 (5 秒,10 秒,15 秒,30 秒) 继续调用 `Query`。 +- 如果返回的 HTTP 状态码为 `50x`,则表示 `Query` 请求失败,但尚不明确 cloud transcoder 是否已退出。出现 `50x` 错误的概率极小,建议使用退避策略 (例如间隔 5 秒,10 秒,15 秒,30 秒) 继续调用 `Query`。 -#### 冗余消息通知服务 +#### 使用消息通知服务 -开通冗余消息功能后,需要你基于 `taskId` 对消息进行去重。举例来说,如果你需要在 cloud transcoder 超时退出后再次开启,流程为: +消息通知服务可以辅助监听云端转码的状态。为了避免消息投递时丢失,建议你开通该服务的冗余消息通知功能。开通后,你需要基于 `taskId` 对消息进行去重。举例来说,如果你需要在 cloud transcoder 超时退出后再次开启,消息去重的逻辑为: 1. 你的服务器收到 `111` 事件,表示转码服务已正常退出。 -2. 收到事件后,你的应用调用 `Acquire`,重新开启转码服务。 -3. 在此期间你的服务器又收到了 `111` 事件。如果以上事件中的 `taskId` 与前一次的 `111` 事件一致,则可以作为冗余事件通知忽略。 -4. 如果你需要完全确保成功开启了转码服务,则仍然需要调用 `Query` 进行查询。 +2. 收到步骤 1 的 `111` 事件后,你调用 `Acquire` 重新开启转码服务。 +3. 在重新开启转码期间,你的服务器又收到了 `111` 事件。如果该事件和步骤 1 收到的 `111` 事件对应的 `taskId` 一致,则可以将该事件通知当冗余通知,可忽略。 +如果你需要完全确认转码服务已成功开启,则还需调用 `Query` 进行查询。 + +
    +
  • 消息通知服务需联系技术支持开通。
  • +
  • 冗余消息功能仍然不能保证 100% 的消息到达率。
  • +
    ## 避免转码服务频繁退出 From f4200889cbb721757bab25bdebe5e5aa8ced302c Mon Sep 17 00:00:00 2001 From: kelzr Date: Fri, 21 Apr 2023 12:16:18 +0800 Subject: [PATCH 6/8] [CT] update after review --- .../best-practice-for-integration.md | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/markdown/cloud-transcoder/best-practice-for-integration.md b/markdown/cloud-transcoder/best-practice-for-integration.md index 3a7e3eca1b0..6883a510472 100644 --- a/markdown/cloud-transcoder/best-practice-for-integration.md +++ b/markdown/cloud-transcoder/best-practice-for-integration.md @@ -1,6 +1,4 @@ 本文介绍使用云端转码服务的最佳实践,包含保障高可用、检查服务状态并及时排查问题、避免服务频繁退出。通过采用这些措施,可以更好保障服务的可靠性和稳定性,从而为你提供更好的业务支持。 - -[TOC] ## 保障 REST 服务高可用 为保障 REST 服务的高可用,避免因区域网络故障造成的服务不可用,声网提供故障迁移、多路备份、切换域名的方案。 @@ -22,12 +20,11 @@ - 主播音视频状态变化回调: [`onRemoteAudioStateChanged`](https://docs.agora.io/cn/live-streaming-premium-4.x/API%20Reference/java_ng/API/toc_audio_process.html#callback_irtcengineeventhandler_onremoteaudiostatechanged)/[`onRemoteVideoStateChanged`](https://docs.agora.io/cn/live-streaming-premium-4.x/API%20Reference/java_ng/API/toc_video_process.html#callback_irtcengineeventhandler_onremotevideostatechanged) - ### 切换域名 ~45f50180-d902-11ed-8efe-b91caddc8ecb~ -## 获取服务状态 +## 检查服务状态 你可以通过云端转码 RESTful API 来获取转码服务状态。相比于云端转码 RESTful API,[消息通知服务](https://docs.agora.io/cn/cloud-transcoding/ncs_transcoding?platform=All%20Platforms)更适合作为辅助手段。 @@ -50,13 +47,14 @@
  • 国内 PCW 限制为 100,其他地区 PCW 限制为 30。如需提升 PCW 限制,请联系技术支持
  • -### 检查转码服务是否已经成功启动 +### 检查转码服务是否成功启动 建议你通过如下步骤检查转码服务是否已成功启动: #### 1. 检查 Create 请求是否成功 -如果 `Create` 请求返回 HTTP 状态码为 `200`,则请求成功。如果 `Create` 请求返回 HTTP 状态码非 `200`,则需要根据状态码采取相应措施: +如果 `Create` 请求响应的 HTTP 状态码为 `200`,则请求成功。如果 `Create` 请求响应的 HTTP 状态码非 `200`,则需要根据状态码采取相应措施: + - 如果返回的 HTTP 状态码为 `201`,则表示转码任务已成功启动并在进行中。 - 如果返回的 HTTP 状态码为 `206`,则表示请求超时,建议使用退避策略,如第一次等待 3 秒后重试、第二次等待 6 秒后重试、第三次等待 9 秒后重试,以免超过 QPS 限制导致失败。如果三次重试均失败,建议更换 UID 再次调用 `Acquire`, 获得一个新的 `tokenName`,并用该 `tokenName` 再次调用 `Create` 方法。 - 如果返回的 HTTP 状态码为 `40x`,则表示请求参数错误,需要进行排查。 @@ -67,17 +65,16 @@ `Create` 请求成功后,你会获得 `taskId`。获得 `taskId` 之后的 5 秒后,使用退避策略调用 `Query` 方法,退避间隔建议小于 `Create` 请求中的 `idleTimeout` (最长空闲频道时间)。如果 `Query` 请求成功,且 `serverResponse` 中的 `status` 参数值为 `4` 或 `5`,则表示 cloud transcoder 已成功启动。如果在获得 `taskId` 之后的 90 秒后 `status` 仍非 `4` 或 `5`, 则可以认为 cloud transcoder 在创建后未成功启动,超时退出。 -
    考虑到频道内用户 UID 不能冲突,因此建议你为 cloud transcoder 准备一个备用 UID,以便在重新发起新的转码任务时使用。主用 UID 和备用 UID 可以交替使用。
    - -### 转码任务的状态监控 +
    频道内用户 UID 不能冲突,因此建议你为 cloud transcoder 准备一个备用 UID,以便在重新发起新的转码任务时使用。主用 UID 和备用 UID 可以交替使用。
    -你可以通过周期性调用 `Query` 方法来确认转码服务正在进行中且状态正常。相比于 `Query`,消息通知服务更适合作为辅助手段。详见[消息通知服务和 query 方法的对比](https://docs.agora.io/cn/faq/ncs_vs_query)。 +### 监控转码任务状态 +你可以通过周期性调用 `Query` 方法和消息通知服务监控转码任务的状态。相比于 `Query`,消息通知服务更适合作为辅助手段。详见[消息通知服务和 query 方法的对比](https://docs.agora.io/cn/faq/ncs_vs_query)。 -#### 周期性频道查询 +#### 周期性查询状态 -如果你对状态查询的可靠性要求较高,声网强烈建议你使用 `Query` 方法周期性查询频道内的转码状态,例如每隔 2 分钟调用一次 `Query`,并根据返回的 HTTP 状态码采取相应措施。 +你可以通过周期性调用 `Query` 方法来确认转码服务正在进行中且状态正常。如果你对状态查询的可靠性要求较高,声网强烈建议你使用 `Query` 方法周期性查询频道内的转码状态,例如每隔 2 分钟调用一次 `Query`,并根据返回的 HTTP 状态码采取相应措施。 - 如果返回的 HTTP 状态码一直为 `40x`,则表示请求参数错误,需要进行排查。 - 如果返回的 HTTP 状态码为 `404`,且已经确认请求参数无误,则表示 cloud transcoder 并未成功启动、或启动后中途退出。建议采用退避策略多次调用 `Query` (例如间隔 5 秒、10 秒、15 秒)进行确认。 From 884a6a5e68a94bbb097c3e15f75da6a6d1cde13d Mon Sep 17 00:00:00 2001 From: kelzr Date: Fri, 21 Apr 2023 14:36:16 +0800 Subject: [PATCH 7/8] [CT] update after review --- markdown/cloud-transcoder/best-practice-for-integration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdown/cloud-transcoder/best-practice-for-integration.md b/markdown/cloud-transcoder/best-practice-for-integration.md index 6883a510472..b49792ffad5 100644 --- a/markdown/cloud-transcoder/best-practice-for-integration.md +++ b/markdown/cloud-transcoder/best-practice-for-integration.md @@ -1,5 +1,5 @@ 本文介绍使用云端转码服务的最佳实践,包含保障高可用、检查服务状态并及时排查问题、避免服务频繁退出。通过采用这些措施,可以更好保障服务的可靠性和稳定性,从而为你提供更好的业务支持。 -## 保障 REST 服务高可用 +## 保障服务高可用 为保障 REST 服务的高可用,避免因区域网络故障造成的服务不可用,声网提供故障迁移、多路备份、切换域名的方案。 From 3e174a1ad28cbe3663e281532413676e0f84dcbe Mon Sep 17 00:00:00 2001 From: kelzr Date: Fri, 21 Apr 2023 14:37:11 +0800 Subject: [PATCH 8/8] [CT] sync --- markdown/cloud-transcoder/API Ref | 639 -------------------- markdown/cloud-transcoder/api.md | 807 ++++++++++++++++++++++++++ markdown/cloud-transcoder/overview.md | 32 + markdown/cloud-transcoder/webhook.md | 270 +++++++++ 4 files changed, 1109 insertions(+), 639 deletions(-) delete mode 100644 markdown/cloud-transcoder/API Ref create mode 100644 markdown/cloud-transcoder/api.md create mode 100644 markdown/cloud-transcoder/overview.md create mode 100644 markdown/cloud-transcoder/webhook.md diff --git a/markdown/cloud-transcoder/API Ref b/markdown/cloud-transcoder/API Ref deleted file mode 100644 index 77c8f211991..00000000000 --- a/markdown/cloud-transcoder/API Ref +++ /dev/null @@ -1,639 +0,0 @@ -Agora provides cloud transcoding service for single or multi-hosted interactive streaming scenarios and supports transcoding and stream mixing on the Agora server to push the streams of multiple hosts to the Agora RTC channel. Audience users in the RTC channel only need to subscribe to the transcoded and mixed streams to watch the live broadcast. - -When you use the cloud transcoding service, audience users do not need to subscribe to the streams of multiple hosts. This can significantly reduce downstream bandwidth use and help improve performance on user devices. - -This page describes how to implement cloud transcoding through RESTful API. - -## Prerequisites - -- Agora RESTful API requires Basic HTTP authentication. Make sure to complete [HTTP Basic Authentication](https://docs.agora.io/en/video-calling/reference/restful-authentication). -- Cloud transcoding is a sub-service of cloud recording. Make sure that the cloud recording service is enabled. See [Project setup](https://docs.agora.io/en/cloud-recording/get-started/getstarted#project-setup). - -## Understand the tech - -The process of transcoding and mixing multiple streams on the Agora server is equivalent to creating a cloud transcoder. The multiple streams before transcoding are the input of the cloud transcoder, and the stream after transcoding is the output. - -You can control the cloud transcoder through the cloud transcoding RESTful API: - -- `Acquire`: Before starting cloud transcoding, you must obtain a cloud transcoding resource for cloud transcoding tasks. -- `Create`: Create a cloud transcoder. The Agora server starts transcoding and mixing the multiple streams you specify into a single stream and pushes it to the Agora RTC channel. -- `Delete`: Destroy the cloud transcoder. The Agora server stops transcoding and mixing streams. -- `Query`: Query the information of the cloud transcoder. The Agora server queries the cloud transcoder you specify. - -## Acquire: Obtain a cloud transcoding resource - -Before starting a cloud transcoding task, you must call the `Acquire` method to obtain a cloud transcoding resource. - -After calling this method successfully, you can get a builderToken in the response body. The validity period of the builderToken is 5 minutes, and you need to use the builderToken to start cloud transcoding within 5 minutes. A builderToken can only be used for one cloud transcoding task. - -### HTTP request - -```http -POST https://api.agora.io/v1/projects//rtsc/cloud-transcoder/builderTokens -``` - -`appId`: (Required) String type parameter. The App ID provided by Agora for each developer. You can get an App ID after creating a project in Agora Console. The App ID identifies each project. - -#### Request header - -- `Content-Type`: `application/json` -- `Authorization`: The value of this field should refer to the `authentication `[instructions ](https://docs.agora.io/en/faq/restful_authentication) - -#### Request body - -The following parameters need to be passed in the request body: - -| Field | Type | Description | -| :----------- | :----------- | :----------------------------------------------------------- | -| `instanceId` | (Required)String | User-specified instance ID. The length must be a maximum of 64 characters. The supported character set range is as follows:
  • All lowercase English letters (a-z)
  • All uppercase English letters (A-Z)
  • Numbers 0-9
  • "-", "_"
    You can use one `instanceId` to generate multiple builderTokens, but only one builderToken can be used to initiate a request in a task. | - -The request body example: - -```json -{ - "instanceId" : "abc13328" -} -``` - -### HTTP response - -#### Response header - -`X-Request-ID`: UUID (Universal Unique Identifier), which identifies this request. -
    • If there is an error in the request, print out the value in the log to troubleshoot the problem.
    • If the response status code of this request is not 2XX, this field might not appear in the response header.
    - -#### Response body - -The response body contains the following fields: - -| Field | Type | Description | -| :----------- | :----- | :---------------------------------------------------- | -| `tokenName` | String | The value of builderToken, which needs to be passed in when calling other methods later. | -| `createTs` | Number | The Unix timestamp in seconds when the builderToken was generated. | -| `instanceId` | Number | The `instanceId` set in request body. | - -Response body example: - -```json -{ - "createTs": 1661324606, - "instanceId": "abc13328", - "tokenName": "nUwUbQf9Zg6tsgtLslGnDg0lk8RYaUE0***" -} -``` - -## Create: Start the task for creating a cloud transcoder - -### HTTP request - -``` -POST https://api.agora.io/v1/projects//rtsc/cloud-transcoder/tasks?builderToken= -``` - -#### Path parameter - -`appId`: (Required) String type parameter. The App ID provided by Agora for each developer. You can get an App ID after creating a project in Agora Console. The App ID identifies each project. - -#### Query parameter - -`builderToken`: (Required)String. Obtain the value of the builderToken through the `Acquire` method.`` - -#### Request header - -- `Content-Type`: `application/json` -- `Authorization`: The value of this field should refer to the `authentication `[instructions ](https://docs.agora.io/en/faq/restful_authentication) - -#### Request body - -The request body is the `services` field of JSON Object type. The field structure is shown in the following figure: - -![](https://web-cdn.agora.io/docs-files/1664351637544) - -- `services` contains the following fields: - - | Field | Type | Description | - | :---------------------------------- | :---------------- | :----------------------------------------------------------- | - | cloudTranscoder | (Required)JSON Object | Service name, set by the developer. The service name used in a cloud transcoder must be unique. | - | cloudTranscoder.serviceType | (Required)String | Service type. Cloud transcoding: `cloudTranscoderV2`. | - | cloudTranscoder.config | (Required)JSON Object | The cloud transcoding parameter settings. Used to set the business parameters of the cloud transcoder. | - | cloudTranscoder.config.transcoder | (Required)String | An object of the cloud transcoder. | - -- **`transcoder`** contains the following fields: - - | Field | Type | Description | - | :--------------------------------- | :---------------- | :----------------------------------------------------------- | - | idleTimeOut | (Optional)Number | The maximum amount of time (seconds) that the cloud transcoder is idle. Idle means that all hosts corresponding to the audio and video streams processed by the cloud transcoder have left the channel. After the idle state exceeds the set `idleTimeOut`, the cloud transcoder is destroyed automatically. The value range is [1,86400], and the default value is 300. | - | audioInputs[] | (Optional)JSON Object | The audio input source configuration for cloud transcoder.
  • If you do not pass a value, Agora use the input source corresponding to `videoInputs[].rtc.rtcUid` as the audio input source of the cloud transcoder. This method is suitable for scenarios where both the audio and video of the host are transcoded.
  • If you pass a value, Agora transcode and mixes the audio input source you specify. This value method is suitable for scenarios where the `audioInputs[].rtc.rtcUid` and `videoInputs[].rtc.rtcUid` are not exactly the same, that is, the video of some hosts is transcoded but the audio is not transcoded. | - | audioInputs[].rtc | (Required)JSON Array | The RTC audio input source for cloud transcoder. Multiple RTC input sources are supported. | - | audioInputs[].rtc.rtcChannel | (Required)String | The name of the RTC channel to which the input source belongs. Currently Agora only supports subscribing to the audio and video sources of a single channel. The audio and video sources must belong to the same channel. | - | audioInputs[].rtc.rtcUid | (Required)Number | The UID corresponding to the input source. The same UID is not allowed within an RTC channel. | - | audioInputs[].rtc.rtcToken | (Required)String | The token required to enter the RTC channel is used to ensure the security of the channel. See [Secure authentication with tokens](https://docs.agora.io/en/interactive-live-streaming/develop/authentication-workflow).| - | videoInputs[] | (Required)JSON Array | The video input configuration for cloud transcoder. | - | videoInputs[].rtc | (Required)JSON Array | The RTC video input source for the cloud transcoder. Multiple RTC input sources are supported. | - | videoInputs[].rtc.rtcChannel | (Required)String | The name of the RTC channel to which the video input source belongs. Currently Agora only supports subscribing to audio and video sources of a single channel. The audio and video sources must belong to the same channel. | - | videoInputs[].rtc.rtcUid | (Required)Number | The UID corresponding to the video input source. | - | videoInputs[].region | (Required)JSON Object | The position of the video input source picture on the canvas. | - | videoInputs[].region.x | (Required)Number | The x coordinate (pixels) of the video on the canvas. The horizontal position of the canvas relative to the origin, where the upper left corner of the canvas is the origin, and the x-coordinate is the upper left corner of the canvas. The value range is [0,3840]. | - | videoInputs[].region.y | (Required)Number | The y coordinate (pixels) of the video on the canvas. The vertical position of the canvas relative to the origin, where the upper left corner of the canvas is the origin, and the y-coordinate is the upper left corner of the canvas. The value range is [0,3840]. | - | videoInputs[].region.width | (Required)Number | The width (pixels) of the video. The value range is [120,3840]. | - | videoInputs[].region.height | (Required)Number | The height (pixels) of the video. The value range is [120,3840]. | - | videoInputs[].region.zOrder | (Required)Number | The layer number of the video. The value range is [0,100]. 0 represents the lowest layer. 100 represents the top layer. | - | videoInputs [].placeholderImageUrl | (Required)String | The URL of the placeholder image when the user is offline. This url must be a valid URL with a `jpg` or `png` suffix. | - | canvas | (Required)JSON Object | The canvas that hosts the cloud transcoder video mixing. | - | canvas.height | (Required)Number | The height (pixel) of the canvas. The value range is [120,3840]. | - | canvas.width | (Required)Number | The width (pixel) of the canvas. The value range is [120,3840]. | - | canvas.color | (Required)String | The background color of the canvas. RGB color value, expressed as a decimal number. For example, 0 is black, 255 is blue. The value range is [0,16777215]. | - | canvas.backgroundImage | (Optional)String | The background color of the canvas. This URL must be valid with a `jpg` or `png` suffix. | - | canvas.fillMode | (Optional)String | The fill mode of the canvas background image.
  • (Default) `FILL`: Scales the screen while maintaining the aspect ratio and cropping in the center.
    ![img](https://web-cdn.agora.io/docs-files/1628837665989)
  • `FIT`:In order to maintain the aspect ratio, zoom the screen to fully display the image.
    ![img](https://web-cdn.agora.io/docs-files/1628837708782) | - | waterMarks [] | (Optional)JSON Array | Watermark input configuration for cloud transcoder. | - | waterMarks [].imageUrl | (Required)String | The URL of the image. This URL must be valid with a `jpg` or `png` suffix. | - | waterMarks [].fillMode | (Optional)String | The adaptation mode of the watermark.
  • (Default) `FILL`: Scales the screen while maintaining the aspect ratio, and cropping in the center.
    ![ img](https://web-cdn.agora.io/docs-files/1628837665989)
  • `FIT`: In order to maintain the aspect ratio, zoom the screen to fully display the image.
    ![img](https://web-cdn.agora.io/docs-files/1628837708782) | - | waterMarks [].region | (Required)JSON Object | The position of the watermark on the canvas. | - | waterMarks [].region.x | (Required)Number | The x coordinate (pixels) of the watermark on the canvas. The horizontal position relative to the origin, where the upper left corner of the canvas is the origin, and the x-coordinate is the upper left corner of the canvas. The value range is [0,3840]. | - | waterMarks [].region.y | (Required)Number | The y coordinate (pixels) of the watermark on the canvas. The vertical position of the canvas relative to the origin, where the upper left corner of the canvas is the origin, and the y-coordinate is the upper left corner of the canvas. The value range is [0,3840]. | - | waterMarks [].region.width | (Required)Number | The width (pixels) of the watermark. The value range is [120,3840]. | - | waterMarks [].region.height | (Required)Number | The height (pixels) of the watermark. The value range is [120,3840]. | - | waterMarks.region.zOrder[] | (Required)Number | The layer number of the watermark image. The value range is [0,100]. 0 represents the lowest layer. 100 represents the top layer. | - | outputs.rtc | (Required)JSON Object | The output configuration for cloud transcoder. | - | outputs.rtc.rtcChannel | (Required)String | The name of the RTC channel to which the output video belongs. | - | outputs.rtc.rtcToken | (Required)String | The token required to enter the RTC channel is used to ensure the security of the channel. | - | outputs.rtc.rtcUid | (Required)Number | The user ID. | - | outputs.audioOption | (Optional)JSON Object | The transcoding configuration for the mixed audio stream. If you do not pass a value, the audio property of Agora transcoding output is `AUDIO_PROFILE_DEFAULT`, which is a 48 kHz sampling rate, music encoding, mono, and a maximum encoding bitrate of 64 Kbps. | - | outputs.audioOption.profileType | (Optional)String | Audio profiles. The values supported are as follows:
  • `AUDIO_PROFILE_DEFAULT`: (Default) A sample rate of 48 kHz, music encoding, mono, and a maximum encoding bitrate of 64 Kbps.
  • `AUDIO_PROFILE_SPEECH_STANDARD`: A sample rate of 32 kHz, audio encoding, mono, and a bitrate of up to 18 Kbps.
  • `AUDIO_PROFILE_MUSIC_STANDARD`: A sample rate of 48 kHz, music encoding, mono, and a bitrate of up to 64 Kbps.
  • `AUDIO_PROFILE_MUSIC_STANDARD_STEREO`: A sample rate of 48 kHz, music encoding, stereo, and a bitrate of up to 80 Kbps.
  • `AUDIO_PROFILE_MUSIC_HIGH_QUALITY`: A sample rate of 48 kHz, music encoding, mono, and a bitrate of up to 96 Kbps.
  • `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO`: A sample rate of 48 kHz, music encoding, stereo, and a bitrate of up to 128 Kbps. | - | outputs.videoOption | (Required)JSON Object | Transcoding configuration for mixed video stream. | - | outputs.videoOption.fps | (Optional)Number | The frame rate (fps) of the output video. The value range is [1,30]. The default value is 15. | - | outputs.videoOption.codec | (Required)String | The codec for the output video. The supported value is `"H264"`. | - | outputs.videoOption.bitrate | (Optional)Number | The bitrate of the output video. The value range is [1,10000]. If you don't pass a value, Agora automatically sets the video bitrate based on network conditions and other video properties. | - | outputs.videoOption.width | (Required)Number | The width (pixels) of the video. The value range is [120,3840]. | - | outputs.videoOption.height | (Required)Number | The height (pixels) of the output video. The value range is [120,3840]. | - -#### Request body example - -**Seneario 1: Audio and video trascoding with canvas and watermark** - -This example is transcoding and mixing the audio and video streams of two hosts with the user IDs `"123"` and `"456"` and publishing them into the channel "test". - -```json -{ - "services":{ - "cloudTranscoder":{ - "serviceType":"cloudTranscoderV2", - "config":{ - "transcoder":{ - "idleTimeout":300, - "audioInputs":[ - { - "rtc":{ - "rtcChannel":"test01", - "rtcUid": 123, - "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7063" - } - }, - { - "rtc":{ - "rtcChannel":"test01", - "rtcUid": 456, - "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7063" - } - } - ], - "canvas":{ - "width":960, - "height":480, - "color":0, - "backgroundImage":"https://XXXX.jpg", - "fillMode": "FIT" - }, - "waterMarks":[ - { - "imageUrl":"https://XXXX.png", - "region":{ - "x":0, - "y":0, - "width":100, - "height":100, - "zOrder":50 - } - } - ], - "videoInputs":[ - { - "rtc":{ - "rtcChannel":"test01", - "rtcUid": 123, - "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7063" - }, - "placeholderImageUrl":"https://XXXX.jpg", - "region":{ - "x":0, - "y":0, - "width":320, - "height":360, - "zOrder":1 - } - }, - { - "rtc":{ - "rtcChannel":"test01", - "rtcUid": 456, - "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7063" - }, - "placeholderImageUrl":"https://XXXX.jpg", - "region":{ - "x":320, - "y":0, - "width":320, - "height":320, - "zOrder":1 - } - } - ], - "outputs":[ - { - "rtc":{ - "rtcChannel":"test", - "rtcUid":1000, - "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7063" - }, - "audioOption":{ - "profileType":"AUDIO_PROFILE_MUSIC_STANDARD" - }, - "videoOption":{ - "fps":30, - "codec":"H264", - "bitrate":800, - "width":960, - "height":480, - "lowBitrateHighQuality":false - } - } - ] - } - } - } - } -} -``` - -**Scenario 2: Audio only with canvas** - -```json -{ - "services":{ - "cloudTranscoder":{ - "serviceType":"cloudTranscoderV2", - "config":{ - "transcoder":{ - "idleTimeout":180, - "audioInputs":[ - { - "rtc":{ - "rtcChannel":"test01", - "rtcUid": 123, - "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7063" - } - }, - { - "rtc":{ - "rtcChannel":"test01", - "rtcUid": 456, - "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7063" - } - } - ], - "canvas":{ - "width":960, - "height":480, - "color":0, - "backgroundImage":"https://XXXX.jpg" - }, - "outputs":[ - { - "rtc":{ - "rtcChannel":"test02", - "rtcUid":1000, - "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7063" - }, - "audioOption":{ - "profileType":"AUDIO_PROFILE_MUSIC_STANDARD" - } - } - ] - } - } - } - } -} -``` - -**Scenario 3: Audio mixing for all users in the channel with canvas** - -```json -{ - "services":{ - "cloudTranscoder":{ - "serviceType":"cloudTranscoderV2", - "config":{ - "transcoder":{ - "idleTimeout":180, - "audioInputs":[ - { - "rtc":{ - "rtcChannel":"test01", - "rtcUid": 0, - "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7063" - } - } - ], - "canvas":{ - "width":960, - "height":480, - "color":0, - "backgroundImage":"https://XXXX.jpg" - }, - "outputs":[ - { - "rtc":{ - "rtcChannel":"test02", - "rtcUid":1000, - "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7063" - }, - "audioOption":{ - "profileType":"AUDIO_PROFILE_MUSIC_STANDARD" - } - } - ] - } - } - } - } -} -``` - -### HTTP response - -#### Response header - -`X-Request-ID`: UUID (Universal Unique Identifier), which identifies this request. -
    • If there is an error in the request, print out the value in the log to troubleshoot the problem.
    • If the response status code of this request is not 2XX, this field might not appear in the response header.
    - -#### Response body - -The field structure contained in the response body is shown in the following figure: - -![](https://web-cdn.agora.io/docs-files/1664351656358) - -The meanings of the fields are shown in the following table: - -| Field | Type | Description | -| :------------------------------------------- | :----------- | :----------------------------------------------------------- | -| taskId | JSON Object | The task ID, which is the UUID, is used to identify the cloud transcoder created by this request. | -| createTs | Number | The Unix timestamp (seconds) when the cloud transcoding task was created. | -| status | String | The running status of the create task:
  • `IDLE`: The task is not started.
  • `PREPARED`: The task has received a request to start.
  • `STARTING`: The task is starting.
  • `CREATED`: The task initialization is completed.
  • `STARTED`: The task has been started.
  • `IN_PROGRESS`: The task is in progress.
  • `STOPPING`: The task is stopping.
  • `STOPPED`: The task has been stopped.
  • `EXIT`: The task exits normally.
  • `FAILURE_STOP`: The task exits abnormally. | -| services | JSON Object | The service information included in the task. | -| services.cloudTranscoder | JSON Object | The service name. | -| services.cloudTranscoder.serviceType | String | Service type. Cloud transcoding: `cloudTranscoderV2`. | -| services.cloudTranscoder.config | JSON Object | The service parameters. | -| services.cloudTranscoder.config.transcoder | (Required)String | The cloud transcoder object. For the fields and meanings included in the cloud transcoder object, refer to the fields and meanings in the request body. | -| services.cloudTranscoder.createTs | Number | The unix timestamp (seconds) when the cloud transcoder was created. | -| services.cloudTranscoder.status | String | The running status of the service:
  • `serviceIdle`:The service is not started.
  • `serviceReady`: The service is ready.
  • `serviceStarted`: The service has been started.
  • `serviceInProgress`: The service is in progress.
  • `serviceCompleted`: The service has been stopped and the tasks are all completed.
  • `servicePartialCompleted`: The service has been stopped and the task is partially completed.
  • `serviceValidationFailed`: The service parameter validation failed.
  • `serviceAbnormal`: The service exited abnormally.
  • `serviceUnknown`: The service status is unknown. | -| services.cloudTranscoder.message | String | The execution information of the service, describing the specific cause of the service exception. | -| services.cloudTranscoder.details | JSON Object | The execution details of the service. | -| eventHandlers | String | Reserved fields. | -| execution | JSON Object | Reserved fields. | -| execution.workflows | String | Reserved fields. | -| properties | String | Reserved fields. | -| sequenceId | String | Reserved fields. | -| variables | JSON Object | Reserved fields. | -| workflows | JSON Object | Reserved fields. | - -Response body example: - -```json -{ - "createTs": 1661324613, - "eventHandlers": {}, - "execution": { - "workflows": {} - }, - "properties": {}, - "sequenceId": "0", - "services": { - "cloudTranscoder": { - "config": {}, - "createTs": 1661324614, - "details": {}, - "message": "", - "serviceType": "cloudTranscoderV2", - "status": "serviceReady" - } - }, - "status": "STARTED", - "taskId": "609f28f2644f1ae1ceb041b7047e39aa", - "variables": {}, - "workflows": {} -} -``` - -## Delete: Destroy the cloud transcoder - -### HTTP request - -``` -DELETE https://api.agora.io/v1/projects//rtsc/cloud-transcoder/tasks/?builderToken= -``` - -#### Path parameter - -- `appId`: (Required) String type parameter. The App ID provided by Agora for each developer. You can get an App ID after creating a project in Agora Console. The App ID identifies each project. -- `taskId`: The task ID of the cloud transcoder, which is UUID, used to identify the cloud transcoder created by this request. - -#### Query parameter - -`builderToken`: (Required)String. Obtain the value of the builderToken through the `Acquire` method.`` - -#### Request header - -- `Content-Type`: `application/json` -- `Authorization`: The value of this field should refer to the `authentication `[instructions ](https://docs.agora.io/en/faq/restful_authentication) - -### HTTP response - -#### Response header - -`X-Request-ID`: UUID (Universal Unique Identifier), which identifies this request. -
    • If there is an error in the request, print out the value in the log to troubleshoot the problem.
    • If the response status code of this request is not 2XX, this field might not appear in the response header.
    - -#### Response body - -The response body contains the following fields: - -![](https://web-cdn.agora.io/docs-files/1664351673569) - -The meanings of the fields are shown in the following table: - -| Field | Type | Description | -| :------------------------------------------- | :----------- | :----------------------------------------------------------- | -| taskId | JSON Object | The task ID, which is UUID, is used to identify the cloud transcoder created by this request. | -| createTs | Number |The unix timestamp (seconds) when the task was created. | -| status | String | The running status of the create task:
  • `IDLE`: The task is not started.
  • `PREPARED`: The task has received a request to start.
  • `STARTING`: The task is starting.
  • `CREATED`: The task initialization is completed.
  • `STARTED`: The task has been started.
  • `IN_PROGRESS`: The task is in progress.
  • `STOPPING`: The task is stopping.
  • `STOPPED`: The task has been stopped.
  • `EXIT`: The task exits normally.
  • `FAILURE_STOP`: The task exits abnormally. | -| services | JSON Object | Service information included in the task. | -| services.cloudTranscoder | JSON Object | The service name. | -| services.cloudTranscoder.serviceType | String | Service type. Cloud transcoding: `cloudTranscoderV2`. | -| services.cloudTranscoder.config | JSON Object | The service parameters. | -| services.cloudTranscoder.config.transcoder | (Required)String | The cloud transcoder object. For the fields and meanings included in the cloud transcoder object, refer to the fields and meanings in the request body. | -| services.cloudTranscoder.createTs | Number | The unix timestamp (seconds) when the cloud transcoder was created. | -| services.cloudTranscoder.status | String | The running status of the service:
  • `serviceIdle`:The service is not started.
  • `serviceReady`: The service is ready.
  • `serviceStarted`: The service has been started.
  • `serviceInProgress`: The service is in progress.
  • `serviceCompleted`: The service has been stopped and the tasks are all completed.
  • `servicePartialCompleted`: The service has been stopped and the task is partially completed.
  • `serviceValidationFailed`: The service parameter validation failed.
  • `serviceAbnormal`: The service exited abnormally.
  • `serviceUnknown`: The service is in unknown status. | -| services.cloudTranscoder.message | String | The execution information of the service, describing the specific cause of the service exception. | -| services.cloudTranscoder.details | JSON Object | The execution details of the service. | -| eventHandlers | String | Reserved fields. | -| execution | JSON Object | Reserved fields. | -| execution.workflows | String | Reserved fields. | -| properties | String | Reserved fields. | -| sequenceId | String | Reserved fields. | -| variables | JSON Object | Reserved fields. | -| workflows | JSON Object | Reserved fields. | - -Response body example: - -```json -{ - "createTs": 1661324613, - "eventHandlers": {}, - "execution": { - "workflows": {} - }, - "properties": {}, - "sequenceId": "0", - "services": { - "cloudTranscoder": { - "config": {}, - "createTs": 1661324614, - "details": {}, - "message": "OnSlaveServiceStopped", - "serviceType": "cloudTranscoderV2", - "status": "serviceCompleted" - } - }, - "status": "STOPPED", - "taskId": "609f28f2644f1ae1ceb041b7047e39aa", - "variables": {}, - "workflows": {} -} -``` - -## Query: Query cloud transcoder status information - -### HTTP request - -``` -GET https://api.agora.io/v1/projects//rtsc/cloud-transcoder/tasks/?builderToken= -``` - -### Path parameter - -- `appId`: (Required) String type parameter. The App ID provided by Agora for each developer. You can get an App ID after creating a project in Agora Console. The App ID identifies each project. -- `taskId`: The task ID of the cloud transcoder, which is UUID, used to identify the cloud transcoder created by this request. - -### Query parameter - -`builderToken`: (Required)String. Obtain the value of the builderToken through the `Acquire` method.```` - -#### Request header - -- `Content-Type`: `application/json` -- `Authorization`: The value of this field should refer to the `authentication `[instructions ](https://docs.agora.io/en/faq/restful_authentication) - -### HTTP response - -#### Response header - -`X-Request-ID`: UUID (Universal Unique Identifier), which identifies this request. -
    • If there is an error in the request, print out the value in the log to troubleshoot the problem.
    • If the response status code of this request is not 2XX, this field might not appear in the response header.
    - -#### Response body - -The response body contains the following fields: - -![](https://web-cdn.agora.io/docs-files/1664351715856) - -The meanings of the fields are shown in the following table: - -| Field | Type | Description | -| :------------------------------------------- | :----------- | :----------------------------------------------------------- | -| taskId | JSON Object | The task ID, which is the UUID, is used to identify the cloud transcoder created by this request. | -| createTs | Number | The unix timestamp (seconds) when the task was created. | -| status | String | The running status of the create task:
  • `IDLE`: The task is not started.
  • `PREPARED`: The task has received a request to start.
  • `STARTING`: The task is starting.
  • `CREATED`: The task initialization is completed.
  • `STARTED`: The task has been started.
  • `IN_PROGRESS`: The task is in progress.
  • `STOPPING`: The task is stopping.
  • `STOPPED`: The task has been stopped.
  • `EXIT`: The task exits normally.
  • `FAILURE_STOP`: The task exits abnormally. | -| services | JSON Object |The service information included in the task. | -| services.cloudTranscoder | JSON Object | The service name. | -| services.cloudTranscoder.serviceType | String | Service type. Cloud transcoding: `cloudTranscoderV2`. | -| services.cloudTranscoder.config | JSON Object | The service parameters. | -| services.cloudTranscoder.config.transcoder | (Required)String | The cloud transcoder object. For the fields and meanings included in the cloud transcoder object, refer to the fields and meanings in the request body. | -| services.cloudTranscoder.createTs | Number | Unix timestamp (seconds) when the cloud transcoder was created. | -| services.cloudTranscoder.status | String | The running status of the service:
  • `serviceIdle`:The service is not started.
  • `serviceReady`: The service is ready.
  • `serviceStarted`: The service has been started.
  • `serviceInProgress`: The service is in progress.
  • `serviceCompleted`: The service has been stopped and the tasks are all completed.
  • `servicePartialCompleted`: The service has been stopped and the task is partially completed.
  • `serviceValidationFailed`: The service parameter validation failed.
  • `serviceAbnormal`: The service exited abnormally.
  • `serviceUnknown`: The service is in unknown status. | -| services.cloudTranscoder.message | String | Execution information of the service, describing the specific cause of the service exception. | -| services.cloudTranscoder.details | JSON Object | The execution details of the service. | -| eventHandlers | String | Reserved fields. | -| execution | JSON Object | Reserved fields. | -| execution.workflows | String | Reserved fields. | -| properties | String | Reserved fields. | -| sequenceId | String | Reserved fields. | -| variables | JSON Object | Reserved fields. | -| workflows | JSON Object | Reserved fields. | - -Response body example: - -```json -{ - "createTs": 1661420011, - "eventHandlers": {}, - "execution": { - "workflows": {} - }, - "properties": {}, - "sequenceId": "0", - "services": { - "cloudTranscoder": { - "config": {}, - "createTs": 1661420011, - "message": "OnSlaveServiceQueryUpdated", - "serviceType": "cloudTranscoderV2", - "status": "serviceInProgress" - } - }, - "status": "IN_PROGRESS", - "taskId": "c0077139e34d0949c719189a393aa7c0", - "variables": {}, - "workflows": {} -} -``` - -## Status codes - -- If the status code is `2XX`, the request is successful. -- If the status code is not `2XX`, the request fails. You can troubleshoot the problem based on the content of the `message` field in the corresponding response body. - -| Status code | Description | -| :---------------------- | :----------------------------------------------------------- | -| 200 OK | The request succeeds. | -| 201 Created | The task is already in progress, do not use the same builderToken to start the task repeatedly. | -| 202 Accepted | The server has received the task request, but has not completed the execution. Use the `Query` method to` query` the execution status. | -| 400 Bad Request | The request has a syntax error (such as a parameter error). If the App ID you fill in `appid` does not have the Cloud Transcoding permission, it also returns `400`. Process it in combination with the `message` field of the response body. | -| 401 Unauthorized | Authorization is invalid. | -| 403 Forbidden | Your App ID has not yet activated the cloud transcoder; contact Agora. | -| 404 Not Found | The cloud transcoder is not found. | -| 409 Conflict |A cloud transcoder already exists with the same name. If you want to create a new cloud transcoder, delete the old cloud transcoder with the same name first. | -| 429 Too Many Requests | The request rate exceeds the upper limit. | -| 500 Unknown | An error occurs in the Agora server. Try uploading the log files later. | -| 501 Not Implemented | This method is not implemented. | -| 503 Service Unavailable | The Agora server is temporarily overloaded or under maintenance. Use the retry mechanism or contact Agora. | -| 504 Gateway Timeout | Agora server internal error, the server acting as a gateway or proxy did not get the request from the upstream server, the upstream server is down. Contact Agora. | - -## Considerations - -This section summarizes the most important considerations for using Push Streaming RESTful API. - -- Do not do any logic to the content of the `message` field in the response body. If the request fails, troubleshoot the problem based on the status code. -- The status code of `202` only means that the server has received the task request. It does not mean that the execution is completed. You need to continue to query the execution status through the `Query` method to determine whether the task is completed. -- After receiving the `404` status code, if the `Create` request has returned successfully and the `Delete `method has not been actively called, or the idle state of the cloud transcoder exceeds the `idleTimeout` field in the request parameters, it is recommended you adopt a backoff algorithm (for example, the interval of 5 seconds, 10 seconds, 15 seconds) to call the `Query` method to confirm. -- After receiving the response status code of` 5xx`, there is generally a problem in the response process of the server. It is recommended that you use a backoff algorithm (such as 5 seconds, 10 seconds, 15 seconds interval) to call the `Query` request for confirmation. \ No newline at end of file diff --git a/markdown/cloud-transcoder/api.md b/markdown/cloud-transcoder/api.md new file mode 100644 index 00000000000..f4018548cff --- /dev/null +++ b/markdown/cloud-transcoder/api.md @@ -0,0 +1,807 @@ +声网针对多人连麦直播场景研发云端转码服务,支持在服务端将单个或多个主播的音视频流转码合流并输入到声网 RTC 频道。频道内观众仅需订阅转码合流后的音视频流即可观看直播。 + +使用云端转码服务后,观众无需订阅多个主播的音视频流,可大幅节省下行带宽压力和客户端设备性能消耗。 + +本文介绍如何通过 RESTful API 实现云端转码,以及如何保障 REST 服务高可用。 + +## 前提条件 + +- 声网 RESTful API 要求 Basic HTTP 认证,请确保完成 [HTTP 基本认证](https://docs.agora.io/cn/cloud-recording/faq/restful_authentication)。 +- 请确保已[联系声网技术支持](https://docs.agora.io/cn/Agora%20Platform/ticket?platform=All%20Platforms)开通云端转码服务。 + +## 技术原理 + +声网服务端将多路流转码合流的过程相当于创建一个 cloud transcoder。转码前的多路流是 cloud transcoder 的输入,转码后的流是 cloud transcoder 的输出。 + +你可以通过云端转码 RESTful API 控制 cloud transcoder: + +- `Acquire`:在开始云端转码前,必须先获取云端转码资源,用于云端转码任务。 +- `Create`:创建 cloud transcoder。声网服务器会开始将你指定的多路流转码合流并输入到声网 RTC 频道。 +- `Delete`:销毁 cloud transcoder。声网服务器会停止转码合流。 +- `Query`:查询 cloud transcoder 信息。声网服务器会查询你指定的 cloud transcoder 的状态信息。 + +## Acquire:获取云端转码资源 + +在开始录制前,必须先调用 `Acquire` 方法获取一个云端转码资源。 + +调用该方法成功后,你可以在响应包体中得到一个 builderToken。builderToken 的时效为 5 分钟,你需要在 5 分钟内使用该 builderToken 开始云端转码。一个 builderToken 仅可用于一次云端转码任务。 + +### HTTP 请求 + +```http +POST https://api.agora.io/v1/projects/{appId}/rtsc/cloud-transcoder/builderTokens +``` + +`appId`: String 型必填参数。声网为每个开发者提供的 App ID。在声网控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。 + +#### 请求头 + +- `Content-Type`: `application/json` +- `Authorization`: 该字段的值需参考[认证说明](https://docs.agora.io/cn/faq/restful_authentication) + +#### 请求包体 + +需要在请求包体中传入以下参数: + +| 字段 | 类型 | 描述 | +| :----------- | :----------- | :----------------------------------------------------------- | +| `instanceId` | String,必填 | 用户指定的实例 ID。长度必须在 64 个字符以内,支持的字符集范围为:
  • 所有小写英文字母(a-z)
  • 所有大写英文字母(A-Z)
  • 数字 0-9
  • "-", "_"
    一个 `instanceId` 可以生成多个 builderToken,但在一个任务中只能使用一个 builderToken 发起请求。 | + +请求包体示例: + +```json +{ + "instanceId" : "abc13328" +} +``` + +### HTTP 响应 + +#### 响应头 + +`X-Request-ID`: UUID(通用唯一识别码),用于标识本次请求。 +
    • 如果请求出错,请在日志中打印出该值,排查问题。
    • 如果本次请求的响应状态码不是 2XX,那么响应 header 中可能无该字段。
    + +#### 响应包体 + +如果状态码为 2XX,则请求成功。响应包体包含以下字段: + +| 字段 | 类型 | 描述 | +| :----------- | :----- | :---------------------------------------------------- | +| `tokenName` | String | builderToken 的值,在后续调用其他方法时需要传入该值。 | +| `createTs` | Number | 生成 builderToken 时的 Unix 时间戳(秒)。 | +| `instanceId` | Number | 请求时设置的 `instanceId`。 | + +响应包体示例: + +```json +{ + "createTs": 1661324606, + "instanceId": "abc13328", + "tokenName": "nUwUbQf9Zg6tsgtLslGnDg0lk8RYaUE0***" +} +``` + +## Create:创建 cloud transcoder + +### HTTP 请求 + +```http +POST https://api.agora.io/v1/projects/{appId}/rtsc/cloud-transcoder/tasks?builderToken={tokenName} +``` + +#### 路径参数 + +`appId`: String 型必填字段。声网为每个开发者提供的 App ID。在声网控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。 + +#### 查询参数 + +`builderToken`: String 型必填字段。通过 `Acquire` 方法获取 builderToken 的参数值 `tokenName`。 + +#### 请求头 + +- `Content-Type`: `application/json` +- `Authorization`: 该字段的值需参考[认证说明](https://docs.agora.io/cn/faq/restful_authentication) + + +#### 请求包体 + +请求包体为 JSON Object 类型的 `services` 字段。字段结构如图所示: + +![](https://web-cdn.agora.io/docs-files/1664351637544) + +- `services` 包含如下字段: + + | 字段 | 类型 | 描述 | + | :---------------------------------- | :---------------- | :----------------------------------------------------------- | + | cloudTranscoder | JSON Object,必填 | 服务名称,开发者自行设置。需要保证一个 cloud transcoder 中使用的服务名称唯一。 | + | cloudTranscoder.serviceType | String,必填 | 服务类型。云端转码:`cloudTranscoderV2`。 | + | cloudTranscoder.config | JSON Object,必填 | 云端转码参数设置。用于设置 cloud transcoder 的业务参数。 | + | cloudTranscoder.config.transcoder | String,必填 | Cloud transcoder 的对象。 | + +- `transcoder` 包含如下字段: + + | 字段 | 类型 | 描述 | + | :--------------------------------- | :---------------- | :----------------------------------------------------------- | + | idleTimeout | Number,可选 | Cloud transcoder 处于空闲状态的最大时长(秒)。空闲指 cloud transcoder 处理的音视频流所对应的所有主播均已离开频道。空闲状态超过设置的 `idleTimeOut` 后, cloud transcoder 会自动销毁。取值范围为 [1,86400],默认值为 300。 | + | audioInputs [] | JSON Object,可选 | Cloud transcoder 的音频输入源配置。
  • 如果你不传值,声网会将 `videoInputs[].rtc.rtcUid` 对应的输入源作为 cloud transcoder 的音频输入源。这种取值方式适用于对主播的音频和视频都转码的场景。
  • 如果你传值,声网会将你指定的音频输入源进行转码混音。这种取值方式适用于 `audioInputs[].rtc.rtcUid` 和 `videoInputs[].rtc.rtcUid` 不完全一致的场景,即部分主播的视频转码但音频不转码。 | + | audioInputs[].rtc | JSON Array,必填 | Cloud transcoder 的 RTC 音频输入源。支持多个 RTC 输入源。 | + | audioInputs[].rtc.rtcChannel | String,必填 | 输入源所属的 RTC 频道名。目前仅支持订阅单个频道的音视频源,音频源和视频源所属频道必须相同。 | + | audioInputs[].rtc.rtcUid | Number,必填 | 音频输入源所对应的 UID。RTC 频道内不允许存在相同的 UID。 | + | audioInputs[].rtc.rtcToken | String,必填 | Cloud transcoder 在进入待转码音频源所属 RTC 频道时所需设置的 Token。该值可用于确保频道安全,避免异常用户扰乱频道内其他用户。详见[使用 Token 鉴权](https://docs.agora.io/cn/live-streaming-premium-4.x/token_server_android_ng?platform=Android)。Cloud transcoder 在待转码音视频源所属 RTC 频道内的 UID 为声网随机分配,因此,生成 Token 时,你使用的 `uid` 必须为 0。 | + | videoInputs [] | JSON Array,必填 | Cloud transcoder 的视频输入配置。 | + | videoInputs[].rtc | JSON Array,必填 | Cloud transcoder 的 RTC 视频输入源。支持多个 RTC 输入源。 | + | videoInputs[].rtc.rtcChannel | String,必填 | 视频输入源所属的 RTC 频道名。目前仅支持订阅单个频道的音视频源,音频源和视频源所属频道必须相同。 | + | videoInputs[].rtc.rtcUid | Number,必填 | 视频输入源所对应的 UID。RTC 频道内不允许存在相同的 UID。 | + | videoInputs[].rtc.rtcToken | String,必填 | Cloud transcoder 在进入待转码视频源所属 RTC 频道时所需设置的 Token。该值可用于确保频道安全,避免异常用户扰乱频道内其他用户。详见[使用 Token 鉴权](https://docs.agora.io/cn/live-streaming-premium-4.x/token_server_android_ng?platform=Android)。Cloud transcoder 在待转码音视频源所属 RTC 频道内的 UID 为声网随机分配,因此,生成 Token 时,你使用的 `uid` 必须为 0。 | + | videoInputs[].region | JSON Object,必填 | 视频输入源画面在画布上的位置。 | + | videoInputs[].region.x | Number,必填 | 画面在画布上的 x 坐标 (px)。以画布左上角为原点,x 坐标为画面左上角相对于原点的横向位移。取值范围为 [0,3840]。 | + | videoInputs[].region.y | Number,必填 | 画面在画布上的 y 坐标 (px)。以画布左上角为原点,y 坐标为画面左上角相对于原点的纵向位移。取值范围为 [0,3840]。 | + | videoInputs[].region.width | Number,必填 | 画面的宽度 (px)。取值范围为 [120,3840]。 | + | videoInputs[].region.height | Number,必填 | 画面的高度 (px)。取值范围为 [120,3840]。 | + | videoInputs[].region.zOrder | Number,必填 | 画面的图层编号。取值范围为 [0,100]。0 代表最下层的图层。100 代表最上层的图层。 | + | videoInputs [].placeholderImageUrl | String,必填 | 用户离线时占位图片的 URL。必须为合法 URL,且包含 `jpg` 或 `png` 后缀。 | + | canvas | JSON Object,必填 | 承载 cloud transcoder 合图的画布。 | + | canvas.height | Number,必填 | 画布的高度 (px)。取值范围为 [120,3840]。 | + | canvas.width | Number,必填 | 画布的宽度 (px)。取值范围为 [120,3840]。 | + | canvas.color | String,必填 | 画布的背景色。RGB 颜色值,以十进制数表示。如 0 代表黑色,255 代表蓝色。取值范围为 [0,16777215]。 | + | canvas.backgroundImage | String,可选 | 画布背景图。必须为合法 URL,且包含 `jpg` 或 `png` 后缀。 | + | canvas.fillMode | String,可选 | 画布背景图的填充模式。
  • (默认)`FILL`:在保持长宽比的前提下,缩放画面,并居中剪裁。
    ![img](https://web-cdn.agora.io/docs-files/1628837665989)
  • `FIT`:在保持长宽比的前提下,缩放画面,使其完整显示。
    ![img](https://web-cdn.agora.io/docs-files/1628837708782) | + | waterMarks [] | JSON Array,可选 | Cloud transcoder 的水印输入配置。 | + | waterMarks [].imageUrl | String,必填 | 水印图片的 URL。必须为合法 URL,且包含 `jpg` 或 `png` 后缀。 | + | waterMarks [].fillMode | String,可选 | 水印的填充模式。
  • (默认)`FILL`:在保持长宽比的前提下,缩放画面,并居中剪裁。
    ![img](https://web-cdn.agora.io/docs-files/1628837665989)
  • `FIT`:在保持长宽比的前提下,缩放画面,使其完整显示。
    ![img](https://web-cdn.agora.io/docs-files/1628837708782) | + | waterMarks [].region | JSON Object,必填 | 水印在画布上的位置。 | + | waterMarks [].region.x | Number,必填 | 水印在画布上的 x 坐标 (px)。以画布左上角为原点,x 坐标为画面左上角相对于原点的横向位移。取值范围为 [0,3840]。 | + | waterMarks [].region.y | Number,必填 | 水印在画布上的 y 坐标 (px)。以画布左上角为原点,y 坐标为画面左上角相对于原点的纵向位移。取值范围为 [0,3840]。 | + | waterMarks [].region.width | Number,必填 | 水印的宽度 (px)。取值范围为 [120,3840]。 | + | waterMarks [].region.height | Number,必填 | 水印的高度 (px)。取值范围为 [120,3840]。 | + | waterMarks [].region.zOrder | Number,必填 | 水印的图层编号。取值范围为 [0,100]。0 代表最下层的图层。100 代表最上层的图层。 | + | outputs.rtc | JSON Object,必填 | cloud transcoder 的输出配置。 | + | outputs.rtc.rtcChannel | String,必填 | 转码输出的音视频流所属的 RTC 频道名。 | + | outputs.rtc.rtcToken | String,必填 | Cloud transcoder 在进入输出音视频流所属 RTC 频道时所需设置的 Token。该值可用于确保频道安全,避免异常用户扰乱频道内其他用户。详见[使用 Token 鉴权](https://docs.agora.io/cn/live-streaming-premium-4.x/token_server_android_ng?platform=Android)。Cloud transcoder 在转码输出音视频流所属 RTC 频道内的 UID 为你指定的 `outputs.rtc.rtcUid`,因此,生成 Token 时,你使用的 `uid` 必须和 `outputs.rtc.rtcUid` 一致。 | + | outputs.rtc.rtcUid | Number,必填 | Cloud transcoder 在转码输出音视频流所属 RTC 频道内的 UID。RTC 频道内不允许存在相同的 UID,因此,请确保该值与频道内其他用户 UID 不同。 | + | outputs.audioOption | JSON Object,可选 | 音频流的转码混音配置。如果你不传值,声网转码输出的音频属性为 `AUDIO_PROFILE_DEFAULT`,即 48 kHz 采样率,音乐编码,单声道,编码码率最大值为 64 Kbps。 | + | outputs.audioOption.profileType | String,可选 | 转码输出的音频属性。支持取值:
  • `AUDIO_PROFILE_DEFAULT`:默认值,48 kHz 采样率,音乐编码,单声道,编码码率最大值为 64 Kbps。
  • `AUDIO_PROFILE_SPEECH_STANDARD`:32 kHz 采样率,语音编码,单声道,编码码率最大值为 18 Kbps。
  • `AUDIO_PROFILE_MUSIC_STANDARD`: 48 KHz 采样率,音乐编码,单声道,编码码率最大值为 64 Kbps。
  • `AUDIO_PROFILE_MUSIC_STANDARD_STEREO`:48 KHz 采样率,音乐编码,双声道,编码码率最大值为 80 Kbps。
  • `AUDIO_PROFILE_MUSIC_HIGH_QUALITY`:48 KHz 采样率,音 乐编码,单声道,编码码率最大值为 96 Kbps。
  • `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO`:48 KHz 采样率,音乐编码,双声道,编码码率最大值为 128 Kbps。 | + | outputs.videoOption | JSON Object,必填 | 视频流的转码合图配置。 | + | outputs.videoOption.fps | Number,可选 | 转码输出视频的帧率 (fps)。取值范围为 [1,30]。默认值为 15。 | + | outputs.videoOption.codec | String,必填 | 转码输出视频的 codec。取值包括:
  • `H264`:标准 H.264 编码
  • `VP8`:标准 VP8 编码 | + | outputs.videoOption.bitrate | Number,可选 | 转码输出视频的码率。取值范围为 [1,10000]。如果你不传值,声网会根据网络情况和其他视频属性自动设置视频码率。 | + | outputs.videoOption.width | Number,必填 | 转码输出视频的宽度 (px)。取值范围为 [120,3840]。 | + | outputs.videoOption.height | Number,必填 | 转码输出视频的高度 (px)。取值范围为 [120,3840]。 | + +#### 请求包体示例 + +**场景一:音视频 + 水印 + 画布** + +将 UID 为 `123`、`456` 两个主播的音视频流转码合流并输入到 test 频道中。 + +```json +{ + "services":{ + "cloudTranscoder":{ + "serviceType":"cloudTranscoderV2", + "config":{ + "transcoder":{ + "idleTimeout":300, + "audioInputs":[ + { + "rtc":{ + "rtcChannel":"test01", + "rtcUid": 123, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + } + }, + { + "rtc":{ + "rtcChannel":"test01", + "rtcUid": 456, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + } + } + ], + "canvas":{ + "width":960, + "height":480, + "color":0, + "backgroundImage":"https://XXXX.jpg", + "fillMode": "FIT" + }, + "waterMarks":[ + { + "imageUrl":"https://XXXX.png", + "region":{ + "x":0, + "y":0, + "width":100, + "height":100, + "zOrder":50 + } + } + ], + "videoInputs":[ + { + "rtc":{ + "rtcChannel":"test01", + "rtcUid": 123, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + }, + "placeholderImageUrl":"https://XXXX.jpg", + "region":{ + "x":0, + "y":0, + "width":320, + "height":360, + "zOrder":1 + } + }, + { + "rtc":{ + "rtcChannel":"test01", + "rtcUid": 456, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + }, + "placeholderImageUrl":"https://XXXX.jpg", + "region":{ + "x":320, + "y":0, + "width":320, + "height":320, + "zOrder":1 + } + } + ], + "outputs":[ + { + "rtc":{ + "rtcChannel":"test", + "rtcUid":1000, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + }, + "audioOption":{ + "profileType":"AUDIO_PROFILE_MUSIC_STANDARD" + }, + "videoOption":{ + "fps":30, + "codec":"H264", + "bitrate":800, + "width":960, + "height":480, + "lowBitrateHighQuality":false + } + } + ] + } + } + } + } +} +``` + +**场景二:纯音频 + 画布** + +```json +{ + "services":{ + "cloudTranscoder":{ + "serviceType":"cloudTranscoderV2", + "config":{ + "transcoder":{ + "idleTimeout":180, + "audioInputs":[ + { + "rtc":{ + "rtcChannel":"test01", + "rtcUid": 123, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + } + }, + { + "rtc":{ + "rtcChannel":"test01", + "rtcUid": 456, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + } + } + ], + "canvas":{ + "width":960, + "height":480, + "color":0, + "backgroundImage":"https://XXXX.jpg" + }, + "outputs":[ + { + "rtc":{ + "rtcChannel":"test02", + "rtcUid":1000, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + }, + "audioOption":{ + "profileType":"AUDIO_PROFILE_MUSIC_STANDARD" + } + } + ] + } + } + } + } +} +``` + +**场景三:全频道混音 + 画布** + +```json +{ + "services":{ + "cloudTranscoder":{ + "serviceType":"cloudTranscoderV2", + "config":{ + "transcoder":{ + "idleTimeout":180, + "audioInputs":[ + { + "rtc":{ + "rtcChannel":"test01", + "rtcUid": 0, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + } + } + ], + "canvas":{ + "width":960, + "height":480, + "color":0, + "backgroundImage":"https://XXXX.jpg" + }, + "outputs":[ + { + "rtc":{ + "rtcChannel":"test02", + "rtcUid":1000, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + }, + "audioOption":{ + "profileType":"AUDIO_PROFILE_MUSIC_STANDARD" + } + } + ] + } + } + } + } +} +``` + +### HTTP 响应 + +#### 响应头 + +`X-Request-ID`: UUID(通用唯一识别码),用于标识本次请求。 +
    • 如果请求出错,请在日志中打印出该值,排查问题。
    • 如果本次请求的响应状态码不是 2XX,那么响应 header 中可能无该字段。
    + +#### 响应包体 + +如果状态码为 2XX,则请求成功。响应包体包含的字段结构如下图所示: + +![](https://web-cdn.agora.io/docs-files/1664351656358) + +字段含义详见下表: + +| 字段 | 类型 | 描述 | +| :------------------------------------------- | :----------- | :----------------------------------------------------------- | +| taskId | JSON Object | 任务 ID,为 UUID,用于标识本次请求创建的 cloud transcoder。 | +| createTs | Number | 创建云端转码任务时的 Unix 时间戳(秒)。 | +| status | String | 创建任务的运行状态:
  • `"IDLE"`: 任务未开始
  • `"PREPARED"`: 任务已收到开启请求
  • `"STARTING"`: 任务正在开启
  • `"CREATED"`: 任务初始化完成
  • `"STARTED"`: 任务已经启动
  • `"IN_PROGRESS"`: 任务正在进行
  • `"STOPPING"`: 任务正在停止
  • `"STOPPED"`: 任务已经停止
  • `"EXIT"`: 任务正常退出
  • `"FAILURE_STOP"`: 任务异常退出 | +| services | JSON Object | 任务中包含的服务信息。 | +| services.cloudTranscoder | JSON Object | 服务名称。 | +| services.cloudTranscoder.serviceType | String | 服务类型。云端转码:`"cloudTranscoderV2"`。 | +| services.cloudTranscoder.config | JSON Object | 服务参数。 | +| services.cloudTranscoder.config.transcoder | String,必填 | Cloud transcoder 对象。包含的字段及含义请参考请求包体字段及含义。 | +| services.cloudTranscoder.createTs | Number | 创建 cloud transcoder 时的 Unix 时间戳(秒)。 | +| services.cloudTranscoder.status | String | 服务的运行状态:
  • `"serviceIdle"`: 服务未开始
  • `"serviceReady"`: 服务已经就绪
  • `"serviceStarted"`: 服务已经开始
  • `"serviceInProgress"`: 服务正在进行
  • `"serviceCompleted"`: 服务已经停止,任务全部完成
  • `"servicePartialCompleted"`: 服务已经停止,任务部分完成
  • `"serviceValidationFailed"`: 服务参数验证失败
  • `"serviceAbnormal"`: 服务异常退出
  • `"serviceUnknown"`: 服务未知状态 | +| services.cloudTranscoder.message | String | 服务的执行信息,描述服务异常的具体原因。 | +| services.cloudTranscoder.details | JSON Object | 服务的执行细节。 | +| eventHandlers | String | 预留字段。 | +| execution | JSON Object | 预留字段。 | +| execution.workflows | String | 预留字段。 | +| properties | String | 预留字段。 | +| sequenceId | String | 预留字段。 | +| variables | JSON Object | 预留字段。 | +| workflows | JSON Object | 预留字段。 | + +响应包体示例: + +```json +{ + "createTs": 1661324613, + "eventHandlers": {}, + "execution": { + "workflows": {} + }, + "properties": {}, + "sequenceId": "0", + "services": { + "cloudTranscoder": { + "config": {}, + "createTs": 1661324614, + "details": {}, + "message": "", + "serviceType": "cloudTranscoderV2", + "status": "serviceReady" + } + }, + "status": "STARTED", + "taskId": "609f28f2644f1ae1ceb041b7047e3***", + "variables": {}, + "workflows": {} +} +``` + +## Delete:销毁 cloud transcoder + +### HTTP 请求 + +```http +DELETE https://api.agora.io/v1/projects/{appId}/rtsc/cloud-transcoder/tasks/{taskId}?builderToken={tokenName} +``` + +#### 路径参数 + +- `appId`: String 型必填字段。声网为每个开发者提供的 App ID。在声网控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。 +- `taskId`: cloud transcoder 的任务 ID,为 UUID,用于标识本次请求创建的 cloud transcoder。 + +#### 查询参数 + +`builderToken`: String 型必填字段。通过 `Acquire` 方法获取 builderToken 的参数值 `tokenName`。 + +#### 请求头 + +- `Content-Type`: `application/json` +- `Authorization`: 该字段的值需参考[认证说明](https://docs.agora.io/cn/faq/restful_authentication) + +### HTTP 响应 + +#### 响应头 + +`X-Request-ID`: UUID(通用唯一识别码),用于标识本次请求。 +
    • 如果请求出错,请在日志中打印出该值,排查问题。
    • 如果本次请求的响应状态码不是 2XX,那么响应 header 中可能无该字段。
    + +#### 响应包体 + +如果状态码为 2XX,则请求成功。响应包体包含以下字段: + +![](https://web-cdn.agora.io/docs-files/1664351673569) + +字段含义详见下表: + +| 字段 | 类型 | 描述 | +| :------------------------------------------- | :----------- | :----------------------------------------------------------- | +| taskId | JSON Object | 任务 ID,为 UUID,用于标识本次请求创建的 cloud transcoder。 | +| createTs | Number | 创建任务时的 Unix 时间戳(秒)。 | +| status | String | 创建任务的运行状态:
  • `IDLE`: 任务未开始
  • `PREPARED`: 任务已收到开启请求
  • `STARTING`: 任务正在开启
  • `CREATED`: 任务初始化完成
  • `STARTED`: 任务已经启动
  • `IN_PROGRESS`: 任务正在进行
  • `STOPPING`: 任务正在停止
  • `STOPPED`: 任务已经停止
  • `EXIT`: 任务正常退出
  • `FAILURE_STOP`: 任务异常退出 | +| services | JSON Object | 任务中包含的服务信息。 | +| services.cloudTranscoder | JSON Object | 服务名称。 | +| services.cloudTranscoder.serviceType | String | 服务类型。云端转码:`cloudTranscoderV2`。 | +| services.cloudTranscoder.config | JSON Object | 服务参数。 | +| services.cloudTranscoder.config.transcoder | String,必填 | Cloud transcoder 对象。包含的字段及含义请参考请求包体字段及含义。 | +| services.cloudTranscoder.createTs | Number | 创建 cloud transcoder 时的 Unix 时间戳(秒)。 | +| services.cloudTranscoder.status | String | 服务的运行状态:
  • `serviceIdle`: 服务未开始
  • `serviceReady`: 服务已经就绪
  • `serviceStarted`: 服务已经开始
  • `serviceInProgress`: 服务正在进行
  • `serviceCompleted`: 服务已经停止,任务全部完成
  • `servicePartialCompleted`: 服务已经停止,任务部分完成
  • `serviceValidationFailed`: 服务参数验证失败
  • `serviceAbnormal`: 服务异常退出
  • `serviceUnknown`: 服务未知状态 | +| services.cloudTranscoder.message | String | 服务的执行信息,描述服务异常的具体原因。 | +| services.cloudTranscoder.details | JSON Object | 服务的执行细节。 | +| eventHandlers | String | 预留字段。 | +| execution | JSON Object | 预留字段。 | +| execution.workflows | String | 预留字段。 | +| properties | String | 预留字段。 | +| sequenceId | String | 预留字段。 | +| variables | JSON Object | 预留字段。 | +| workflows | JSON Object | 预留字段。 | + +响应包体示例: + +```json +{ + "createTs": 1661324613, + "eventHandlers": {}, + "execution": { + "workflows": {} + }, + "properties": {}, + "sequenceId": "0", + "services": { + "cloudTranscoder": { + "config": {}, + "createTs": 1661324614, + "details": {}, + "message": "OnSlaveServiceStopped", + "serviceType": "cloudTranscoderV2", + "status": "serviceCompleted" + } + }, + "status": "STOPPED", + "taskId": "609f28f2644f1ae1ceb041b7047e3***", + "variables": {}, + "workflows": {} +} +``` + +## Update:更新指定的 cloud transcoder + +### HTTP 请求 + +```http +PATCH https://api.agora.io/v1/projects/{appId}/rtsc/cloud-transcoder/tasks/{taskId}?builderToken={tokenName}&sequenceId={sequenceId}&updateMask=services.cloudTranscoder.config +``` + +#### 路径参数 + +- `appId`: String 型必填字段。声网为每个开发者提供的 App ID。在声网控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。 +- `taskId`: cloud transcoder 的任务 ID,为 UUID,用于标识本次请求创建的 cloud transcoder。 + +#### 查询参数 + +- `builderToken`: String 型必填字段。通过 `Acquire` 方法获取 `builderToken` 的参数值 `tokenName`。 +- `sequenceId`:Number 型必填字段。`Update` 请求的序列号。取值需要大于或等于 0。请确保后一次 `Update` 请求的序列号大于前一次 `Update` 请求的序列号。序列号可以确保声网服务器按照你指定的最新配置来更新 cloud transcoder。 + +>声网推荐你在第一次调用 `Update` 时,将 `sequence` 设置为 `0`。在第二次调用 `Update` 时,将 `sequence` 填 `1`。在第三次调用 `Update` 时,将 `sequence` 填 `2`。依次类推。声网服务器会按照最新 `Update` 请求(即最大的序列号)更新 cloud transcoder。 + +```http +PATCH https://api.agora.io/v1/projects/{appId}/rtsc/cloud-transcoder/tasks/{taskId}?builderToken={tokenName}&sequenceId={sequenceId}&updateMask=services.cloudTranscoder.config +``` + +#### 请求头 + +- `Content-Type`: `application/json` +- `Authorization`: 该字段的值需参考[认证说明](https://docs.agora.io/cn/faq/restful_authentication) + +#### 请求包体 + +请求包体包含字段及含义详见 [Create 请求包体](#create)。 + +### HTTP 响应 + +#### 响应头 + +`X-Request-ID`: UUID(通用唯一识别码),用于标识本次请求。 +
    • 如果请求出错,请在日志中打印出该值,排查问题。
    • 如果本次请求的响应状态码不是 2XX,那么响应 header 中可能无该字段。
    + +#### 响应包体 + +- 如果状态码为 2XX,则请求成功。包体为空。 + +- 如果状态码不为 2XX,请求失败。包体中包含 String 类型的 `message` 字段,描述失败的具体原因。 + + +### 请求示例 + +`Update` 仅支持在以下场景中更新 cloud transcoder: + +- 订阅或取消订阅频道内的主播的音视频流 +新增或删除 `audioInputs[]`、`videoInputs[]` 中的 `rtc` 成员。 +- 更新合图布局中各主播的位置 +修改 `videoInputs[]` 中的 `region` 字段 +- 更新输出音视频的音频配置项、视频配置项 +更新 `outputs[]` 中的 `audioOption`、`videoOption` 字段 + +
  • 你需要全量设置包体中的字段,对于不想要更新的字段,请维持原设置。
  • 除以上列举字段,其余字段均不支持更新。
  • 请按照调用 Create 时设置的场景更新 cloud transcoder,否则会发生未知异常。 + +音视频场景下更新 cloud transcoder 示例代码如下: + + ```json +{ + "services":{ + "cloudTranscoder":{ + "serviceType":"cloudTranscoderV2", + "config":{ + "transcoder":{ + "idleTimeout":300, + "audioInputs":[ + { + "rtc":{ + "rtcChannel":"test", + "rtcUid": 123, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + } + }, + { + "rtc":{ + "rtcChannel":"test01", + "rtcUid":456, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + } + } + ], + "canvas":{ + "width":960, + "height":480, + "color":0, + "backgroundImage":"https://XXXX.jpg", + "fillMode": "FIT" + }, + "waterMarks":[ + { + "imageUrl":"https://XXXX.png", + "region":{ + "x":0, + "y":0, + "width":100, + "height":100, + "zOrder":50 + } + } + ], + "videoInputs":[ + { + "rtc":{ + "rtcChannel":"test01", + "rtcUid":123, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + }, + "placeholderImageUrl":"https://XXXX.jpg", + "region":{ + "x":0, + "y":0, + "width":320, + "height":360, + "zOrder":1 + } + }, + { + "rtc":{ + "rtcChannel":"test01", + "rtcUid":456, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + }, + "placeholderImageUrl":"https://XXXX.jpg", + "region":{ + "x":320, + "y":0, + "width":320, + "height":320, + "zOrder":1 + } + } + ], + "outputs":[ + { + "rtc":{ + "rtcChannel":"test02", + "rtcUid":1000, + "rtcToken":"aab8b8f5a8cd4469a63042fcfafe7***" + }, + "audioOption":{ + "profileType":"AUDIO_PROFILE_MUSIC_STANDARD" + }, + "videoOption":{ + "fps":30, + "codec":"H264", + "bitrate":800, + "width":960, + "height":480, + "lowBitrateHighQuality":false + } + } + ] + } + } + } + } +} +``` + + +## Query:查询 cloud transcoder 状态信息 + +### HTTP 请求 + +```http +GET https://api.agora.io/v1/projects/{appid}/rtsc/cloud-transcoder/tasks/{taskId}?builderToken={tokenName> +``` + +### 路径参数 + +- `appId`: String 型必填字段。声网为每个开发者提供的 App ID。在声网控制台创建一个项目后即可得到一个 App ID。一个 App ID 是一个项目的唯一标识。 +- `taskId`: cloud transcoder 的任务 ID,为 UUID,用于标识本次请求创建的 cloud transcoder。 + +### 查询参数 + +`builderToken`: String 型必填字段。通过 `Acquire` 方法获取 `builderToken` 的参数值 `tokenName`。 + +#### 请求头 + +- `Content-Type`: `application/json` +- `Authorization`: 该字段的值需参考[认证说明](https://docs.agora.io/cn/faq/restful_authentication) + +### HTTP 响应 + +#### 响应头 + +`X-Request-ID`: UUID(通用唯一识别码),用于标识本次请求。 +
    • 如果请求出错,请在日志中打印出该值,排查问题。
    • 如果本次请求的响应状态码不是 2XX,那么响应 header 中可能无该字段。
    + +#### 响应包体 + +响应包体包含以下字段: + +![](https://web-cdn.agora.io/docs-files/1664351715856) + +字段含义详见下表: + +| 字段 | 类型 | 描述 | +| :------------------------------------------- | :----------- | :----------------------------------------------------------- | +| taskId | JSON Object | 任务 ID,为 UUID,用于标识本次请求创建的 cloud transcoder。 | +| createTs | Number | 创建任务时的 Unix 时间戳(秒)。 | +| status | String | 创建任务的运行状态:
  • `IDLE`: 任务未开始
  • `PREPARED`: 任务已收到开启请求
  • `STARTING`: 任务正在开启
  • `CREATED`: 任务初始化完成
  • `STARTED`: 任务已经启动
  • `IN_PROGRESS`: 任务正在进行
  • `STOPPING`: 任务正在停止
  • `STOPPED`: 任务已经停止
  • `EXIT`: 任务正常退出
  • `FAILURE_STOP`: 任务异常退出 | +| services | JSON Object | 任务中包含的服务信息。 | +| services.cloudTranscoder | JSON Object | 服务名称。 | +| services.cloudTranscoder.serviceType | String | 服务类型。云端转码:`cloudTranscoderV2`。 | +| services.cloudTranscoder.config | JSON Object | 服务参数。 | +| services.cloudTranscoder.config.transcoder | String,必填 | Cloud transcoder 对象。包含的字段及含义请参考请求包体字段及含义。 | +| services.cloudTranscoder.createTs | Number | 创建 cloud transcoder 时的 Unix 时间戳(秒)。 | +| services.cloudTranscoder.status | String | 服务的运行状态:
  • `serviceIdle`: 服务未开始
  • `serviceReady`: 服务已经就绪
  • `serviceStarted`: 服务已经开始
  • `serviceInProgress`: 服务正在进行
  • `serviceCompleted`: 服务已经停止,任务全部完成
  • `servicePartialCompleted`: 服务已经停止,任务部分完成
  • `serviceValidationFailed`: 服务参数验证失败
  • `serviceAbnormal`: 服务异常退出
  • `serviceUnknown`: 服务未知状态 | +| services.cloudTranscoder.message | String | 服务的执行信息,描述服务异常的具体原因。 | +| services.cloudTranscoder.details | JSON Object | 服务的执行细节。 | +| eventHandlers | String | 预留字段。 | +| execution | JSON Object | 预留字段。 | +| execution.workflows | String | 预留字段。 | +| properties | String | 预留字段。 | +| sequenceId | String | 预留字段。 | +| variables | JSON Object | 预留字段。 | +| workflows | JSON Object | 预留字段。 | + +响应包体示例: + +```json +{ + "createTs": 1661420011, + "eventHandlers": {}, + "execution": { + "workflows": {} + }, + "properties": {}, + "sequenceId": "0", + "services": { + "cloudTranscoder": { + "config": {}, + "createTs": 1661420011, + "message": "OnSlaveServiceQueryUpdated", + "serviceType": "cloudTranscoderV2", + "status": "serviceInProgress" + } + }, + "status": "IN_PROGRESS", + "taskId": "c0077139e34d0949c719189a393aa7c0", + "variables": {}, + "workflows": {} +} +``` + + +## 状态码汇总表 + +- 如果状态码为 `2XX`,则请求成功。 +- 如果状态码不为 `2XX`,则请求失败。请根据对应的响应包体中的 `message` 字段内容排查问题。 + +| 状态码 | 含义 | +| :---------------------- | :----------------------------------------------------------- | +| 200 OK | 请求成功。 | +| 201 Created | 任务已经在进行中 ,请勿用同一个 builderToken 重复开启任务。 | +| 202 Accepted | 服务端已经收到任务请求,但未执行完成。请通过 `Query` 方法查询执行状态。 | +| 400 Bad Request | 请求的语法错误(如参数错误)。如果你填入的 `appid` 没有开通云端录制权限,也会返回 `400`,请结合响应报文的 `message` 字段进行处理。 | +| 401 Unauthorized | Authorization 无效。 | +| 403 Forbidden | 你的 App ID 尚未开通 cloud transcoder,请联系我们。 | +| 404 Not Found | 找不到 cloud transcoder。 | +| 409 Conflict | 已经存在使用相同 `instanceId` 的 cloud transcoder 任务。如果你想创建新的 cloud transcoder,请先将旧的 cloud transcoder 删除。 | +| 429 Too Many Requests | 请求速率超过上限。 | +| 500 Unknown |声网服务器内部错误,请联系我们。 | +| 501 Not Implemented |该方法未实现。 | +| 503 Service Unavailable |声网服务器暂时超载或在临时维护中。请使用重试机制或联系我们。 | +| 504 Gateway Timeout |声网服务器内部错误,充当网关或代理的服务器未从上游服务器获取请求,上游服务器已关闭。请联系我们。 | + +## 注意事项 + +本节总结使用云端转码 RESTful API 的重要注意事项。 + +- 请不要对响应报文包体里的 `message` 字段的内容做任何逻辑,处理如果请求失败请结合状态码排查问题。 +- `202` 的状态码仅表示服务端已经收到任务请求,但不代表执行完成,需要继续通过 `Query` 方法查询执行状态来判断任务是否执行完成。 +- 收到 `404` 的状态码后,如果 `Create` 请求已返回成功且没有主动调用 `Delete` 方法,或者 cloud transcoder 的空闲状态超过请求参数中的 `idleTimeout` 字段,建议采取退避算法(例如间隔 5 秒、10 秒、15 秒)调用 `Query` 方法进行确认。 +- 收到 `5xx` 的响应状态码后,一般是服务端在响应的过程中出现了问题,建议采取退避算法(例如间隔 5 秒、10 秒、15 秒)调用 `Query` 请求进行确认。 \ No newline at end of file diff --git a/markdown/cloud-transcoder/overview.md b/markdown/cloud-transcoder/overview.md new file mode 100644 index 00000000000..f77d01e28da --- /dev/null +++ b/markdown/cloud-transcoder/overview.md @@ -0,0 +1,32 @@ +## 概述 + +声网针对**音视频直播**场景提供云端转码服务,支持在服务端拉取单个或多个主播的音视频源流,进行混音、合图、转码等处理后,发布到声网 RTC 频道中,以供观众端订阅。使用云端转码服务后,观众无需订阅多个主播的音视频流,可大幅节省下行带宽压力和客户端设备性能消耗。 + +## 技术原理 + +下图展示了使用声网服务来实现云端转码的工作流程。 + +![](https://web-cdn.agora.io/docs-files/1668165007849) + +你可以通过你的业务服务器发起云端转码请求,云端转码服务会从 RTC 频道中订阅主播的音视频流,并进行混音、合图或转码处理,再将处理后的音视频流发布到 RTC 频道中。观众端可根据实际场景选择订阅主播源流或转码处理后的音视频流: + +- 单个主播场景:可订阅主播源流或转码后的音视频流。 +- 多个主播连麦场景:订阅多个主播混音、合图、转码后的音视频流。 + +## 服务优势 + +### 能耗低 + +当观众端设备性能较差,无法在端上同时处理多路高清音视频流的编解码、渲染时,可通过该服务进行转码处理后再发布到 RTC 频道,以降低端上性能消耗。 + +### 低码率 + +观众端在下行网络较差时订阅多路主播视频流或单路主播高清视频流时,可通过该服务进行混音、合图、并转码处理成低码率流后再发布到 RTC 频道,从而提升视频流畅度。 + +### 兼容性 + +支持标准 H.264 和 VP8 编码。当主播使用设备平台为 Native,观众使用设备平台为 Web,可通过云端转码服务将主播源流转为 VP8 编码,提升 Web 端观众端用户体验。 + +## 计费说明 + +该服务目前处于公测阶段,可免费使用。 \ No newline at end of file diff --git a/markdown/cloud-transcoder/webhook.md b/markdown/cloud-transcoder/webhook.md new file mode 100644 index 00000000000..c5479bff9d0 --- /dev/null +++ b/markdown/cloud-transcoder/webhook.md @@ -0,0 +1,270 @@ +## 概述 + +声网消息通知服务可以将**云端转码**业务中的发生的一些事件以 HTTPS 请求的方式通知到你的服务器。 + +![](https://web-cdn.agora.io/docs-files/1675668130158) + +## 开通服务 + +使用声网消息通知服务前需要申请开通并进行配置,关于如何**开通服务**以及**消息通知回调的数据格式**详见[消息通知服务](https://docs.agora.io/cn/AgoraPlatform/ncs)。 + +## 事件 + +消息通知服务器可以通知云端转码业务下的四种事件: + +- 创建云端转码事件 +- 云端转码配置更新事件 +- 云端转码状态变化事件 +- 停止云端转码事件 + +### 事件公共字段 + +云端转码事件 `payload` 包含以下公共字段: + +- `taskId`:String 型字段。任务 ID。它是声网服务器生成的一个 UUID(通用唯一识别码),标识一个已创建的 cloud transcoder。 + +- `instanceId`:String 型可选字段。调用 `Acquire` 时为本次云端转码指定的实例 ID。 + +- `sequence`:Number 类型,消息序列号,从 0 开始计数。消息可能乱序到达或者丢失重发,可以通过该参数标识消息。 + +- `sendts`:Number 类型, 事件发生的时间 (UTC 时间)。Unix 时间戳,精确到毫秒。 + + - `serviceScene`:服务场景。云端转码的服务场景为 `rtsc/cloud-transcoder`。 + - `details`: JSON Object 型字段。消息内容,详见具体事件。 + + + +### 开始云端转码事件 + +当你调用 `Create` 成功创建一个 cloud transcoder 时,消息通知服务器会向你的服务器通知该事件。 + +`eventType` 为 110(`cloud_transcoder_started`),`payload` 示例如下: + +```json +{ + "taskId":"1234", + "instanceId":"123", + "sequence":123, + "sendts":1656573243385, + "serviceScene":"rtsc/cloud-transcoder", + "details":{ + "event":"cloud_transcoder_started", + "state":"Transcoder success", + "createTs":1658112464000, + "transcoder":{ + "inputs":[ + { + "rtcChannel":"test01", + "rtcUid":123, + "audio":true, + "video":false + }, + { + "rtcChannel":"test01", + "rtcUid":456, + "audio":true, + "video":true + } + ], + "outputs":[ + { + "rtcChannel":"test01", + "rtcUid":1000, + "audio":true, + "video":true + } + ], + "userConfigDetail":"{XXXX}" + } + } +} +``` + +`details `包含如下字段: + +- `event`: String 型字段。回调事件类型。`cloud_transcoder_started` 表示成功创建一个 cloud transcoder。 + +- `state`: String 型字段,云端转码的状态。`Transcoder success 表示`成功创建一个 cloud transcoder,开始云端转码。 + + - `createTs`:Number 型字段。创建 cloud transcoder 时的 Unix 时间戳(秒)。 + + - `userConfigDetail`:String 类型。请求包体中的配置内容(`cloudTranscoder.config`)。 + + - `transcoder`:JSON Object 型字段。Cloud transcoder 的输入和输出配置。 + + - `inputs`[]:JSON Object 型字段。Cloud transcoder 的音视频输入源配置。 + + - `rtcChannel`:String 型字段。音视频输入源所属的 RTC 频道名。 + + - `rtcUid`:Number 型字段。音视频输入源所对应的 UID。 + - ` audio`:Bool 型字段。是否有音频输入源: + - `true`:有音频输入源。 + - `false`:无音频输入源。 + - `video`:Bool 型字段。是否有视频输入源: + - `true`:有视频输入源。 + - `false`:无视频输入源。 + - `outputs`[]:JSON Object 型字段。Cloud transcoder 的音视频输出配置。 + + - `rtcChannel`:String 型字段。输出音视频所属的 RTC 频道名。 + + - `rtcUid`:Number 型字段。输出音视频所对应的 UID。 + + - `audio`:Bool 型字段。是否有音频输出: + - `true`:有音频输出。 + - `false`:无音频输出。 + - `video`:Bool 型字段。是否有视频输出: + - `true`:有视频输出。 + - `false`:无视频输出。 + +### 云端转码配置更新事件 + +当你调用 `Update` 成功更新一个 cloud transcoder 配置时,消息通知服务器会向你的服务器通知该事件。 + +`eventType` 为 113(`cloud_transcoder_updated`)。 + +```json +{ + "taskId": "1234", + "instanceId": "123", + "sequence": 123, + "sendts": 1656573243385, + "serviceScene": "rtsc/cloud-transcoder", + "details": { + "event": "cloud_transcoder_updated", + "state": "running", + "createTs": 1658112464000, + "updateTs": 1658112464000, + "transcoder": { + "inputs": [ + { + "rtcChannel": "test01", + "rtcUid": 123, + "audio": true, + "video": false + }, + { + "rtcChannel": "test01", + "rtcUid": 456, + "audio": true, + "video": true + } + ], + "outputs": [ + { + "rtcChannel": "test01", + "rtcUid": 1000, + "audio": true, + "video": true + } + ], + "userConfigDetail": "json_string" + } + } +} +``` + +`details `包含如下字段: + +- `event`: String 型字段。回调事件类型。`cloud_transcoder_started` 表示成功创建一个 cloud transcoder。 + +- `state`: String 型字段,云端转码的状态。`running 表示 c`loud transcoder 正常运行中,正在进行云端转码。 + +- `createT`s:Number 型字段。创建 cloud transcoder 时的 Unix 时间戳(秒)。 + +- `updateTs`:Number 型字段。更新 cloud transcoder 配置时的 Unix 时间戳(秒)。 + +- `userConfigDetail`:String 类型。请求包体中的配置内容(`cloudTranscoder.config`)。 + +- `transcoder`:JSON Object 型字段。Cloud transcoder 的输入和输出配置。 + + - `inputs`[]:JSON Object 型字段。Cloud transcoder 的音视频输入源配置。 + + - `rtcChannel`:String 型字段。音视频输入源所属的 RTC 频道名。 + + - `rtcUid`:Number 型字段。音视频输入源所对应的 UID。 + + - `audio`:Bool 型字段。是否有音频输入源: + + - `true`:有音频输入源。 + - `false`:无音频输入源。 + + - `video`:Bool 型字段。是否有视频输入源: + + - `true`:有视频输入源。 + - `false`:无视频输入源。 + + - `outputs`[]:JSON Object 型字段。Cloud transcoder 的音视频输出配置。 + + - `rtcChannel`:String 型字段。输出音视频所属的 RTC 频道名。 + + - `rtcUid`:Number 型字段。输出音视频所对应的 UID。 + + - `audio`:Bool 型字段。是否有音频输出: + + - `true`:有音频输出。 + - `false`:无音频输出。 + + - `video`:Bool 型字段。是否有视频输出: + + - `true`:有视频输出。 + - `false`:无视频输出。 + +### 云端转码状态变化事件 + +成功创建一个 cloud transcoder 后,当 cloud transcoder 运行状态改变时,消息通知服务器会向你的服务器通知该事件。 + +`eventType` 为 112(`cloud_transcoder_status`),`payload` 示例如下: + +```json +{ + "taskId": "1234", + "instanceId": "123", + "sequence": 123, + "sendts": 1656573243385, + "serviceScene": "rtsc/cloud-transcoder", + "details": { + "event": "cloud_transcoder_status", + "state": "running", + "createTs": 1658112464000, + "updateTs": 1658112464000 + } +} +``` + +`details `包含如下字段: + +- `event`: String 型字段。回调事件类型。`cloud_transcoder_started` 表示成功创建一个 cloud transcoder。 +- `state`: String 型字段,云端转码的状态。`running` 表示 cloud transcoder 正常运行中,正在进行云端转码。 +- `createTs`:Number 型字段。创建 cloud transcoder 时的 Unix 时间戳(秒)。 +- `updateTs`:Number 型字段。更新 cloud transcoder 配置时的 Unix 时间戳(秒)。 + + + +### 停止云端转码事件 + +当一个 cloud transcoder 被销毁而停止云端转码时,消息通知服务器会向你的服务器通知该事件。 + +`eventType` 为 111(`cloud_transcoder_stopped`),`payload` 示例如下: + +``` +{ + "taskId": "1234", + "instanceId": "123", + "sequence": 123, + "sendts": 1656573243385, + "serviceScene": "rtsc/cloud-transcoder", + "details": { + "event": "cloud_transcoder_stopped", + "stopReason": "Stop request", + "createTs": 1658112464000, + "updateTs": 1658112464000 + } +} +``` + +`details `包含如下字段: + +- `event`: String 型字段。回调事件类型。`cloud_transcoder_started` 表示成功创建一个 cloud transcoder。 +- `stopReason`: String 型字段,云端转码停止的原因。你可以根据该字段排查云端转码异常停止的原因。 +- `createTs`:Number 型字段。创建 cloud transcoder 时的 Unix 时间戳(秒)。 +- `updateTs`:Number 型字段。更新 cloud transcoder 配置时的 Unix 时间戳(秒)。 \ No newline at end of file