From d56f01cc687cda9535c2d996f14a934acc3c2d18 Mon Sep 17 00:00:00 2001 From: seymourtang Date: Fri, 15 Nov 2024 12:49:36 +0800 Subject: [PATCH] feat:Implement of rest client api --- .github/workflows/maven.yml | 31 + .gitignore | 45 + .pre-commit-config.yaml | 5 + Makefile | 9 + README.md | 295 ++- agora-rest-client-core/assembly.xml | 21 + agora-rest-client-core/pom.xml | 239 ++ .../io/agora/rest/AgoraVersion.java | 9 + .../java/io/agora/rest/AgoraException.java | 22 + .../main/java/io/agora/rest/AgoraService.java | 34 + .../io/agora/rest/core/AgoraProperty.java | 89 + .../agora/rest/core/BasicAuthCredential.java | 36 + .../main/java/io/agora/rest/core/Codec.java | 10 + .../main/java/io/agora/rest/core/Context.java | 11 + .../java/io/agora/rest/core/Credential.java | 10 + .../io/agora/rest/core/DefaultContext.java | 79 + .../rest/core/DefaultDomainDNSResolver.java | 73 + .../agora/rest/core/DefaultErrorMapper.java | 82 + .../io/agora/rest/core/DomainDNSResolver.java | 9 + .../java/io/agora/rest/core/DomainPool.java | 104 + .../java/io/agora/rest/core/ErrorMapper.java | 11 + .../io/agora/rest/core/HttpClientFactory.java | 43 + .../java/io/agora/rest/core/HttpProperty.java | 134 + .../java/io/agora/rest/core/JsonCodec.java | 68 + .../java/io/agora/rest/core/RegionArea.java | 57 + .../exception/AgoraBadGatewayException.java | 7 + .../exception/AgoraBadRequestException.java | 9 + .../exception/AgoraForbiddenException.java | 9 + .../AgoraGatewayTimeoutException.java | 7 + .../AgoraInternalServerErrorException.java | 7 + .../AgoraInvalidArgumentException.java | 9 + .../rest/exception/AgoraJsonException.java | 13 + .../exception/AgoraNeedRetryException.java | 9 + .../exception/AgoraNotFoundException.java | 9 + .../AgoraServiceUnavailableException.java | 7 + .../AgoraTooManyRequestException.java | 9 + .../exception/AgoraUnauthorizedException.java | 9 + .../rest/exception/AgoraUnknownException.java | 9 + .../cloudrecording/CloudRecordingApi.java | 84 + .../rest/services/cloudrecording/README.md | 299 +++ .../api/AcquireResourceAPI.java | 22 + .../cloudrecording/api/QueryResourceAPI.java | 38 + .../cloudrecording/api/StartResourceAPI.java | 54 + .../cloudrecording/api/StopResourceAPI.java | 24 + .../cloudrecording/api/UpdateResourceAPI.java | 39 + .../api/req/AcquireResourceReq.java | 170 ++ .../api/req/StartResourceReq.java | 2256 +++++++++++++++++ .../api/req/StopResourceReq.java | 133 + .../api/req/UpdateLayoutResourceReq.java | 497 ++++ .../api/req/UpdateResourceReq.java | 761 ++++++ .../api/res/AcquireResourceRes.java | 47 + .../api/res/QueryResourceRes.java | 724 ++++++ .../api/res/StartResourceRes.java | 59 + .../api/res/StopResourceRes.java | 59 + .../api/res/UpdateLayoutResourceRes.java | 59 + .../api/res/UpdateResourceRes.java | 59 + .../enums/CloudRecordingModeEnum.java | 17 + .../individual/IndividualScenario.java | 158 ++ .../AcquireIndividualResourceClientReq.java | 101 + .../StartIndividualRecordingClientReq.java | 155 ++ ...eIndividualRecordingResourceClientReq.java | 47 + .../QueryIndividualRecordingResourceRes.java | 119 + ...alRecordingVideoScreenshotResourceRes.java | 119 + .../scenario/mix/MixScenario.java | 149 ++ .../AcquireMixRecordingResourceClientReq.java | 101 + .../StartMixRecordingResourceClientReq.java | 101 + ...teLayoutMixRecordingResourceClientReq.java | 157 ++ .../UpdateMixRecordingResourceClientReq.java | 47 + ...QueryMixHLSAndMP4RecordingResourceRes.java | 119 + .../res/QueryMixHLSRecordingResourceRes.java | 119 + .../scenario/web/WebScenario.java | 116 + .../AcquireWebRecordingResourceClientReq.java | 101 + .../StartWebRecordingResourceClientReq.java | 83 + .../UpdateWebRecordingResourceClientReq.java | 65 + .../web/res/QueryWebRecordingResourceRes.java | 119 + .../java/io/agora/rest/utils/ByteUtils.java | 12 + .../rest/core/DomainDNSResolverTest.java | 26 + examples/cloudrecording/README.md | 65 + examples/cloudrecording/pom.xml | 54 + .../rest/examples/cloudrecording/Main.java | 149 ++ .../cloudrecording/scenario/BaseScenario.java | 43 + .../scenario/IndividualRecordingScenario.java | 925 +++++++ .../scenario/MixRecordingScenario.java | 447 ++++ .../scenario/WebRecordingScenario.java | 396 +++ .../src/main/resources/logback.xml | 12 + pom.xml | 22 + 86 files changed, 11166 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/maven.yml create mode 100644 .pre-commit-config.yaml create mode 100644 Makefile create mode 100644 agora-rest-client-core/assembly.xml create mode 100644 agora-rest-client-core/pom.xml create mode 100644 agora-rest-client-core/src/main/java-templates/io/agora/rest/AgoraVersion.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/AgoraException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/AgoraService.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/AgoraProperty.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/BasicAuthCredential.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/Codec.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/Context.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/Credential.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultContext.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultDomainDNSResolver.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultErrorMapper.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/DomainDNSResolver.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/DomainPool.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/ErrorMapper.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/HttpClientFactory.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/HttpProperty.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/JsonCodec.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/core/RegionArea.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraBadGatewayException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraBadRequestException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraForbiddenException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraGatewayTimeoutException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraInternalServerErrorException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraInvalidArgumentException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraJsonException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraNeedRetryException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraNotFoundException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraServiceUnavailableException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraTooManyRequestException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraUnauthorizedException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraUnknownException.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/CloudRecordingApi.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/README.md create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/AcquireResourceAPI.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/QueryResourceAPI.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/StartResourceAPI.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/StopResourceAPI.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/UpdateResourceAPI.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/AcquireResourceReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/StartResourceReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/StopResourceReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/UpdateLayoutResourceReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/UpdateResourceReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/AcquireResourceRes.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/QueryResourceRes.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/StartResourceRes.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/StopResourceRes.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/UpdateLayoutResourceRes.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/UpdateResourceRes.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/enums/CloudRecordingModeEnum.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/IndividualScenario.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/AcquireIndividualResourceClientReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/StartIndividualRecordingClientReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/UpdateIndividualRecordingResourceClientReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/res/QueryIndividualRecordingResourceRes.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/res/QueryIndividualRecordingVideoScreenshotResourceRes.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/MixScenario.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/AcquireMixRecordingResourceClientReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/StartMixRecordingResourceClientReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/UpdateLayoutMixRecordingResourceClientReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/UpdateMixRecordingResourceClientReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/res/QueryMixHLSAndMP4RecordingResourceRes.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/res/QueryMixHLSRecordingResourceRes.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/WebScenario.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/AcquireWebRecordingResourceClientReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/StartWebRecordingResourceClientReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/UpdateWebRecordingResourceClientReq.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/res/QueryWebRecordingResourceRes.java create mode 100644 agora-rest-client-core/src/main/java/io/agora/rest/utils/ByteUtils.java create mode 100644 agora-rest-client-core/src/test/java/io/agora/rest/core/DomainDNSResolverTest.java create mode 100644 examples/cloudrecording/README.md create mode 100644 examples/cloudrecording/pom.xml create mode 100644 examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/Main.java create mode 100644 examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/BaseScenario.java create mode 100644 examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/IndividualRecordingScenario.java create mode 100644 examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/MixRecordingScenario.java create mode 100644 examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/WebRecordingScenario.java create mode 100644 examples/cloudrecording/src/main/resources/logback.xml create mode 100644 pom.xml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..8b8d471 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,31 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Java CI with Maven + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 8 + uses: actions/setup-java@v4 + with: + java-version: '8' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml -DskipTests diff --git a/.gitignore b/.gitignore index 524f096..74ee21e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ # Compiled class file *.class @@ -22,3 +57,13 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* replay_pid* + +### Mac OS ### +.DS_Store + +### exlude .env +.env + +.idea + +bin \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..3b2f918 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +repos: + - repo: https://github.com/gitleaks/gitleaks + rev: v8.21.2 + hooks: + - id: gitleaks diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3ac2d0b --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +.PHONY: install + +install: + @echo "Installing..." + @mvn clean install -DskipTests +package: + @echo "Packaging..." + @mvn clean package -DskipTests + diff --git a/README.md b/README.md index 2099ac1..c1548b4 100644 --- a/README.md +++ b/README.md @@ -1 +1,294 @@ -# agora-rest-client-java \ No newline at end of file +# Agora REST Client for Java + +[![Agora REST Client for Java](https://img.shields.io/maven-central/v/io.agora/agora-rest-client-core.svg?colorB=brightgreen)](https://mvnrepository.com/artifact/io.agora/agora-rest-client-core) +

+GitHub License +Java CI with Maven +GitHub +GitHub Issues or Pull Requests +

+ +`agora-rest-client-java`是用 Java 语言编写的一个开源项目,专门为 Agora REST API 设计。它包含了 Agora 官方提供的 REST +API 接口的包装和内部实现,可以帮助开发者更加方便的集成服务端 Agora REST API。 + +> 注意: 该 SDK 经过一些测试以确保其基本功能正常运作。然而,由于软件开发的复杂性,我们无法保证它是完全没有缺陷的。 +> +>该SDK目前可能存在一些潜在的 BUG 或不稳定性。我们鼓励社区的开发者和用户积极参与,共同改进这个项目。 + +## 特性 + +* 封装了 Agora REST API 的请求和响应处理,简化与 Agora REST API 的通信流程 +* 当遇到 DNS 解析失败、网络错误或者请求超时等问题的时候,提供了自动切换最佳域名的能力,以保障请求 REST API 服务的可用性 +* 提供了易于使用的 API,可轻松地实现调用 Agora REST API 的常见功能,如开启云录制、停止云录制等 +* 基于 Java 语言,具有异步性、并发性和可扩展性 + +## 支持的服务 + +* [云端录制 Cloud Recording ](./agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/README.md) + +## 环境准备 + +* [Java 1.8 或以上版本](https://www.java.com) +* 在声网 [Console 平台](https://console.shengwang.cn/)申请的 App ID 和 App Certificate +* 在声网 [Console 平台](https://console.shengwang.cn/)的 Basic Auth 认证信息 +* 在声网 [Console 平台](https://console.shengwang.cn/)开启相关的服务能力 + +## 安装 + +首先,在`poml.xml`文件中添加 REST Client 依赖: + +```xml + + io.agora + agora-rest-client-core + 0.1.2-BETA + +``` + +## 使用示例 + +以调用云录制服务为例: + +```java +package com.company.example; + +import io.agora.rest.AgoraException; +import io.agora.rest.AgoraService; +import io.agora.rest.core.AgoraProperty; +import io.agora.rest.core.BasicAuthCredential; +import io.agora.rest.core.Credential; +import io.agora.rest.core.RegionArea; +import io.agora.rest.services.cloudrecording.api.req.StartResourceReq; +import io.agora.rest.services.cloudrecording.api.res.AcquireResourceRes; +import io.agora.rest.services.cloudrecording.api.res.StartResourceRes; +import io.agora.rest.services.cloudrecording.api.res.StopResourceRes; +import io.agora.rest.services.cloudrecording.scenario.mix.req.AcquireMixRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.mix.req.StartMixRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.mix.res.QueryMixHLSAndMP4RecordingResourceRes; + +import java.util.Arrays; +import java.util.Collections; + +public class Main { + private static String appId = ""; + + private static String cname = ""; + + private static String uid = ""; + + private static String username = ""; + + private static String password = ""; + + private static String token = ""; + + private static String accessKey = ""; + + private static String secretKey = ""; + + private static Integer region = 0; // + + private static String bucket = ""; + + private static Integer vendor = 0; // + + public static void main(String[] args) throws Exception { + + Credential basicAuthCredential = new BasicAuthCredential(username, password); + + // Initialize AgoraService + AgoraService agoraService = new AgoraService( + AgoraProperty.builder() + .appId(appId) + .credential(basicAuthCredential) + // Specify the region where the server is located. + // Optional values are CN, NA, EU, AP, and the client will automatically + // switch to use the best domain name according to the configured region + .regionArea(RegionArea.CNRegionArea) + .build() + ); + + + AcquireResourceRes acquireResourceRes; + + // Acquire resource + try { + acquireResourceRes = agoraService.cloudRecording() + .mixScenario() + .acquire(cname, uid, AcquireMixRecordingResourceClientReq.builder() + .build()) + .block(); + } catch (AgoraException e) { + System.out.printf("agora error:%s", e.getMessage()); + return; + } catch (Exception e) { + System.out.printf("unknown error:%s", e.getMessage()); + return; + } + + // Check if the response is null + if (acquireResourceRes == null || acquireResourceRes.getResourceId() == null) { + System.out.println("failed to get resource"); + return; + } + + + System.out.printf("resourceId:%s", acquireResourceRes.getResourceId()); + + System.out.println("acquire resource success"); + + // Define storage config + StartResourceReq.StorageConfig storageConfig = StartResourceReq.StorageConfig.builder() + .accessKey(accessKey) + .secretKey(secretKey) + .bucket(bucket) + .vendor(vendor) + .region(region) + .build(); + + // Define start resource request + StartMixRecordingResourceClientReq startResourceReq = StartMixRecordingResourceClientReq.builder() + .token(token) + .recordingConfig(StartResourceReq.RecordingConfig.builder() + .channelType(1) + .streamTypes(2) + .maxIdleTime(30) + .audioProfile(2) + .transcodingConfig(StartResourceReq.TranscodingConfig.builder() + .width(640) + .height(480) + .fps(15) + .bitrate(800) + .mixedVideoLayout(0) + .backgroundColor("#000000") + .build()) + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .build()) + .recordingFileConfig(StartResourceReq.RecordingFileConfig.builder() + .avFileType(Arrays.asList("hls", "mp4")) + .build()) + .storageConfig(storageConfig) + .build(); + + + StartResourceRes startResourceRes; + + // Start resource + try { + startResourceRes = agoraService.cloudRecording() + .mixScenario() + .start(cname, uid, + acquireResourceRes.getResourceId(), + startResourceReq) + .block(); + + } catch (AgoraException e) { + System.out.printf("agora error:%s", e.getMessage()); + return; + } catch (Exception e) { + System.out.printf("unknown error:%s", e.getMessage()); + return; + } + + // Check if the response is null + if (startResourceRes == null || startResourceRes.getSid() == null) { + System.out.println("failed to start resource"); + return; + } + + System.out.printf("sid:%s", startResourceRes.getSid()); + + System.out.println("start resource success"); + + Thread.sleep(3000); + + QueryMixHLSAndMP4RecordingResourceRes queryResourceResp; + + // Query resource + try { + queryResourceRes = agoraService.cloudRecording() + .mixScenario() + .queryHLSAndMP4(startResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + + } catch (AgoraException e) { + System.out.printf("agora error:%s", e.getMessage()); + return; + } catch (Exception e) { + System.out.printf("unknown error:%s", e.getMessage()); + return; + } + + if (queryResourceRes == null || queryResourceResp.getServerResponse() == null) { + System.out.println("failed to query resource"); + return; + } + + System.out.println("query resource success"); + + Thread.sleep(3000); + + StopResourceRes stopResourceRes; + + // Stop resource + try { + stopResourceRes = agoraService.cloudRecording() + .mixScenario() + .stop(cname, uid, startResourceRes.getResourceId(), startResourceRes.getSid(), + true) + .block(); + } catch (AgoraException e) { + System.out.printf("agora error:%s", e.getMessage()); + return; + } catch (Exception e) { + System.out.printf("unknown error:%s", e.getMessage()); + return; + } + + // Check if the response is null + if (stopResourceRes == null || stopResourceRes.getSid() == null) { + System.out.println("failed to stop resource"); + } else { + System.out.println("stop resource success"); + } + + } +} + + +``` + +更多的示例可在 [Example](./examples) 查看 + +## 集成遇到困难,该如何联系声网获取协助 + +> 方案1:如果您已经在使用声网服务或者在对接中,可以直接联系对接的销售或服务 +> +> 方案2:发送邮件给 [support@agora.io](mailto:support@agora.io) 咨询 +> +> 方案3:扫码加入我们的微信交流群提问 +> +> +--- + +## 贡献 + +本项目欢迎并接受贡献。如果您在使用中遇到问题或有改进建议,请提出 issue 或向我们提交 Pull Request。 + +# SemVer 版本规范 + +本项目使用语义化版本号规范 (SemVer) 来管理版本。格式为 MAJOR.MINOR.PATCH。 + +* MAJOR 版本号表示不向后兼容的重大更改。 +* MINOR 版本号表示向后兼容的新功能或增强。 +* PATCH 版本号表示向后兼容的错误修复和维护。 + 有关详细信息,请参阅 [语义化版本](https://semver.org/lang/zh-CN/) 规范。 + +## 参考 + +* [Agora API 文档](https://doc.shengwang.cn/) + +## 许可证 + +该项目使用MIT许可证,详细信息请参阅LICENSE文件。 diff --git a/agora-rest-client-core/assembly.xml b/agora-rest-client-core/assembly.xml new file mode 100644 index 0000000..06cf7b6 --- /dev/null +++ b/agora-rest-client-core/assembly.xml @@ -0,0 +1,21 @@ + + jar-with-dependencies + + zip + + false + + + ${project.build.directory} + + ${project.build.finalName}-javadoc.jar + ${project.build.finalName}-sources.jar + ${project.build.finalName}.jar + ${project.build.finalName}.pom + + / + + + \ No newline at end of file diff --git a/agora-rest-client-core/pom.xml b/agora-rest-client-core/pom.xml new file mode 100644 index 0000000..429db9a --- /dev/null +++ b/agora-rest-client-core/pom.xml @@ -0,0 +1,239 @@ + + + 4.0.0 + io.agora + + agora-rest-client-core + 0.1.2.1-BETA + Agora REST Client for Java + Agora REST Client + https://github.com/AgoraIO-Community/agora-rest-client-java + + jar + + + + Agora IO Community License + https://github.com/AgoraIO-Community/agora-rest-client-java/blob/master/LICENSE + + + + + + Agora IO Community + https://github.com/AgoraIO-Community + https://www.agora.io + + + + + scm:git:https://github.com/AgoraIO-Community/agora-rest-client-java.git + scm:git:https://github.com/AgoraIO-Community/agora-rest-client-java.git + + https://github.com/AgoraIO-Community/agora-rest-client-java + + + + 3.1 + 8 + 8 + 3.3.1 + 3.1.0 + 3.1.2 + 3.3.0 + UTF-8 + 2.0.16 + 2.18.1 + 5.11.3 + 1.3.14 + 3.6.2 + 1.1.24 + + + + + + ch.qos.logback + logback-classic + ${logback.version} + test + + + ch.qos.logback + logback-core + ${logback.version} + test + + + org.slf4j + slf4j-api + ${slf4j.version} + + + io.projectreactor + reactor-core + ${reactor-core.version} + + + io.projectreactor.netty + reactor-netty-core + ${reactor-netty-core.version} + + + io.projectreactor.netty + reactor-netty-http + ${reactor-netty-core.version} + + + io.netty + netty-resolver-dns-native-macos + 4.1.114.Final + runtime + osx-aarch_64 + + + + org.junit.jupiter + junit-jupiter + ${junit.version} + test + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + + + + + .. + + LICENSE + + META-INF + + + src + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.plugin.version} + + ${maven.compiler.plugin.source} + ${maven.compiler.plugin.target} + UTF-8 + + + + org.apache.maven.plugins + maven-source-plugin + ${maven.source.plugin.version} + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven.javadoc.plugin.version} + + -Xdoclint:none + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-dependency-plugin + ${maven.dependency.plugin.version} + + + copy-pom + package + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + pom + ${project.build.directory} + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + ${maven.assembly.plugin.version} + + + assembly.xml + + false + + + + make-assembly + package + + single + + + + + + org.codehaus.mojo + templating-maven-plugin + 1.0.0 + + + filter-src + + filter-sources + + + src/main/java-templates + + ${project.build.directory}/generated-sources/java-templates + + + + + + + + diff --git a/agora-rest-client-core/src/main/java-templates/io/agora/rest/AgoraVersion.java b/agora-rest-client-core/src/main/java-templates/io/agora/rest/AgoraVersion.java new file mode 100644 index 0000000..4a5ea6f --- /dev/null +++ b/agora-rest-client-core/src/main/java-templates/io/agora/rest/AgoraVersion.java @@ -0,0 +1,9 @@ +package io.agora.rest; + +public class AgoraVersion { + private static final String version = "${project.version}"; + + public static String getVersion() { + return version; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/AgoraException.java b/agora-rest-client-core/src/main/java/io/agora/rest/AgoraException.java new file mode 100644 index 0000000..5a690fe --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/AgoraException.java @@ -0,0 +1,22 @@ +package io.agora.rest; + +public class AgoraException extends RuntimeException { + + private Integer errCode; + + public AgoraException(String message) { + super(message); + } + + public AgoraException(String message, Throwable cause) { + super(message, cause); + } + + public Integer getErrCode() { + return errCode; + } + + public void setErrCode(Integer errCode) { + this.errCode = errCode; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/AgoraService.java b/agora-rest-client-core/src/main/java/io/agora/rest/AgoraService.java new file mode 100644 index 0000000..0700d42 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/AgoraService.java @@ -0,0 +1,34 @@ +package io.agora.rest; + +import io.agora.rest.core.AgoraProperty; +import io.agora.rest.core.Context; +import io.agora.rest.core.DefaultContext; +import io.agora.rest.services.cloudrecording.CloudRecordingApi; + +public class AgoraService { + + private final AgoraProperty agoraProperty; + + private final Context context; + + private final CloudRecordingApi cloudRecordingApi; + + public AgoraService(AgoraProperty agoraProperty) { + this.agoraProperty = agoraProperty; + this.context = new DefaultContext(agoraProperty); + this.cloudRecordingApi = new CloudRecordingApi(context); + } + + public Context context() { + return context; + } + + + public AgoraProperty getAgoraProperty() { + return agoraProperty; + } + + public CloudRecordingApi cloudRecording() { + return cloudRecordingApi; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/AgoraProperty.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/AgoraProperty.java new file mode 100644 index 0000000..a8a0cb5 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/AgoraProperty.java @@ -0,0 +1,89 @@ +package io.agora.rest.core; + +public class AgoraProperty { + private final String appId; + + private final Credential credential; + + private final RegionArea regionArea; + + private final HttpProperty httpProperty; + + private AgoraProperty(Builder builder) { + this.appId = builder.appId; + this.credential = builder.credential; + this.regionArea = builder.regionArea; + this.httpProperty = builder.httpProperty; + } + + public static Builder builder() { + return new Builder(); + } + + public String getAppId() { + return appId; + } + + public Credential getCredential() { + return credential; + } + + public RegionArea getRegionArea() { + return regionArea; + } + + public HttpProperty getHttpProperty() { + return httpProperty; + } + + @Override + public String toString() { + return "AgoraProperty{" + + "appId='" + appId + '\'' + + ", credential=" + credential + + ", regionArea=" + regionArea + + ", httpProperty=" + httpProperty + + '}'; + } + + public static class Builder { + + private String appId; + + private Credential credential; + + private RegionArea regionArea; + + private HttpProperty httpProperty; + + private Builder() { + } + + public Builder appId(String appId) { + this.appId = appId; + return this; + } + + public Builder credential(Credential credential) { + this.credential = credential; + return this; + } + + public Builder regionArea(RegionArea regionArea) { + this.regionArea = regionArea; + return this; + } + + private Builder httpProperty(HttpProperty httpProperty) { + this.httpProperty = httpProperty; + return this; + } + + public AgoraProperty build() { + if (httpProperty == null) { + this.httpProperty = HttpProperty.builder().build(); + } + return new AgoraProperty(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/BasicAuthCredential.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/BasicAuthCredential.java new file mode 100644 index 0000000..2555e09 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/BasicAuthCredential.java @@ -0,0 +1,36 @@ +package io.agora.rest.core; + +import io.netty.handler.codec.http.HttpHeaders; + +public class BasicAuthCredential implements Credential { + + private final String username; + + private final String password; + + private final static String name = "BasicAuth"; + + public BasicAuthCredential(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public String getName() { + return name; + } + + @Override + public void setAuthorization(HttpHeaders headers) { + headers.set("Authorization", + "Basic " + java.util.Base64.getEncoder().encodeToString((username + ":" + password).getBytes())); + } + + @Override + public String toString() { + return "BasicAuthCredential{" + + "username='" + username + '\'' + + ", password='" + password + '\'' + + '}'; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/Codec.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/Codec.java new file mode 100644 index 0000000..a992b6e --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/Codec.java @@ -0,0 +1,10 @@ +package io.agora.rest.core; + +import io.netty.buffer.ByteBuf; + +public interface Codec { + + ByteBuf encode(Object obj); + + T decode(ByteBuf buffer, Class clazz); +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/Context.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/Context.java new file mode 100644 index 0000000..2f67669 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/Context.java @@ -0,0 +1,11 @@ +package io.agora.rest.core; + +import io.netty.handler.codec.http.HttpMethod; +import reactor.core.publisher.Mono; + +public interface Context { + + Mono sendRequest(String path, HttpMethod method, Object requestBody, Class clazz); + + AgoraProperty getProperty(); +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/Credential.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/Credential.java new file mode 100644 index 0000000..1e89c72 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/Credential.java @@ -0,0 +1,10 @@ +package io.agora.rest.core; + +import io.netty.handler.codec.http.HttpHeaders; + +public interface Credential { + + String getName(); + + void setAuthorization(HttpHeaders headers); +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultContext.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultContext.java new file mode 100644 index 0000000..6017160 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultContext.java @@ -0,0 +1,79 @@ +package io.agora.rest.core; + +import io.agora.rest.exception.AgoraUnknownException; +import io.netty.handler.codec.http.HttpMethod; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; +import reactor.netty.ChannelBindException; +import reactor.netty.http.client.HttpClient; +import reactor.util.retry.Retry; + +import java.net.UnknownHostException; +import java.time.Duration; + +public class DefaultContext implements Context { + + private static final Logger logger = LoggerFactory.getLogger(DefaultContext.class); + + private final AgoraProperty property; + + private final HttpClient httpClient; + + private final Codec codec; + + private final DomainPool domainPool; + + public DefaultContext(AgoraProperty property) { + this.property = property; + this.httpClient = HttpClientFactory.createHttpClient(property); + this.domainPool = new DomainPool(property.getRegionArea()); + this.codec = new JsonCodec(); + } + + @Override + public Mono sendRequest(String path, HttpMethod method, Object requestBody, Class clazz) { + return Mono.defer(() -> { + this.domainPool.selectBestDomain(); + + return Mono.defer(() -> httpClient + .doOnRequest((req, conn) -> + logger.debug("request:{},{}{}", req.method(), req.requestHeaders().get("host"), req.uri())) + .headers(h -> h.add("Content-Type", "application/json")) + .request(method) + .uri(Mono.just(this.domainPool.getCurrentUrl() + path)) + .send(Mono.create(sink -> sink.success(codec.encode(requestBody)))) + .responseSingle((rsp, buf) -> buf.switchIfEmpty( + Mono.error(new AgoraUnknownException("Empty response from Agora server"))) + .flatMap(byteBuf -> { + ErrorMapper mapper = new DefaultErrorMapper(); + + mapper.statusCode(rsp); + mapper.checkError(byteBuf); + + return Mono.just(byteBuf); + }) + ).map(buf -> { + T response = codec.decode(buf, clazz); + buf.release(); + logger.debug("response:{}", response); + return response; + })) + .retryWhen(Retry.fixedDelay(3, Duration.ofMillis(500)). + filter(e -> e instanceof ChannelBindException || e instanceof UnknownHostException) + .doBeforeRetry(retrySignal -> { + domainPool.nextRegion(); + logger.warn("Retry attempt: {}, next backoff: {}", retrySignal.totalRetries() + 1, Duration.ofMillis(500)); + }) + .onRetryExhaustedThrow((retryBackoffSpec, retrySignal) -> { + logger.error("Retry exhausted: {}", retrySignal.totalRetries()); + return retrySignal.failure(); + })); + }); + } + + @Override + public AgoraProperty getProperty() { + return this.property; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultDomainDNSResolver.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultDomainDNSResolver.java new file mode 100644 index 0000000..53c0bd1 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultDomainDNSResolver.java @@ -0,0 +1,73 @@ +package io.agora.rest.core; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; + +import java.net.InetAddress; +import java.time.Duration; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class DefaultDomainDNSResolver implements DomainDNSResolver { + + private final Logger logger = LoggerFactory.getLogger(DefaultDomainDNSResolver.class); + + private final Duration timeout = Duration.ofSeconds(3); + + public Mono resolve(List domains, String regionPrefix) { + return Flux.fromIterable(domains) + .flatMap(domain -> { + String url = regionPrefix + "." + domain; + long startTime = System.nanoTime(); + return Mono.fromCallable(() -> InetAddress.getAllByName(url)) + .subscribeOn(Schedulers.boundedElastic()) + .map(addrs -> { + long took = System.nanoTime() - startTime; + logger.debug("url:{}, IP:{}, took:{}ms", url, addrs, + TimeUnit.NANOSECONDS.toMillis(took)); + + return new DomainResult(domain, took); + }) + .onErrorResume(e -> { + long took = System.nanoTime() - startTime; + logger.error("resolve domain failed, url:{}, err:{}, took:{}ms", url, e.getMessage(), + TimeUnit.NANOSECONDS.toMillis(took)); + + return Mono.empty(); + }); + }) + .collectList() + .map(results -> results.stream() + .min(Comparator.comparingLong(DomainResult::getTime)) + .map(DomainResult::getDomain) + .orElse(null)) + .timeout(timeout) + .onErrorResume(e -> { + logger.error("all domain resolve failed, err:{}", e.getMessage()); + + return Mono.empty(); + }); + } + + private static class DomainResult { + private final String domain; + private final long time; + + public DomainResult(String domain, long time) { + this.domain = domain; + this.time = time; + } + + public String getDomain() { + return domain; + } + + public long getTime() { + return time; + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultErrorMapper.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultErrorMapper.java new file mode 100644 index 0000000..6ffb6c6 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/DefaultErrorMapper.java @@ -0,0 +1,82 @@ +package io.agora.rest.core; + +import io.agora.rest.AgoraException; +import io.agora.rest.exception.*; +import io.agora.rest.utils.ByteUtils; +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.HttpResponseStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.netty.http.client.HttpClientResponse; + +public class DefaultErrorMapper implements ErrorMapper { + + private static final Logger logger = LoggerFactory.getLogger(DefaultErrorMapper.class); + + private HttpClientResponse response; + + private int statusCode; + + public DefaultErrorMapper() { + } + + @Override + public void statusCode(HttpClientResponse response) { + this.statusCode = response.status().code(); + this.response = response; + + } + + @Override + public void checkError(ByteBuf buf) { + if (this.statusCode >= 400) { + throw convertException(this.response, buf); + } + } + + public AgoraException convertException(HttpClientResponse response, ByteBuf buf) { + HttpResponseStatus status = response.status(); + + byte[] body = ByteUtils.toByteArray(buf); + String reason = String.format("%s %s -> %d %s,body:%s", response.method(), response.uri(), status.code(), + status.reasonPhrase(), new String(body)); + logger.info("reason:{}", reason); + + AgoraException exception = new AgoraUnknownException(reason); + switch (statusCode) { + case 400: + case 405: + case 406: + case 415: + exception = new AgoraBadRequestException(reason); + break; + case 401: + exception = new AgoraUnauthorizedException(reason); + break; + case 403: + exception = new AgoraForbiddenException(reason); + break; + case 404: + exception = new AgoraNotFoundException(reason); + break; + case 429: + exception = new AgoraTooManyRequestException(reason); + break; + case 500: + exception = new AgoraInternalServerErrorException(reason); + break; + case 502: + exception = new AgoraBadGatewayException(reason); + break; + case 503: + exception = new AgoraServiceUnavailableException(reason); + break; + case 504: + exception = new AgoraGatewayTimeoutException(reason); + } + + exception.setErrCode(this.statusCode); + + return exception; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/DomainDNSResolver.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/DomainDNSResolver.java new file mode 100644 index 0000000..b73af21 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/DomainDNSResolver.java @@ -0,0 +1,9 @@ +package io.agora.rest.core; + +import reactor.core.publisher.Mono; + +import java.util.List; + +public interface DomainDNSResolver { + Mono resolve(List domains, String regionPrefix); +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/DomainPool.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/DomainPool.java new file mode 100644 index 0000000..c0d4dcf --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/DomainPool.java @@ -0,0 +1,104 @@ +package io.agora.rest.core; + +import io.agora.rest.exception.AgoraInvalidArgumentException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.locks.ReentrantLock; + +public class DomainPool { + + private String currentDomain; + + private Instant lastUpdate; + + private final List currentRegionPrefixes; + + private final List domainSuffixes; + + private final List regionPrefixes; + + private static final Duration updateDuration = Duration.ofSeconds(30); + + private final ReentrantLock locker = new ReentrantLock(true); + + private final DomainDNSResolver resolver; + + private final Logger logger = LoggerFactory.getLogger(DomainPool.class); + + public DomainPool(RegionArea domainArea) { + if (domainArea == null || domainArea == RegionArea.UnkonwnRegionArea) { + throw new AgoraInvalidArgumentException("invalid domain area"); + } + + this.domainSuffixes = new ArrayList<>(domainArea.getMajorDomainSuffixes()); + this.resolver = new DefaultDomainDNSResolver(); + this.regionPrefixes = new ArrayList<>(domainArea.getRegionDomainPrefixes()); + this.currentRegionPrefixes = new ArrayList<>(domainArea.getRegionDomainPrefixes()); + this.currentDomain = domainArea.getMajorDomainSuffixes().get(0); + + this.lastUpdate = Instant.now(); + } + + private boolean domainNeedUpdate() { + return Duration.between(lastUpdate, Instant.now()).compareTo(updateDuration) > 0; + } + + public void selectBestDomain() { + // 提前判断domain是否需要更新,避免多线程情况下重复获取锁 + if (!domainNeedUpdate()) { + return; + } + if (!locker.tryLock()) { + return; + } + + try { + if (domainNeedUpdate()) { + logger.debug("Need to update domainPool"); + String bestDomain = resolver.resolve(domainSuffixes, currentRegionPrefixes.get(0)).block(); + if (bestDomain != null) { + logger.debug("Selected best domain: {}", bestDomain); + selectDomain(bestDomain); + } else { + logger.warn("No suitable domain found, using current domain: {}", currentDomain); + } + } + } finally { + locker.unlock(); + } + } + + public void nextRegion() { + locker.lock(); + try { + currentRegionPrefixes.remove(0); + if (currentRegionPrefixes.isEmpty()) { + currentRegionPrefixes.addAll(regionPrefixes); + } + } finally { + locker.unlock(); + } + } + + private void selectDomain(String domain) { + if (domainSuffixes.contains(domain)) { + currentDomain = domain; + lastUpdate = Instant.now(); + } + } + + public String getCurrentUrl() { + locker.lock(); + try { + return "https://" + currentRegionPrefixes.get(0) + "." + currentDomain; + } finally { + locker.unlock(); + } + } + +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/ErrorMapper.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/ErrorMapper.java new file mode 100644 index 0000000..bd0321b --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/ErrorMapper.java @@ -0,0 +1,11 @@ +package io.agora.rest.core; + +import io.netty.buffer.ByteBuf; +import reactor.netty.http.client.HttpClientResponse; + +public interface ErrorMapper { + + void statusCode(HttpClientResponse response); + + void checkError(ByteBuf buf); +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/HttpClientFactory.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/HttpClientFactory.java new file mode 100644 index 0000000..24d196b --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/HttpClientFactory.java @@ -0,0 +1,43 @@ +package io.agora.rest.core; + +import io.agora.rest.AgoraVersion; +import io.netty.handler.logging.LogLevel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.netty.http.client.HttpClient; +import reactor.netty.resources.ConnectionProvider; + +import java.time.Duration; + +public class HttpClientFactory { + + private static final Logger logger = LoggerFactory.getLogger(HttpClientFactory.class); + + public static HttpClient createHttpClient(AgoraProperty agoraProperty) { + ConnectionProvider connectionProvider = ConnectionProvider.builder("agora-rest-client") + .maxConnections(agoraProperty.getHttpProperty().getHttpConnectionPoolSize()) + .pendingAcquireTimeout(Duration.ofMillis(agoraProperty.getHttpProperty().getHttpConnectionPendingAcquireTimout())) + .maxIdleTime(Duration.ofMillis(agoraProperty.getHttpProperty().getHttpConnectionMaxIdleTime())) + .maxLifeTime(Duration.ofMillis(agoraProperty.getHttpProperty().getHttpConnectionMaxLifeTime())) + .evictInBackground(Duration.ofMillis(agoraProperty.getHttpProperty().getHttpConnectionEvictInBackground())) + .pendingAcquireMaxCount(agoraProperty.getHttpProperty().getHttpConnectionPendingAcquireMaxCount()) + .lifo() + .build(); + + return HttpClient.create(connectionProvider) + .headers(h -> { + h.add("User-Agent", String.format( + "AgoraRESTClient Language/java LanguageVersion/%s Arch/%s OS/%s SDKVersion/%s", + System.getProperty("java.version"), + System.getProperty("os.arch"), + System.getProperty("os.name"), + AgoraVersion.getVersion())); + if (agoraProperty.getCredential() != null) { + agoraProperty.getCredential().setAuthorization(h); + } + }) + .wiretap("io.agora.rest.core.http", LogLevel.DEBUG, agoraProperty.getHttpProperty().getHttpLogFormat()) + .doOnRequestError((req, t) -> logger.error("request error:{}", t.getMessage())); + + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/HttpProperty.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/HttpProperty.java new file mode 100644 index 0000000..86bea89 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/HttpProperty.java @@ -0,0 +1,134 @@ +package io.agora.rest.core; + +import reactor.netty.transport.logging.AdvancedByteBufFormat; + +public class HttpProperty { + + private final int httpConnectionPoolSize; + + private final int httpConnectionMaxIdleTime; + + private final int httpConnectionMaxLifeTime; + + private final int httpConnectionEvictInBackground; + + private final int httpConnectionPendingAcquireTimout; + + private final int httpConnectionPendingAcquireMaxCount; + + private final AdvancedByteBufFormat httpLogFormat; + + public static Builder builder() { + return new Builder(); + } + + private HttpProperty(Builder builder) { + httpConnectionPoolSize = builder.httpConnectionPoolSize; + httpConnectionMaxIdleTime = builder.httpConnectionMaxIdleTime; + httpConnectionMaxLifeTime = builder.httpConnectionMaxLifeTime; + httpConnectionEvictInBackground = builder.httpConnectionEvictInBackground; + httpConnectionPendingAcquireTimout = builder.httpConnectionPendingAcquireTimout; + httpConnectionPendingAcquireMaxCount = builder.httpConnectionPendingAcquireMaxCount; + httpLogFormat = builder.httpLogFormat; + } + + public int getHttpConnectionPoolSize() { + return httpConnectionPoolSize; + } + + public int getHttpConnectionMaxIdleTime() { + return httpConnectionMaxIdleTime; + } + + public int getHttpConnectionMaxLifeTime() { + return httpConnectionMaxLifeTime; + } + + public int getHttpConnectionEvictInBackground() { + return httpConnectionEvictInBackground; + } + + public int getHttpConnectionPendingAcquireTimout() { + return httpConnectionPendingAcquireTimout; + } + + public int getHttpConnectionPendingAcquireMaxCount() { + return httpConnectionPendingAcquireMaxCount; + } + + public AdvancedByteBufFormat getHttpLogFormat() { + return httpLogFormat; + } + + @Override + public String toString() { + return "HttpProperty{" + + "httpConnectionPoolSize=" + httpConnectionPoolSize + + ", httpConnectionMaxIdleTime=" + httpConnectionMaxIdleTime + + ", httpConnectionMaxLifeTime=" + httpConnectionMaxLifeTime + + ", httpConnectionEvictInBackground=" + httpConnectionEvictInBackground + + ", httpConnectionPendingAcquireTimout=" + httpConnectionPendingAcquireTimout + + ", httpConnectionPendingAcquireMaxCount=" + httpConnectionPendingAcquireMaxCount + + ", httpLogFormat=" + httpLogFormat + + '}'; + } + + public static final class Builder { + private int httpConnectionPoolSize = 50; + + private int httpConnectionMaxIdleTime = 10 * 1000; + + private int httpConnectionMaxLifeTime = 60 * 1000; + + private int httpConnectionEvictInBackground = 120 * 1000; + + private int httpConnectionPendingAcquireTimout = 60 * 1000; + + private int httpConnectionPendingAcquireMaxCount = 100; + + private AdvancedByteBufFormat httpLogFormat = AdvancedByteBufFormat.SIMPLE; + + private Builder() { + + } + + public Builder httpConnectionPoolSize(int val) { + httpConnectionPoolSize = val; + return this; + } + + public Builder httpConnectionMaxIdleTime(int val) { + httpConnectionMaxIdleTime = val; + return this; + } + + public Builder httpConnectionMaxLifeTime(int val) { + httpConnectionMaxLifeTime = val; + return this; + } + + public Builder httpConnectionEvictInBackground(int val) { + httpConnectionEvictInBackground = val; + return this; + } + + public Builder httpConnectionPendingAcquireTimout(int val) { + httpConnectionPendingAcquireTimout = val; + return this; + } + + public Builder httpConnectionPendingAcquireMaxCount(int val) { + httpConnectionPendingAcquireMaxCount = val; + return this; + } + + public Builder httpLogFormat(AdvancedByteBufFormat val) { + httpLogFormat = val; + return this; + } + + public HttpProperty build() { + return new HttpProperty(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/JsonCodec.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/JsonCodec.java new file mode 100644 index 0000000..9172a81 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/JsonCodec.java @@ -0,0 +1,68 @@ +package io.agora.rest.core; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.agora.rest.exception.AgoraJsonException; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +public class JsonCodec implements Codec { + + private static final Logger logger = LoggerFactory.getLogger(JsonCodec.class); + + private final ObjectMapper objectMapper; + + public JsonCodec() { + this.objectMapper = new ObjectMapper(); + this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + } + + public ByteBuf encode(Object object) { + ByteBuf buffer = Unpooled.buffer(); + try { + byte[] bytes = this.objectMapper.writeValueAsBytes(object); + + if (object != null) { + logger.debug("request:{}", new String(bytes)); + } + buffer.writeBytes(bytes); + } catch (JsonProcessingException e) { + throw new AgoraJsonException(String.format("could not encode object: %s", e.getMessage()), + e); + } + + return buffer; + } + + public T decode(ByteBuf buffer, Class tClass) { + byte[] array; + final int offset; + int len = buffer.readableBytes(); + if (buffer.hasArray()) { + array = buffer.array(); + offset = buffer.arrayOffset() + buffer.readerIndex(); + } else { + array = ByteBufUtil.getBytes(buffer, buffer.readerIndex(), len, false); + offset = 0; + } + + logger.debug("response:{}", new String(array, offset, len)); + + try { + return this.objectMapper.readValue(array, offset, len, tClass); + } catch (IOException e) { + throw new AgoraJsonException( + String.format("could not decode class %s: %s", tClass.getName(), + e.getMessage()), + e); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/core/RegionArea.java b/agora-rest-client-core/src/main/java/io/agora/rest/core/RegionArea.java new file mode 100644 index 0000000..32293a6 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/core/RegionArea.java @@ -0,0 +1,57 @@ +package io.agora.rest.core; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public enum RegionArea { + /** + * Unknown region area + */ + UnkonwnRegionArea(Collections.emptyList(), Collections.emptyList()), + + /** + * US region area + */ + USRegionArea( + Arrays.asList("api-us-west-1", "api-us-east-1"), + Arrays.asList("agora.io", "sd-rtn.com")), + + /** + * EU region area + */ + EURegionArea( + Arrays.asList("api-eu-west-1", "api-eu-central-1"), + Arrays.asList("agora.io", "sd-rtn.com")), + + /** + * AP region area + */ + APRegionArea( + Arrays.asList("api-ap-southeast-1", "api-ap-northeast-1"), + Arrays.asList("agora.io", "sd-rtn.com")), + + /** + * CN region area + */ + CNRegionArea( + Arrays.asList("api-cn-east-1", "api-cn-north-1"), + Arrays.asList("sd-rtn.com", "agora.io")); + + private final List regionDomainPrefixes; + + private final List majorDomainSuffixes; + + RegionArea(List regionDomainPrefixes, List majorDomainSuffixes) { + this.regionDomainPrefixes = Collections.unmodifiableList(regionDomainPrefixes); + this.majorDomainSuffixes = Collections.unmodifiableList(majorDomainSuffixes); + } + + public List getRegionDomainPrefixes() { + return regionDomainPrefixes; + } + + public List getMajorDomainSuffixes() { + return majorDomainSuffixes; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraBadGatewayException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraBadGatewayException.java new file mode 100644 index 0000000..674596a --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraBadGatewayException.java @@ -0,0 +1,7 @@ +package io.agora.rest.exception; + +public class AgoraBadGatewayException extends AgoraNeedRetryException { + public AgoraBadGatewayException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraBadRequestException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraBadRequestException.java new file mode 100644 index 0000000..9dbca14 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraBadRequestException.java @@ -0,0 +1,9 @@ +package io.agora.rest.exception; + +import io.agora.rest.AgoraException; + +public class AgoraBadRequestException extends AgoraException { + public AgoraBadRequestException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraForbiddenException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraForbiddenException.java new file mode 100644 index 0000000..2c0431a --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraForbiddenException.java @@ -0,0 +1,9 @@ +package io.agora.rest.exception; + +import io.agora.rest.AgoraException; + +public class AgoraForbiddenException extends AgoraException { + public AgoraForbiddenException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraGatewayTimeoutException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraGatewayTimeoutException.java new file mode 100644 index 0000000..6f8f02f --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraGatewayTimeoutException.java @@ -0,0 +1,7 @@ +package io.agora.rest.exception; + +public class AgoraGatewayTimeoutException extends AgoraNeedRetryException { + public AgoraGatewayTimeoutException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraInternalServerErrorException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraInternalServerErrorException.java new file mode 100644 index 0000000..6af0435 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraInternalServerErrorException.java @@ -0,0 +1,7 @@ +package io.agora.rest.exception; + +public class AgoraInternalServerErrorException extends AgoraNeedRetryException { + public AgoraInternalServerErrorException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraInvalidArgumentException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraInvalidArgumentException.java new file mode 100644 index 0000000..36cc717 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraInvalidArgumentException.java @@ -0,0 +1,9 @@ +package io.agora.rest.exception; + +import io.agora.rest.AgoraException; + +public class AgoraInvalidArgumentException extends AgoraException { + public AgoraInvalidArgumentException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraJsonException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraJsonException.java new file mode 100644 index 0000000..af3b2e6 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraJsonException.java @@ -0,0 +1,13 @@ +package io.agora.rest.exception; + +import io.agora.rest.AgoraException; + +public class AgoraJsonException extends AgoraException { + public AgoraJsonException(String message) { + super(message); + } + + public AgoraJsonException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraNeedRetryException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraNeedRetryException.java new file mode 100644 index 0000000..8081e24 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraNeedRetryException.java @@ -0,0 +1,9 @@ +package io.agora.rest.exception; + +import io.agora.rest.AgoraException; + +public class AgoraNeedRetryException extends AgoraException { + public AgoraNeedRetryException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraNotFoundException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraNotFoundException.java new file mode 100644 index 0000000..40957f9 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraNotFoundException.java @@ -0,0 +1,9 @@ +package io.agora.rest.exception; + +import io.agora.rest.AgoraException; + +public class AgoraNotFoundException extends AgoraException { + public AgoraNotFoundException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraServiceUnavailableException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraServiceUnavailableException.java new file mode 100644 index 0000000..a087b8b --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraServiceUnavailableException.java @@ -0,0 +1,7 @@ +package io.agora.rest.exception; + +public class AgoraServiceUnavailableException extends AgoraNeedRetryException { + public AgoraServiceUnavailableException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraTooManyRequestException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraTooManyRequestException.java new file mode 100644 index 0000000..f772b8a --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraTooManyRequestException.java @@ -0,0 +1,9 @@ +package io.agora.rest.exception; + +import io.agora.rest.AgoraException; + +public class AgoraTooManyRequestException extends AgoraException { + public AgoraTooManyRequestException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraUnauthorizedException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraUnauthorizedException.java new file mode 100644 index 0000000..0ebfe91 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraUnauthorizedException.java @@ -0,0 +1,9 @@ +package io.agora.rest.exception; + +import io.agora.rest.AgoraException; + +public class AgoraUnauthorizedException extends AgoraException { + public AgoraUnauthorizedException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraUnknownException.java b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraUnknownException.java new file mode 100644 index 0000000..12e4c4d --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/exception/AgoraUnknownException.java @@ -0,0 +1,9 @@ +package io.agora.rest.exception; + +import io.agora.rest.AgoraException; + +public class AgoraUnknownException extends AgoraException { + public AgoraUnknownException(String message) { + super(message); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/CloudRecordingApi.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/CloudRecordingApi.java new file mode 100644 index 0000000..f0fd0b8 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/CloudRecordingApi.java @@ -0,0 +1,84 @@ +package io.agora.rest.services.cloudrecording; + +import io.agora.rest.core.Context; +import io.agora.rest.services.cloudrecording.api.*; +import io.agora.rest.services.cloudrecording.api.req.*; +import io.agora.rest.services.cloudrecording.api.res.*; +import io.agora.rest.services.cloudrecording.enums.CloudRecordingModeEnum; +import io.agora.rest.services.cloudrecording.scenario.individual.IndividualScenario; +import io.agora.rest.services.cloudrecording.scenario.mix.MixScenario; +import io.agora.rest.services.cloudrecording.scenario.web.WebScenario; +import reactor.core.publisher.Mono; + +public class CloudRecordingApi { + + private final AcquireResourceAPI acquireResourceAPI; + + private final QueryResourceAPI queryResourceAPI; + + private final StartResourceAPI startResourceAPI; + + private final UpdateResourceAPI updateResourceAPI; + + private final StopResourceAPI stopResourceAPI; + + private final IndividualScenario individualScenario; + + private final WebScenario webScenario; + + private final MixScenario mixScenario; + + public CloudRecordingApi(Context context) { + this.acquireResourceAPI = new AcquireResourceAPI(context); + this.queryResourceAPI = new QueryResourceAPI(context); + this.startResourceAPI = new StartResourceAPI(context); + this.stopResourceAPI = new StopResourceAPI(context); + this.updateResourceAPI = new UpdateResourceAPI(context); + + this.individualScenario = new IndividualScenario(acquireResourceAPI, queryResourceAPI, startResourceAPI, + updateResourceAPI, stopResourceAPI); + this.webScenario = new WebScenario(acquireResourceAPI, queryResourceAPI, startResourceAPI, updateResourceAPI, + stopResourceAPI); + this.mixScenario = new MixScenario(acquireResourceAPI, queryResourceAPI, startResourceAPI, updateResourceAPI, + stopResourceAPI); + } + + public Mono acquire(AcquireResourceReq request) { + return acquireResourceAPI.handle(request); + } + + public Mono start(String resourceId, CloudRecordingModeEnum mode, StartResourceReq request) { + return startResourceAPI.handle(resourceId, mode, request); + } + + public Mono query(String resourceId, String sid, CloudRecordingModeEnum mode) { + return queryResourceAPI.handle(resourceId, sid, mode); + } + + public Mono stop(String resourceId, String sid, CloudRecordingModeEnum mode, + StopResourceReq request) { + return stopResourceAPI.handle(resourceId, sid, mode, request); + } + + public Mono update(String resourceId, String sid, CloudRecordingModeEnum mode, + UpdateResourceReq request) { + return updateResourceAPI.handle(resourceId, sid, mode, request); + } + + public Mono updateLayout(String resourceId, String sid, CloudRecordingModeEnum mode, + UpdateLayoutResourceReq request) { + return updateResourceAPI.handleLayout(resourceId, sid, mode, request); + } + + public IndividualScenario individualScenario() { + return individualScenario; + } + + public WebScenario webScenario() { + return webScenario; + } + + public MixScenario mixScenario() { + return mixScenario; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/README.md b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/README.md new file mode 100644 index 0000000..390f4bf --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/README.md @@ -0,0 +1,299 @@ +# 云端录制服务 +## 服务简介 +云端录制是声网为音视频通话和直播研发的录制组件,提供 RESTful API 供开发者实现录制功能,并将录制文件存至第三方云存储。云端录制有稳定可靠、简单易用、成本可控、方案灵活、支持私有化部署等优势,是在线教育、视频会议、金融监管、客户服务场景的理想录制方案。 + +## 环境准备 + +- 获取声网App ID -------- [声网Agora - 文档中心 - 如何获取 App ID](https://docs.agora.io/cn/Agora%20Platform/get_appid_token?platform=All%20Platforms#%E8%8E%B7%E5%8F%96-app-id) + + > - 点击创建应用 + > + > ![](https://accktvpic.oss-cn-beijing.aliyuncs.com/pic/github_readme/create_app_1.jpg) + > + > - 选择你要创建的应用类型 + > + > ![](https://accktvpic.oss-cn-beijing.aliyuncs.com/pic/github_readme/create_app_2.jpg) + +- 获取App 证书 ----- [声网Agora - 文档中心 - 获取 App 证书](https://docs.agora.io/cn/Agora%20Platform/get_appid_token?platform=All%20Platforms#%E8%8E%B7%E5%8F%96-app-%E8%AF%81%E4%B9%A6) + + > 在声网控制台的项目管理页面,找到你的项目,点击配置。 + > ![](https://fullapp.oss-cn-beijing.aliyuncs.com/scenario_api/callapi/config/1641871111769.png) + > 点击主要证书下面的复制图标,即可获取项目的 App 证书。 + > ![](https://fullapp.oss-cn-beijing.aliyuncs.com/scenario_api/callapi/config/1637637672988.png) + +- 开启云录制服务 + > ![](https://fullapp.oss-cn-beijing.aliyuncs.com/scenario_api/callapi/config/rtm_config1.jpg) + > ![](https://fullapp.oss-cn-beijing.aliyuncs.com/scenario_api/callapi/config/rtm_config2.jpg) + > ![](https://fullapp.oss-cn-beijing.aliyuncs.com/agora-rest-client/go/open_cloud_recording.png) + +## API V1 接口调用示例 +### 获取云端录制资源 +> 在开始云端录制之前,你需要调用 acquire 方法获取一个 Resource ID。一个 Resource ID 只能用于一次云端录制服务。 + +需要设置的参数有: +- appId: 声网的项目 AppID +- username: 声网的Basic Auth认证的用户名 +- password: 声网的Basic Auth认证的密码 +- cname: 频道名 +- uid: 用户 UID +- 更多 clientRequest中的参数见 [Acquire](https://doc.shengwang.cn/doc/cloud-recording/restful/cloud-recording/operations/post-v1-apps-appid-cloud_recording-acquire) 接口文档 + +通过调用`Acquire().Do`方法来实现获取云端录制资源 +```java + String appId = ""; + String cname = ""; + String uid = ""; + String username = ""; + String password = ""; + + Credential basicAuthCredential = new BasicAuthCredential(username, password); + AgoraService agoraService = new AgoraService( + AgoraProperty.builder() + .appId(appId) + .credential(basicAuthCredential) + .regionArea(RegionArea.CNRegionArea) + .build() + ); + + AcquireResourceReq acquireResourceReq = AcquireResourceReq.builder().cname(cname).uid(uid) + .clientRequest(AcquireResourceReq.ClientRequest.builder().scene(1) + .resourceExpiredHour(24).build()) + .build(); + + logger.info("request:{},clientRequest:{}", acquireResourceReq, acquireResourceReq.getClientRequest()); + + AcquireResourceRes acquireResourceRes = null; + try { + acquireResourceRes = agoraService.cloudRecording().acquire(acquireResourceReq).block(); + + assertNotNull(acquireResourceResp); + logger.info("acquire resource response:{}", acquireResourceRes); + } catch (AgoraException e) { + logger.error("Agora error:{}", e.getMessage()); + } catch (Exception e) { + logger.error("Internal error:{}", e.getMessage()); + } +``` + +### 开始云端录制 +> 通过 acquire 方法获取云端录制资源后,调用 start 方法开始云端录制。 + +需要设置的参数有: +- cname: 频道名 +- uid: 用户 UID +- resourceId: 云端录制资源ID +- mode: 云端录制模式 +- storageConfig: 存储配置 +- 更多 clientRequest中的参数见 [Start](https://doc.shengwang.cn/doc/cloud-recording/restful/cloud-recording/operations/post-v1-apps-appid-cloud_recording-resourceid-resourceid-mode-mode-start) 接口文档 + +通过调用`start`方法来实现开始云端录制 +```java + StartResourceReq.StorageConfig storageConfig = StartResourceReq.StorageConfig.builder() + .accessKey("") + .secretKey("") + .fileNamePrefix(Collections.singletonList("")) + .bucket("") + .vendor(2) + .region(3) + .build(); + + StartResourceReq startResourceReq = StartResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(StartResourceReq.StartClientRequest.builder() + .recordingFileConfig(StartResourceReq.RecordingFileConfig.builder() + .avFileType(Arrays.asList("hls", "mp4")) + .build()) + .storageConfig(storageConfig) + .extensionServiceConfig(StartResourceReq.ExtensionServiceConfig + .builder() + .errorHandlePolicy("error_abort") + .extensionServices(Arrays.asList( + StartResourceReq.ExtensionService + .builder() + .serviceParam(StartResourceReq.WebRecordingServiceParam + .builder() + .url("https://www.example.com") + .audioProfile(2) + .videoWidth(1280) + .videoHeight(720) + .maxRecordingHour( + 1) + .build()) + .errorHandlePolicy( + "error_abort") + .serviceName("web_recorder_service") + .build(), + StartResourceReq.ExtensionService + .builder() + .serviceParam(StartResourceReq.RtmpPublishServiceParam + .builder() + .outputs(Collections + .singletonList(StartResourceReq.Outputs + .builder() + .rtmpUrl( + "rtmp://xxx.xxx.xxx.xxx:1935/live/test") + .build())) + .build()) + .serviceName("rtmp_publish_service") + .errorHandlePolicy( + "error_abort") + .build())) + .build()) + .build()) + .build(); + + StartResourceRes startResourceRes = null; + + try { + startResourceRes = agoraService.cloudRecording() + .start(resourceId,mode, startResourceReq) + .block(); + logger.info("start resource response:{}", startResourceRes); + + } catch (AgoraException e) { + logger.error("Agora error:{}", e.getMessage()); + } catch (Exception e) { + logger.error("Internal error:{}", e.getMessage()); + + } +``` + +### 停止云端录制 +> 开始录制后,你可以调用 stop 方法离开频道,停止录制。录制停止后如需再次录制,必须再调用 acquire 方法请求一个新的 Resource ID。 + +需要设置的参数有: +- cname: 频道名 +- uid: 用户ID +- resourceId: 云端录制资源ID +- sid: 会话ID +- mode: 云端录制模式 +- 更多 clientRequest中的参数见 [Stop](https://doc.shengwang.cn/doc/cloud-recording/restful/cloud-recording/operations/post-v1-apps-appid-cloud_recording-resourceid-resourceid-sid-sid-mode-mode-stop) 接口文档 + +因为Stop 接口返回的不是一个固定的结构体,所以需要根据返回的serverResponseMode来判断具体的返回类型 + +通过调用`stop`方法来实现停止云端录制 +```java + StopResourceReq stopResourceReq = StopResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(StopResourceReq.StopClientRequest.builder() + .asyncStop(true) + .build()) + .build(); + + StopResourceRes stopResourceRes; + try { + stopResourceRes = agoraService.cloudRecording() + .stop(resourceId, sid, mode, stopResourceReq) + .block(); + logger.info("stop resource response:{}", stopResourceRes); + } catch (AgoraException e) { + logger.error("Agora error:{}", e.getMessage()); + } catch (Exception e) { + logger.error("Internal error:{}", e.getMessage()); + } + +``` + +### 查询云端录制状态 +> 开始录制后,你可以调用 query 方法查询录制状态。 + +需要设置的参数有: +- cname: 频道名 +- uid: 用户ID +- resourceId: 云端录制资源ID +- sid: 会话ID +- mode: 云端录制模式 +- 更多 clientRequest中的参数见[Query](https://doc.shengwang.cn/doc/cloud-recording/restful/cloud-recording/operations/get-v1-apps-appid-cloud_recording-resourceid-resourceid-sid-sid-mode-mode-query)接口文档 + +因为 Query 接口返回的不是一个固定的结构体,所以需要根据返回的serverResponseMode来判断具体的返回类型 + +通过调用`query`方法来实现查询云端录制状态 +```java + QueryResourceRes queryResourceRes = null; + + try { + queryResourceRes = agoraService.cloudRecording() + .query(resourceId, sid,mode) + .block(); + + logger.info("query resource response:{}", queryResourceRes); + switch (queryResourceRes.getServerResponseType()) { + case QUERY_SERVER_RESPONSE_UNKNOWN_TYPE: + logger.error("Unknown server response type"); + break; + case QUERY_INDIVIDUAL_RECORDING_SERVER_RESPONSE_TYPE: + logger.info("individual recording server response:{}", + queryResourceRes.getQueryIndividualRecordingServerResponse()); + break; + case QUERY_INDIVIDUAL_VIDEO_SCREENSHOT_SERVER_RESPONSE_TYPE: + logger.info("individual video screenshot server response:{}", + queryResourceRes.getQueryIndividualVideoScreenshotServerResponse()); + break; + case QUERY_MIX_RECORDING_HLS_SERVER_RESPONSE_TYPE: + logger.info("mix recording hls server response:{}", + queryResourceRes.getMixRecordingHLSServerResponse()); + break; + case QUERY_MIX_RECORDING_HLS_AND_MP4_SERVER_RESPONSE_TYPE: + logger.info("mix recording hls and mp4 server response:{}", + queryResourceRes.getMixRecordingHLSAndMP4ServerResponse()); + break; + case QUERY_WEB_RECORDING_SERVER_RESPONSE_TYPE: + logger.info("web recording server response:{}", + queryResourceRes.getWebRecordingServerResponse()); + break; + } + } catch (AgoraException e) { + logger.error("Agora error:{}", e.getMessage()); + } catch (Exception e) { + logger.error("Internal error:{}", e.getMessage()); + } +``` + +### 更新云端录制设置 +> 开始录制后,你可以调用 update 方法更新如下录制配置: +> * 对单流录制和合流录制,更新订阅名单。 +> * 对页面录制,设置暂停/恢复页面录制,或更新页面录制转推到 CDN 的推流地址(URL)。 + +需要设置的参数有: +- cname: 频道名 +- uid: 用户 UID +- resourceId: 云端录制资源ID +- sid: 会话ID +- mode: 云端录制模式 +- 更多 clientRequest中的参数见 [Update](https://doc.shengwang.cn/doc/cloud-recording/restful/cloud-recording/operations/post-v1-apps-appid-cloud_recording-resourceid-resourceid-sid-sid-mode-mode-update) 接口文档 + +通过调用`update`方法来实现更新云端录制设置 +```java + UpdateResourceReq updateResourceReq = UpdateResourceReq.builder() + .uid(uid) + .cname(cname) + .clientRequest(UpdateResourceReq.ClientRequest.builder() + .webRecordingConfig(UpdateResourceReq.WebRecordingConfig.builder() + .onHold(true) + .build()) + .rtmpPublishConfig(UpdateResourceReq.RtmpPublishConfig.builder() + .outputs(Collections.singletonList( + UpdateResourceReq.UpdateOutput.builder() + .rtmpURL("rtmp://yyy.yyy.yyy.yyy:1935/live/test") + .build())) + .build()) + .build()) + .build(); + + UpdateResourceRes updateResourceRes; + try { + updateResourceRes = agoraService.cloudRecording() + .update(resourceId, sid, mode, updateResourceReq) + .block(); + logger.info("update resource response:{}", updateResourceRes); + } catch (AgoraException e) { + logger.error("Agora error:{}", e.getMessage()); + } catch (Exception e) { + logger.error("Internal error:{}", e.getMessage()); + } +``` + +## 错误码和响应状态码处理 +具体的业务响应码请参考 [业务响应码](https://doc.shengwang.cn/doc/cloud-recording/restful/response-code) 文档 diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/AcquireResourceAPI.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/AcquireResourceAPI.java new file mode 100644 index 0000000..e269c84 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/AcquireResourceAPI.java @@ -0,0 +1,22 @@ +package io.agora.rest.services.cloudrecording.api; + +import io.agora.rest.core.Context; +import io.agora.rest.services.cloudrecording.api.req.AcquireResourceReq; +import io.agora.rest.services.cloudrecording.api.res.AcquireResourceRes; +import io.netty.handler.codec.http.HttpMethod; +import reactor.core.publisher.Mono; + +public class AcquireResourceAPI { + + private final Context context; + + public AcquireResourceAPI(Context context) { + this.context = context; + } + + public Mono handle(AcquireResourceReq request) { + String path = String.format("/v1/apps/%s/cloud_recording/acquire", + this.context.getProperty().getAppId()); + return this.context.sendRequest(path, HttpMethod.POST, request, AcquireResourceRes.class); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/QueryResourceAPI.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/QueryResourceAPI.java new file mode 100644 index 0000000..63774b0 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/QueryResourceAPI.java @@ -0,0 +1,38 @@ +package io.agora.rest.services.cloudrecording.api; + +import io.agora.rest.core.Context; +import io.agora.rest.exception.AgoraJsonException; +import io.agora.rest.services.cloudrecording.api.res.QueryResourceRes; +import io.agora.rest.services.cloudrecording.enums.CloudRecordingModeEnum; +import io.netty.handler.codec.http.HttpMethod; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +public class QueryResourceAPI { + + private static final Logger logger = LoggerFactory.getLogger(QueryResourceAPI.class); + + private final Context context; + + public QueryResourceAPI(Context context) { + this.context = context; + } + + public Mono handle(String resourceId, String sid, CloudRecordingModeEnum mode) { + String path = String.format("/v1/apps/%s/cloud_recording/resourceid/%s/sid/%s/mode/%s/query", + this.context.getProperty().getAppId(), resourceId, sid, mode.getMode()); + return this.context.sendRequest(path, HttpMethod.GET, null, QueryResourceRes.class) + .handle((resp, sink) -> { + try { + resp.setServerResponse(mode); + } catch (Exception e) { + sink.error(new AgoraJsonException("Failed to set server response", e)); + return; + } + + logger.debug("response:{}", resp); + sink.next(resp); + }); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/StartResourceAPI.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/StartResourceAPI.java new file mode 100644 index 0000000..cc9b65f --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/StartResourceAPI.java @@ -0,0 +1,54 @@ +package io.agora.rest.services.cloudrecording.api; + +import io.agora.rest.core.Context; +import io.agora.rest.exception.AgoraNeedRetryException; +import io.agora.rest.services.cloudrecording.api.req.StartResourceReq; +import io.agora.rest.services.cloudrecording.api.res.StartResourceRes; +import io.agora.rest.services.cloudrecording.enums.CloudRecordingModeEnum; +import io.netty.handler.codec.http.HttpMethod; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; +import reactor.util.retry.Retry; +import reactor.util.retry.RetryBackoffSpec; + +import java.time.Duration; +import java.util.function.Predicate; + + +public class StartResourceAPI { + + private static final Logger logger = LoggerFactory.getLogger(StartResourceAPI.class); + + private final Context context; + + private final static int MAX_ATTEMPTS = 3; + + public StartResourceAPI(Context context) { + this.context = context; + } + + public Mono handle(String resourceId, CloudRecordingModeEnum mode, StartResourceReq request) { + String path = String.format("/v1/apps/%s/cloud_recording/resourceid/%s/mode/%s/start", + this.context.getProperty().getAppId(), resourceId, mode.getMode()); + + return this.context.sendRequest(path, HttpMethod.POST, request, StartResourceRes.class) + .retryWhen(customRetry(MAX_ATTEMPTS, e -> e instanceof AgoraNeedRetryException)); + } + + + private RetryBackoffSpec customRetry(int maxAttempts, Predicate retryPredicate) { + return Retry.backoff(maxAttempts, Duration.ofSeconds(1)) // 最多重试5次,初始间隔1秒 + .maxBackoff(Duration.ofSeconds(5)) // 最大间隔5秒 + .filter(retryPredicate) // 重试条件 + .doBeforeRetry(retrySignal -> { + long retryCount = retrySignal.totalRetries() + 1; // 第几次重试 + Duration nextBackoff = Duration.ofSeconds(retryCount); // 下次重试间隔 + logger.warn("Retry attempt: {}, next backoff: {}", retryCount, nextBackoff); + }).onRetryExhaustedThrow((retryBackoffSpec, retrySignal) -> { + logger.error("Retry exhausted: {}", retrySignal.totalRetries()); + return retrySignal.failure(); + }); + } + +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/StopResourceAPI.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/StopResourceAPI.java new file mode 100644 index 0000000..d3d9774 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/StopResourceAPI.java @@ -0,0 +1,24 @@ +package io.agora.rest.services.cloudrecording.api; + +import io.agora.rest.core.Context; +import io.agora.rest.services.cloudrecording.api.req.StopResourceReq; +import io.agora.rest.services.cloudrecording.api.res.StopResourceRes; +import io.agora.rest.services.cloudrecording.enums.CloudRecordingModeEnum; +import io.netty.handler.codec.http.HttpMethod; +import reactor.core.publisher.Mono; + +public class StopResourceAPI { + + private final Context context; + + public StopResourceAPI(Context context) { + this.context = context; + } + + public Mono handle(String resourceId, String sid, CloudRecordingModeEnum mode, + StopResourceReq request) { + String path = String.format("/v1/apps/%s/cloud_recording/resourceid/%s/sid/%s/mode/%s/stop", + this.context.getProperty().getAppId(), resourceId, sid, mode.getMode()); + return this.context.sendRequest(path, HttpMethod.POST, request, StopResourceRes.class); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/UpdateResourceAPI.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/UpdateResourceAPI.java new file mode 100644 index 0000000..eb60572 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/UpdateResourceAPI.java @@ -0,0 +1,39 @@ +package io.agora.rest.services.cloudrecording.api; + +import io.agora.rest.core.Context; +import io.agora.rest.services.cloudrecording.api.req.UpdateLayoutResourceReq; +import io.agora.rest.services.cloudrecording.api.req.UpdateResourceReq; +import io.agora.rest.services.cloudrecording.api.res.UpdateLayoutResourceRes; +import io.agora.rest.services.cloudrecording.api.res.UpdateResourceRes; +import io.agora.rest.services.cloudrecording.enums.CloudRecordingModeEnum; +import io.netty.handler.codec.http.HttpMethod; +import reactor.core.publisher.Mono; + +public class UpdateResourceAPI { + + private final Context context; + + public UpdateResourceAPI(Context context) { + this.context = context; + } + + public Mono handle(String resourceId, String sid, CloudRecordingModeEnum mode, + UpdateResourceReq request) { + String path = String.format("/v1/apps/%s/cloud_recording/resourceid/%s/sid/%s/mode/%s/update", + this.context.getProperty().getAppId(), + resourceId, + sid, + mode.getMode()); + return this.context.sendRequest(path, HttpMethod.POST, request, UpdateResourceRes.class); + } + + public Mono handleLayout(String resourceId, String sid, CloudRecordingModeEnum mode, + UpdateLayoutResourceReq request) { + String path = String.format("/v1/apps/%s/cloud_recording/resourceid/%s/sid/%s/mode/%s/updateLayout", + this.context.getProperty().getAppId(), + resourceId, + sid, + mode.getMode()); + return this.context.sendRequest(path, HttpMethod.POST, request, UpdateLayoutResourceRes.class); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/AcquireResourceReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/AcquireResourceReq.java new file mode 100644 index 0000000..d1ee78a --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/AcquireResourceReq.java @@ -0,0 +1,170 @@ +package io.agora.rest.services.cloudrecording.api.req; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public class AcquireResourceReq { + + @JsonProperty("cname") + private String cname; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("clientRequest") + private ClientRequest clientRequest; + + private AcquireResourceReq(Builder builder) { + this.cname = builder.cname; + this.uid = builder.uid; + this.clientRequest = builder.clientRequest; + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public ClientRequest getClientRequest() { + return clientRequest; + } + + public void setClientRequest(ClientRequest clientRequest) { + this.clientRequest = clientRequest; + } + + public static class ClientRequest { + @JsonProperty("scene") + private Integer scene; + + @JsonProperty("resourceExpiredHour") + private Integer resourceExpiredHour; + + @JsonProperty("excludeResourceIds") + private List excludeResourceIds; + + @JsonProperty("regionAffinity") + private Integer regionAffinity; + + @JsonProperty("startParameter") + private StartResourceReq.StartClientRequest startParameter; + + private ClientRequest(Builder builder) { + this.scene = builder.scene; + this.resourceExpiredHour = builder.resourceExpiredHour; + this.excludeResourceIds = builder.excludeResourceIds; + this.regionAffinity = builder.regionAffinity; + this.startParameter = builder.startParameter; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private Integer scene; + + private Integer resourceExpiredHour; + + private List excludeResourceIds; + + private Integer regionAffinity; + + private StartResourceReq.StartClientRequest startParameter; + + public Builder scene(Integer scene) { + this.scene = scene; + return this; + } + + public Builder resourceExpiredHour(Integer resourceExpiredHour) { + this.resourceExpiredHour = resourceExpiredHour; + return this; + } + + public Builder excludeResourceIds(List excludeResourceIds) { + this.excludeResourceIds = excludeResourceIds; + return this; + } + + public Builder regionAffinity(Integer regionAffinity) { + this.regionAffinity = regionAffinity; + return this; + } + + public Builder startParameter(StartResourceReq.StartClientRequest startParameter) { + this.startParameter = startParameter; + return this; + } + + public ClientRequest build() { + return new ClientRequest(this); + } + } + + @Override + public String toString() { + return "ClientRequest{" + + "scene=" + scene + + ", resourceExpiredHour=" + resourceExpiredHour + + ", excludeResourceIds=" + excludeResourceIds + + ", regionAffinity=" + regionAffinity + + ", startParameter=" + startParameter + + '}'; + } + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private String cname; + + private String uid; + + private ClientRequest clientRequest; + + public Builder cname(String cname) { + this.cname = cname; + return this; + } + + public Builder uid(String uid) { + this.uid = uid; + return this; + } + + public Builder clientRequest(ClientRequest clientRequest) { + this.clientRequest = clientRequest; + return this; + } + + public AcquireResourceReq build() { + return new AcquireResourceReq(this); + } + } + + @Override + public String toString() { + return "AcquireResourceReq{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", clientRequest=" + clientRequest + + '}'; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/StartResourceReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/StartResourceReq.java new file mode 100644 index 0000000..1018159 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/StartResourceReq.java @@ -0,0 +1,2256 @@ +package io.agora.rest.services.cloudrecording.api.req; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public class StartResourceReq { + + @JsonProperty("cname") + private String cname; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("clientRequest") + private StartClientRequest clientRequest; + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public StartClientRequest getClientRequest() { + return clientRequest; + } + + public void setClientRequest(StartClientRequest clientRequest) { + this.clientRequest = clientRequest; + } + + @Override + public String toString() { + return "StartResourceReq{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", clientRequest=" + clientRequest + + '}'; + } + + public interface ServiceParam { + } + + public static Builder builder() { + return new Builder(); + } + + public static class StartClientRequest { + + @JsonProperty("token") + private String token; + + @JsonProperty("appsCollection") + private AppsCollection appsCollection; + + @JsonProperty("recordingConfig") + private RecordingConfig recordingConfig; + + @JsonProperty("transcodeOptions") + private TranscodeOptions transcodeOptions; + + @JsonProperty("recordingFileConfig") + private RecordingFileConfig recordingFileConfig; + + @JsonProperty("snapshotConfig") + private SnapshotConfig snapshotConfig; + + @JsonProperty("storageConfig") + private StorageConfig storageConfig; + + @JsonProperty("extensionServiceConfig") + private ExtensionServiceConfig extensionServiceConfig; + + public static Builder builder() { + return new Builder(); + } + + private StartClientRequest(Builder builder) { + setToken(builder.token); + setAppsCollection(builder.appsCollection); + setRecordingConfig(builder.recordingConfig); + setTranscodeOptions(builder.transcodeOptions); + setRecordingFileConfig(builder.recordingFileConfig); + setSnapshotConfig(builder.snapshotConfig); + setStorageConfig(builder.storageConfig); + setExtensionServiceConfig(builder.extensionServiceConfig); + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public AppsCollection getAppsCollection() { + return appsCollection; + } + + public void setAppsCollection(AppsCollection appsCollection) { + this.appsCollection = appsCollection; + } + + public RecordingConfig getRecordingConfig() { + return recordingConfig; + } + + public void setRecordingConfig(RecordingConfig recordingConfig) { + this.recordingConfig = recordingConfig; + } + + public TranscodeOptions getTranscodeOptions() { + return transcodeOptions; + } + + public void setTranscodeOptions(TranscodeOptions transcodeOptions) { + this.transcodeOptions = transcodeOptions; + } + + public RecordingFileConfig getRecordingFileConfig() { + return recordingFileConfig; + } + + public void setRecordingFileConfig(RecordingFileConfig recordingFileConfig) { + this.recordingFileConfig = recordingFileConfig; + } + + public SnapshotConfig getSnapshotConfig() { + return snapshotConfig; + } + + public void setSnapshotConfig(SnapshotConfig snapshotConfig) { + this.snapshotConfig = snapshotConfig; + } + + public StorageConfig getStorageConfig() { + return storageConfig; + } + + public void setStorageConfig(StorageConfig storageConfig) { + this.storageConfig = storageConfig; + } + + public ExtensionServiceConfig getExtensionServiceConfig() { + return extensionServiceConfig; + } + + public void setExtensionServiceConfig(ExtensionServiceConfig extensionServiceConfig) { + this.extensionServiceConfig = extensionServiceConfig; + } + + @Override + public String toString() { + return "StartClientRequest{" + + "token='" + token + '\'' + + ", appsCollection=" + appsCollection + + ", recordingConfig=" + recordingConfig + + ", transcodeOptions=" + transcodeOptions + + ", recordingFileConfig=" + recordingFileConfig + + ", snapshotConfig=" + snapshotConfig + + ", storageConfig=" + storageConfig + + ", extensionServiceConfig=" + extensionServiceConfig + + '}'; + } + + public static final class Builder { + + private String token; + + private AppsCollection appsCollection; + + private RecordingConfig recordingConfig; + + private TranscodeOptions transcodeOptions; + + private RecordingFileConfig recordingFileConfig; + + private SnapshotConfig snapshotConfig; + + private StorageConfig storageConfig; + + private ExtensionServiceConfig extensionServiceConfig; + + private Builder() { + } + + public static Builder builder() { + return new Builder(); + } + + public Builder token(String val) { + token = val; + return this; + } + + public Builder appsCollection(AppsCollection val) { + appsCollection = val; + return this; + } + + public Builder recordingConfig(RecordingConfig val) { + recordingConfig = val; + return this; + } + + public Builder transcodeOptions(TranscodeOptions val) { + transcodeOptions = val; + return this; + } + + public Builder recordingFileConfig(RecordingFileConfig val) { + recordingFileConfig = val; + return this; + } + + public Builder snapshotConfig(SnapshotConfig val) { + snapshotConfig = val; + return this; + } + + public Builder storageConfig(StorageConfig val) { + storageConfig = val; + return this; + } + + public Builder extensionServiceConfig(ExtensionServiceConfig val) { + extensionServiceConfig = val; + return this; + } + + public StartClientRequest build() { + return new StartClientRequest(this); + } + } + } + + public static class AppsCollection { + + @JsonProperty("combinationPolicy") + private String combinationPolicy; + + public static Builder builder() { + return new Builder(); + } + + private AppsCollection(Builder builder) { + setCombinationPolicy(builder.combinationPolicy); + } + + public String getCombinationPolicy() { + return combinationPolicy; + } + + public void setCombinationPolicy(String combinationPolicy) { + this.combinationPolicy = combinationPolicy; + } + + @Override + public String toString() { + return "AppsCollection{" + + "combinationPolicy='" + combinationPolicy + '\'' + + '}'; + } + + public static final class Builder { + + private String combinationPolicy; + + private Builder() { + } + + public static Builder builder() { + return new Builder(); + } + + public Builder combinationPolicy(String val) { + combinationPolicy = val; + return this; + } + + public AppsCollection build() { + return new AppsCollection(this); + } + } + } + + public static class RecordingConfig { + + @JsonProperty("channelType") + private Integer channelType; + + @JsonProperty("streamTypes") + private Integer streamTypes; + + @JsonProperty("streamMode") + private String streamMode; + + @JsonProperty("decryptionMode") + private Integer decryptionMode; + + @JsonProperty("secret") + private String secret; + + @JsonProperty("salt") + private String salt; + + @JsonProperty("audioProfile") + private Integer audioProfile; + + @JsonProperty("videoStreamType") + private Integer videoStreamType; + + @JsonProperty("maxIdleTime") + private Integer maxIdleTime; + + @JsonProperty("transcodingConfig") + private TranscodingConfig transcodingConfig; + + @JsonProperty("subscribeAudioUids") + private List subscribeAudioUIDs; + + @JsonProperty("unSubscribeAudioUids") + private List unsubscribeAudioUIDs; + + @JsonProperty("subscribeVideoUids") + private List subscribeVideoUIDs; + + @JsonProperty("unSubscribeVideoUids") + private List unsubscribeVideoUIDs; + + @JsonProperty("subscribeUidGroup") + private Integer subscribeUidGroup; + + public static Builder builder() { + return new Builder(); + } + + private RecordingConfig(Builder builder) { + setChannelType(builder.channelType); + setStreamTypes(builder.streamTypes); + setStreamMode(builder.streamMode); + setDecryptionMode(builder.decryptionMode); + setSecret(builder.secret); + setSalt(builder.salt); + setAudioProfile(builder.audioProfile); + setVideoStreamType(builder.videoStreamType); + setMaxIdleTime(builder.maxIdleTime); + setTranscodingConfig(builder.transcodingConfig); + setSubscribeAudioUIDs(builder.subscribeAudioUIDs); + setUnsubscribeAudioUIDs(builder.unsubscribeAudioUIDs); + setSubscribeVideoUIDs(builder.subscribeVideoUIDs); + setUnsubscribeVideoUIDs(builder.unsubscribeVideoUIDs); + setSubscribeUidGroup(builder.subscribeUidGroup); + } + + public Integer getChannelType() { + return channelType; + } + + public void setChannelType(Integer channelType) { + this.channelType = channelType; + } + + public Integer getStreamTypes() { + return streamTypes; + } + + public void setStreamTypes(Integer streamTypes) { + this.streamTypes = streamTypes; + } + + public String getStreamMode() { + return streamMode; + } + + public void setStreamMode(String streamMode) { + this.streamMode = streamMode; + } + + public Integer getDecryptionMode() { + return decryptionMode; + } + + public void setDecryptionMode(Integer decryptionMode) { + this.decryptionMode = decryptionMode; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public String getSalt() { + return salt; + } + + public void setSalt(String salt) { + this.salt = salt; + } + + public Integer getAudioProfile() { + return audioProfile; + } + + public void setAudioProfile(Integer audioProfile) { + this.audioProfile = audioProfile; + } + + public Integer getVideoStreamType() { + return videoStreamType; + } + + public void setVideoStreamType(Integer videoStreamType) { + this.videoStreamType = videoStreamType; + } + + public Integer getMaxIdleTime() { + return maxIdleTime; + } + + public void setMaxIdleTime(Integer maxIdleTime) { + this.maxIdleTime = maxIdleTime; + } + + public TranscodingConfig getTranscodingConfig() { + return transcodingConfig; + } + + public void setTranscodingConfig(TranscodingConfig transcodingConfig) { + this.transcodingConfig = transcodingConfig; + } + + public List getSubscribeAudioUIDs() { + return subscribeAudioUIDs; + } + + public void setSubscribeAudioUIDs(List subscribeAudioUIDs) { + this.subscribeAudioUIDs = subscribeAudioUIDs; + } + + public List getUnsubscribeAudioUIDs() { + return unsubscribeAudioUIDs; + } + + public void setUnsubscribeAudioUIDs(List unsubscribeAudioUIDs) { + this.unsubscribeAudioUIDs = unsubscribeAudioUIDs; + } + + public List getSubscribeVideoUIDs() { + return subscribeVideoUIDs; + } + + public void setSubscribeVideoUIDs(List subscribeVideoUIDs) { + this.subscribeVideoUIDs = subscribeVideoUIDs; + } + + public List getUnsubscribeVideoUIDs() { + return unsubscribeVideoUIDs; + } + + public void setUnsubscribeVideoUIDs(List unsubscribeVideoUIDs) { + this.unsubscribeVideoUIDs = unsubscribeVideoUIDs; + } + + public Integer getSubscribeUidGroup() { + return subscribeUidGroup; + } + + public void setSubscribeUidGroup(Integer subscribeUidGroup) { + this.subscribeUidGroup = subscribeUidGroup; + } + + @Override + public String toString() { + return "RecordingConfig{" + + "channelType=" + channelType + + ", streamTypes=" + streamTypes + + ", streamMode='" + streamMode + '\'' + + ", decryptionMode=" + decryptionMode + + ", secret='" + secret + '\'' + + ", salt='" + salt + '\'' + + ", audioProfile=" + audioProfile + + ", videoStreamType=" + videoStreamType + + ", maxIdleTime=" + maxIdleTime + + ", transcodingConfig=" + transcodingConfig + + ", subscribeAudioUIDs=" + subscribeAudioUIDs + + ", unsubscribeAudioUIDs=" + unsubscribeAudioUIDs + + ", subscribeVideoUIDs=" + subscribeVideoUIDs + + ", unsubscribeVideoUIDs=" + unsubscribeVideoUIDs + + ", subscribeUidGroup=" + subscribeUidGroup + + '}'; + } + + public static final class Builder { + + private Integer channelType; + private Integer streamTypes; + private String streamMode; + private Integer decryptionMode; + private String secret; + private String salt; + private Integer audioProfile; + private Integer videoStreamType; + private Integer maxIdleTime; + private TranscodingConfig transcodingConfig; + private List subscribeAudioUIDs; + private List unsubscribeAudioUIDs; + private List subscribeVideoUIDs; + private List unsubscribeVideoUIDs; + private Integer subscribeUidGroup; + + private Builder() { + } + + public Builder channelType(Integer val) { + channelType = val; + return this; + } + + public Builder streamTypes(Integer val) { + streamTypes = val; + return this; + } + + public Builder streamMode(String val) { + streamMode = val; + return this; + } + + public Builder decryptionMode(Integer val) { + decryptionMode = val; + return this; + } + + public Builder secret(String val) { + secret = val; + return this; + } + + public Builder salt(String val) { + salt = val; + return this; + } + + public Builder audioProfile(Integer val) { + audioProfile = val; + return this; + } + + public Builder videoStreamType(Integer val) { + videoStreamType = val; + return this; + } + + public Builder maxIdleTime(Integer val) { + maxIdleTime = val; + return this; + } + + public Builder transcodingConfig(TranscodingConfig val) { + transcodingConfig = val; + return this; + } + + public Builder subscribeAudioUIDs(List val) { + subscribeAudioUIDs = val; + return this; + } + + public Builder unsubscribeAudioUIDs(List val) { + unsubscribeAudioUIDs = val; + return this; + } + + public Builder subscribeVideoUIDs(List val) { + subscribeVideoUIDs = val; + return this; + } + + public Builder unsubscribeVideoUIDs(List val) { + unsubscribeVideoUIDs = val; + return this; + } + + public Builder subscribeUidGroup(Integer val) { + subscribeUidGroup = val; + return this; + } + + public RecordingConfig build() { + return new RecordingConfig(this); + } + } + } + + public static class Container { + + @JsonProperty("format") + private String format; + + public static Builder builder() { + return new Builder(); + } + + private Container(Builder builder) { + setFormat(builder.format); + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + @Override + public String toString() { + return "Container{" + + "format='" + format + '\'' + + '}'; + } + + public static final class Builder { + + private String format; + + private Builder() { + } + + public Builder format(String val) { + format = val; + return this; + } + + public Container build() { + return new Container(this); + } + } + } + + public static class TranscodeOptions { + + @JsonProperty("container") + private Container container; + + @JsonProperty("transConfig") + private TransConfig transConfig; + + @JsonProperty("audio") + private Audio audio; + + public static Builder builder() { + return new Builder(); + } + + private TranscodeOptions(Builder builder) { + setContainer(builder.container); + setTransConfig(builder.transConfig); + setAudio(builder.audio); + } + + public Container getContainer() { + return container; + } + + public void setContainer(Container container) { + this.container = container; + } + + public TransConfig getTransConfig() { + return transConfig; + } + + public void setTransConfig(TransConfig transConfig) { + this.transConfig = transConfig; + } + + public Audio getAudio() { + return audio; + } + + public void setAudio(Audio audio) { + this.audio = audio; + } + + @Override + public String toString() { + return "TranscodeOptions{" + + "container=" + container + + ", transConfig=" + transConfig + + ", audio=" + audio + + '}'; + } + + public static final class Builder { + + private Container container; + private TransConfig transConfig; + private Audio audio; + + private Builder() { + } + + public Builder container(Container val) { + container = val; + return this; + } + + public Builder transConfig(TransConfig val) { + transConfig = val; + return this; + } + + public Builder audio(Audio val) { + audio = val; + return this; + } + + public TranscodeOptions build() { + return new TranscodeOptions(this); + } + } + } + + public static class TransConfig { + + @JsonProperty("transMode") + private String transMode; + + public static Builder builder() { + return new Builder(); + } + + private TransConfig(Builder builder) { + setTransMode(builder.transMode); + } + + public String getTransMode() { + return transMode; + } + + public void setTransMode(String transMode) { + this.transMode = transMode; + } + + @Override + public String toString() { + return "TransConfig{" + + "transMode='" + transMode + '\'' + + '}'; + } + + public static final class Builder { + + private String transMode; + + private Builder() { + } + + public Builder transMode(String val) { + transMode = val; + return this; + } + + public TransConfig build() { + return new TransConfig(this); + } + } + } + + public static class Audio { + + @JsonProperty("sampleRate") + private String sampleRate; + + @JsonProperty("bitrate") + private String bitRate; + + @JsonProperty("channels") + private String channels; + + public static Builder builder() { + return new Builder(); + } + + private Audio(Builder builder) { + setSampleRate(builder.sampleRate); + setBitRate(builder.bitRate); + setChannels(builder.channels); + } + + public String getSampleRate() { + return sampleRate; + } + + public void setSampleRate(String sampleRate) { + this.sampleRate = sampleRate; + } + + public String getBitRate() { + return bitRate; + } + + public void setBitRate(String bitRate) { + this.bitRate = bitRate; + } + + public String getChannels() { + return channels; + } + + public void setChannels(String channels) { + this.channels = channels; + } + + @Override + public String toString() { + return "Audio{" + + "sampleRate='" + sampleRate + '\'' + + ", bitRate='" + bitRate + '\'' + + ", channels='" + channels + '\'' + + '}'; + } + + public static final class Builder { + + private String sampleRate; + + private String bitRate; + + private String channels; + + private Builder() { + } + + public Builder sampleRate(String val) { + sampleRate = val; + return this; + } + + public Builder bitRate(String val) { + bitRate = val; + return this; + } + + public Builder channels(String val) { + channels = val; + return this; + } + + public Audio build() { + return new Audio(this); + } + } + } + + public static class TranscodingConfig { + + @JsonProperty("width") + private Integer width; + + @JsonProperty("height") + private Integer height; + + @JsonProperty("fps") + private Integer fps; + + @JsonProperty("bitrate") + private Integer bitrate; + + @JsonProperty("maxResolutionUid") + private String maxResolutionUid; + + @JsonProperty("mixedVideoLayout") + private Integer mixedVideoLayout; + + @JsonProperty("backgroundColor") + private String backgroundColor; + + @JsonProperty("backgroundImage") + private String backgroundImage; + + @JsonProperty("defaultUserBackgroundImage") + private String defaultUserBackgroundImage; + + @JsonProperty("layoutConfig") + private List layoutConfig; + + @JsonProperty("backgroundConfig") + private List backgroundConfig; + + public static Builder builder() { + return new Builder(); + } + + private TranscodingConfig(Builder builder) { + setWidth(builder.width); + setHeight(builder.height); + setFps(builder.fps); + setBitrate(builder.bitrate); + setMaxResolutionUid(builder.maxResolutionUid); + setMixedVideoLayout(builder.mixedVideoLayout); + setBackgroundColor(builder.backgroundColor); + setBackgroundImage(builder.backgroundImage); + setDefaultUserBackgroundImage(builder.defaultUserBackgroundImage); + setLayoutConfig(builder.layoutConfig); + setBackgroundConfig(builder.backgroundConfig); + } + + public Integer getWidth() { + return width; + } + + public void setWidth(Integer width) { + this.width = width; + } + + public Integer getHeight() { + return height; + } + + public void setHeight(Integer height) { + this.height = height; + } + + public Integer getFps() { + return fps; + } + + public void setFps(Integer fps) { + this.fps = fps; + } + + public Integer getBitrate() { + return bitrate; + } + + public void setBitrate(Integer bitrate) { + this.bitrate = bitrate; + } + + public String getMaxResolutionUid() { + return maxResolutionUid; + } + + public void setMaxResolutionUid(String maxResolutionUid) { + this.maxResolutionUid = maxResolutionUid; + } + + public Integer getMixedVideoLayout() { + return mixedVideoLayout; + } + + public void setMixedVideoLayout(Integer mixedVideoLayout) { + this.mixedVideoLayout = mixedVideoLayout; + } + + public String getBackgroundColor() { + return backgroundColor; + } + + public void setBackgroundColor(String backgroundColor) { + this.backgroundColor = backgroundColor; + } + + public String getBackgroundImage() { + return backgroundImage; + } + + public void setBackgroundImage(String backgroundImage) { + this.backgroundImage = backgroundImage; + } + + public String getDefaultUserBackgroundImage() { + return defaultUserBackgroundImage; + } + + public void setDefaultUserBackgroundImage(String defaultUserBackgroundImage) { + this.defaultUserBackgroundImage = defaultUserBackgroundImage; + } + + public List getLayoutConfig() { + return layoutConfig; + } + + public void setLayoutConfig(List layoutConfig) { + this.layoutConfig = layoutConfig; + } + + public List getBackgroundConfig() { + return backgroundConfig; + } + + public void setBackgroundConfig(List backgroundConfig) { + this.backgroundConfig = backgroundConfig; + } + + @Override + public String toString() { + return "TranscodingConfig{" + + "width=" + width + + ", height=" + height + + ", fps=" + fps + + ", bitrate=" + bitrate + + ", maxResolutionUid='" + maxResolutionUid + '\'' + + ", mixedVideoLayout=" + mixedVideoLayout + + ", backgroundColor='" + backgroundColor + '\'' + + ", backgroundImage='" + backgroundImage + '\'' + + ", defaultUserBackgroundImage='" + defaultUserBackgroundImage + '\'' + + ", layoutConfig=" + layoutConfig + + ", backgroundConfig=" + backgroundConfig + + '}'; + } + + public static final class Builder { + + private Integer width; + + private Integer height; + + private Integer fps; + + private Integer bitrate; + + private String maxResolutionUid; + + private Integer mixedVideoLayout; + + private String backgroundColor; + + private String backgroundImage; + + private String defaultUserBackgroundImage; + + private List layoutConfig; + + private List backgroundConfig; + + private Builder() { + } + + public Builder width(Integer val) { + width = val; + return this; + } + + public Builder height(Integer val) { + height = val; + return this; + } + + public Builder fps(Integer val) { + fps = val; + return this; + } + + public Builder bitrate(Integer val) { + bitrate = val; + return this; + } + + public Builder maxResolutionUid(String val) { + maxResolutionUid = val; + return this; + } + + public Builder mixedVideoLayout(Integer val) { + mixedVideoLayout = val; + return this; + } + + public Builder backgroundColor(String val) { + backgroundColor = val; + return this; + } + + public Builder backgroundImage(String val) { + backgroundImage = val; + return this; + } + + public Builder defaultUserBackgroundImage(String val) { + defaultUserBackgroundImage = val; + return this; + } + + public Builder layoutConfig(List val) { + layoutConfig = val; + return this; + } + + public Builder backgroundConfig(List val) { + backgroundConfig = val; + return this; + } + + public TranscodingConfig build() { + return new TranscodingConfig(this); + } + } + } + + public static class LayoutConfig { + + @JsonProperty("uid") + private String uid; + + @JsonProperty("x_axis") + private Float xAxis; + + @JsonProperty("y_axis") + private Float yAxis; + + @JsonProperty("width") + private Float width; + + @JsonProperty("height") + private Float height; + + @JsonProperty("alpha") + private Float alpha; + + @JsonProperty("render_mode") + private Integer renderMode; + + public static Builder builder() { + return new Builder(); + } + + private LayoutConfig(Builder builder) { + setUid(builder.uid); + setxAxis(builder.xAxis); + setyAxis(builder.yAxis); + setWidth(builder.width); + setHeight(builder.height); + setAlpha(builder.alpha); + setRenderMode(builder.renderMode); + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public Float getxAxis() { + return xAxis; + } + + public void setxAxis(Float xAxis) { + this.xAxis = xAxis; + } + + public Float getyAxis() { + return yAxis; + } + + public void setyAxis(Float yAxis) { + this.yAxis = yAxis; + } + + public Float getWidth() { + return width; + } + + public void setWidth(Float width) { + this.width = width; + } + + public Float getHeight() { + return height; + } + + public void setHeight(Float height) { + this.height = height; + } + + public Float getAlpha() { + return alpha; + } + + public void setAlpha(Float alpha) { + this.alpha = alpha; + } + + public Integer getRenderMode() { + return renderMode; + } + + public void setRenderMode(Integer renderMode) { + this.renderMode = renderMode; + } + + @Override + public String toString() { + return "LayoutConfig{" + + "uid='" + uid + '\'' + + ", xAxis=" + xAxis + + ", yAxis=" + yAxis + + ", width=" + width + + ", height=" + height + + ", alpha=" + alpha + + ", renderMode=" + renderMode + + '}'; + } + + public static final class Builder { + + private String uid; + + private Float xAxis; + + private Float yAxis; + + private Float width; + + private Float height; + + private Float alpha; + + private Integer renderMode; + + private Builder() { + } + + public Builder uid(String val) { + uid = val; + return this; + } + + public Builder yAxis(Float val) { + yAxis = val; + return this; + } + + public Builder xAxis(Float val) { + xAxis = val; + return this; + } + + public Builder width(Float val) { + width = val; + return this; + } + + public Builder height(Float val) { + height = val; + return this; + } + + public Builder alpha(Float val) { + alpha = val; + return this; + } + + public Builder renderMode(Integer val) { + renderMode = val; + return this; + } + + public LayoutConfig build() { + return new LayoutConfig(this); + } + } + } + + public static class RecordingFileConfig { + + @JsonProperty("avFileType") + private List avFileType; + + public static Builder builder() { + return new Builder(); + } + + private RecordingFileConfig(Builder builder) { + setAvFileType(builder.avFileType); + } + + public List getAvFileType() { + return avFileType; + } + + public void setAvFileType(List avFileType) { + this.avFileType = avFileType; + } + + @Override + public String toString() { + return "RecordingFileConfig{" + + "avFileType=" + avFileType + + '}'; + } + + public static final class Builder { + + private List avFileType; + + private Builder() { + } + + public Builder avFileType(List val) { + avFileType = val; + return this; + } + + public RecordingFileConfig build() { + return new RecordingFileConfig(this); + } + } + } + + public static class SnapshotConfig { + + @JsonProperty("captureInterval") + private Integer captureInterval; + + @JsonProperty("fileType") + private List fileType; + + public static Builder builder() { + return new Builder(); + } + + private SnapshotConfig(Builder builder) { + setCaptureInterval(builder.captureInterval); + setFileType(builder.fileType); + } + + public Integer getCaptureInterval() { + return captureInterval; + } + + public void setCaptureInterval(Integer captureInterval) { + this.captureInterval = captureInterval; + } + + public List getFileType() { + return fileType; + } + + public void setFileType(List fileType) { + this.fileType = fileType; + } + + @Override + public String toString() { + return "SnapshotConfig{" + + "captureInterval=" + captureInterval + + ", fileType=" + fileType + + '}'; + } + + public static final class Builder { + + private Integer captureInterval; + + private List fileType; + + private Builder() { + } + + public Builder captureInterval(Integer val) { + captureInterval = val; + return this; + } + + public Builder fileType(List val) { + fileType = val; + return this; + } + + public SnapshotConfig build() { + return new SnapshotConfig(this); + } + } + } + + public static class StorageConfig { + + @JsonProperty("vendor") + private Integer vendor; + + @JsonProperty("region") + private Integer region; + + @JsonProperty("bucket") + private String bucket; + + @JsonProperty("accessKey") + private String accessKey; + + @JsonProperty("secretKey") + private String secretKey; + + @JsonProperty("fileNamePrefix") + private List fileNamePrefix; + + @JsonProperty("stsToken") + private String stsToken; + + @JsonProperty("stsExpiration") + private Integer stsExpiration; + + @JsonProperty("extensionParams") + private ExtensionParams extensionParams; + + public static Builder builder() { + return new Builder(); + } + + private StorageConfig(Builder builder) { + setVendor(builder.vendor); + setRegion(builder.region); + setBucket(builder.bucket); + setAccessKey(builder.accessKey); + setSecretKey(builder.secretKey); + setFileNamePrefix(builder.fileNamePrefix); + setStsToken(builder.stsToken); + setStsExpiration(builder.stsExpiration); + setExtensionParams(builder.extensionParams); + } + + public Integer getVendor() { + return vendor; + } + + public void setVendor(Integer vendor) { + this.vendor = vendor; + } + + public Integer getRegion() { + return region; + } + + public void setRegion(Integer region) { + this.region = region; + } + + public String getBucket() { + return bucket; + } + + public void setBucket(String bucket) { + this.bucket = bucket; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public List getFileNamePrefix() { + return fileNamePrefix; + } + + public void setFileNamePrefix(List fileNamePrefix) { + this.fileNamePrefix = fileNamePrefix; + } + + public String getStsToken() { + return stsToken; + } + + public void setStsToken(String stsToken) { + this.stsToken = stsToken; + } + + public Integer getStsExpiration() { + return stsExpiration; + } + + public void setStsExpiration(Integer stsExpiration) { + this.stsExpiration = stsExpiration; + } + + public ExtensionParams getExtensionParams() { + return extensionParams; + } + + public void setExtensionParams(ExtensionParams extensionParams) { + this.extensionParams = extensionParams; + } + + @Override + public String toString() { + return "StorageConfig{" + + "vendor=" + vendor + + ", region=" + region + + ", bucket='" + bucket + '\'' + + ", accessKey='" + accessKey + '\'' + + ", secretKey='" + secretKey + '\'' + + ", fileNamePrefix=" + fileNamePrefix + + ", stsToken='" + stsToken + '\'' + + ", stsExpiration=" + stsExpiration + + ", extensionParams=" + extensionParams + + '}'; + } + + public static final class Builder { + + private Integer vendor; + + private Integer region; + + private String bucket; + + private String accessKey; + + private String secretKey; + + private List fileNamePrefix; + + private String stsToken; + + private Integer stsExpiration; + + private ExtensionParams extensionParams; + + private Builder() { + } + + public Builder vendor(Integer val) { + vendor = val; + return this; + } + + public Builder region(Integer val) { + region = val; + return this; + } + + public Builder bucket(String val) { + bucket = val; + return this; + } + + public Builder accessKey(String val) { + accessKey = val; + return this; + } + + public Builder secretKey(String val) { + secretKey = val; + return this; + } + + public Builder fileNamePrefix(List val) { + fileNamePrefix = val; + return this; + } + + public Builder stsToken(String val) { + stsToken = val; + return this; + } + + public Builder stsExpiration(Integer val) { + stsExpiration = val; + return this; + } + + public Builder extensionParams(ExtensionParams val) { + extensionParams = val; + return this; + } + + public StorageConfig build() { + return new StorageConfig(this); + } + } + } + + public static class ExtensionParams { + + @JsonProperty("sse") + private String sse; + + @JsonProperty("tag") + private String tag; + + public static Builder builder() { + return new Builder(); + } + + private ExtensionParams(Builder builder) { + setSse(builder.sse); + setTag(builder.tag); + } + + public String getSse() { + return sse; + } + + public void setSse(String sse) { + this.sse = sse; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + @Override + public String toString() { + return "ExtensionParams{" + + "sse='" + sse + '\'' + + ", tag='" + tag + '\'' + + '}'; + } + + public static final class Builder { + + private String sse; + + private String tag; + + private Builder() { + } + + public Builder sse(String val) { + sse = val; + return this; + } + + public Builder tag(String val) { + tag = val; + return this; + } + + public ExtensionParams build() { + return new ExtensionParams(this); + } + } + } + + public static class ExtensionServiceConfig { + + @JsonProperty("errorHandlePolicy") + private String errorHandlePolicy; + + @JsonProperty("extensionServices") + private List extensionServices; + + @JsonProperty("serviceParam") + private ServiceParam serviceParam; + + public static Builder builder() { + return new Builder(); + } + + private ExtensionServiceConfig(Builder builder) { + setErrorHandlePolicy(builder.errorHandlePolicy); + setExtensionServices(builder.extensionServices); + setServiceParam(builder.serviceParam); + } + + public String getErrorHandlePolicy() { + return errorHandlePolicy; + } + + public void setErrorHandlePolicy(String errorHandlePolicy) { + this.errorHandlePolicy = errorHandlePolicy; + } + + public List getExtensionServices() { + return extensionServices; + } + + public void setExtensionServices(List extensionServices) { + this.extensionServices = extensionServices; + } + + public ServiceParam getServiceParam() { + return serviceParam; + } + + public void setServiceParam(ServiceParam serviceParam) { + this.serviceParam = serviceParam; + } + + @Override + public String toString() { + return "ExtensionServiceConfig{" + + "errorHandlePolicy='" + errorHandlePolicy + '\'' + + ", extensionServices=" + extensionServices + + ", serviceParam=" + serviceParam + + '}'; + } + + public static final class Builder { + + private String errorHandlePolicy; + + private List extensionServices; + + private ServiceParam serviceParam; + + private Builder() { + } + + public Builder errorHandlePolicy(String val) { + errorHandlePolicy = val; + return this; + } + + public Builder extensionServices(List val) { + extensionServices = val; + return this; + } + + public Builder serviceParam(ServiceParam val) { + serviceParam = val; + return this; + } + + public ExtensionServiceConfig build() { + return new ExtensionServiceConfig(this); + } + } + } + + public static class ExtensionService { + + @JsonProperty("serviceName") + private String serviceName; + + @JsonProperty("errorHandlePolicy") + private String errorHandlePolicy; + + @JsonProperty("serviceParam") + private ServiceParam serviceParam; + + public static Builder builder() { + return new Builder(); + } + + private ExtensionService(Builder builder) { + setServiceName(builder.serviceName); + setErrorHandlePolicy(builder.errorHandlePolicy); + setServiceParam(builder.serviceParam); + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getErrorHandlePolicy() { + return errorHandlePolicy; + } + + public void setErrorHandlePolicy(String errorHandlePolicy) { + this.errorHandlePolicy = errorHandlePolicy; + } + + public ServiceParam getServiceParam() { + return serviceParam; + } + + public void setServiceParam(ServiceParam serviceParam) { + this.serviceParam = serviceParam; + } + + @Override + public String toString() { + return "ExtensionService{" + + "serviceName='" + serviceName + '\'' + + ", errorHandlePolicy='" + errorHandlePolicy + '\'' + + ", serviceParam=" + serviceParam + + '}'; + } + + public static final class Builder { + + private String serviceName; + + private String errorHandlePolicy; + + private ServiceParam serviceParam; + + private Builder() { + } + + public Builder serviceName(String val) { + serviceName = val; + return this; + } + + public Builder errorHandlePolicy(String val) { + errorHandlePolicy = val; + return this; + } + + public Builder serviceParam(ServiceParam val) { + serviceParam = val; + return this; + } + + public ExtensionService build() { + return new ExtensionService(this); + } + } + } + + public static class Outputs { + + @JsonProperty("rtmpUrl") + private String rtmpUrl; + + public static Builder builder() { + return new Builder(); + } + + private Outputs(Builder builder) { + setRtmpUrl(builder.rtmpUrl); + } + + public String getRtmpUrl() { + return rtmpUrl; + } + + public void setRtmpUrl(String rtmpUrl) { + this.rtmpUrl = rtmpUrl; + } + + @Override + public String toString() { + return "Outputs{" + + "rtmpUrl='" + rtmpUrl + '\'' + + '}'; + } + + public static final class Builder { + private String rtmpUrl; + + private Builder() { + } + + public Builder rtmpUrl(String val) { + rtmpUrl = val; + return this; + } + + public Outputs build() { + return new Outputs(this); + } + } + } + + public static class WebRecordingServiceParam implements ServiceParam { + + @JsonProperty("url") + private String url; + + @JsonProperty("VideoBitrate") + private Integer videoBitRate; + + @JsonProperty("videoFps") + private Integer videoFPS; + + @JsonProperty("audioProfile") + private Integer audioProfile; + + @JsonProperty("mobile") + private Boolean mobile; + + @JsonProperty("videoWidth") + private Integer videoWidth; + + @JsonProperty("videoHeight") + private Integer videoHeight; + + @JsonProperty("maxRecordingHour") + private Integer maxRecordingHour; + + @JsonProperty("maxVideoDuration") + private Integer maxVideoDuration; + + @JsonProperty("onhold") + private Boolean onhold; + + @JsonProperty("readyTimeout") + private Integer readyTimeout; + + public static Builder builder() { + return new Builder(); + } + + private WebRecordingServiceParam(Builder builder) { + setUrl(builder.url); + setVideoBitRate(builder.videoBitRate); + setVideoFPS(builder.videoFPS); + setAudioProfile(builder.audioProfile); + setMobile(builder.mobile); + setVideoWidth(builder.videoWidth); + setVideoHeight(builder.videoHeight); + setMaxRecordingHour(builder.maxRecordingHour); + setMaxVideoDuration(builder.maxVideoDuration); + setOnhold(builder.onhold); + setReadyTimeout(builder.readyTimeout); + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public Integer getVideoBitRate() { + return videoBitRate; + } + + public void setVideoBitRate(Integer videoBitRate) { + this.videoBitRate = videoBitRate; + } + + public Integer getVideoFPS() { + return videoFPS; + } + + public void setVideoFPS(Integer videoFPS) { + this.videoFPS = videoFPS; + } + + public Integer getAudioProfile() { + return audioProfile; + } + + public void setAudioProfile(Integer audioProfile) { + this.audioProfile = audioProfile; + } + + public Boolean getMobile() { + return mobile; + } + + public void setMobile(Boolean mobile) { + this.mobile = mobile; + } + + public Integer getVideoWidth() { + return videoWidth; + } + + public void setVideoWidth(Integer videoWidth) { + this.videoWidth = videoWidth; + } + + public Integer getVideoHeight() { + return videoHeight; + } + + public void setVideoHeight(Integer videoHeight) { + this.videoHeight = videoHeight; + } + + public Integer getMaxRecordingHour() { + return maxRecordingHour; + } + + public void setMaxRecordingHour(Integer maxRecordingHour) { + this.maxRecordingHour = maxRecordingHour; + } + + public Integer getMaxVideoDuration() { + return maxVideoDuration; + } + + public void setMaxVideoDuration(Integer maxVideoDuration) { + this.maxVideoDuration = maxVideoDuration; + } + + public Boolean getOnhold() { + return onhold; + } + + public void setOnhold(Boolean onhold) { + this.onhold = onhold; + } + + public Integer getReadyTimeout() { + return readyTimeout; + } + + public void setReadyTimeout(Integer readyTimeout) { + this.readyTimeout = readyTimeout; + } + + @Override + public String toString() { + return "WebRecordingServiceParam{" + + "url='" + url + '\'' + + ", videoBitRate=" + videoBitRate + + ", videoFPS=" + videoFPS + + ", audioProfile=" + audioProfile + + ", mobile=" + mobile + + ", videoWidth=" + videoWidth + + ", videoHeight=" + videoHeight + + ", maxRecordingHour=" + maxRecordingHour + + ", maxVideoDuration=" + maxVideoDuration + + ", onhold=" + onhold + + ", readyTimeout=" + readyTimeout + + '}'; + } + + public static final class Builder { + + private String url; + + private Integer videoBitRate; + + private Integer videoFPS; + + private Integer audioProfile; + + private Boolean mobile; + + private Integer videoWidth; + + private Integer videoHeight; + + private Integer maxRecordingHour; + + private Integer maxVideoDuration; + + private Boolean onhold; + + private Integer readyTimeout; + + private Builder() { + } + + public Builder url(String val) { + url = val; + return this; + } + + public Builder videoBitRate(Integer val) { + videoBitRate = val; + return this; + } + + public Builder videoFPS(Integer val) { + videoFPS = val; + return this; + } + + public Builder audioProfile(Integer val) { + audioProfile = val; + return this; + } + + public Builder mobile(Boolean val) { + mobile = val; + return this; + } + + public Builder videoWidth(Integer val) { + videoWidth = val; + return this; + } + + public Builder videoHeight(Integer val) { + videoHeight = val; + return this; + } + + public Builder maxRecordingHour(Integer val) { + maxRecordingHour = val; + return this; + } + + public Builder maxVideoDuration(Integer val) { + maxVideoDuration = val; + return this; + } + + public Builder onhold(Boolean val) { + onhold = val; + return this; + } + + public Builder readyTimeout(Integer val) { + readyTimeout = val; + return this; + } + + public WebRecordingServiceParam build() { + return new WebRecordingServiceParam(this); + } + } + } + + public static class RtmpPublishServiceParam implements ServiceParam { + + @JsonProperty("outputs") + private List outputs; + + public static Builder builder() { + return new Builder(); + } + + private RtmpPublishServiceParam(Builder builder) { + setOutputs(builder.outputs); + } + + public List getOutputs() { + return outputs; + } + + public void setOutputs(List outputs) { + this.outputs = outputs; + } + + @Override + public String toString() { + return "RtmpPublishServiceParam{" + + "outputs=" + outputs + + '}'; + } + + public static final class Builder { + + private List outputs; + + private Builder() { + } + + public Builder outputs(List val) { + outputs = val; + return this; + } + + public RtmpPublishServiceParam build() { + return new RtmpPublishServiceParam(this); + } + } + } + + public static class BackgroundConfig { + + @JsonProperty("uid") + private String uid; + + @JsonProperty("image_url") + private String imageUrl; + + @JsonProperty("render_mode") + private Integer renderMode; + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + public Integer getRenderMode() { + return renderMode; + } + + public void setRenderMode(Integer renderMode) { + this.renderMode = renderMode; + } + + @Override + public String toString() { + return "BackgroundConfig{" + + "uid='" + uid + '\'' + + ", imageUrl='" + imageUrl + '\'' + + ", renderMode=" + renderMode + + '}'; + } + } + + public static class Builder { + + private String cname; + + private String uid; + + private StartClientRequest clientRequest; + + private Builder() { + } + + public Builder cname(String cname) { + this.cname = cname; + return this; + } + + public Builder uid(String uid) { + this.uid = uid; + return this; + } + + public Builder clientRequest(StartClientRequest clientRequest) { + this.clientRequest = clientRequest; + return this; + } + + public StartResourceReq build() { + StartResourceReq startResourceReq = new StartResourceReq(); + startResourceReq.setCname(cname); + startResourceReq.setUid(uid); + startResourceReq.setClientRequest(clientRequest); + return startResourceReq; + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/StopResourceReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/StopResourceReq.java new file mode 100644 index 0000000..15eed6e --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/StopResourceReq.java @@ -0,0 +1,133 @@ +package io.agora.rest.services.cloudrecording.api.req; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class StopResourceReq { + + @JsonProperty("cname") + private String cname; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("clientRequest") + private StopClientRequest clientRequest; + + public static Builder builder() { + return new Builder(); + } + + private StopResourceReq(Builder builder) { + setCname(builder.cname); + setUid(builder.uid); + setClientRequest(builder.clientRequest); + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public StopClientRequest getClientRequest() { + return clientRequest; + } + + public void setClientRequest(StopClientRequest clientRequest) { + this.clientRequest = clientRequest; + } + + @Override + public String toString() { + return "StopResourceReq{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", clientRequest=" + clientRequest + + '}'; + } + + public static class StopClientRequest { + @JsonProperty("async_stop") + private boolean asyncStop; + + public static Builder builder() { + return new Builder(); + } + + private StopClientRequest(Builder builder) { + setAsyncStop(builder.asyncStop); + } + + public boolean isAsyncStop() { + return asyncStop; + } + + public void setAsyncStop(boolean asyncStop) { + this.asyncStop = asyncStop; + } + + @Override + public String toString() { + return "StopClientRequest{" + + "asyncStop=" + asyncStop + + '}'; + } + + public static final class Builder { + private boolean asyncStop; + + private Builder() { + } + + public Builder asyncStop(boolean val) { + asyncStop = val; + return this; + } + + public StopClientRequest build() { + return new StopClientRequest(this); + } + } + } + + public static final class Builder { + + private String cname; + + private String uid; + + private StopClientRequest clientRequest; + + private Builder() { + } + + public Builder cname(String val) { + cname = val; + return this; + } + + public Builder uid(String val) { + uid = val; + return this; + } + + public Builder clientRequest(StopClientRequest val) { + clientRequest = val; + return this; + } + + public StopResourceReq build() { + return new StopResourceReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/UpdateLayoutResourceReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/UpdateLayoutResourceReq.java new file mode 100644 index 0000000..5bb02f2 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/UpdateLayoutResourceReq.java @@ -0,0 +1,497 @@ +package io.agora.rest.services.cloudrecording.api.req; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public class UpdateLayoutResourceReq { + + @JsonProperty("cname") + private String cname; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("clientRequest") + private ClientRequest clientRequest; + + private UpdateLayoutResourceReq(Builder builder) { + this.cname = builder.cname; + this.uid = builder.uid; + this.clientRequest = builder.clientRequest; + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public ClientRequest getClientRequest() { + return clientRequest; + } + + public void setClientRequest(ClientRequest clientRequest) { + this.clientRequest = clientRequest; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private String cname; + + private String uid; + + private ClientRequest clientRequest; + + private Builder() { + } + + public Builder cname(String cname) { + this.cname = cname; + return this; + } + + public Builder uid(String uid) { + this.uid = uid; + return this; + } + + public Builder clientRequest(ClientRequest clientRequest) { + this.clientRequest = clientRequest; + return this; + } + + public UpdateLayoutResourceReq build() { + return new UpdateLayoutResourceReq(this); + } + } + + public static class ClientRequest { + + @JsonProperty("maxResolutionUid") + private String maxResolutionUID; + + @JsonProperty("mixedVideoLayout") + private int mixedVideoLayout; + + @JsonProperty("backgroundColor") + private String backgroundColor; + + @JsonProperty("backgroundImage") + private String backgroundImage; + + @JsonProperty("defaultUserBackgroundImage") + private String defaultUserBackgroundImage; + + @JsonProperty("layoutConfig") + private List layoutConfig; + + @JsonProperty("backgroundConfig") + private List backgroundConfig; + + private ClientRequest(Builder builder) { + this.maxResolutionUID = builder.maxResolutionUID; + this.mixedVideoLayout = builder.mixedVideoLayout; + this.backgroundColor = builder.backgroundColor; + this.backgroundImage = builder.backgroundImage; + this.defaultUserBackgroundImage = builder.defaultUserBackgroundImage; + this.layoutConfig = builder.layoutConfig; + this.backgroundConfig = builder.backgroundConfig; + } + + public String getMaxResolutionUID() { + return maxResolutionUID; + } + + public void setMaxResolutionUID(String maxResolutionUID) { + this.maxResolutionUID = maxResolutionUID; + } + + public int getMixedVideoLayout() { + return mixedVideoLayout; + } + + public void setMixedVideoLayout(int mixedVideoLayout) { + this.mixedVideoLayout = mixedVideoLayout; + } + + public String getBackgroundColor() { + return backgroundColor; + } + + public void setBackgroundColor(String backgroundColor) { + this.backgroundColor = backgroundColor; + } + + public String getBackgroundImage() { + return backgroundImage; + } + + public void setBackgroundImage(String backgroundImage) { + this.backgroundImage = backgroundImage; + } + + public String getDefaultUserBackgroundImage() { + return defaultUserBackgroundImage; + } + + public void setDefaultUserBackgroundImage(String defaultUserBackgroundImage) { + this.defaultUserBackgroundImage = defaultUserBackgroundImage; + } + + public List getLayoutConfig() { + return layoutConfig; + } + + public void setLayoutConfig(List layoutConfig) { + this.layoutConfig = layoutConfig; + } + + public List getBackgroundConfig() { + return backgroundConfig; + } + + public void setBackgroundConfig(List backgroundConfig) { + this.backgroundConfig = backgroundConfig; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private String maxResolutionUID; + + private int mixedVideoLayout; + + private String backgroundColor; + + private String backgroundImage; + + private String defaultUserBackgroundImage; + + private List layoutConfig; + + private List backgroundConfig; + + private Builder() { + } + + public Builder maxResolutionUID(String maxResolutionUID) { + this.maxResolutionUID = maxResolutionUID; + return this; + } + + public Builder mixedVideoLayout(int mixedVideoLayout) { + this.mixedVideoLayout = mixedVideoLayout; + return this; + } + + public Builder backgroundColor(String backgroundColor) { + this.backgroundColor = backgroundColor; + return this; + } + + public Builder backgroundImage(String backgroundImage) { + this.backgroundImage = backgroundImage; + return this; + } + + public Builder defaultUserBackgroundImage(String defaultUserBackgroundImage) { + this.defaultUserBackgroundImage = defaultUserBackgroundImage; + return this; + } + + public Builder layoutConfig(List layoutConfig) { + this.layoutConfig = layoutConfig; + return this; + } + + public Builder backgroundConfig(List backgroundConfig) { + this.backgroundConfig = backgroundConfig; + return this; + } + + public ClientRequest build() { + return new ClientRequest(this); + } + } + + @Override + public String toString() { + return "ClientRequest{" + + "maxResolutionUID='" + maxResolutionUID + '\'' + + ", mixedVideoLayout=" + mixedVideoLayout + + ", backgroundColor='" + backgroundColor + '\'' + + ", backgroundImage='" + backgroundImage + '\'' + + ", defaultUserBackgroundImage='" + defaultUserBackgroundImage + '\'' + + ", layoutConfig=" + layoutConfig + + ", backgroundConfig=" + backgroundConfig + + '}'; + } + } + + public static class LayoutConfig { + + @JsonProperty("uid") + private String uid; + + @JsonProperty("x_axis") + private Float xAxis; + + @JsonProperty("y_axis") + private Float yAxis; + + @JsonProperty("width") + private Float width; + + @JsonProperty("height") + private Float height; + + @JsonProperty("alpha") + private Float alpha; + + @JsonProperty("render_mode") + private Integer renderMode; + + private LayoutConfig(Builder builder) { + this.uid = builder.uid; + this.xAxis = builder.xAxis; + this.yAxis = builder.yAxis; + this.width = builder.width; + this.height = builder.height; + this.alpha = builder.alpha; + this.renderMode = builder.renderMode; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public Float getXAxis() { + return xAxis; + } + + public void setXAxis(Float xAxis) { + this.xAxis = xAxis; + } + + public Float getYAxis() { + return yAxis; + } + + public void setYAxis(Float yAxis) { + this.yAxis = yAxis; + } + + public Float getWidth() { + return width; + } + + public void setWidth(Float width) { + this.width = width; + } + + public Float getHeight() { + return height; + } + + public void setHeight(Float height) { + this.height = height; + } + + public Float getAlpha() { + return alpha; + } + + public void setAlpha(Float alpha) { + this.alpha = alpha; + } + + public Integer getRenderMode() { + return renderMode; + } + + public void setRenderMode(Integer renderMode) { + this.renderMode = renderMode; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private String uid; + + private Float xAxis; + + private Float yAxis; + + private Float width; + + private Float height; + + private Float alpha; + + private Integer renderMode; + + private Builder() { + } + + public Builder uid(String uid) { + this.uid = uid; + return this; + } + + public Builder xAxis(Float xAxis) { + this.xAxis = xAxis; + return this; + } + + public Builder yAxis(Float yAxis) { + this.yAxis = yAxis; + return this; + } + + public Builder width(Float width) { + this.width = width; + return this; + } + + public Builder height(Float height) { + this.height = height; + return this; + } + + public Builder alpha(Float alpha) { + this.alpha = alpha; + return this; + } + + public Builder renderMode(Integer renderMode) { + this.renderMode = renderMode; + return this; + } + + public LayoutConfig build() { + return new LayoutConfig(this); + } + } + + @Override + public String toString() { + return "LayoutConfig{" + + "uid='" + uid + '\'' + + ", xAxis=" + xAxis + + ", yAxis=" + yAxis + + ", width=" + width + + ", height=" + height + + ", alpha=" + alpha + + ", renderMode=" + renderMode + + '}'; + } + } + + public static class BackgroundConfig { + + @JsonProperty("uid") + private String uid; + + @JsonProperty("image_url") + private String imageURL; + + @JsonProperty("render_mode") + private Integer renderMode; + + private BackgroundConfig(Builder builder) { + this.uid = builder.uid; + this.imageURL = builder.imageURL; + this.renderMode = builder.renderMode; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getImageURL() { + return imageURL; + } + + public void setImageURL(String imageURL) { + this.imageURL = imageURL; + } + + public Integer getRenderMode() { + return renderMode; + } + + public void setRenderMode(Integer renderMode) { + this.renderMode = renderMode; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private String uid; + + private String imageURL; + + private Integer renderMode; + + public Builder uid(String uid) { + this.uid = uid; + return this; + } + + public Builder imageURL(String imageURL) { + this.imageURL = imageURL; + return this; + } + + public Builder renderMode(Integer renderMode) { + this.renderMode = renderMode; + return this; + } + + public BackgroundConfig build() { + return new BackgroundConfig(this); + } + } + + @Override + public String toString() { + return "BackgroundConfig{" + + "uid='" + uid + '\'' + + ", imageURL='" + imageURL + '\'' + + ", renderMode=" + renderMode + + '}'; + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/UpdateResourceReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/UpdateResourceReq.java new file mode 100644 index 0000000..807e7ec --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/req/UpdateResourceReq.java @@ -0,0 +1,761 @@ +package io.agora.rest.services.cloudrecording.api.req; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public class UpdateResourceReq { + + @JsonProperty("cname") + private String cname; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("clientRequest") + private ClientRequest clientRequest; + + public static Builder builder() { + return new Builder(); + } + + private UpdateResourceReq(Builder builder) { + setCname(builder.cname); + setUid(builder.uid); + setClientRequest(builder.clientRequest); + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public ClientRequest getClientRequest() { + return clientRequest; + } + + public void setClientRequest(ClientRequest clientRequest) { + this.clientRequest = clientRequest; + } + + @Override + public String toString() { + return "UpdateResourceReq{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", clientRequest=" + clientRequest + + '}'; + } + + public static class ClientRequest { + + @JsonProperty("streamSubscribe") + private StreamSubscribe streamSubscribe; + + @JsonProperty("webRecordingConfig") + private WebRecordingConfig webRecordingConfig; + + @JsonProperty("rtmpPublishConfig") + private RtmpPublishConfig rtmpPublishConfig; + + public static Builder builder() { + return new Builder(); + } + + private ClientRequest(Builder builder) { + setStreamSubscribe(builder.streamSubscribe); + setWebRecordingConfig(builder.webRecordingConfig); + setRtmpPublishConfig(builder.rtmpPublishConfig); + } + + public StreamSubscribe getStreamSubscribe() { + return streamSubscribe; + } + + public void setStreamSubscribe(StreamSubscribe streamSubscribe) { + this.streamSubscribe = streamSubscribe; + } + + public WebRecordingConfig getWebRecordingConfig() { + return webRecordingConfig; + } + + public void setWebRecordingConfig(WebRecordingConfig webRecordingConfig) { + this.webRecordingConfig = webRecordingConfig; + } + + public RtmpPublishConfig getRtmpPublishConfig() { + return rtmpPublishConfig; + } + + public void setRtmpPublishConfig(RtmpPublishConfig rtmpPublishConfig) { + this.rtmpPublishConfig = rtmpPublishConfig; + } + + @Override + public String toString() { + return "ClientRequest{" + + "streamSubscribe=" + streamSubscribe + + ", webRecordingConfig=" + webRecordingConfig + + ", rtmpPublishConfig=" + rtmpPublishConfig + + '}'; + } + + public static final class Builder { + + private StreamSubscribe streamSubscribe; + + private WebRecordingConfig webRecordingConfig; + + private RtmpPublishConfig rtmpPublishConfig; + + private Builder() { + } + + public Builder streamSubscribe(StreamSubscribe val) { + streamSubscribe = val; + return this; + } + + public Builder webRecordingConfig(WebRecordingConfig val) { + webRecordingConfig = val; + return this; + } + + public Builder rtmpPublishConfig(RtmpPublishConfig val) { + rtmpPublishConfig = val; + return this; + } + + public ClientRequest build() { + return new ClientRequest(this); + } + } + } + + public static class StreamSubscribe { + + @JsonProperty("audioUidList") + private AudioUIDList audioUidList; + + @JsonProperty("videoUidList") + private VideoUIDList videoUidList; + + public static Builder builder() { + return new Builder(); + } + + private StreamSubscribe(Builder builder) { + setAudioUidList(builder.audioUidList); + setVideoUidList(builder.videoUidList); + } + + public AudioUIDList getAudioUidList() { + return audioUidList; + } + + public void setAudioUidList(AudioUIDList audioUidList) { + this.audioUidList = audioUidList; + } + + public VideoUIDList getVideoUidList() { + return videoUidList; + } + + public void setVideoUidList(VideoUIDList videoUidList) { + this.videoUidList = videoUidList; + } + + @Override + public String toString() { + return "StreamSubscribe{" + + "audioUidList=" + audioUidList + + ", videoUidList=" + videoUidList + + '}'; + } + + public static final class Builder { + + private AudioUIDList audioUidList; + + private VideoUIDList videoUidList; + + private Builder() { + } + + public Builder audioUidList(AudioUIDList val) { + audioUidList = val; + return this; + } + + public Builder videoUidList(VideoUIDList val) { + videoUidList = val; + return this; + } + + public StreamSubscribe build() { + return new StreamSubscribe(this); + } + } + } + + public static class AudioUIDList { + + @JsonProperty("subscribeAudioUids") + private List subscribeAudioUIDs; + + @JsonProperty("unSubscribeAudioUids") + private List unsubscribeAudioUIDs; + + public static Builder builder() { + return new Builder(); + } + + private AudioUIDList(Builder builder) { + setSubscribeAudioUIDs(builder.subscribeAudioUIDs); + setUnsubscribeAudioUIDs(builder.unsubscribeAudioUIDs); + } + + public List getSubscribeAudioUIDs() { + return subscribeAudioUIDs; + } + + public void setSubscribeAudioUIDs(List subscribeAudioUIDs) { + this.subscribeAudioUIDs = subscribeAudioUIDs; + } + + public List getUnsubscribeAudioUIDs() { + return unsubscribeAudioUIDs; + } + + public void setUnsubscribeAudioUIDs(List unsubscribeAudioUIDs) { + this.unsubscribeAudioUIDs = unsubscribeAudioUIDs; + } + + @Override + public String toString() { + return "AudioUIDList{" + + "subscribeAudioUIDs=" + subscribeAudioUIDs + + ", unsubscribeAudioUIDs=" + unsubscribeAudioUIDs + + '}'; + } + + public static final class Builder { + + private List subscribeAudioUIDs; + + private List unsubscribeAudioUIDs; + + private Builder() { + } + + public Builder subscribeAudioUIDs(List val) { + subscribeAudioUIDs = val; + return this; + } + + public Builder unsubscribeAudioUIDs(List val) { + unsubscribeAudioUIDs = val; + return this; + } + + public AudioUIDList build() { + return new AudioUIDList(this); + } + } + } + + public static class VideoUIDList { + + @JsonProperty("subscribeVideoUids") + private List subscribeVideoUIDs; + + @JsonProperty("unSubscribeVideoUids") + private List unsubscribeVideoUIDs; + + public static Builder builder() { + return new Builder(); + } + + private VideoUIDList(Builder builder) { + setSubscribeVideoUIDs(builder.subscribeVideoUIDs); + setUnsubscribeVideoUIDs(builder.unsubscribeVideoUIDs); + } + + public List getSubscribeVideoUIDs() { + return subscribeVideoUIDs; + } + + public void setSubscribeVideoUIDs(List subscribeVideoUIDs) { + this.subscribeVideoUIDs = subscribeVideoUIDs; + } + + public List getUnsubscribeVideoUIDs() { + return unsubscribeVideoUIDs; + } + + public void setUnsubscribeVideoUIDs(List unsubscribeVideoUIDs) { + this.unsubscribeVideoUIDs = unsubscribeVideoUIDs; + } + + @Override + public String toString() { + return "VideoUIDList{" + + "subscribeVideoUIDs=" + subscribeVideoUIDs + + ", unsubscribeVideoUIDs=" + unsubscribeVideoUIDs + + '}'; + } + + public static final class Builder { + + private List subscribeVideoUIDs; + + private List unsubscribeVideoUIDs; + + private Builder() { + } + + public Builder subscribeVideoUIDs(List val) { + subscribeVideoUIDs = val; + return this; + } + + public Builder unsubscribeVideoUIDs(List val) { + unsubscribeVideoUIDs = val; + return this; + } + + public VideoUIDList build() { + return new VideoUIDList(this); + } + } + } + + public static class WebRecordingConfig { + @JsonProperty("onhold") + private Boolean onHold; + + public static Builder builder() { + return new Builder(); + } + + private WebRecordingConfig(Builder builder) { + setOnHold(builder.onHold); + } + + public Boolean getOnHold() { + return onHold; + } + + public void setOnHold(Boolean onHold) { + this.onHold = onHold; + } + + @Override + public String toString() { + return "WebRecordingConfig{" + + "onHold=" + onHold + + '}'; + } + + public static final class Builder { + + private Boolean onHold; + + private Builder() { + } + + public Builder onHold(Boolean val) { + onHold = val; + return this; + } + + public WebRecordingConfig build() { + return new WebRecordingConfig(this); + } + } + } + + public static class RtmpPublishConfig { + + @JsonProperty("outputs") + private List outputs; + + public static Builder builder() { + return new Builder(); + } + + private RtmpPublishConfig(Builder builder) { + setOutputs(builder.outputs); + } + + public List getOutputs() { + return outputs; + } + + public void setOutputs(List outputs) { + this.outputs = outputs; + } + + @Override + public String toString() { + return "RtmpPublishConfig{" + + "outputs=" + outputs + + '}'; + } + + public static final class Builder { + + private List outputs; + + private Builder() { + } + + public Builder outputs(List val) { + outputs = val; + return this; + } + + public RtmpPublishConfig build() { + return new RtmpPublishConfig(this); + } + } + } + + public static class UpdateOutput { + + @JsonProperty("rtmpUrl") + private String rtmpURL; + + public static Builder builder() { + return new Builder(); + } + + private UpdateOutput(Builder builder) { + setRtmpURL(builder.rtmpURL); + } + + public String getRtmpURL() { + return rtmpURL; + } + + public void setRtmpURL(String rtmpURL) { + this.rtmpURL = rtmpURL; + } + + @Override + public String toString() { + return "UpdateOutput{" + + "rtmpURL='" + rtmpURL + '\'' + + '}'; + } + + public static final class Builder { + + private String rtmpURL; + + private Builder() { + } + + public Builder rtmpURL(String val) { + rtmpURL = val; + return this; + } + + public UpdateOutput build() { + return new UpdateOutput(this); + } + } + } + + public static class StorageConfig { + + @JsonProperty("vendor") + private Integer vendor; + + @JsonProperty("region") + private Integer region; + + @JsonProperty("bucket") + private String bucket; + + @JsonProperty("accessKey") + private String accessKey; + + @JsonProperty("secretKey") + private String secretKey; + + @JsonProperty("fileNamePrefix") + private List fileNamePrefix; + + @JsonProperty("stsToken") + private String stsToken; + + @JsonProperty("stsExpiration") + private Integer stsExpiration; + + @JsonProperty("extensionParams") + private ExtensionParams extensionParams; + + public static Builder builder() { + return new Builder(); + } + + private StorageConfig(Builder builder) { + setVendor(builder.vendor); + setRegion(builder.region); + setBucket(builder.bucket); + setAccessKey(builder.accessKey); + setSecretKey(builder.secretKey); + setFileNamePrefix(builder.fileNamePrefix); + setStsToken(builder.stsToken); + setStsExpiration(builder.stsExpiration); + setExtensionParams(builder.extensionParams); + } + + public Integer getVendor() { + return vendor; + } + + public void setVendor(Integer vendor) { + this.vendor = vendor; + } + + public Integer getRegion() { + return region; + } + + public void setRegion(Integer region) { + this.region = region; + } + + public String getBucket() { + return bucket; + } + + public void setBucket(String bucket) { + this.bucket = bucket; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public List getFileNamePrefix() { + return fileNamePrefix; + } + + public void setFileNamePrefix(List fileNamePrefix) { + this.fileNamePrefix = fileNamePrefix; + } + + public String getStsToken() { + return stsToken; + } + + public void setStsToken(String stsToken) { + this.stsToken = stsToken; + } + + public Integer getStsExpiration() { + return stsExpiration; + } + + public void setStsExpiration(Integer stsExpiration) { + this.stsExpiration = stsExpiration; + } + + public ExtensionParams getExtensionParams() { + return extensionParams; + } + + public void setExtensionParams(ExtensionParams extensionParams) { + this.extensionParams = extensionParams; + } + + public static final class Builder { + + private Integer vendor; + + private Integer region; + + private String bucket; + + private String accessKey; + + private String secretKey; + + private List fileNamePrefix; + + private String stsToken; + + private Integer stsExpiration; + + private ExtensionParams extensionParams; + + private Builder() { + } + + public Builder vendor(Integer val) { + vendor = val; + return this; + } + + public Builder region(Integer val) { + region = val; + return this; + } + + public Builder bucket(String val) { + bucket = val; + return this; + } + + public Builder accessKey(String val) { + accessKey = val; + return this; + } + + public Builder secretKey(String val) { + secretKey = val; + return this; + } + + public Builder fileNamePrefix(List val) { + fileNamePrefix = val; + return this; + } + + public Builder stsToken(String val) { + stsToken = val; + return this; + } + + public Builder stsExpiration(Integer val) { + stsExpiration = val; + return this; + } + + public Builder extensionParams(ExtensionParams val) { + extensionParams = val; + return this; + } + + public StorageConfig build() { + return new StorageConfig(this); + } + } + } + + public static class ExtensionParams { + + @JsonProperty("sse") + private String sse; + + @JsonProperty("tag") + private String tag; + + public static Builder builder() { + return new Builder(); + } + + private ExtensionParams(Builder builder) { + setSse(builder.sse); + setTag(builder.tag); + } + + public String getSse() { + return sse; + } + + public void setSse(String sse) { + this.sse = sse; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public static final class Builder { + + private String sse; + + private String tag; + + private Builder() { + } + + public Builder sse(String val) { + sse = val; + return this; + } + + public Builder tag(String val) { + tag = val; + return this; + } + + public ExtensionParams build() { + return new ExtensionParams(this); + } + } + } + + public static final class Builder { + + private String cname; + + private String uid; + + private ClientRequest clientRequest; + + private Builder() { + } + + public Builder cname(String val) { + cname = val; + return this; + } + + public Builder uid(String val) { + uid = val; + return this; + } + + public Builder clientRequest(ClientRequest val) { + clientRequest = val; + return this; + } + + public UpdateResourceReq build() { + return new UpdateResourceReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/AcquireResourceRes.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/AcquireResourceRes.java new file mode 100644 index 0000000..225c3e4 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/AcquireResourceRes.java @@ -0,0 +1,47 @@ +package io.agora.rest.services.cloudrecording.api.res; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AcquireResourceRes { + @JsonProperty("cname") + private String cname; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("resourceId") + private String resourceId; + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + @Override + public String toString() { + return "AcquireResourceRes{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", resourceId='" + resourceId + '\'' + + '}'; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/QueryResourceRes.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/QueryResourceRes.java new file mode 100644 index 0000000..c755e53 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/QueryResourceRes.java @@ -0,0 +1,724 @@ +package io.agora.rest.services.cloudrecording.api.res; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.agora.rest.exception.AgoraJsonException; +import io.agora.rest.services.cloudrecording.enums.CloudRecordingModeEnum; + +import java.util.List; + +public class QueryResourceRes { + @JsonProperty("cname") + private String cname; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("resourceId") + private String resourceId; + + @JsonProperty("sid") + private String sid; + + @JsonProperty("serverResponse") + private JsonNode serverResponse; + + @JsonIgnore + private ServerResponseType serverResponseType; + + @JsonIgnore + private QueryIndividualRecordingServerResponse queryIndividualRecordingServerResponse; + + @JsonIgnore + private QueryIndividualVideoScreenshotServerResponse queryIndividualVideoScreenshotServerResponse; + + @JsonIgnore + private MixRecordingHLSServerResponse mixRecordingHLSServerResponse; + + @JsonIgnore + private MixRecordingHLSAndMP4ServerResponse mixRecordingHLSAndMP4ServerResponse; + + @JsonIgnore + private WebRecordingServerResponse webRecordingServerResponse; + + @JsonIgnore + public void setServerResponse(CloudRecordingModeEnum mode) throws Exception { + JsonNode fileListModeNode = this.serverResponse.path("fileListMode"); + this.serverResponseType = ServerResponseType.QUERY_SERVER_RESPONSE_UNKNOWN_TYPE; + + ObjectMapper objectMapper = new ObjectMapper(); + + switch (mode) { + case INDIVIDUAL: + if (fileListModeNode.isTextual() && "json".equals(fileListModeNode.asText())) { + this.serverResponseType = ServerResponseType.QUERY_INDIVIDUAL_RECORDING_SERVER_RESPONSE_TYPE; + this.queryIndividualRecordingServerResponse = objectMapper.treeToValue(this.serverResponse, + QueryIndividualRecordingServerResponse.class); + } else { + this.serverResponseType = ServerResponseType.QUERY_INDIVIDUAL_VIDEO_SCREENSHOT_SERVER_RESPONSE_TYPE; + this.queryIndividualVideoScreenshotServerResponse = objectMapper.treeToValue(this.serverResponse, + QueryIndividualVideoScreenshotServerResponse.class); + } + break; + case MIX: + if (fileListModeNode.isMissingNode()) { + break; + } + + if ("string".equals(fileListModeNode.asText())) { + this.serverResponseType = ServerResponseType.QUERY_MIX_RECORDING_HLS_SERVER_RESPONSE_TYPE; + this.mixRecordingHLSServerResponse = objectMapper.treeToValue(this.serverResponse, + MixRecordingHLSServerResponse.class); + } else if ("json".equals(fileListModeNode.asText())) { + this.serverResponseType = ServerResponseType.QUERY_MIX_RECORDING_HLS_AND_MP4_SERVER_RESPONSE_TYPE; + this.mixRecordingHLSAndMP4ServerResponse = objectMapper.treeToValue(this.serverResponse, + MixRecordingHLSAndMP4ServerResponse.class); + } else { + throw new AgoraJsonException("unknown fileList mode"); + } + break; + case WEB: + this.serverResponseType = ServerResponseType.QUERY_WEB_RECORDING_SERVER_RESPONSE_TYPE; + this.webRecordingServerResponse = objectMapper.treeToValue(this.serverResponse, + WebRecordingServerResponse.class); + break; + } + + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getSid() { + return sid; + } + + public void setSid(String sid) { + this.sid = sid; + } + + public JsonNode getServerResponse() { + return serverResponse; + } + + public void setServerResponse(JsonNode serverResponse) { + this.serverResponse = serverResponse; + } + + public ServerResponseType getServerResponseType() { + return serverResponseType; + } + + public void setServerResponseType(ServerResponseType serverResponseType) { + this.serverResponseType = serverResponseType; + } + + public QueryIndividualRecordingServerResponse getQueryIndividualRecordingServerResponse() { + return queryIndividualRecordingServerResponse; + } + + public void setQueryIndividualRecordingServerResponse(QueryIndividualRecordingServerResponse queryIndividualRecordingServerResponse) { + this.queryIndividualRecordingServerResponse = queryIndividualRecordingServerResponse; + } + + public QueryIndividualVideoScreenshotServerResponse getQueryIndividualVideoScreenshotServerResponse() { + return queryIndividualVideoScreenshotServerResponse; + } + + public void setQueryIndividualVideoScreenshotServerResponse(QueryIndividualVideoScreenshotServerResponse queryIndividualVideoScreenshotServerResponse) { + this.queryIndividualVideoScreenshotServerResponse = queryIndividualVideoScreenshotServerResponse; + } + + public MixRecordingHLSServerResponse getMixRecordingHLSServerResponse() { + return mixRecordingHLSServerResponse; + } + + public void setMixRecordingHLSServerResponse(MixRecordingHLSServerResponse mixRecordingHLSServerResponse) { + this.mixRecordingHLSServerResponse = mixRecordingHLSServerResponse; + } + + public MixRecordingHLSAndMP4ServerResponse getMixRecordingHLSAndMP4ServerResponse() { + return mixRecordingHLSAndMP4ServerResponse; + } + + public void setMixRecordingHLSAndMP4ServerResponse(MixRecordingHLSAndMP4ServerResponse mixRecordingHLSAndMP4ServerResponse) { + this.mixRecordingHLSAndMP4ServerResponse = mixRecordingHLSAndMP4ServerResponse; + } + + public WebRecordingServerResponse getWebRecordingServerResponse() { + return webRecordingServerResponse; + } + + public void setWebRecordingServerResponse(WebRecordingServerResponse webRecordingServerResponse) { + this.webRecordingServerResponse = webRecordingServerResponse; + } + + @Override + public String toString() { + return "QueryResourceRes{" + + "webRecordingServerResponse=" + webRecordingServerResponse + + ", mixRecordingHLSAndMP4ServerResponse=" + mixRecordingHLSAndMP4ServerResponse + + ", mixRecordingHLSServerResponse=" + mixRecordingHLSServerResponse + + ", queryIndividualVideoScreenshotServerResponse=" + queryIndividualVideoScreenshotServerResponse + + ", queryIndividualRecordingServerResponse=" + queryIndividualRecordingServerResponse + + ", serverResponseType=" + serverResponseType + + ", serverResponse=" + serverResponse + + ", sid='" + sid + '\'' + + ", resourceId='" + resourceId + '\'' + + ", uid='" + uid + '\'' + + ", cname='" + cname + '\'' + + '}'; + } + + public enum ServerResponseType { + QUERY_SERVER_RESPONSE_UNKNOWN_TYPE, + QUERY_INDIVIDUAL_RECORDING_SERVER_RESPONSE_TYPE, + QUERY_INDIVIDUAL_VIDEO_SCREENSHOT_SERVER_RESPONSE_TYPE, + QUERY_MIX_RECORDING_HLS_SERVER_RESPONSE_TYPE, + QUERY_MIX_RECORDING_HLS_AND_MP4_SERVER_RESPONSE_TYPE, + QUERY_WEB_RECORDING_SERVER_RESPONSE_TYPE + } + + public static class QueryIndividualRecordingServerResponse { + @JsonProperty("status") + private Integer status; + + @JsonProperty("fileListMode") + private String fileListMode; + + @JsonProperty("fileList") + private List fileList; + + @JsonProperty("sliceStartTime") + private Long sliceStartTime; + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public String getFileListMode() { + return fileListMode; + } + + public void setFileListMode(String fileListMode) { + this.fileListMode = fileListMode; + } + + public List getFileList() { + return fileList; + } + + public void setFileList(List fileList) { + this.fileList = fileList; + } + + public Long getSliceStartTime() { + return sliceStartTime; + } + + public void setSliceStartTime(Long sliceStartTime) { + this.sliceStartTime = sliceStartTime; + } + + @Override + public String toString() { + return "QueryIndividualRecordingServerResponse{" + + "status=" + status + + ", fileListMode='" + fileListMode + '\'' + + ", fileList=" + fileList + + ", sliceStartTime=" + sliceStartTime + + '}'; + } + + public static class FileDetail { + @JsonProperty("fileName") + private String fileName; + + @JsonProperty("trackType") + private String trackType; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("mixedAllUser") + private Boolean mixedAllUser; + + @JsonProperty("isPlayable") + private Boolean isPlayable; + + @JsonProperty("sliceStartTime") + private Long sliceStartTime; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getTrackType() { + return trackType; + } + + public void setTrackType(String trackType) { + this.trackType = trackType; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public Boolean getMixedAllUser() { + return mixedAllUser; + } + + public void setMixedAllUser(Boolean mixedAllUser) { + this.mixedAllUser = mixedAllUser; + } + + public Boolean getPlayable() { + return isPlayable; + } + + public void setPlayable(Boolean playable) { + isPlayable = playable; + } + + public Long getSliceStartTime() { + return sliceStartTime; + } + + public void setSliceStartTime(Long sliceStartTime) { + this.sliceStartTime = sliceStartTime; + } + + @Override + public String toString() { + return "FileDetail{" + + "fileName='" + fileName + '\'' + + ", trackType='" + trackType + '\'' + + ", uid='" + uid + '\'' + + ", mixedAllUser=" + mixedAllUser + + ", isPlayable=" + isPlayable + + ", sliceStartTime=" + sliceStartTime + + '}'; + } + } + } + + public static class QueryIndividualVideoScreenshotServerResponse { + @JsonProperty("status") + private Integer status; + + @JsonProperty("sliceStartTime") + private Long sliceStartTime; + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Long getSliceStartTime() { + return sliceStartTime; + } + + public void setSliceStartTime(Long sliceStartTime) { + this.sliceStartTime = sliceStartTime; + } + } + + public static class MixRecordingHLSServerResponse { + @JsonProperty("status") + private Integer status; + + @JsonProperty("fileListMode") + private String fileListMode; + + @JsonProperty("fileList") + private String fileList; + + @JsonProperty("sliceStartTime") + private Long sliceStartTime; + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public String getFileListMode() { + return fileListMode; + } + + public void setFileListMode(String fileListMode) { + this.fileListMode = fileListMode; + } + + public String getFileList() { + return fileList; + } + + public void setFileList(String fileList) { + this.fileList = fileList; + } + + public Long getSliceStartTime() { + return sliceStartTime; + } + + public void setSliceStartTime(Long sliceStartTime) { + this.sliceStartTime = sliceStartTime; + } + + @Override + public String toString() { + return "MixRecordingHLSServerResponse{" + + "status=" + status + + ", fileListMode='" + fileListMode + '\'' + + ", fileList='" + fileList + '\'' + + ", sliceStartTime=" + sliceStartTime + + '}'; + } + } + + public static class MixRecordingHLSAndMP4ServerResponse { + @JsonProperty("status") + private Integer status; + + @JsonProperty("fileListMode") + private String fileListMode; + + @JsonProperty("fileList") + private List fileList; + + @JsonProperty("sliceStartTime") + private Long sliceStartTime; + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public String getFileListMode() { + return fileListMode; + } + + public void setFileListMode(String fileListMode) { + this.fileListMode = fileListMode; + } + + public List getFileList() { + return fileList; + } + + public void setFileList(List fileList) { + this.fileList = fileList; + } + + public Long getSliceStartTime() { + return sliceStartTime; + } + + public void setSliceStartTime(Long sliceStartTime) { + this.sliceStartTime = sliceStartTime; + } + + @Override + public String toString() { + return "MixRecordingHLSAndMP4ServerResponse{" + + "status=" + status + + ", fileListMode='" + fileListMode + '\'' + + ", fileList=" + fileList + + ", sliceStartTime=" + sliceStartTime + + '}'; + } + + public static class FileDetail { + @JsonProperty("fileName") + private String fileName; + + @JsonProperty("trackType") + private String trackType; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("mixedAllUser") + private Boolean mixedAllUser; + + @JsonProperty("isPlayable") + private Boolean isPlayable; + + @JsonProperty("sliceStartTime") + private Long sliceStartTime; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getTrackType() { + return trackType; + } + + public void setTrackType(String trackType) { + this.trackType = trackType; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public Boolean getMixedAllUser() { + return mixedAllUser; + } + + public void setMixedAllUser(Boolean mixedAllUser) { + this.mixedAllUser = mixedAllUser; + } + + public Boolean getPlayable() { + return isPlayable; + } + + public void setPlayable(Boolean playable) { + isPlayable = playable; + } + + public Long getSliceStartTime() { + return sliceStartTime; + } + + public void setSliceStartTime(Long sliceStartTime) { + this.sliceStartTime = sliceStartTime; + } + + @Override + public String toString() { + return "FileDetail{" + + "fileName='" + fileName + '\'' + + ", trackType='" + trackType + '\'' + + ", uid='" + uid + '\'' + + ", mixedAllUser=" + mixedAllUser + + ", isPlayable=" + isPlayable + + ", sliceStartTime=" + sliceStartTime + + '}'; + } + } + } + + public static class WebRecordingServerResponse { + @JsonProperty("status") + private Integer status; + + @JsonProperty("extensionServiceState") + private List extensionServiceState; + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public List getExtensionServiceState() { + return extensionServiceState; + } + + public void setExtensionServiceState(List extensionServiceState) { + this.extensionServiceState = extensionServiceState; + } + + @Override + public String toString() { + return "WebRecordingServerResponse{" + + "status=" + status + + ", extensionServiceState=" + extensionServiceState + + '}'; + } + + public static class ExtensionServiceState { + @JsonProperty("payload") + private Payload payload; + + @JsonProperty("serviceName") + private String serviceName; + + @Override + public String toString() { + return "ExtensionServiceState{" + + "payload=" + payload + + ", serviceName='" + serviceName + '\'' + + '}'; + } + + public static class Payload { + @JsonProperty("fileList") + private List fileList; + + @JsonProperty("onhold") + private Boolean onhold; + + @JsonProperty("state") + private String state; + + @JsonProperty("outputs") + private List outputs; + + public List getFileList() { + return fileList; + } + + public void setFileList(List fileList) { + this.fileList = fileList; + } + + public Boolean getOnhold() { + return onhold; + } + + public void setOnhold(Boolean onhold) { + this.onhold = onhold; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public List getOutputs() { + return outputs; + } + + public void setOutputs(List outputs) { + this.outputs = outputs; + } + + @Override + public String toString() { + return "Payload{" + + "fileList=" + fileList + + ", onhold=" + onhold + + ", state='" + state + '\'' + + ", outputs=" + outputs + + '}'; + } + + public static class FileDetail { + @JsonProperty("filename") + private String filename; + + @JsonProperty("sliceStartTime") + private Long sliceStartTime; + + public String getFilename() { + return filename; + } + + public void setFilename(String filename) { + this.filename = filename; + } + + public Long getSliceStartTime() { + return sliceStartTime; + } + + public void setSliceStartTime(Long sliceStartTime) { + this.sliceStartTime = sliceStartTime; + } + + @Override + public String toString() { + return "FileDetail{" + + "filename='" + filename + '\'' + + ", sliceStartTime=" + sliceStartTime + + '}'; + } + } + + public static class Output { + @JsonProperty("rtmpUrl") + private String rtmpUrl; + + @JsonProperty("status") + private String status; + + public String getRtmpUrl() { + return rtmpUrl; + } + + public void setRtmpUrl(String rtmpUrl) { + this.rtmpUrl = rtmpUrl; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + @Override + public String toString() { + return "Output{" + + "rtmpUrl='" + rtmpUrl + '\'' + + ", status='" + status + '\'' + + '}'; + } + } + } + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/StartResourceRes.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/StartResourceRes.java new file mode 100644 index 0000000..521dd06 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/StartResourceRes.java @@ -0,0 +1,59 @@ +package io.agora.rest.services.cloudrecording.api.res; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class StartResourceRes { + @JsonProperty("cname") + private String cname; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("resourceId") + private String resourceId; + + @JsonProperty("sid") + private String sid; + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getSid() { + return sid; + } + + public void setSid(String sid) { + this.sid = sid; + } + + @Override + public String toString() { + return "StartResourceRes{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", resourceId='" + resourceId + '\'' + + ", sid='" + sid + '\'' + + '}'; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/StopResourceRes.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/StopResourceRes.java new file mode 100644 index 0000000..72fff3e --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/StopResourceRes.java @@ -0,0 +1,59 @@ +package io.agora.rest.services.cloudrecording.api.res; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class StopResourceRes { + @JsonProperty("cname") + private String cname; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("resourceId") + private String resourceId; + + @JsonProperty("sid") + private String sid; + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getSid() { + return sid; + } + + public void setSid(String sid) { + this.sid = sid; + } + + @Override + public String toString() { + return "StopResourceRes{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", resourceId='" + resourceId + '\'' + + ", sid='" + sid + '\'' + + '}'; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/UpdateLayoutResourceRes.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/UpdateLayoutResourceRes.java new file mode 100644 index 0000000..6b42726 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/UpdateLayoutResourceRes.java @@ -0,0 +1,59 @@ +package io.agora.rest.services.cloudrecording.api.res; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class UpdateLayoutResourceRes { + @JsonProperty("cname") + private String cname; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("resourceId") + private String resourceId; + + @JsonProperty("sid") + private String sid; + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getSid() { + return sid; + } + + public void setSid(String sid) { + this.sid = sid; + } + + @Override + public String toString() { + return "UpdateLayoutResourceRes{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", resourceId='" + resourceId + '\'' + + ", sid='" + sid + '\'' + + '}'; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/UpdateResourceRes.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/UpdateResourceRes.java new file mode 100644 index 0000000..2a3893b --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/api/res/UpdateResourceRes.java @@ -0,0 +1,59 @@ +package io.agora.rest.services.cloudrecording.api.res; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class UpdateResourceRes { + @JsonProperty("cname") + private String cname; + + @JsonProperty("uid") + private String uid; + + @JsonProperty("resourceId") + private String resourceId; + + @JsonProperty("sid") + private String sid; + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getSid() { + return sid; + } + + public void setSid(String sid) { + this.sid = sid; + } + + @Override + public String toString() { + return "UpdateResourceRes{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", resourceId='" + resourceId + '\'' + + ", sid='" + sid + '\'' + + '}'; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/enums/CloudRecordingModeEnum.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/enums/CloudRecordingModeEnum.java new file mode 100644 index 0000000..993396e --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/enums/CloudRecordingModeEnum.java @@ -0,0 +1,17 @@ +package io.agora.rest.services.cloudrecording.enums; + +public enum CloudRecordingModeEnum { + INDIVIDUAL("individual"), + MIX("mix"), + WEB("web"); + + private final String mode; + + CloudRecordingModeEnum(String mode) { + this.mode = mode; + } + + public String getMode() { + return mode; + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/IndividualScenario.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/IndividualScenario.java new file mode 100644 index 0000000..66be84f --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/IndividualScenario.java @@ -0,0 +1,158 @@ +package io.agora.rest.services.cloudrecording.scenario.individual; + +import io.agora.rest.services.cloudrecording.api.*; +import io.agora.rest.services.cloudrecording.api.req.AcquireResourceReq; +import io.agora.rest.services.cloudrecording.api.req.StartResourceReq; +import io.agora.rest.services.cloudrecording.api.req.StopResourceReq; +import io.agora.rest.services.cloudrecording.api.req.UpdateResourceReq; +import io.agora.rest.services.cloudrecording.api.res.AcquireResourceRes; +import io.agora.rest.services.cloudrecording.api.res.StartResourceRes; +import io.agora.rest.services.cloudrecording.api.res.StopResourceRes; +import io.agora.rest.services.cloudrecording.api.res.UpdateResourceRes; +import io.agora.rest.services.cloudrecording.enums.CloudRecordingModeEnum; +import io.agora.rest.services.cloudrecording.scenario.individual.req.AcquireIndividualResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.individual.req.StartIndividualRecordingClientReq; +import io.agora.rest.services.cloudrecording.scenario.individual.req.UpdateIndividualRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.individual.res.QueryIndividualRecordingResourceRes; +import io.agora.rest.services.cloudrecording.scenario.individual.res.QueryIndividualRecordingVideoScreenshotResourceRes; +import reactor.core.publisher.Mono; + +public class IndividualScenario { + + private final AcquireResourceAPI acquireResourceAPI; + + private final QueryResourceAPI queryResourceAPI; + + private final StartResourceAPI startResourceAPI; + + private final UpdateResourceAPI updateResourceAPI; + + private final StopResourceAPI stopResourceAPI; + + public IndividualScenario(AcquireResourceAPI acquireResourceAPI, + QueryResourceAPI queryResourceAPI, + StartResourceAPI startResourceAPI, + UpdateResourceAPI updateResourceAPI, + StopResourceAPI stopResourceAPI) { + this.acquireResourceAPI = acquireResourceAPI; + this.queryResourceAPI = queryResourceAPI; + this.startResourceAPI = startResourceAPI; + this.updateResourceAPI = updateResourceAPI; + this.stopResourceAPI = stopResourceAPI; + } + + public Mono acquire(String cname, String uid, boolean enablePostpone, + AcquireIndividualResourceClientReq clientRequest) { + int scene = 0; + + if (enablePostpone) { + scene = 2; + } + + StartResourceReq.StartClientRequest startParameter = null; + if (clientRequest.getStartParameter() != null) { + startParameter = StartResourceReq.StartClientRequest.builder() + .token(clientRequest.getStartParameter().getToken()) + .storageConfig(clientRequest.getStartParameter() + .getStorageConfig()) + .recordingConfig(clientRequest.getStartParameter() + .getRecordingConfig()) + .recordingFileConfig(clientRequest.getStartParameter() + .getRecordingFileConfig()) + .snapshotConfig(clientRequest.getStartParameter() + .getSnapshotConfig()) + .appsCollection(clientRequest.getStartParameter() + .getAppsCollection()) + .transcodeOptions(clientRequest.getStartParameter() + .getTranscodeOptions()) + .build(); + } + + AcquireResourceReq req = AcquireResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(AcquireResourceReq.ClientRequest.builder() + .scene(scene) + .resourceExpiredHour(clientRequest.getResourceExpiredHour()) + .regionAffinity(clientRequest.getRegionAffinity()) + .excludeResourceIds(clientRequest.getExcludeResourceIds()) + .startParameter(startParameter) + .build()) + .build(); + + return this.acquireResourceAPI.handle(req); + } + + public Mono start(String cname, String uid, String resourceId, + StartIndividualRecordingClientReq clientRequest) { + return this.startResourceAPI.handle(resourceId, CloudRecordingModeEnum.INDIVIDUAL, StartResourceReq + .builder() + .cname(cname) + .uid(uid) + .clientRequest(StartResourceReq.StartClientRequest.builder() + .token(clientRequest.getToken()) + .storageConfig(clientRequest.getStorageConfig()) + .recordingConfig(clientRequest.getRecordingConfig()) + .recordingFileConfig(clientRequest.getRecordingFileConfig()) + .snapshotConfig(clientRequest.getSnapshotConfig()) + .appsCollection(clientRequest.getAppsCollection()) + .transcodeOptions(clientRequest.getTranscodeOptions()) + .build()) + .build()); + } + + public Mono query(String resourceId, String sid) { + return this.queryResourceAPI.handle(resourceId, sid, CloudRecordingModeEnum.INDIVIDUAL) + .handle((res, sink) -> { + sink.next(QueryIndividualRecordingResourceRes.builder() + .cname(res.getCname()) + .uid(res.getUid()) + .resourceId(res.getResourceId()) + .sid(res.getSid()) + .serverResponse(res.getQueryIndividualRecordingServerResponse()) + .build()); + + sink.complete(); + }); + } + + public Mono queryVideoScreenshot(String resourceId, + String sid) { + return this.queryResourceAPI.handle(resourceId, sid, CloudRecordingModeEnum.INDIVIDUAL) + .handle((res, sink) -> { + sink.next(QueryIndividualRecordingVideoScreenshotResourceRes.builder() + .cname(res.getCname()) + .uid(res.getUid()) + .resourceId(res.getResourceId()) + .sid(res.getSid()) + .serverResponse(res + .getQueryIndividualVideoScreenshotServerResponse()) + .build()); + + sink.complete(); + }); + } + + public Mono update(String cname, String uid, String resourceId, String sid, + UpdateIndividualRecordingResourceClientReq clientRequest) { + return this.updateResourceAPI.handle(resourceId, sid, CloudRecordingModeEnum.INDIVIDUAL, + UpdateResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(UpdateResourceReq.ClientRequest.builder() + .streamSubscribe(clientRequest.getStreamSubscribe()) + .build()) + .build()); + } + + public Mono stop(String cname, String uid, String resourceId, String sid, boolean asyncStop) { + return this.stopResourceAPI.handle(resourceId, sid, CloudRecordingModeEnum.INDIVIDUAL, + StopResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(StopResourceReq.StopClientRequest.builder() + .asyncStop(asyncStop) + .build()) + .build()); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/AcquireIndividualResourceClientReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/AcquireIndividualResourceClientReq.java new file mode 100644 index 0000000..0f9056b --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/AcquireIndividualResourceClientReq.java @@ -0,0 +1,101 @@ +package io.agora.rest.services.cloudrecording.scenario.individual.req; + +import java.util.List; + +public class AcquireIndividualResourceClientReq { + + private Integer resourceExpiredHour; + + private List excludeResourceIds; + + private Integer regionAffinity; + + private StartIndividualRecordingClientReq startParameter; + + public static Builder builder() { + return new Builder(); + } + + private AcquireIndividualResourceClientReq(Builder builder) { + setResourceExpiredHour(builder.resourceExpiredHour); + setExcludeResourceIds(builder.excludeResourceIds); + setRegionAffinity(builder.regionAffinity); + setStartParameter(builder.startParameter); + } + + public Integer getResourceExpiredHour() { + return resourceExpiredHour; + } + + public void setResourceExpiredHour(Integer resourceExpiredHour) { + this.resourceExpiredHour = resourceExpiredHour; + } + + public List getExcludeResourceIds() { + return excludeResourceIds; + } + + public void setExcludeResourceIds(List excludeResourceIds) { + this.excludeResourceIds = excludeResourceIds; + } + + public Integer getRegionAffinity() { + return regionAffinity; + } + + public void setRegionAffinity(Integer regionAffinity) { + this.regionAffinity = regionAffinity; + } + + public StartIndividualRecordingClientReq getStartParameter() { + return startParameter; + } + + public void setStartParameter(StartIndividualRecordingClientReq startParameter) { + this.startParameter = startParameter; + } + + @Override + public String toString() { + return "AcquireIndividualResourceClientReq{" + + "resourceExpiredHour=" + resourceExpiredHour + + ", excludeResourceIds=" + excludeResourceIds + + ", regionAffinity=" + regionAffinity + + ", startParameter=" + startParameter + + '}'; + } + + public static final class Builder { + private Integer resourceExpiredHour; + private List excludeResourceIds; + private Integer regionAffinity; + private StartIndividualRecordingClientReq startParameter; + + private Builder() { + } + + public Builder resourceExpiredHour(Integer val) { + resourceExpiredHour = val; + return this; + } + + public Builder excludeResourceIds(List val) { + excludeResourceIds = val; + return this; + } + + public Builder regionAffinity(Integer val) { + regionAffinity = val; + return this; + } + + public Builder startParameter(StartIndividualRecordingClientReq val) { + startParameter = val; + return this; + } + + public AcquireIndividualResourceClientReq build() { + return new AcquireIndividualResourceClientReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/StartIndividualRecordingClientReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/StartIndividualRecordingClientReq.java new file mode 100644 index 0000000..0f976b2 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/StartIndividualRecordingClientReq.java @@ -0,0 +1,155 @@ +package io.agora.rest.services.cloudrecording.scenario.individual.req; + +import io.agora.rest.services.cloudrecording.api.req.StartResourceReq; + +public class StartIndividualRecordingClientReq { + + private String token; + + private StartResourceReq.AppsCollection appsCollection; + + private StartResourceReq.RecordingConfig recordingConfig; + + private StartResourceReq.TranscodeOptions transcodeOptions; + + private StartResourceReq.RecordingFileConfig recordingFileConfig; + + private StartResourceReq.SnapshotConfig snapshotConfig; + + private StartResourceReq.StorageConfig storageConfig; + + public static Builder builder() { + return new Builder(); + } + + private StartIndividualRecordingClientReq(Builder builder) { + setToken(builder.token); + setAppsCollection(builder.appsCollection); + setRecordingConfig(builder.recordingConfig); + setTranscodeOptions(builder.transcodeOptions); + setRecordingFileConfig(builder.recordingFileConfig); + setSnapshotConfig(builder.snapshotConfig); + setStorageConfig(builder.storageConfig); + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public StartResourceReq.AppsCollection getAppsCollection() { + return appsCollection; + } + + public void setAppsCollection(StartResourceReq.AppsCollection appsCollection) { + this.appsCollection = appsCollection; + } + + public StartResourceReq.RecordingConfig getRecordingConfig() { + return recordingConfig; + } + + public void setRecordingConfig(StartResourceReq.RecordingConfig recordingConfig) { + this.recordingConfig = recordingConfig; + } + + public StartResourceReq.TranscodeOptions getTranscodeOptions() { + return transcodeOptions; + } + + public void setTranscodeOptions(StartResourceReq.TranscodeOptions transcodeOptions) { + this.transcodeOptions = transcodeOptions; + } + + public StartResourceReq.RecordingFileConfig getRecordingFileConfig() { + return recordingFileConfig; + } + + public void setRecordingFileConfig(StartResourceReq.RecordingFileConfig recordingFileConfig) { + this.recordingFileConfig = recordingFileConfig; + } + + public StartResourceReq.SnapshotConfig getSnapshotConfig() { + return snapshotConfig; + } + + public void setSnapshotConfig(StartResourceReq.SnapshotConfig snapshotConfig) { + this.snapshotConfig = snapshotConfig; + } + + public StartResourceReq.StorageConfig getStorageConfig() { + return storageConfig; + } + + public void setStorageConfig(StartResourceReq.StorageConfig storageConfig) { + this.storageConfig = storageConfig; + } + + @Override + public String toString() { + return "StartIndividualRecordingClientReq{" + + "token='" + token + '\'' + + ", appsCollection=" + appsCollection + + ", recordingConfig=" + recordingConfig + + ", transcodeOptions=" + transcodeOptions + + ", recordingFileConfig=" + recordingFileConfig + + ", snapshotConfig=" + snapshotConfig + + ", storageConfig=" + storageConfig + + '}'; + } + + public static final class Builder { + private String token; + private StartResourceReq.AppsCollection appsCollection; + private StartResourceReq.RecordingConfig recordingConfig; + private StartResourceReq.TranscodeOptions transcodeOptions; + private StartResourceReq.RecordingFileConfig recordingFileConfig; + private StartResourceReq.SnapshotConfig snapshotConfig; + private StartResourceReq.StorageConfig storageConfig; + + private Builder() { + } + + public Builder token(String val) { + token = val; + return this; + } + + public Builder appsCollection(StartResourceReq.AppsCollection val) { + appsCollection = val; + return this; + } + + public Builder recordingConfig(StartResourceReq.RecordingConfig val) { + recordingConfig = val; + return this; + } + + public Builder transcodeOptions(StartResourceReq.TranscodeOptions val) { + transcodeOptions = val; + return this; + } + + public Builder recordingFileConfig(StartResourceReq.RecordingFileConfig val) { + recordingFileConfig = val; + return this; + } + + public Builder snapshotConfig(StartResourceReq.SnapshotConfig val) { + snapshotConfig = val; + return this; + } + + public Builder storageConfig(StartResourceReq.StorageConfig val) { + storageConfig = val; + return this; + } + + public StartIndividualRecordingClientReq build() { + return new StartIndividualRecordingClientReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/UpdateIndividualRecordingResourceClientReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/UpdateIndividualRecordingResourceClientReq.java new file mode 100644 index 0000000..8241814 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/req/UpdateIndividualRecordingResourceClientReq.java @@ -0,0 +1,47 @@ +package io.agora.rest.services.cloudrecording.scenario.individual.req; + +import io.agora.rest.services.cloudrecording.api.req.UpdateResourceReq; + +public class UpdateIndividualRecordingResourceClientReq { + + private UpdateResourceReq.StreamSubscribe streamSubscribe; + + public static Builder builder() { + return new Builder(); + } + + private UpdateIndividualRecordingResourceClientReq(Builder builder) { + setStreamSubscribe(builder.streamSubscribe); + } + + public UpdateResourceReq.StreamSubscribe getStreamSubscribe() { + return streamSubscribe; + } + + public void setStreamSubscribe(UpdateResourceReq.StreamSubscribe streamSubscribe) { + this.streamSubscribe = streamSubscribe; + } + + @Override + public String toString() { + return "UpdateIndividualRecordingResourceClientReq{" + + "streamSubscribe=" + streamSubscribe + + '}'; + } + + public static final class Builder { + private UpdateResourceReq.StreamSubscribe streamSubscribe; + + private Builder() { + } + + public Builder streamSubscribe(UpdateResourceReq.StreamSubscribe val) { + streamSubscribe = val; + return this; + } + + public UpdateIndividualRecordingResourceClientReq build() { + return new UpdateIndividualRecordingResourceClientReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/res/QueryIndividualRecordingResourceRes.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/res/QueryIndividualRecordingResourceRes.java new file mode 100644 index 0000000..850e8ec --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/res/QueryIndividualRecordingResourceRes.java @@ -0,0 +1,119 @@ +package io.agora.rest.services.cloudrecording.scenario.individual.res; + +import io.agora.rest.services.cloudrecording.api.res.QueryResourceRes; + +public class QueryIndividualRecordingResourceRes { + + private String cname; + + private String uid; + + private String resourceId; + + private String sid; + + private QueryResourceRes.QueryIndividualRecordingServerResponse serverResponse; + + public static Builder builder() { + return new Builder(); + } + + private QueryIndividualRecordingResourceRes(Builder builder) { + setCname(builder.cname); + setUid(builder.uid); + setResourceId(builder.resourceId); + setSid(builder.sid); + setServerResponse(builder.serverResponse); + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getSid() { + return sid; + } + + public void setSid(String sid) { + this.sid = sid; + } + + public QueryResourceRes.QueryIndividualRecordingServerResponse getServerResponse() { + return serverResponse; + } + + public void setServerResponse(QueryResourceRes.QueryIndividualRecordingServerResponse serverResponse) { + this.serverResponse = serverResponse; + } + + @Override + public String toString() { + return "QueryIndividualRecordingResourceRes{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", resourceId='" + resourceId + '\'' + + ", sid='" + sid + '\'' + + ", serverResponse=" + serverResponse + + '}'; + } + + public static final class Builder { + private String cname; + private String uid; + private String resourceId; + private String sid; + private QueryResourceRes.QueryIndividualRecordingServerResponse serverResponse; + + private Builder() { + } + + public Builder cname(String val) { + cname = val; + return this; + } + + public Builder uid(String val) { + uid = val; + return this; + } + + public Builder resourceId(String val) { + resourceId = val; + return this; + } + + public Builder sid(String val) { + sid = val; + return this; + } + + public Builder serverResponse(QueryResourceRes.QueryIndividualRecordingServerResponse val) { + serverResponse = val; + return this; + } + + public QueryIndividualRecordingResourceRes build() { + return new QueryIndividualRecordingResourceRes(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/res/QueryIndividualRecordingVideoScreenshotResourceRes.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/res/QueryIndividualRecordingVideoScreenshotResourceRes.java new file mode 100644 index 0000000..f4face4 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/individual/res/QueryIndividualRecordingVideoScreenshotResourceRes.java @@ -0,0 +1,119 @@ +package io.agora.rest.services.cloudrecording.scenario.individual.res; + +import io.agora.rest.services.cloudrecording.api.res.QueryResourceRes; + +public class QueryIndividualRecordingVideoScreenshotResourceRes { + + private String cname; + + private String uid; + + private String resourceId; + + private String sid; + + private QueryResourceRes.QueryIndividualVideoScreenshotServerResponse serverResponse; + + public static Builder builder() { + return new Builder(); + } + + private QueryIndividualRecordingVideoScreenshotResourceRes(Builder builder) { + setCname(builder.cname); + setUid(builder.uid); + setResourceId(builder.resourceId); + setSid(builder.sid); + setServerResponse(builder.serverResponse); + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getSid() { + return sid; + } + + public void setSid(String sid) { + this.sid = sid; + } + + public QueryResourceRes.QueryIndividualVideoScreenshotServerResponse getServerResponse() { + return serverResponse; + } + + public void setServerResponse(QueryResourceRes.QueryIndividualVideoScreenshotServerResponse serverResponse) { + this.serverResponse = serverResponse; + } + + @Override + public String toString() { + return "QueryIndividualRecordingVideoScreenshotResourceRes{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", resourceId='" + resourceId + '\'' + + ", sid='" + sid + '\'' + + ", serverResponse=" + serverResponse + + '}'; + } + + public static final class Builder { + private String cname; + private String uid; + private String resourceId; + private String sid; + private QueryResourceRes.QueryIndividualVideoScreenshotServerResponse serverResponse; + + private Builder() { + } + + public Builder cname(String val) { + cname = val; + return this; + } + + public Builder uid(String val) { + uid = val; + return this; + } + + public Builder resourceId(String val) { + resourceId = val; + return this; + } + + public Builder sid(String val) { + sid = val; + return this; + } + + public Builder serverResponse(QueryResourceRes.QueryIndividualVideoScreenshotServerResponse val) { + serverResponse = val; + return this; + } + + public QueryIndividualRecordingVideoScreenshotResourceRes build() { + return new QueryIndividualRecordingVideoScreenshotResourceRes(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/MixScenario.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/MixScenario.java new file mode 100644 index 0000000..c325d1a --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/MixScenario.java @@ -0,0 +1,149 @@ +package io.agora.rest.services.cloudrecording.scenario.mix; + +import io.agora.rest.services.cloudrecording.api.*; +import io.agora.rest.services.cloudrecording.api.req.*; +import io.agora.rest.services.cloudrecording.api.res.*; +import io.agora.rest.services.cloudrecording.enums.CloudRecordingModeEnum; +import io.agora.rest.services.cloudrecording.scenario.mix.req.AcquireMixRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.mix.req.StartMixRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.mix.req.UpdateLayoutMixRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.mix.req.UpdateMixRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.mix.res.QueryMixHLSAndMP4RecordingResourceRes; +import io.agora.rest.services.cloudrecording.scenario.mix.res.QueryMixHLSRecordingResourceRes; +import reactor.core.publisher.Mono; + +public class MixScenario { + + private final AcquireResourceAPI acquireResourceAPI; + + private final QueryResourceAPI queryResourceAPI; + + private final StartResourceAPI startResourceAPI; + + private final UpdateResourceAPI updateResourceAPI; + + private final StopResourceAPI stopResourceAPI; + + public MixScenario(AcquireResourceAPI acquireResourceAPI, + QueryResourceAPI queryResourceAPI, + StartResourceAPI startResourceAPI, + UpdateResourceAPI updateResourceAPI, + StopResourceAPI stopResourceAPI) { + this.acquireResourceAPI = acquireResourceAPI; + this.queryResourceAPI = queryResourceAPI; + this.startResourceAPI = startResourceAPI; + this.updateResourceAPI = updateResourceAPI; + this.stopResourceAPI = stopResourceAPI; + } + + public Mono acquire(String cname, String uid, + AcquireMixRecordingResourceClientReq clientRequest) { + + StartResourceReq.StartClientRequest startParameter = null; + if (clientRequest.getStartParameter() != null) { + startParameter = StartResourceReq.StartClientRequest.builder() + .token(clientRequest.getStartParameter().getToken()) + .storageConfig(clientRequest.getStartParameter().getStorageConfig()) + .recordingConfig(clientRequest.getStartParameter().getRecordingConfig()) + .recordingFileConfig(clientRequest.getStartParameter().getRecordingFileConfig()) + .build(); + } + + + return this.acquireResourceAPI.handle(AcquireResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(AcquireResourceReq.ClientRequest.builder() + .scene(0) + .resourceExpiredHour(clientRequest.getResourceExpiredHour()) + .regionAffinity(clientRequest.getRegionAffinity()) + .excludeResourceIds(clientRequest.getExcludeResourceIds()) + .startParameter(startParameter) + .build()) + .build()); + } + + public Mono start(String cname, String uid, String resourceId, + StartMixRecordingResourceClientReq clientRequest) { + return this.startResourceAPI.handle(resourceId, CloudRecordingModeEnum.MIX, StartResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(StartResourceReq.StartClientRequest.builder() + .token(clientRequest.getToken()) + .storageConfig(clientRequest.getStorageConfig()) + .recordingConfig(clientRequest.getRecordingConfig()) + .recordingFileConfig(clientRequest.getRecordingFileConfig()) + .build()) + .build()); + } + + public Mono queryHLS(String resourceId, String sid) { + return this.queryResourceAPI.handle(resourceId, sid, CloudRecordingModeEnum.MIX).handle((res, sink) -> { + sink.next(QueryMixHLSRecordingResourceRes.builder() + .cname(res.getCname()) + .uid(res.getUid()) + .resourceId(res.getResourceId()) + .sid(res.getSid()) + .serverResponse(res.getMixRecordingHLSServerResponse()) + .build()); + + sink.complete(); + }); + } + + public Mono queryHLSAndMP4(String resourceId, String sid) { + return this.queryResourceAPI.handle(resourceId, sid, CloudRecordingModeEnum.MIX).handle((res, sink) -> { + sink.next(QueryMixHLSAndMP4RecordingResourceRes.builder() + .cname(res.getCname()) + .uid(res.getUid()) + .resourceId(res.getResourceId()) + .sid(res.getSid()) + .serverResponse(res.getMixRecordingHLSAndMP4ServerResponse()) + .build()); + + sink.complete(); + }); + } + + public Mono updateLayout(String cname, String uid, String resourceId, String sid, + UpdateLayoutMixRecordingResourceClientReq clientRequest) { + return this.updateResourceAPI.handleLayout(resourceId, sid, CloudRecordingModeEnum.MIX, + UpdateLayoutResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(UpdateLayoutResourceReq.ClientRequest.builder() + .maxResolutionUID(clientRequest.getMaxResolutionUID()) + .mixedVideoLayout(clientRequest.getMixedVideoLayout()) + .backgroundColor(clientRequest.getBackgroundColor()) + .defaultUserBackgroundImage(clientRequest + .getDefaultUserBackgroundImage()) + .layoutConfig(clientRequest.getLayoutConfig()) + .backgroundImage(clientRequest.getBackgroundImage()) + .backgroundConfig(clientRequest.getBackgroundConfig()) + .build()) + .build()); + } + + public Mono update(String cname, String uid, String resourceId, String sid, + UpdateMixRecordingResourceClientReq clientRequest) { + return this.updateResourceAPI.handle(resourceId, sid, CloudRecordingModeEnum.MIX, + UpdateResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(UpdateResourceReq.ClientRequest.builder() + .streamSubscribe(clientRequest.getStreamSubscribe()) + .build()) + .build()); + } + + public Mono stop(String cname, String uid, String resourceId, String sid, boolean asyncStop) { + return this.stopResourceAPI.handle(resourceId, sid, CloudRecordingModeEnum.MIX, + StopResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(StopResourceReq.StopClientRequest.builder() + .asyncStop(asyncStop) + .build()) + .build()); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/AcquireMixRecordingResourceClientReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/AcquireMixRecordingResourceClientReq.java new file mode 100644 index 0000000..96a732c --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/AcquireMixRecordingResourceClientReq.java @@ -0,0 +1,101 @@ +package io.agora.rest.services.cloudrecording.scenario.mix.req; + +import java.util.List; + +public class AcquireMixRecordingResourceClientReq { + + private Integer resourceExpiredHour; + + private List excludeResourceIds; + + private Integer regionAffinity; + + private StartMixRecordingResourceClientReq startParameter; + + public static Builder builder() { + return new Builder(); + } + + private AcquireMixRecordingResourceClientReq(Builder builder) { + setResourceExpiredHour(builder.resourceExpiredHour); + setExcludeResourceIds(builder.excludeResourceIds); + setRegionAffinity(builder.regionAffinity); + setStartParameter(builder.startParameter); + } + + public Integer getRegionAffinity() { + return regionAffinity; + } + + public void setRegionAffinity(Integer regionAffinity) { + this.regionAffinity = regionAffinity; + } + + public Integer getResourceExpiredHour() { + return resourceExpiredHour; + } + + public void setResourceExpiredHour(Integer resourceExpiredHour) { + this.resourceExpiredHour = resourceExpiredHour; + } + + public List getExcludeResourceIds() { + return excludeResourceIds; + } + + public void setExcludeResourceIds(List excludeResourceIds) { + this.excludeResourceIds = excludeResourceIds; + } + + public StartMixRecordingResourceClientReq getStartParameter() { + return startParameter; + } + + public void setStartParameter(StartMixRecordingResourceClientReq startParameter) { + this.startParameter = startParameter; + } + + @Override + public String toString() { + return "AcquireMixRecordingResourceClientReq{" + + "resourceExpiredHour=" + resourceExpiredHour + + ", excludeResourceIds=" + excludeResourceIds + + ", regionAffinity=" + regionAffinity + + ", startParameter=" + startParameter + + '}'; + } + + public static final class Builder { + private Integer resourceExpiredHour; + private List excludeResourceIds; + private Integer regionAffinity; + private StartMixRecordingResourceClientReq startParameter; + + private Builder() { + } + + public Builder resourceExpiredHour(Integer val) { + resourceExpiredHour = val; + return this; + } + + public Builder excludeResourceIds(List val) { + excludeResourceIds = val; + return this; + } + + public Builder regionAffinity(Integer val) { + regionAffinity = val; + return this; + } + + public Builder startParameter(StartMixRecordingResourceClientReq val) { + startParameter = val; + return this; + } + + public AcquireMixRecordingResourceClientReq build() { + return new AcquireMixRecordingResourceClientReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/StartMixRecordingResourceClientReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/StartMixRecordingResourceClientReq.java new file mode 100644 index 0000000..b474383 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/StartMixRecordingResourceClientReq.java @@ -0,0 +1,101 @@ +package io.agora.rest.services.cloudrecording.scenario.mix.req; + +import io.agora.rest.services.cloudrecording.api.req.StartResourceReq; + +public class StartMixRecordingResourceClientReq { + + private String token; + + private StartResourceReq.RecordingConfig recordingConfig; + + private StartResourceReq.RecordingFileConfig recordingFileConfig; + + private StartResourceReq.StorageConfig storageConfig; + + public static Builder builder() { + return new Builder(); + } + + private StartMixRecordingResourceClientReq(Builder builder) { + setToken(builder.token); + setRecordingConfig(builder.recordingConfig); + setRecordingFileConfig(builder.recordingFileConfig); + setStorageConfig(builder.storageConfig); + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public StartResourceReq.RecordingConfig getRecordingConfig() { + return recordingConfig; + } + + public void setRecordingConfig(StartResourceReq.RecordingConfig recordingConfig) { + this.recordingConfig = recordingConfig; + } + + public StartResourceReq.RecordingFileConfig getRecordingFileConfig() { + return recordingFileConfig; + } + + public void setRecordingFileConfig(StartResourceReq.RecordingFileConfig recordingFileConfig) { + this.recordingFileConfig = recordingFileConfig; + } + + public StartResourceReq.StorageConfig getStorageConfig() { + return storageConfig; + } + + public void setStorageConfig(StartResourceReq.StorageConfig storageConfig) { + this.storageConfig = storageConfig; + } + + @Override + public String toString() { + return "StartMixRecordingResourceClientReq{" + + "token='" + token + '\'' + + ", recordingConfig=" + recordingConfig + + ", recordingFileConfig=" + recordingFileConfig + + ", storageConfig=" + storageConfig + + '}'; + } + + public static final class Builder { + private String token; + private StartResourceReq.RecordingConfig recordingConfig; + private StartResourceReq.RecordingFileConfig recordingFileConfig; + private StartResourceReq.StorageConfig storageConfig; + + private Builder() { + } + + public Builder token(String val) { + token = val; + return this; + } + + public Builder recordingConfig(StartResourceReq.RecordingConfig val) { + recordingConfig = val; + return this; + } + + public Builder recordingFileConfig(StartResourceReq.RecordingFileConfig val) { + recordingFileConfig = val; + return this; + } + + public Builder storageConfig(StartResourceReq.StorageConfig val) { + storageConfig = val; + return this; + } + + public StartMixRecordingResourceClientReq build() { + return new StartMixRecordingResourceClientReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/UpdateLayoutMixRecordingResourceClientReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/UpdateLayoutMixRecordingResourceClientReq.java new file mode 100644 index 0000000..da226e3 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/UpdateLayoutMixRecordingResourceClientReq.java @@ -0,0 +1,157 @@ +package io.agora.rest.services.cloudrecording.scenario.mix.req; + +import io.agora.rest.services.cloudrecording.api.req.UpdateLayoutResourceReq; + +import java.util.List; + +public class UpdateLayoutMixRecordingResourceClientReq { + + private String maxResolutionUID; + + private int mixedVideoLayout; + + private String backgroundColor; + + private String backgroundImage; + + private String defaultUserBackgroundImage; + + private List layoutConfig; + + private List backgroundConfig; + + public static Builder builder() { + return new Builder(); + } + + private UpdateLayoutMixRecordingResourceClientReq(Builder builder) { + setMaxResolutionUID(builder.maxResolutionUID); + setMixedVideoLayout(builder.mixedVideoLayout); + setBackgroundColor(builder.backgroundColor); + setBackgroundImage(builder.backgroundImage); + setDefaultUserBackgroundImage(builder.defaultUserBackgroundImage); + setLayoutConfig(builder.layoutConfig); + setBackgroundConfig(builder.backgroundConfig); + } + + public String getMaxResolutionUID() { + return maxResolutionUID; + } + + public void setMaxResolutionUID(String maxResolutionUID) { + this.maxResolutionUID = maxResolutionUID; + } + + public int getMixedVideoLayout() { + return mixedVideoLayout; + } + + public void setMixedVideoLayout(int mixedVideoLayout) { + this.mixedVideoLayout = mixedVideoLayout; + } + + public String getBackgroundColor() { + return backgroundColor; + } + + public void setBackgroundColor(String backgroundColor) { + this.backgroundColor = backgroundColor; + } + + public String getBackgroundImage() { + return backgroundImage; + } + + public void setBackgroundImage(String backgroundImage) { + this.backgroundImage = backgroundImage; + } + + public String getDefaultUserBackgroundImage() { + return defaultUserBackgroundImage; + } + + public void setDefaultUserBackgroundImage(String defaultUserBackgroundImage) { + this.defaultUserBackgroundImage = defaultUserBackgroundImage; + } + + public List getLayoutConfig() { + return layoutConfig; + } + + public void setLayoutConfig(List layoutConfig) { + this.layoutConfig = layoutConfig; + } + + public List getBackgroundConfig() { + return backgroundConfig; + } + + public void setBackgroundConfig(List backgroundConfig) { + this.backgroundConfig = backgroundConfig; + } + + @Override + public String toString() { + return "UpdateLayoutMixRecordingResourceClientReq{" + + "maxResolutionUID='" + maxResolutionUID + '\'' + + ", mixedVideoLayout=" + mixedVideoLayout + + ", backgroundColor='" + backgroundColor + '\'' + + ", backgroundImage='" + backgroundImage + '\'' + + ", defaultUserBackgroundImage='" + defaultUserBackgroundImage + '\'' + + ", layoutConfig=" + layoutConfig + + ", backgroundConfig=" + backgroundConfig + + '}'; + } + + public static final class Builder { + private String maxResolutionUID; + private int mixedVideoLayout; + private String backgroundColor; + private String backgroundImage; + private String defaultUserBackgroundImage; + private List layoutConfig; + private List backgroundConfig; + + private Builder() { + } + + public Builder maxResolutionUID(String val) { + maxResolutionUID = val; + return this; + } + + public Builder mixedVideoLayout(int val) { + mixedVideoLayout = val; + return this; + } + + public Builder backgroundColor(String val) { + backgroundColor = val; + return this; + } + + public Builder backgroundImage(String val) { + backgroundImage = val; + return this; + } + + public Builder defaultUserBackgroundImage(String val) { + defaultUserBackgroundImage = val; + return this; + } + + public Builder layoutConfig(List val) { + layoutConfig = val; + return this; + } + + public Builder backgroundConfig(List val) { + backgroundConfig = val; + return this; + } + + public UpdateLayoutMixRecordingResourceClientReq build() { + return new UpdateLayoutMixRecordingResourceClientReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/UpdateMixRecordingResourceClientReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/UpdateMixRecordingResourceClientReq.java new file mode 100644 index 0000000..104a9f7 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/req/UpdateMixRecordingResourceClientReq.java @@ -0,0 +1,47 @@ +package io.agora.rest.services.cloudrecording.scenario.mix.req; + +import io.agora.rest.services.cloudrecording.api.req.UpdateResourceReq; + +public class UpdateMixRecordingResourceClientReq { + + private UpdateResourceReq.StreamSubscribe streamSubscribe; + + public static Builder builder() { + return new Builder(); + } + + private UpdateMixRecordingResourceClientReq(Builder builder) { + setStreamSubscribe(builder.streamSubscribe); + } + + public UpdateResourceReq.StreamSubscribe getStreamSubscribe() { + return streamSubscribe; + } + + public void setStreamSubscribe(UpdateResourceReq.StreamSubscribe streamSubscribe) { + this.streamSubscribe = streamSubscribe; + } + + @Override + public String toString() { + return "UpdateMixRecordingResourceClientReq{" + + "streamSubscribe=" + streamSubscribe + + '}'; + } + + public static final class Builder { + private UpdateResourceReq.StreamSubscribe streamSubscribe; + + private Builder() { + } + + public Builder streamSubscribe(UpdateResourceReq.StreamSubscribe val) { + streamSubscribe = val; + return this; + } + + public UpdateMixRecordingResourceClientReq build() { + return new UpdateMixRecordingResourceClientReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/res/QueryMixHLSAndMP4RecordingResourceRes.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/res/QueryMixHLSAndMP4RecordingResourceRes.java new file mode 100644 index 0000000..67d3082 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/res/QueryMixHLSAndMP4RecordingResourceRes.java @@ -0,0 +1,119 @@ +package io.agora.rest.services.cloudrecording.scenario.mix.res; + +import io.agora.rest.services.cloudrecording.api.res.QueryResourceRes; + +public class QueryMixHLSAndMP4RecordingResourceRes { + + private String cname; + + private String uid; + + private String resourceId; + + private String sid; + + private QueryResourceRes.MixRecordingHLSAndMP4ServerResponse serverResponse; + + public static Builder builder() { + return new Builder(); + } + + private QueryMixHLSAndMP4RecordingResourceRes(Builder builder) { + setCname(builder.cname); + setUid(builder.uid); + setResourceId(builder.resourceId); + setSid(builder.sid); + setServerResponse(builder.serverResponse); + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getSid() { + return sid; + } + + public void setSid(String sid) { + this.sid = sid; + } + + public QueryResourceRes.MixRecordingHLSAndMP4ServerResponse getServerResponse() { + return serverResponse; + } + + public void setServerResponse(QueryResourceRes.MixRecordingHLSAndMP4ServerResponse serverResponse) { + this.serverResponse = serverResponse; + } + + @Override + public String toString() { + return "QueryMixHLSAndMP4RecordingResourceRes{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", resourceId='" + resourceId + '\'' + + ", sid='" + sid + '\'' + + ", serverResponse=" + serverResponse + + '}'; + } + + public static final class Builder { + private String cname; + private String uid; + private String resourceId; + private String sid; + private QueryResourceRes.MixRecordingHLSAndMP4ServerResponse serverResponse; + + private Builder() { + } + + public Builder cname(String val) { + cname = val; + return this; + } + + public Builder uid(String val) { + uid = val; + return this; + } + + public Builder resourceId(String val) { + resourceId = val; + return this; + } + + public Builder sid(String val) { + sid = val; + return this; + } + + public Builder serverResponse(QueryResourceRes.MixRecordingHLSAndMP4ServerResponse val) { + serverResponse = val; + return this; + } + + public QueryMixHLSAndMP4RecordingResourceRes build() { + return new QueryMixHLSAndMP4RecordingResourceRes(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/res/QueryMixHLSRecordingResourceRes.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/res/QueryMixHLSRecordingResourceRes.java new file mode 100644 index 0000000..8841f93 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/mix/res/QueryMixHLSRecordingResourceRes.java @@ -0,0 +1,119 @@ +package io.agora.rest.services.cloudrecording.scenario.mix.res; + +import io.agora.rest.services.cloudrecording.api.res.QueryResourceRes; + +public class QueryMixHLSRecordingResourceRes { + + private String cname; + + private String uid; + + private String resourceId; + + private String sid; + + private QueryResourceRes.MixRecordingHLSServerResponse serverResponse; + + public static Builder builder() { + return new Builder(); + } + + private QueryMixHLSRecordingResourceRes(Builder builder) { + setCname(builder.cname); + setUid(builder.uid); + setResourceId(builder.resourceId); + setSid(builder.sid); + setServerResponse(builder.serverResponse); + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getSid() { + return sid; + } + + public void setSid(String sid) { + this.sid = sid; + } + + public QueryResourceRes.MixRecordingHLSServerResponse getServerResponse() { + return serverResponse; + } + + public void setServerResponse(QueryResourceRes.MixRecordingHLSServerResponse serverResponse) { + this.serverResponse = serverResponse; + } + + @Override + public String toString() { + return "QueryMixHLSRecordingResourceRes{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", resourceId='" + resourceId + '\'' + + ", sid='" + sid + '\'' + + ", serverResponse=" + serverResponse + + '}'; + } + + public static final class Builder { + private String cname; + private String uid; + private String resourceId; + private String sid; + private QueryResourceRes.MixRecordingHLSServerResponse serverResponse; + + private Builder() { + } + + public Builder cname(String val) { + cname = val; + return this; + } + + public Builder uid(String val) { + uid = val; + return this; + } + + public Builder resourceId(String val) { + resourceId = val; + return this; + } + + public Builder sid(String val) { + sid = val; + return this; + } + + public Builder serverResponse(QueryResourceRes.MixRecordingHLSServerResponse val) { + serverResponse = val; + return this; + } + + public QueryMixHLSRecordingResourceRes build() { + return new QueryMixHLSRecordingResourceRes(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/WebScenario.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/WebScenario.java new file mode 100644 index 0000000..6df0b22 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/WebScenario.java @@ -0,0 +1,116 @@ +package io.agora.rest.services.cloudrecording.scenario.web; + +import io.agora.rest.services.cloudrecording.api.*; +import io.agora.rest.services.cloudrecording.api.req.AcquireResourceReq; +import io.agora.rest.services.cloudrecording.api.req.StartResourceReq; +import io.agora.rest.services.cloudrecording.api.req.StopResourceReq; +import io.agora.rest.services.cloudrecording.api.req.UpdateResourceReq; +import io.agora.rest.services.cloudrecording.api.res.AcquireResourceRes; +import io.agora.rest.services.cloudrecording.api.res.StartResourceRes; +import io.agora.rest.services.cloudrecording.api.res.StopResourceRes; +import io.agora.rest.services.cloudrecording.api.res.UpdateResourceRes; +import io.agora.rest.services.cloudrecording.enums.CloudRecordingModeEnum; +import io.agora.rest.services.cloudrecording.scenario.web.req.AcquireWebRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.web.req.StartWebRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.web.req.UpdateWebRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.web.res.QueryWebRecordingResourceRes; +import reactor.core.publisher.Mono; + +public class WebScenario { + + private final AcquireResourceAPI acquireResourceAPI; + + private final QueryResourceAPI queryResourceAPI; + + private final StartResourceAPI startResourceAPI; + + private final UpdateResourceAPI updateResourceAPI; + + private final StopResourceAPI stopResourceAPI; + + public WebScenario(AcquireResourceAPI acquireResourceAPI, + QueryResourceAPI queryResourceAPI, + StartResourceAPI startResourceAPI, + UpdateResourceAPI updateResourceAPI, + StopResourceAPI stopResourceAPI) { + this.acquireResourceAPI = acquireResourceAPI; + this.queryResourceAPI = queryResourceAPI; + this.startResourceAPI = startResourceAPI; + this.updateResourceAPI = updateResourceAPI; + this.stopResourceAPI = stopResourceAPI; + } + + public Mono acquire(String cname, String uid, + AcquireWebRecordingResourceClientReq clientRequest) { + StartResourceReq.StartClientRequest startParameter = null; + + if (clientRequest.getStartParameter() != null) { + startParameter = StartResourceReq.StartClientRequest.builder() + .storageConfig(clientRequest.getStartParameter().getStorageConfig()) + .recordingFileConfig(clientRequest.getStartParameter().getRecordingFileConfig()) + .extensionServiceConfig(clientRequest.getStartParameter().getExtensionServiceConfig()) + .build(); + } + + return this.acquireResourceAPI.handle(AcquireResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(AcquireResourceReq.ClientRequest.builder() + .scene(1) + .resourceExpiredHour(clientRequest.getResourceExpiredHour()) + .regionAffinity(clientRequest.getRegionAffinity()) + .excludeResourceIds(clientRequest.getExcludeResourceIds()) + .startParameter(startParameter) + .build()) + .build()); + } + + public Mono start(String cname, String uid, String resourceId, + StartWebRecordingResourceClientReq clientRequest) { + return this.startResourceAPI.handle(resourceId, CloudRecordingModeEnum.WEB, StartResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(StartResourceReq.StartClientRequest.builder() + .storageConfig(clientRequest.getStorageConfig()) + .recordingFileConfig(clientRequest.getRecordingFileConfig()) + .extensionServiceConfig(clientRequest.getExtensionServiceConfig()) + .build()) + .build()); + } + + public Mono query(String resourceId, String sid) { + return this.queryResourceAPI.handle(resourceId, sid, CloudRecordingModeEnum.WEB).handle((res, sink) -> { + sink.next(QueryWebRecordingResourceRes.builder() + .cname(res.getCname()) + .uid(res.getUid()) + .resourceId(res.getResourceId()) + .sid(res.getSid()) + .serverResponse(res.getWebRecordingServerResponse()) + .build()); + + sink.complete(); + }); + } + + public Mono update(String cname, String uid, String resourceId, String sid, + UpdateWebRecordingResourceClientReq clientRequest) { + return this.updateResourceAPI.handle(resourceId, sid, CloudRecordingModeEnum.WEB, UpdateResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(UpdateResourceReq.ClientRequest.builder() + .webRecordingConfig(clientRequest.getWebRecordingConfig()) + .rtmpPublishConfig(clientRequest.getRtmpPublishConfig()) + .build()) + .build()); + } + + public Mono stop(String cname, String uid, String resourceId, String sid, boolean asyncStop) { + return this.stopResourceAPI.handle(resourceId, sid, CloudRecordingModeEnum.WEB, StopResourceReq.builder() + .cname(cname) + .uid(uid) + .clientRequest(StopResourceReq.StopClientRequest.builder() + .asyncStop(asyncStop) + .build()) + .build()); + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/AcquireWebRecordingResourceClientReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/AcquireWebRecordingResourceClientReq.java new file mode 100644 index 0000000..2d8506e --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/AcquireWebRecordingResourceClientReq.java @@ -0,0 +1,101 @@ +package io.agora.rest.services.cloudrecording.scenario.web.req; + +import java.util.List; + +public class AcquireWebRecordingResourceClientReq { + + private Integer resourceExpiredHour; + + private List excludeResourceIds; + + private Integer regionAffinity; + + private StartWebRecordingResourceClientReq startParameter; + + public static Builder builder() { + return new Builder(); + } + + private AcquireWebRecordingResourceClientReq(Builder builder) { + setResourceExpiredHour(builder.resourceExpiredHour); + setExcludeResourceIds(builder.excludeResourceIds); + setRegionAffinity(builder.regionAffinity); + setStartParameter(builder.startParameter); + } + + public Integer getResourceExpiredHour() { + return resourceExpiredHour; + } + + public void setResourceExpiredHour(Integer resourceExpiredHour) { + this.resourceExpiredHour = resourceExpiredHour; + } + + public List getExcludeResourceIds() { + return excludeResourceIds; + } + + public void setExcludeResourceIds(List excludeResourceIds) { + this.excludeResourceIds = excludeResourceIds; + } + + public Integer getRegionAffinity() { + return regionAffinity; + } + + public void setRegionAffinity(Integer regionAffinity) { + this.regionAffinity = regionAffinity; + } + + public StartWebRecordingResourceClientReq getStartParameter() { + return startParameter; + } + + public void setStartParameter(StartWebRecordingResourceClientReq startParameter) { + this.startParameter = startParameter; + } + + @Override + public String toString() { + return "AcquireWebRecordingResourceClientReq{" + + "resourceExpiredHour=" + resourceExpiredHour + + ", excludeResourceIds=" + excludeResourceIds + + ", regionAffinity=" + regionAffinity + + ", startParameter=" + startParameter + + '}'; + } + + public static final class Builder { + private Integer resourceExpiredHour; + private List excludeResourceIds; + private Integer regionAffinity; + private StartWebRecordingResourceClientReq startParameter; + + private Builder() { + } + + public Builder resourceExpiredHour(Integer val) { + resourceExpiredHour = val; + return this; + } + + public Builder excludeResourceIds(List val) { + excludeResourceIds = val; + return this; + } + + public Builder regionAffinity(Integer val) { + regionAffinity = val; + return this; + } + + public Builder startParameter(StartWebRecordingResourceClientReq val) { + startParameter = val; + return this; + } + + public AcquireWebRecordingResourceClientReq build() { + return new AcquireWebRecordingResourceClientReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/StartWebRecordingResourceClientReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/StartWebRecordingResourceClientReq.java new file mode 100644 index 0000000..556f4d3 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/StartWebRecordingResourceClientReq.java @@ -0,0 +1,83 @@ +package io.agora.rest.services.cloudrecording.scenario.web.req; + +import io.agora.rest.services.cloudrecording.api.req.StartResourceReq; + +public class StartWebRecordingResourceClientReq { + + private StartResourceReq.RecordingFileConfig recordingFileConfig; + + private StartResourceReq.StorageConfig storageConfig; + + private StartResourceReq.ExtensionServiceConfig extensionServiceConfig; + + public static Builder builder() { + return new Builder(); + } + + private StartWebRecordingResourceClientReq(Builder builder) { + setRecordingFileConfig(builder.recordingFileConfig); + setStorageConfig(builder.storageConfig); + setExtensionServiceConfig(builder.extensionServiceConfig); + } + + public StartResourceReq.RecordingFileConfig getRecordingFileConfig() { + return recordingFileConfig; + } + + public void setRecordingFileConfig(StartResourceReq.RecordingFileConfig recordingFileConfig) { + this.recordingFileConfig = recordingFileConfig; + } + + public StartResourceReq.StorageConfig getStorageConfig() { + return storageConfig; + } + + public void setStorageConfig(StartResourceReq.StorageConfig storageConfig) { + this.storageConfig = storageConfig; + } + + public StartResourceReq.ExtensionServiceConfig getExtensionServiceConfig() { + return extensionServiceConfig; + } + + public void setExtensionServiceConfig(StartResourceReq.ExtensionServiceConfig extensionServiceConfig) { + this.extensionServiceConfig = extensionServiceConfig; + } + + @Override + public String toString() { + return "StartWebRecordingResourceClientReq{" + + "recordingFileConfig=" + recordingFileConfig + + ", storageConfig=" + storageConfig + + ", extensionServiceConfig=" + extensionServiceConfig + + '}'; + } + + public static final class Builder { + private StartResourceReq.RecordingFileConfig recordingFileConfig; + private StartResourceReq.StorageConfig storageConfig; + private StartResourceReq.ExtensionServiceConfig extensionServiceConfig; + + private Builder() { + } + + public Builder recordingFileConfig(StartResourceReq.RecordingFileConfig val) { + recordingFileConfig = val; + return this; + } + + public Builder storageConfig(StartResourceReq.StorageConfig val) { + storageConfig = val; + return this; + } + + public Builder extensionServiceConfig(StartResourceReq.ExtensionServiceConfig val) { + extensionServiceConfig = val; + return this; + } + + public StartWebRecordingResourceClientReq build() { + return new StartWebRecordingResourceClientReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/UpdateWebRecordingResourceClientReq.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/UpdateWebRecordingResourceClientReq.java new file mode 100644 index 0000000..9c8155c --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/req/UpdateWebRecordingResourceClientReq.java @@ -0,0 +1,65 @@ +package io.agora.rest.services.cloudrecording.scenario.web.req; + +import io.agora.rest.services.cloudrecording.api.req.UpdateResourceReq; + +public class UpdateWebRecordingResourceClientReq { + + private UpdateResourceReq.WebRecordingConfig webRecordingConfig; + + private UpdateResourceReq.RtmpPublishConfig rtmpPublishConfig; + + public static Builder builder() { + return new Builder(); + } + + private UpdateWebRecordingResourceClientReq(Builder builder) { + setWebRecordingConfig(builder.webRecordingConfig); + setRtmpPublishConfig(builder.rtmpPublishConfig); + } + + public UpdateResourceReq.WebRecordingConfig getWebRecordingConfig() { + return webRecordingConfig; + } + + public void setWebRecordingConfig(UpdateResourceReq.WebRecordingConfig webRecordingConfig) { + this.webRecordingConfig = webRecordingConfig; + } + + public UpdateResourceReq.RtmpPublishConfig getRtmpPublishConfig() { + return rtmpPublishConfig; + } + + public void setRtmpPublishConfig(UpdateResourceReq.RtmpPublishConfig rtmpPublishConfig) { + this.rtmpPublishConfig = rtmpPublishConfig; + } + + @Override + public String toString() { + return "UpdateWebRecordingResourceClientReq{" + + "webRecordingConfig=" + webRecordingConfig + + ", rtmpPublishConfig=" + rtmpPublishConfig + + '}'; + } + + public static final class Builder { + private UpdateResourceReq.WebRecordingConfig webRecordingConfig; + private UpdateResourceReq.RtmpPublishConfig rtmpPublishConfig; + + private Builder() { + } + + public Builder webRecordingConfig(UpdateResourceReq.WebRecordingConfig val) { + webRecordingConfig = val; + return this; + } + + public Builder rtmpPublishConfig(UpdateResourceReq.RtmpPublishConfig val) { + rtmpPublishConfig = val; + return this; + } + + public UpdateWebRecordingResourceClientReq build() { + return new UpdateWebRecordingResourceClientReq(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/res/QueryWebRecordingResourceRes.java b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/res/QueryWebRecordingResourceRes.java new file mode 100644 index 0000000..1d6c7f3 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/scenario/web/res/QueryWebRecordingResourceRes.java @@ -0,0 +1,119 @@ +package io.agora.rest.services.cloudrecording.scenario.web.res; + +import io.agora.rest.services.cloudrecording.api.res.QueryResourceRes; + +public class QueryWebRecordingResourceRes { + + private String cname; + + private String uid; + + private String resourceId; + + private String sid; + + private QueryResourceRes.WebRecordingServerResponse serverResponse; + + public static Builder builder() { + return new Builder(); + } + + private QueryWebRecordingResourceRes(Builder builder) { + setCname(builder.cname); + setUid(builder.uid); + setResourceId(builder.resourceId); + setSid(builder.sid); + setServerResponse(builder.serverResponse); + } + + public String getCname() { + return cname; + } + + public void setCname(String cname) { + this.cname = cname; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getSid() { + return sid; + } + + public void setSid(String sid) { + this.sid = sid; + } + + public QueryResourceRes.WebRecordingServerResponse getServerResponse() { + return serverResponse; + } + + public void setServerResponse(QueryResourceRes.WebRecordingServerResponse serverResponse) { + this.serverResponse = serverResponse; + } + + @Override + public String toString() { + return "QueryWebRecordingResourceRes{" + + "cname='" + cname + '\'' + + ", uid='" + uid + '\'' + + ", resourceId='" + resourceId + '\'' + + ", sid='" + sid + '\'' + + ", serverResponse=" + serverResponse + + '}'; + } + + public static final class Builder { + private String cname; + private String uid; + private String resourceId; + private String sid; + private QueryResourceRes.WebRecordingServerResponse serverResponse; + + private Builder() { + } + + public Builder cname(String val) { + cname = val; + return this; + } + + public Builder uid(String val) { + uid = val; + return this; + } + + public Builder resourceId(String val) { + resourceId = val; + return this; + } + + public Builder sid(String val) { + sid = val; + return this; + } + + public Builder serverResponse(QueryResourceRes.WebRecordingServerResponse val) { + serverResponse = val; + return this; + } + + public QueryWebRecordingResourceRes build() { + return new QueryWebRecordingResourceRes(this); + } + } +} diff --git a/agora-rest-client-core/src/main/java/io/agora/rest/utils/ByteUtils.java b/agora-rest-client-core/src/main/java/io/agora/rest/utils/ByteUtils.java new file mode 100644 index 0000000..3267d51 --- /dev/null +++ b/agora-rest-client-core/src/main/java/io/agora/rest/utils/ByteUtils.java @@ -0,0 +1,12 @@ +package io.agora.rest.utils; + +import io.netty.buffer.ByteBuf; + +public class ByteUtils { + + public static byte[] toByteArray(ByteBuf buf) { + byte[] bytes = new byte[buf.readableBytes()]; + buf.getBytes(buf.readerIndex(), bytes); + return bytes; + } +} diff --git a/agora-rest-client-core/src/test/java/io/agora/rest/core/DomainDNSResolverTest.java b/agora-rest-client-core/src/test/java/io/agora/rest/core/DomainDNSResolverTest.java new file mode 100644 index 0000000..7b9cf2e --- /dev/null +++ b/agora-rest-client-core/src/test/java/io/agora/rest/core/DomainDNSResolverTest.java @@ -0,0 +1,26 @@ +package io.agora.rest.core; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class DomainDNSResolverTest { + + private static final Logger logger = LoggerFactory.getLogger(DomainDNSResolverTest.class); + + @Test + public void testDomainDNSResolver() { + DomainDNSResolver resolver = new DefaultDomainDNSResolver(); + assertNotNull(resolver); + + String domain = resolver.resolve(Arrays.asList("agora.io", "sd-rtn.com"), + RegionArea.CNRegionArea.getRegionDomainPrefixes().get(0)).block(); + + logger.info("Domain: {}", domain); + assertNotNull(domain); + } +} \ No newline at end of file diff --git a/examples/cloudrecording/README.md b/examples/cloudrecording/README.md new file mode 100644 index 0000000..52897a0 --- /dev/null +++ b/examples/cloudrecording/README.md @@ -0,0 +1,65 @@ +# CloudRecording Example + +> 这是 Agora Cloud Recording 的一个示例项目,使用了 Agora Cloud Recording RESTful API,实现了频道录制的功能。本示例支持合流录制、单流录制和页面录制三种模式。 + +## 运行示例项目 + +### 前提条件 + +配置环境变量,环境变量包括以下参数内容: + +```bash +export APP_ID= +export CNAME= +export USER_ID= +export BASIC_AUTH_USERNAME= +export BASIC_AUTH_PASSWORD= +export TOKEN= +export STORAGE_CONFIG_VENDOR= +export STORAGE_CONFIG_REGION= +export STORAGE_CONFIG_BUCKET= +export STORAGE_CONFIG_ACCESS_KEY= +export STORAGE_CONFIG_SECRET_KEY= +``` + +相关的参数可以通过可在 [CloudRecording 服务说明](../../agora-rest-client-core/src/main/java/io/agora/rest/services/cloudrecording/README.md) 查看 + +### 执行 + +请确保在主模块目录已经执行了模块安装操作: + +```bash +make install +``` + +接着,在当前模块下,通过分别执行下面的命令来体验不同场景的`CloudRecording`示例: + +```bash +mvn exec:java -Dexec.mainClass="io.agora.rest.examples.cloudrecording.Main" -Dexec.args="--mode=mix --mix_scene=" +mvn exec:java -Dexec.mainClass="io.agora.rest.examples.cloudrecording.Main" -Dexec.args="--mode=individual --individual_scene=" +mvn exec:java -Dexec.mainClass="io.agora.rest.examples.cloudrecording.Main" -Dexec.args="--mode=web --web_scene=" +``` + +其中 `mode` 表示云录制模式: + +* mix: 合流录制 +* individual: 单流录制 +* web: 页面录制 + +其中 `mix_scene` 表示合流录制场景: + +* hls: 录制hls格式 +* hls_and_mp4: 录制hls和mp4格式 + +其中 `individual_scene` 表示单流录制场景: + +* recording: 仅录制 +* snapshot: 仅截图 +* recording_and_snapshot: 录制+截图 +* recording_and_postpone_transcoding: 录制+延时转码 +* recording_and_audio_mix: 录制+延时混音 + +其中 `web_scene` 表示页面录制场景: + +* web_recorder: 页面录制 +* web_recorder_and_rtmp_publish: 页面录制+转推到CDN diff --git a/examples/cloudrecording/pom.xml b/examples/cloudrecording/pom.xml new file mode 100644 index 0000000..cf32efd --- /dev/null +++ b/examples/cloudrecording/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + io.agora + agora-rest-client-parent + 1.0 + ../../pom.xml + + cloudrecording + 1.0 + + + 8 + 8 + UTF-8 + 2.0.16 + 1.3.14 + 4.7.6 + 0.1.2.1-BETA + + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + ch.qos.logback + logback-core + ${logback.version} + + + io.agora + agora-rest-client-core + ${agora-rest-client-core.version} + compile + + + info.picocli + picocli + ${picocli.version} + + + + \ No newline at end of file diff --git a/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/Main.java b/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/Main.java new file mode 100644 index 0000000..6a5f35b --- /dev/null +++ b/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/Main.java @@ -0,0 +1,149 @@ +package io.agora.rest.examples.cloudrecording; + +import io.agora.rest.core.BasicAuthCredential; +import io.agora.rest.core.RegionArea; +import io.agora.rest.examples.cloudrecording.scenario.IndividualRecordingScenario; +import io.agora.rest.examples.cloudrecording.scenario.MixRecordingScenario; +import io.agora.rest.examples.cloudrecording.scenario.WebRecordingScenario; +import io.agora.rest.services.cloudrecording.api.req.StartResourceReq; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import picocli.CommandLine; +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; + +import java.util.concurrent.Callable; + +@Command(name = "Main", mixinStandardHelpOptions = true, version = "0.1.0", + description = "Agora Recording Service") +public class Main implements Callable { + private static final Logger logger = LoggerFactory.getLogger(Main.class); + + private String appId; + + private String cname; + + private String uid; + + private String username; + + private String password; + + private String token; + + private final RegionArea region = RegionArea.CNRegionArea; + + private StartResourceReq.StorageConfig storageConfig; + + @Option(names = {"-m", "--mode"}, description = "mix, web, individual") + private String mode = ""; + + @Option(names = {"-ms", "--mix_scene"}, description = "hls, hls_and_mp4") + private String mixScene = ""; + + @Option(names = {"-is", "--individual_scene"}, description = "recording, snapshot, recording_and_snapshot, recording_and_postpone_transcoding, recording_and_audio_mix") + private String individualScene = ""; + + @Option(names = {"-ws", "--web_scene"}, description = "web_recorder, web_recorder_and_rtmp_publish") + private String webScene = ""; + + public static void main(String[] args) { + logger.info("Start cloud recording service"); + int exitCode = new CommandLine(new Main()).execute(args); + System.exit(exitCode); + } + + private void loadEnv() { + appId = System.getenv("APP_ID"); + cname = System.getenv("CNAME"); + uid = System.getenv("USER_ID"); + username = System.getenv("BASIC_AUTH_USERNAME"); + password = System.getenv("BASIC_AUTH_PASSWORD"); + token = System.getenv("TOKEN"); + storageConfig = StartResourceReq.StorageConfig.builder() + .vendor(Integer.parseInt(System.getenv("STORAGE_CONFIG_VENDOR"))) + .region(Integer.parseInt(System.getenv("STORAGE_CONFIG_REGION"))) + .bucket(System.getenv("STORAGE_CONFIG_BUCKET")) + .accessKey(System.getenv("STORAGE_CONFIG_ACCESS_KEY")) + .secretKey(System.getenv("STORAGE_CONFIG_SECRET_KEY")) + .build(); + } + + private void handleMixMode() { + MixRecordingScenario mixScenario = new MixRecordingScenario(region, appId, cname, uid, new BasicAuthCredential(username, password)); + + switch (mixScene) { + case "hls": + mixScenario.runHLS(token, storageConfig); + break; + case "hls_and_mp4": + mixScenario.runHLSAndMP4(token, storageConfig); + break; + default: + throw new IllegalArgumentException("invalid mix_scene:" + mixScene); + } + } + + private void handleIndividualMode() { + IndividualRecordingScenario individualScenario = new IndividualRecordingScenario(region, appId, cname, uid, new BasicAuthCredential(username, password)); + + switch (individualScene) { + case "recording": + individualScenario.runRecording(token, storageConfig); + break; + case "snapshot": + individualScenario.runSnapshot(token, storageConfig); + break; + case "recording_and_snapshot": + individualScenario.runRecordingAndSnapshot(token, storageConfig); + break; + case "recording_and_postpone_transcoding": + individualScenario.runRecordingAndPostponeTranscoding(token, storageConfig); + break; + case "recording_and_audio_mix": + individualScenario.runRecordingAndAudioMix(token, storageConfig); + break; + default: + throw new IllegalArgumentException("invalid individual_scene: " + individualScene); + } + } + + private void handleWebMode() { + WebRecordingScenario webScenario = new WebRecordingScenario(region, appId, cname, uid, new BasicAuthCredential(username, password)); + + switch (webScene) { + case "web_recorder": + webScenario.runWebRecorder(storageConfig); + break; + case "web_recorder_and_rtmp_publish": + webScenario.runWebRecorderAndRtmpPublish(storageConfig); + break; + default: + throw new IllegalArgumentException("invalid web_scene: " + webScene); + } + } + + @Override + public Integer call() throws Exception { + loadEnv(); + + logger.info("appId: {}, cname: {}, uid: {}, username: {}, password: {}, token: {}, region: {}, storageConfig: {}", + appId, cname, uid, username, password, token, region, storageConfig); + + switch (mode) { + case "mix": + handleMixMode(); + break; + case "individual": + handleIndividualMode(); + break; + case "web": + handleWebMode(); + break; + default: + throw new IllegalArgumentException("Invalid mode: " + mode); + } + + return 0; + } +} diff --git a/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/BaseScenario.java b/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/BaseScenario.java new file mode 100644 index 0000000..8ad7b0f --- /dev/null +++ b/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/BaseScenario.java @@ -0,0 +1,43 @@ +package io.agora.rest.examples.cloudrecording.scenario; + +import io.agora.rest.AgoraService; +import io.agora.rest.core.AgoraProperty; +import io.agora.rest.core.Credential; +import io.agora.rest.core.RegionArea; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BaseScenario { + + private static final Logger logger = LoggerFactory.getLogger(BaseScenario.class); + + protected final RegionArea region; + + protected final String appId; + + protected final String cname; + + protected final String uid; + + protected final Credential credential; + + protected final AgoraService agoraService; + + public BaseScenario(RegionArea region, String appId, String cname, String uid, Credential credential) { + this.region = region; + this.appId = appId; + this.cname = cname; + this.uid = uid; + this.credential = credential; + + AgoraProperty agoraProperty = AgoraProperty.builder() + .appId(appId) + .credential(credential) + .regionArea(region) + .build(); + + logger.info("AgoraProperty: {}", agoraProperty); + + this.agoraService = new AgoraService(agoraProperty); + } +} diff --git a/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/IndividualRecordingScenario.java b/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/IndividualRecordingScenario.java new file mode 100644 index 0000000..055d1b0 --- /dev/null +++ b/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/IndividualRecordingScenario.java @@ -0,0 +1,925 @@ +package io.agora.rest.examples.cloudrecording.scenario; + +import io.agora.rest.AgoraException; +import io.agora.rest.core.Credential; +import io.agora.rest.core.RegionArea; +import io.agora.rest.services.cloudrecording.api.req.StartResourceReq; +import io.agora.rest.services.cloudrecording.api.req.UpdateResourceReq; +import io.agora.rest.services.cloudrecording.api.res.AcquireResourceRes; +import io.agora.rest.services.cloudrecording.api.res.StartResourceRes; +import io.agora.rest.services.cloudrecording.api.res.StopResourceRes; +import io.agora.rest.services.cloudrecording.api.res.UpdateResourceRes; +import io.agora.rest.services.cloudrecording.scenario.individual.req.AcquireIndividualResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.individual.req.StartIndividualRecordingClientReq; +import io.agora.rest.services.cloudrecording.scenario.individual.req.UpdateIndividualRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.individual.res.QueryIndividualRecordingResourceRes; +import io.agora.rest.services.cloudrecording.scenario.individual.res.QueryIndividualRecordingVideoScreenshotResourceRes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; + +public class IndividualRecordingScenario extends BaseScenario { + private static final Logger logger = LoggerFactory.getLogger(IndividualRecordingScenario.class); + + public IndividualRecordingScenario(RegionArea region, String appId, String cname, String uid, Credential credential) { + super(region, appId, cname, uid, credential); + } + + public void runRecording(String token, StartResourceReq.StorageConfig storageConfig) { + // acquire + AcquireResourceRes acquireResourceRes; + try { + acquireResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .acquire(cname, uid, false, AcquireIndividualResourceClientReq.builder() + .resourceExpiredHour(1) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to acquire resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + logger.info("Acquire resource successfully,acquireResourceResp:{}", acquireResourceRes); + + if (acquireResourceRes == null) { + logger.error("Failed to acquire resource, acquireResourceRes is null"); + return; + } + + // start + + StartResourceRes startResourceRes; + + try { + startResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .start(cname, uid, acquireResourceRes.getResourceId(), StartIndividualRecordingClientReq.builder() + .token(token) + .recordingConfig(StartResourceReq.RecordingConfig.builder() + .channelType(1) + .streamTypes(2) + .maxIdleTime(30) + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .subscribeUidGroup(0) + .build()) + .recordingFileConfig(StartResourceReq.RecordingFileConfig.builder() + .avFileType(Collections.singletonList("hls")) + .build()) + .storageConfig(storageConfig) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to start resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (startResourceRes == null) { + logger.error("Failed to start resource, startResourceRes is null"); + return; + } + + logger.info("Start resource successfully,startResourceResp:{}", startResourceRes); + + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryIndividualRecordingResourceRes queryIndividualRecordingResourceRes; + try { + queryIndividualRecordingResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryIndividualRecordingResourceRes == null) { + logger.error("Failed to query resource, queryIndividualRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryIndividualRecordingResourceResp:{}", queryIndividualRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // update + UpdateResourceRes updateResourceRes; + + try { + updateResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .update(cname, uid, acquireResourceRes.getResourceId(), startResourceRes.getSid(), UpdateIndividualRecordingResourceClientReq.builder() + .streamSubscribe(UpdateResourceReq.StreamSubscribe.builder() + .audioUidList(UpdateResourceReq.AudioUIDList.builder() + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .build()) + + .videoUidList(UpdateResourceReq.VideoUIDList.builder() + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .build()) + .build()) + .build()).block(); + + } catch (AgoraException e) { + logger.error("Failed to update resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (updateResourceRes == null) { + logger.error("Failed to update resource, updateResourceRes is null"); + return; + } + + logger.info("Update resource successfully,updateResourceResp:{}", updateResourceRes); + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryIndividualRecordingResourceRes queryIndividualRecordingResourceRes; + try { + queryIndividualRecordingResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryIndividualRecordingResourceRes == null) { + logger.error("Failed to query resource, queryIndividualRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryIndividualRecordingResourceResp:{}", queryIndividualRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + StopResourceRes stopResourceRes; + try { + stopResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .stop(cname, uid, startResourceRes.getResourceId(), startResourceRes.getSid(), false) + .block(); + } catch (AgoraException e) { + logger.error("Failed to stop resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (stopResourceRes == null) { + logger.error("Failed to stop resource, stopResourceRes is null"); + return; + } + + logger.info("Stop resource successfully,stopResourceResp:{}", stopResourceRes); + } + + public void runSnapshot(String token, StartResourceReq.StorageConfig storageConfig) { + // Run snapshot implementation + + // acquire + AcquireResourceRes acquireResourceRes; + try { + acquireResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .acquire(cname, uid, false, AcquireIndividualResourceClientReq.builder() + .resourceExpiredHour(1) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to acquire resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + logger.info("Acquire resource successfully,acquireResourceResp:{}", acquireResourceRes); + + if (acquireResourceRes == null) { + logger.error("Failed to acquire resource, acquireResourceRes is null"); + return; + } + + // start + StartResourceRes startResourceRes; + + try { + startResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .start(cname, uid, acquireResourceRes.getResourceId(), StartIndividualRecordingClientReq.builder() + .token(token) + .recordingConfig(StartResourceReq.RecordingConfig.builder() + .channelType(1) + .streamTypes(2) + .maxIdleTime(30) + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .subscribeUidGroup(0) + .build()) + .snapshotConfig(StartResourceReq.SnapshotConfig.builder() + .captureInterval(5) + .fileType(Collections.singletonList("jpg")) + .build()) + .storageConfig(storageConfig) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to start resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (startResourceRes == null) { + logger.error("Failed to start resource, startResourceRes is null"); + return; + } + + logger.info("Start resource successfully,startResourceResp:{}", startResourceRes); + + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryIndividualRecordingVideoScreenshotResourceRes queryIndividualRecordingVideoScreenshotResourceRes; + try { + queryIndividualRecordingVideoScreenshotResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .queryVideoScreenshot(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryIndividualRecordingVideoScreenshotResourceRes == null) { + logger.error("Failed to query resource, queryIndividualRecordingVideoScreenshotResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryIndividualRecordingVideoScreenshotResourceResp:{}", queryIndividualRecordingVideoScreenshotResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // update + UpdateResourceRes updateResourceRes; + + try { + updateResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .update(cname, uid, acquireResourceRes.getResourceId(), startResourceRes.getSid(), UpdateIndividualRecordingResourceClientReq.builder() + .streamSubscribe(UpdateResourceReq.StreamSubscribe.builder() + .audioUidList(UpdateResourceReq.AudioUIDList.builder() + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .build()) + + .videoUidList(UpdateResourceReq.VideoUIDList.builder() + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .build()) + .build()) + .build()).block(); + + } catch (AgoraException e) { + logger.error("Failed to update resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (updateResourceRes == null) { + logger.error("Failed to update resource, updateResourceRes is null"); + return; + } + + logger.info("Update resource successfully,updateResourceResp:{}", updateResourceRes); + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryIndividualRecordingVideoScreenshotResourceRes queryIndividualRecordingVideoScreenshotResourceRes; + try { + queryIndividualRecordingVideoScreenshotResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .queryVideoScreenshot(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryIndividualRecordingVideoScreenshotResourceRes == null) { + logger.error("Failed to query resource, queryIndividualRecordingVideoScreenshotResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryIndividualRecordingVideoScreenshotResourceResp:{}", queryIndividualRecordingVideoScreenshotResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + StopResourceRes stopResourceRes; + try { + stopResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .stop(cname, uid, startResourceRes.getResourceId(), startResourceRes.getSid(), false) + .block(); + } catch (AgoraException e) { + logger.error("Failed to stop resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (stopResourceRes == null) { + logger.error("Failed to stop resource, stopResourceRes is null"); + return; + } + + logger.info("Stop resource successfully,stopResourceResp:{}", stopResourceRes); + } + + public void runRecordingAndSnapshot(String token, StartResourceReq.StorageConfig storageConfig) { + // Run recording and snapshot implementation + + // acquire + AcquireResourceRes acquireResourceRes; + try { + acquireResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .acquire(cname, uid, false, AcquireIndividualResourceClientReq.builder() + .resourceExpiredHour(1) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to acquire resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + logger.info("Acquire resource successfully,acquireResourceResp:{}", acquireResourceRes); + + if (acquireResourceRes == null) { + logger.error("Failed to acquire resource, acquireResourceRes is null"); + return; + } + + // start + StartResourceRes startResourceRes; + + try { + startResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .start(cname, uid, acquireResourceRes.getResourceId(), StartIndividualRecordingClientReq.builder() + .token(token) + .recordingConfig(StartResourceReq.RecordingConfig.builder() + .channelType(1) + .streamTypes(2) + .maxIdleTime(30) + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .subscribeUidGroup(0) + .build()) + .recordingFileConfig(StartResourceReq.RecordingFileConfig.builder() + .avFileType(Collections.singletonList("hls")) + .build()) + .snapshotConfig(StartResourceReq.SnapshotConfig.builder() + .captureInterval(5) + .fileType(Collections.singletonList("jpg")) + .build()) + .storageConfig(storageConfig) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to start resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (startResourceRes == null) { + logger.error("Failed to start resource, startResourceRes is null"); + return; + } + + logger.info("Start resource successfully,startResourceResp:{}", startResourceRes); + + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryIndividualRecordingResourceRes queryIndividualRecordingResourceRes; + try { + queryIndividualRecordingResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryIndividualRecordingResourceRes == null) { + logger.error("Failed to query resource, queryIndividualRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryIndividualRecordingResourceResp:{}", queryIndividualRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // update + UpdateResourceRes updateResourceRes; + + try { + updateResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .update(cname, uid, acquireResourceRes.getResourceId(), startResourceRes.getSid(), UpdateIndividualRecordingResourceClientReq.builder() + .streamSubscribe(UpdateResourceReq.StreamSubscribe.builder() + .audioUidList(UpdateResourceReq.AudioUIDList.builder() + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .build()) + + .videoUidList(UpdateResourceReq.VideoUIDList.builder() + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .build()) + .build()) + .build()).block(); + + } catch (AgoraException e) { + logger.error("Failed to update resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (updateResourceRes == null) { + logger.error("Failed to update resource, updateResourceRes is null"); + return; + } + + logger.info("Update resource successfully,updateResourceResp:{}", updateResourceRes); + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryIndividualRecordingResourceRes queryIndividualRecordingResourceRes; + try { + queryIndividualRecordingResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryIndividualRecordingResourceRes == null) { + logger.error("Failed to query resource, queryIndividualRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryIndividualRecordingResourceResp:{}", queryIndividualRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + StopResourceRes stopResourceRes; + try { + stopResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .stop(cname, uid, startResourceRes.getResourceId(), startResourceRes.getSid(), false) + .block(); + } catch (AgoraException e) { + logger.error("Failed to stop resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (stopResourceRes == null) { + logger.error("Failed to stop resource, stopResourceRes is null"); + return; + } + + logger.info("Stop resource successfully,stopResourceResp:{}", stopResourceRes); + } + + public void runRecordingAndPostponeTranscoding(String token, StartResourceReq.StorageConfig storageConfig) { + // Run recording and postpone transcoding implementation + + // acquire + AcquireResourceRes acquireResourceRes; + try { + acquireResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .acquire(cname, uid, true, AcquireIndividualResourceClientReq.builder() + .resourceExpiredHour(1) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to acquire resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + logger.info("Acquire resource successfully,acquireResourceResp:{}", acquireResourceRes); + + if (acquireResourceRes == null) { + logger.error("Failed to acquire resource, acquireResourceRes is null"); + return; + } + + // start + StartResourceRes startResourceRes; + + try { + startResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .start(cname, uid, acquireResourceRes.getResourceId(), StartIndividualRecordingClientReq.builder() + .token(token) + .recordingConfig(StartResourceReq.RecordingConfig.builder() + .channelType(1) + .streamTypes(2) + .maxIdleTime(30) + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .subscribeUidGroup(0) + .build()) + .recordingFileConfig(StartResourceReq.RecordingFileConfig.builder() + .avFileType(Collections.singletonList("hls")) + .build()) + .appsCollection(StartResourceReq.AppsCollection.builder() + .combinationPolicy("postpone_transcoding") + .build()) + .transcodeOptions(StartResourceReq.TranscodeOptions.builder() + .container(StartResourceReq.Container.builder() + .format("mp4") + .build()) + .transConfig(StartResourceReq.TransConfig.builder() + .transMode("postponeTranscoding") + .build()) + .build()) + .storageConfig(storageConfig) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to start resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (startResourceRes == null) { + logger.error("Failed to start resource, startResourceRes is null"); + return; + } + + logger.info("Start resource successfully,startResourceResp:{}", startResourceRes); + + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryIndividualRecordingResourceRes queryIndividualRecordingResourceRes; + try { + queryIndividualRecordingResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryIndividualRecordingResourceRes == null) { + logger.error("Failed to query resource, queryIndividualRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryIndividualRecordingResourceResp:{}", queryIndividualRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // update + UpdateResourceRes updateResourceRes; + + try { + updateResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .update(cname, uid, acquireResourceRes.getResourceId(), startResourceRes.getSid(), UpdateIndividualRecordingResourceClientReq.builder() + .streamSubscribe(UpdateResourceReq.StreamSubscribe.builder() + .audioUidList(UpdateResourceReq.AudioUIDList.builder() + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .build()) + + .videoUidList(UpdateResourceReq.VideoUIDList.builder() + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .build()) + .build()) + .build()).block(); + + } catch (AgoraException e) { + logger.error("Failed to update resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (updateResourceRes == null) { + logger.error("Failed to update resource, updateResourceRes is null"); + return; + } + + logger.info("Update resource successfully,updateResourceResp:{}", updateResourceRes); + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryIndividualRecordingResourceRes queryIndividualRecordingResourceRes; + try { + queryIndividualRecordingResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryIndividualRecordingResourceRes == null) { + logger.error("Failed to query resource, queryIndividualRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryIndividualRecordingResourceResp:{}", queryIndividualRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + StopResourceRes stopResourceRes; + try { + stopResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .stop(cname, uid, startResourceRes.getResourceId(), startResourceRes.getSid(), false) + .block(); + } catch (AgoraException e) { + logger.error("Failed to stop resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (stopResourceRes == null) { + logger.error("Failed to stop resource, stopResourceRes is null"); + return; + } + + logger.info("Stop resource successfully,stopResourceResp:{}", stopResourceRes); + } + + public void runRecordingAndAudioMix(String token, StartResourceReq.StorageConfig storageConfig) { + // Run recording and audio mix implementation + + // acquire + AcquireResourceRes acquireResourceRes; + try { + acquireResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .acquire(cname, uid, true, AcquireIndividualResourceClientReq.builder() + .resourceExpiredHour(1) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to acquire resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + logger.info("Acquire resource successfully,acquireResourceResp:{}", acquireResourceRes); + + if (acquireResourceRes == null) { + logger.error("Failed to acquire resource, acquireResourceRes is null"); + return; + } + + // start + StartResourceRes startResourceRes; + + try { + startResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .start(cname, uid, acquireResourceRes.getResourceId(), StartIndividualRecordingClientReq.builder() + .token(token) + .recordingConfig(StartResourceReq.RecordingConfig.builder() + .channelType(1) + .streamTypes(0) + .streamMode("original") + .maxIdleTime(30) + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .subscribeUidGroup(0) + .build()) + .recordingFileConfig(StartResourceReq.RecordingFileConfig.builder() + .avFileType(Collections.singletonList("hls")) + .build()) + .appsCollection(StartResourceReq.AppsCollection.builder() + .combinationPolicy("postpone_transcoding") + .build()) + .transcodeOptions(StartResourceReq.TranscodeOptions.builder() + .container(StartResourceReq.Container.builder() + .format("mp3") + .build()) + .transConfig(StartResourceReq.TransConfig.builder() + .transMode("audioMix") + .build()) + .audio(StartResourceReq.Audio.builder() + .sampleRate("48000") + .bitRate("48000") + .channels("2") + .build()) + .build()) + .storageConfig(storageConfig) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to start resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (startResourceRes == null) { + logger.error("Failed to start resource, startResourceRes is null"); + return; + } + + logger.info("Start resource successfully,startResourceResp:{}", startResourceRes); + + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryIndividualRecordingResourceRes queryIndividualRecordingResourceRes; + try { + queryIndividualRecordingResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryIndividualRecordingResourceRes == null) { + logger.error("Failed to query resource, queryIndividualRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryIndividualRecordingResourceResp:{}", queryIndividualRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // update + UpdateResourceRes updateResourceRes; + + try { + updateResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .update(cname, uid, acquireResourceRes.getResourceId(), startResourceRes.getSid(), UpdateIndividualRecordingResourceClientReq.builder() + .streamSubscribe(UpdateResourceReq.StreamSubscribe.builder() + .audioUidList(UpdateResourceReq.AudioUIDList.builder() + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .build()) + .build()) + .build()).block(); + + } catch (AgoraException e) { + logger.error("Failed to update resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (updateResourceRes == null) { + logger.error("Failed to update resource, updateResourceRes is null"); + return; + } + + logger.info("Update resource successfully,updateResourceResp:{}", updateResourceRes); + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryIndividualRecordingResourceRes queryIndividualRecordingResourceRes; + try { + queryIndividualRecordingResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryIndividualRecordingResourceRes == null) { + logger.error("Failed to query resource, queryIndividualRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryIndividualRecordingResourceResp:{}", queryIndividualRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + StopResourceRes stopResourceRes; + try { + stopResourceRes = this.agoraService.cloudRecording() + .individualScenario() + .stop(cname, uid, startResourceRes.getResourceId(), startResourceRes.getSid(), false) + .block(); + } catch (AgoraException e) { + logger.error("Failed to stop resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (stopResourceRes == null) { + logger.error("Failed to stop resource, stopResourceRes is null"); + return; + } + + logger.info("Stop resource successfully,stopResourceResp:{}", stopResourceRes); + } +} diff --git a/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/MixRecordingScenario.java b/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/MixRecordingScenario.java new file mode 100644 index 0000000..9fa3886 --- /dev/null +++ b/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/MixRecordingScenario.java @@ -0,0 +1,447 @@ +package io.agora.rest.examples.cloudrecording.scenario; + +import io.agora.rest.AgoraException; +import io.agora.rest.core.Credential; +import io.agora.rest.core.RegionArea; +import io.agora.rest.services.cloudrecording.api.req.StartResourceReq; +import io.agora.rest.services.cloudrecording.api.req.UpdateResourceReq; +import io.agora.rest.services.cloudrecording.api.res.*; +import io.agora.rest.services.cloudrecording.scenario.mix.req.AcquireMixRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.mix.req.StartMixRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.mix.req.UpdateLayoutMixRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.mix.req.UpdateMixRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.mix.res.QueryMixHLSAndMP4RecordingResourceRes; +import io.agora.rest.services.cloudrecording.scenario.mix.res.QueryMixHLSRecordingResourceRes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.Collections; + +public class MixRecordingScenario extends BaseScenario { + private static final Logger logger = LoggerFactory.getLogger(MixRecordingScenario.class); + + public MixRecordingScenario(RegionArea region, String appId, String cname, String uid, Credential credential) { + super(region, appId, cname, uid, credential); + } + + public void runHLS(String token, StartResourceReq.StorageConfig storageConfig) { + // Run HLS implementation + + // acquire + AcquireResourceRes acquireResourceRes; + try { + acquireResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .acquire(cname, uid, AcquireMixRecordingResourceClientReq.builder() + .resourceExpiredHour(1) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to acquire resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + logger.info("Acquire resource successfully,acquireResourceResp:{}", acquireResourceRes); + + if (acquireResourceRes == null) { + logger.error("Failed to acquire resource, acquireResourceRes is null"); + return; + } + + // start + StartResourceRes startResourceRes; + + try { + startResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .start(cname, uid, acquireResourceRes.getResourceId(), StartMixRecordingResourceClientReq.builder() + .token(token) + .recordingConfig(StartResourceReq.RecordingConfig.builder() + .channelType(1) + .streamTypes(2) + .maxIdleTime(30) + .audioProfile(2) + .transcodingConfig(StartResourceReq.TranscodingConfig.builder() + .width(640) + .height(480) + .fps(15) + .bitrate(800) + .mixedVideoLayout(0) + .backgroundColor("#000000") + .build()) + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .build()) + .recordingFileConfig(StartResourceReq.RecordingFileConfig.builder() + .avFileType(Collections.singletonList("hls")) + .build()) + .storageConfig(storageConfig) + .build()) + .block(); + + } catch (AgoraException e) { + logger.error("Failed to start resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (startResourceRes == null) { + logger.error("Failed to start resource, startResourceRes is null"); + return; + } + + logger.info("Start resource successfully,startResourceResp:{}", startResourceRes); + + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryMixHLSRecordingResourceRes queryMixHLSRecordingResourceRes; + try { + queryMixHLSRecordingResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .queryHLS(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryMixHLSRecordingResourceRes == null) { + logger.error("Failed to query resource, queryMixHLSRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryMixHLSRecordingResourceResp:{}", queryMixHLSRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // update + UpdateResourceRes updateResourceRes; + + try { + updateResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .update(cname, uid, acquireResourceRes.getResourceId(), startResourceRes.getSid(), UpdateMixRecordingResourceClientReq.builder() + .streamSubscribe(UpdateResourceReq.StreamSubscribe.builder() + .audioUidList(UpdateResourceReq.AudioUIDList.builder() + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .build()) + .videoUidList(UpdateResourceReq.VideoUIDList.builder() + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .build()) + .build()) + .build()).block(); + + } catch (AgoraException e) { + logger.error("Failed to update resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (updateResourceRes == null) { + logger.error("Failed to update resource, updateResourceRes is null"); + return; + } + + logger.info("Update resource successfully,updateResourceResp:{}", updateResourceRes); + + + // update + UpdateLayoutResourceRes updateLayoutResourceRes; + + try { + updateLayoutResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .updateLayout(cname, uid, acquireResourceRes.getResourceId(), startResourceRes.getSid(), UpdateLayoutMixRecordingResourceClientReq.builder() + .mixedVideoLayout(1) + .backgroundColor("#FF0000") + .build()).block(); + + } catch (AgoraException e) { + logger.error("Failed to update layout resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (updateLayoutResourceRes == null) { + logger.error("Failed to update layout resource, updateLayoutResourceRes is null"); + return; + } + + logger.info("Update resource successfully,updateLayoutResourceResp:{}", updateLayoutResourceRes); + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryMixHLSRecordingResourceRes queryMixHLSRecordingResourceRes; + try { + queryMixHLSRecordingResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .queryHLS(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryMixHLSRecordingResourceRes == null) { + logger.error("Failed to query resource, queryMixHLSRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryMixHLSRecordingResourceResp:{}", queryMixHLSRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + StopResourceRes stopResourceRes; + try { + stopResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .stop(cname, uid, startResourceRes.getResourceId(), startResourceRes.getSid(), false) + .block(); + } catch (AgoraException e) { + logger.error("Failed to stop resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (stopResourceRes == null) { + logger.error("Failed to stop resource, stopResourceRes is null"); + return; + } + + logger.info("Stop resource successfully,stopResourceResp:{}", stopResourceRes); + } + + public void runHLSAndMP4(String token, StartResourceReq.StorageConfig storageConfig) { + // Run HLS and MP4 implementation + + // acquire + AcquireResourceRes acquireResourceRes; + try { + acquireResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .acquire(cname, uid, AcquireMixRecordingResourceClientReq.builder() + .resourceExpiredHour(1) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to acquire resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + logger.info("Acquire resource successfully,acquireResourceResp:{}", acquireResourceRes); + + if (acquireResourceRes == null) { + logger.error("Failed to acquire resource, acquireResourceRes is null"); + return; + } + + // start + StartResourceRes startResourceRes; + + try { + startResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .start(cname, uid, acquireResourceRes.getResourceId(), StartMixRecordingResourceClientReq.builder() + .token(token) + .recordingConfig(StartResourceReq.RecordingConfig.builder() + .channelType(1) + .streamTypes(2) + .maxIdleTime(30) + .audioProfile(2) + .transcodingConfig(StartResourceReq.TranscodingConfig.builder() + .width(640) + .height(480) + .fps(15) + .bitrate(800) + .mixedVideoLayout(0) + .backgroundColor("#000000") + .build()) + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .build()) + .recordingFileConfig(StartResourceReq.RecordingFileConfig.builder() + .avFileType(Arrays.asList("hls", "mp4")) + .build()) + .storageConfig(storageConfig) + .build()) + .block(); + + } catch (AgoraException e) { + logger.error("Failed to start resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (startResourceRes == null) { + logger.error("Failed to start resource, startResourceRes is null"); + return; + } + + logger.info("Start resource successfully,startResourceResp:{}", startResourceRes); + + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryMixHLSAndMP4RecordingResourceRes queryMixHLSAndMP4RecordingResourceRes; + try { + queryMixHLSAndMP4RecordingResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .queryHLSAndMP4(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryMixHLSAndMP4RecordingResourceRes == null) { + logger.error("Failed to query resource, queryMixHLSAndMP4RecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryMixHLSAndMP4RecordingResourceResp:{}", queryMixHLSAndMP4RecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // update + UpdateResourceRes updateResourceRes; + + try { + updateResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .update(cname, uid, acquireResourceRes.getResourceId(), startResourceRes.getSid(), UpdateMixRecordingResourceClientReq.builder() + .streamSubscribe(UpdateResourceReq.StreamSubscribe.builder() + .audioUidList(UpdateResourceReq.AudioUIDList.builder() + .subscribeAudioUIDs(Collections.singletonList("#allstream#")) + .build()) + .videoUidList(UpdateResourceReq.VideoUIDList.builder() + .subscribeVideoUIDs(Collections.singletonList("#allstream#")) + .build()) + .build()) + .build()).block(); + + } catch (AgoraException e) { + logger.error("Failed to update resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (updateResourceRes == null) { + logger.error("Failed to update resource, updateResourceRes is null"); + return; + } + + logger.info("Update resource successfully,updateResourceResp:{}", updateResourceRes); + + + // update + UpdateLayoutResourceRes updateLayoutResourceRes; + + try { + updateLayoutResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .updateLayout(cname, uid, acquireResourceRes.getResourceId(), startResourceRes.getSid(), UpdateLayoutMixRecordingResourceClientReq.builder() + .mixedVideoLayout(1) + .backgroundColor("#FF0000") + .build()).block(); + + } catch (AgoraException e) { + logger.error("Failed to update layout resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (updateLayoutResourceRes == null) { + logger.error("Failed to update layout resource, updateLayoutResourceRes is null"); + return; + } + + logger.info("Update resource successfully,updateLayoutResourceResp:{}", updateLayoutResourceRes); + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryMixHLSAndMP4RecordingResourceRes queryMixHLSAndMP4RecordingResourceRes; + try { + queryMixHLSAndMP4RecordingResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .queryHLSAndMP4(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryMixHLSAndMP4RecordingResourceRes == null) { + logger.error("Failed to query resource, queryMixHLSAndMP4RecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryMixHLSAndMP4RecordingResourceResp:{}", queryMixHLSAndMP4RecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + StopResourceRes stopResourceRes; + try { + stopResourceRes = this.agoraService.cloudRecording() + .mixScenario() + .stop(cname, uid, startResourceRes.getResourceId(), startResourceRes.getSid(), false) + .block(); + } catch (AgoraException e) { + logger.error("Failed to stop resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (stopResourceRes == null) { + logger.error("Failed to stop resource, stopResourceRes is null"); + return; + } + + logger.info("Stop resource successfully,stopResourceResp:{}", stopResourceRes); + } +} diff --git a/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/WebRecordingScenario.java b/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/WebRecordingScenario.java new file mode 100644 index 0000000..c29dc66 --- /dev/null +++ b/examples/cloudrecording/src/main/java/io/agora/rest/examples/cloudrecording/scenario/WebRecordingScenario.java @@ -0,0 +1,396 @@ +package io.agora.rest.examples.cloudrecording.scenario; + +import io.agora.rest.AgoraException; +import io.agora.rest.core.Credential; +import io.agora.rest.core.RegionArea; +import io.agora.rest.services.cloudrecording.api.req.StartResourceReq; +import io.agora.rest.services.cloudrecording.api.req.UpdateResourceReq; +import io.agora.rest.services.cloudrecording.api.res.AcquireResourceRes; +import io.agora.rest.services.cloudrecording.api.res.StartResourceRes; +import io.agora.rest.services.cloudrecording.api.res.StopResourceRes; +import io.agora.rest.services.cloudrecording.api.res.UpdateResourceRes; +import io.agora.rest.services.cloudrecording.scenario.web.req.AcquireWebRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.web.req.StartWebRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.web.req.UpdateWebRecordingResourceClientReq; +import io.agora.rest.services.cloudrecording.scenario.web.res.QueryWebRecordingResourceRes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.Collections; + +public class WebRecordingScenario extends BaseScenario { + private static final Logger logger = LoggerFactory.getLogger(WebRecordingScenario.class); + + public WebRecordingScenario(RegionArea region, String appId, String cname, String uid, Credential credential) { + super(region, appId, cname, uid, credential); + } + + public void runWebRecorder(StartResourceReq.StorageConfig storageConfig) { + // Run web recorder implementation + + // acquire + AcquireResourceRes acquireResourceRes; + try { + acquireResourceRes = this.agoraService.cloudRecording() + .webScenario() + .acquire(cname, uid, AcquireWebRecordingResourceClientReq.builder() + .resourceExpiredHour(1) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to acquire resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + logger.info("Acquire resource successfully,acquireResourceResp:{}", acquireResourceRes); + + if (acquireResourceRes == null) { + logger.error("Failed to acquire resource, acquireResourceRes is null"); + return; + } + + // start + StartResourceRes startResourceRes; + + try { + startResourceRes = this.agoraService.cloudRecording() + .webScenario() + .start(cname, uid, acquireResourceRes.getResourceId(), + StartWebRecordingResourceClientReq.builder() + .recordingFileConfig(StartResourceReq.RecordingFileConfig.builder() + .avFileType(Arrays.asList("hls", "mp4")) + .build()) + .storageConfig(storageConfig) + .extensionServiceConfig(StartResourceReq.ExtensionServiceConfig.builder() + .errorHandlePolicy("error_abort") + .extensionServices(Collections.singletonList(StartResourceReq.ExtensionService.builder() + .serviceName("web_recorder_service") + .errorHandlePolicy("error_abort") + .serviceParam(StartResourceReq.WebRecordingServiceParam.builder() + .url("https://live.bilibili.com/") + .audioProfile(2) + .videoWidth(1280) + .videoHeight(720) + .maxRecordingHour(1) + .build()) + .build())) + .build()) + .build()) + .block(); + + } catch (AgoraException e) { + logger.error("Failed to start resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (startResourceRes == null) { + logger.error("Failed to start resource, startResourceRes is null"); + return; + } + + logger.info("Start resource successfully,startResourceResp:{}", startResourceRes); + + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryWebRecordingResourceRes queryWebRecordingResourceRes; + try { + queryWebRecordingResourceRes = this.agoraService.cloudRecording() + .webScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryWebRecordingResourceRes == null) { + logger.error("Failed to query resource, queryWebRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryWebRecordingResourceResp:{}", queryWebRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // update + UpdateResourceRes updateResourceRes; + + try { + updateResourceRes = this.agoraService.cloudRecording() + .webScenario() + .update(cname, uid, acquireResourceRes.getResourceId(), startResourceRes.getSid(), UpdateWebRecordingResourceClientReq.builder() + .webRecordingConfig(UpdateResourceReq.WebRecordingConfig.builder() + .onHold(false) + .build()) + .build()).block(); + + } catch (AgoraException e) { + logger.error("Failed to update resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (updateResourceRes == null) { + logger.error("Failed to update resource, updateResourceRes is null"); + return; + } + + logger.info("Update resource successfully,updateResourceResp:{}", updateResourceRes); + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryWebRecordingResourceRes queryWebRecordingResourceRes; + try { + queryWebRecordingResourceRes = this.agoraService.cloudRecording() + .webScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryWebRecordingResourceRes == null) { + logger.error("Failed to query resource, queryWebRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryWebRecordingResourceResp:{}", queryWebRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + StopResourceRes stopResourceRes; + try { + stopResourceRes = this.agoraService.cloudRecording() + .webScenario() + .stop(cname, uid, startResourceRes.getResourceId(), startResourceRes.getSid(), false) + .block(); + } catch (AgoraException e) { + logger.error("Failed to stop resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (stopResourceRes == null) { + logger.error("Failed to stop resource, stopResourceRes is null"); + return; + } + + logger.info("Stop resource successfully,stopResourceResp:{}", stopResourceRes); + } + + public void runWebRecorderAndRtmpPublish(StartResourceReq.StorageConfig storageConfig) { + // Run web recorder and RTMP publish implementation + + // acquire + AcquireResourceRes acquireResourceRes; + try { + acquireResourceRes = this.agoraService.cloudRecording() + .webScenario() + .acquire(cname, uid, AcquireWebRecordingResourceClientReq.builder() + .resourceExpiredHour(1) + .build()).block(); + } catch (AgoraException e) { + logger.error("Failed to acquire resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + logger.info("Acquire resource successfully,acquireResourceResp:{}", acquireResourceRes); + + if (acquireResourceRes == null) { + logger.error("Failed to acquire resource, acquireResourceRes is null"); + return; + } + + // start + StartResourceRes startResourceRes; + + try { + startResourceRes = this.agoraService.cloudRecording() + .webScenario() + .start(cname, uid, acquireResourceRes.getResourceId(), + StartWebRecordingResourceClientReq.builder() + .recordingFileConfig(StartResourceReq.RecordingFileConfig.builder() + .avFileType(Arrays.asList("hls", "mp4")) + .build()) + .storageConfig(storageConfig) + .extensionServiceConfig(StartResourceReq.ExtensionServiceConfig.builder() + .errorHandlePolicy("error_abort") + .extensionServices(Arrays.asList(StartResourceReq.ExtensionService.builder() + .serviceName("web_recorder_service") + .errorHandlePolicy("error_abort") + .serviceParam(StartResourceReq.WebRecordingServiceParam.builder() + .url("https://live.bilibili.com/") + .audioProfile(2) + .videoWidth(1280) + .videoHeight(720) + .maxRecordingHour(1) + .build()) + .build(), + StartResourceReq.ExtensionService.builder() + .serviceName("rtmp_publish_service") + .errorHandlePolicy("error_ignore") + .serviceParam(StartResourceReq.RtmpPublishServiceParam.builder() + .outputs(Collections.singletonList(StartResourceReq.Outputs.builder() + .rtmpUrl("rtmp://xxx.xxx.xxx.xxx:1935/live/test") + .build())) + .build()) + .build() + )) + .build()) + .build()) + .block(); + + } catch (AgoraException e) { + logger.error("Failed to start resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (startResourceRes == null) { + logger.error("Failed to start resource, startResourceRes is null"); + return; + } + + logger.info("Start resource successfully,startResourceResp:{}", startResourceRes); + + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryWebRecordingResourceRes queryWebRecordingResourceRes; + try { + queryWebRecordingResourceRes = this.agoraService.cloudRecording() + .webScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryWebRecordingResourceRes == null) { + logger.error("Failed to query resource, queryWebRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryWebRecordingResourceResp:{}", queryWebRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // update + UpdateResourceRes updateResourceRes; + + try { + updateResourceRes = this.agoraService.cloudRecording() + .webScenario() + .update(cname, uid, acquireResourceRes.getResourceId(), startResourceRes.getSid(), UpdateWebRecordingResourceClientReq.builder() + .webRecordingConfig(UpdateResourceReq.WebRecordingConfig.builder() + .onHold(false) + .build()) + .rtmpPublishConfig(UpdateResourceReq.RtmpPublishConfig.builder() + .outputs(Collections.singletonList(UpdateResourceReq.UpdateOutput.builder() + .rtmpURL("rtmp://yyy.yyy.yyy.yyy:1935/live/test") + .build()) + ).build()) + .build()) + .block(); + + } catch (AgoraException e) { + logger.error("Failed to update resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (updateResourceRes == null) { + logger.error("Failed to update resource, updateResourceRes is null"); + return; + } + + logger.info("Update resource successfully,updateResourceResp:{}", updateResourceRes); + + // query resource detail + for (int i = 0; i < 3; i++) { + QueryWebRecordingResourceRes queryWebRecordingResourceRes; + try { + queryWebRecordingResourceRes = this.agoraService.cloudRecording() + .webScenario() + .query(acquireResourceRes.getResourceId(), startResourceRes.getSid()) + .block(); + } catch (AgoraException e) { + logger.error("Failed to query resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + if (queryWebRecordingResourceRes == null) { + logger.error("Failed to query resource, queryWebRecordingResourceRes is null"); + return; + } + + logger.info("Query resource successfully,queryWebRecordingResourceResp:{}", queryWebRecordingResourceRes); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + StopResourceRes stopResourceRes; + try { + stopResourceRes = this.agoraService.cloudRecording() + .webScenario() + .stop(cname, uid, startResourceRes.getResourceId(), startResourceRes.getSid(), false) + .block(); + } catch (AgoraException e) { + logger.error("Failed to stop resource,err:{}", e.getMessage()); + return; + } catch (Exception e) { + logger.error("Unknown exception,err:{}", e.getMessage()); + return; + } + + if (stopResourceRes == null) { + logger.error("Failed to stop resource, stopResourceRes is null"); + return; + } + + logger.info("Stop resource successfully,stopResourceResp:{}", stopResourceRes); + } +} diff --git a/examples/cloudrecording/src/main/resources/logback.xml b/examples/cloudrecording/src/main/resources/logback.xml new file mode 100644 index 0000000..e23488b --- /dev/null +++ b/examples/cloudrecording/src/main/resources/logback.xml @@ -0,0 +1,12 @@ + + + + + %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n + + + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..925438e --- /dev/null +++ b/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + + io.agora + agora-rest-client-parent + 1.0 + pom + + agora-rest-client-core + examples/cloudrecording + + + + 8 + 8 + UTF-8 + + +