使用 Java SDK 开始云端录制
本文向新手介绍如何使用声网 Java SDK 开始第一次云端录制。
Java SDK 旨在帮助开发者更轻松集成声网 RESTful API。该 SDK 具有如下特性:
- 简化通信流畅:通过封装 RESTful API 的请求和响应处理,让你与 RESTful API 的通信更加简单。
- 保障可用性:遇到 DNS 解析失败、网络错误、请求超时等网络问题时,会自动切换到最佳域名,确保 REST 服务的可用性。
- API 易用性:提供简洁易懂的 API,让你能轻松实现开启云端录制、停止云端录制等常用功能。
- 其他优势:基于 Java 语言编写,具有高效性、并发性、可扩展性。
前提条件
开始前请确保你的本地开发环境满足如下条件:
-
Java 1.8 或以上版本。
-
参考开通服务在声网控制台开通云端录制,并复制保存 App ID、临时 Token、客户 ID 和客户密钥。
注意临时 Token 的有效期是 24 小时。Token 过期会导致加入频道失败。
-
云端录制文件需要上传到第三方云存储。开始录制前,请开通第三方云存储服务,并获取 Bucket、Access Key、Secret Key 以备用。
-
在项目中实现了基础的音视频互动场景。你也可以参考文档使用声网实时互动 Web Demo 在浏览器中模拟一个音视频互动场景。
创建项目并安装 SDK
-
在你的 IDE 中创建一个 Java 项目。以 IntelliJ IDEA 为例,设置你的项目名称、保存路径,并将 Build system 设为 Maven。完成创建后,点击 Create。
-
在项目的
pom.xml
文件中的<dependencies>
区域添加如下行,将 REST Client 的依赖添加到项目中:XML<dependencies>
<dependency>
<groupId>io.agora</groupId>
<artifactId>agora-rest-client-core</artifactId>
<version>0.2.0</version>
</dependency>
</dependencies>
进行云端录制
本节介绍进行云端录制的极简流程。为方便说明,本节以录制之前模拟的音视频直播为例,并假设录制主播的音频和视频录制到 MP4 文件中。
定义变量
在 Main.java
文件中,添加如下代码,定义或配置关键参数,取值参考前提条件。
public class Main {
// 定义关键参数
private static String appId = "<your_app_id>";
private static String cname = "show";
private static String uid = "123";
private static String username = "<your_customer_id>";
private static String password = "<your_customer_secret>";
private static String token = "<your_token>";
// 配置云存储
private static String accessKey = "<your_storage_access_key>";
private static String secretKey = "<your_storage_secret_key>";
private static Integer region = 1;
private static String bucket = "<your_storage_bucket_name>";
private static Integer vendor = 2;
}
其中,
cname
值设为show
,表示加入录制实时音视频互动所在的频道。vendor
值设为2
代表使用阿里云;region
值设为1
表示CN_Shanghai
。如果你使用其他云存储厂商,参考第三方云存储地区说明赋值。
创建并初始化 Client
在 main
方法中,添加如下代码,创建并初始化 Client。
Credential credential = new BasicAuthCredential(username, password);
// Initialize AgoraConfig
AgoraConfig agoraConfig = AgoraConfig.builder()
.appId(appId)
.credential(credential)
// Specify the region where the server is located.
// Optional values are CN, US, EU, AP, and the client will automatically
// switch to use the best domain name according to the configured region
.domainArea(DomainArea.CN)
.build();
// Initialize CloudRecordingClient
CloudRecordingClient cloudRecordingClient = CloudRecordingClient.create(agoraConfig);
申请录制服务器资源
调用 acquire
申请录制服务器资源。
AcquireResourceRes acquireResourceRes;
// Acquire resource
try {
acquireResourceRes = cloudRecordingClient
.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");
开始录制
获取资源后,调用 start
开始录制。
// 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)
.build())
.recordingFileConfig(StartResourceReq.RecordingFileConfig.builder()
.avFileType(Arrays.asList("hls", "mp4"))
.build())
.storageConfig(storageConfig)
.build();
StartResourceRes startResourceRes;
// Start resource
try {
startResourceRes = cloudRecordingClient
.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);
停止录制
完成录制后,调用 stop
结束录制。
StopResourceRes stopResourceRes;
// Stop resource
try {
stopResourceRes = cloudRecordingClient
.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");
}
完整示例代码
Main.java
文件中完整代码如下,你可自行比对:
public class Main {
private static String appId = "<your appId>";
private static String cname = "<your cname>";
private static String uid = "<your uid>";
private static String username = "<the username of basic auth credential>";
private static String password = "<the password of basic auth credential>";
private static String token = "<your token>";
private static String accessKey = "<your accessKey>";
private static String secretKey = "<your secretKey>";
private static Integer region = 1; // <your region>
private static String bucket = "<your bucket>";
private static Integer vendor = 2; // <your vendor>
public static void main(String[] args) throws Exception {
Credential credential = new BasicAuthCredential(username, password);
// Initialize AgoraConfig
AgoraConfig agoraConfig = AgoraConfig.builder()
.appId(appId)
.credential(credential)
// Specify the region where the server is located.
// Optional values are CN, US, EU, AP, and the client will automatically
// switch to use the best domain name according to the configured region
.domainArea(DomainArea.CN)
.build();
// Initialize CloudRecordingClient
CloudRecordingClient cloudRecordingClient = CloudRecordingClient.create(agoraConfig);
AcquireResourceRes acquireResourceRes;
// Acquire resource
try {
acquireResourceRes = cloudRecordingClient
.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)
.build())
.recordingFileConfig(StartResourceReq.RecordingFileConfig.builder()
.avFileType(Arrays.asList("hls", "mp4"))
.build())
.storageConfig(storageConfig)
.build();
StartResourceRes startResourceRes;
// Start resource
try {
startResourceRes = cloudRecordingClient
.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 queryResourceRes;
// Query resource
try {
queryResourceRes = cloudRecordingClient
.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 || queryResourceRes.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 = cloudRecordingClient
.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");
}
}
}
查看录制文件
参考第三方云存储官方文档操作,查看云存储中的文件。根据 start
方法中 storageconfig.fileNamePrefix
参数的设置,录制生成文件位于 quickstart
目录下。如下截图以阿里云为例:
录制过程中生成了 .m3u8
、.ts
和 mp4
文件。最终 quickstart
文件夹内包含如下:
.
├── <sid>_testchannel.m3u8
├── <sid>_testchannel_0.mp4
└── <sid>_testchannel_20241119070642248.ts
根据你在 start
方法中设置的录制时间,云存储中可能会有多个 .ts 文件。录制文件介绍请参考录制文件命名和切片规则。
进阶设置
本文提供的示例代码仅为快速上手时使用。在实际业务中,你需要根据实际业务场景修改请求参数。如下示例代码展示了录制直播频道中所有的音视频流,且输出的视频流需要转码的参数配置:
// 配置录制选项
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();
云端录制支持设置的所有参数请参考 API 文档。
参考信息
示例项目
完成快速开始后,你可以体验更多云端录制示例: