# Agora-Recording-Java-SDK
**Repository Path**: pandason125/Agora-Recording-Java-SDK
## Basic Information
- **Project Name**: Agora-Recording-Java-SDK
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2025-07-16
- **Last Updated**: 2025-07-16
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Agora Recording Java SDK
中文 | [English](./README.md)
## 目录
1. [简介](#简介)
2. [开发环境要求](#开发环境要求)
- [硬件环境](#硬件环境)
- [网络要求](#网络要求)
- [带宽需求](#带宽需求)
- [软件环境](#软件环境)
3. [SDK 下载](#SDK下载)
4. [集成 SDK](#集成SDK)
- [1. Maven 集成](#1-maven-集成)
- [2. 本地 SDK 集成](#2-本地-sdk-集成)
- [3. 加载原生库 (.so 文件)](#3-加载原生库-so-文件)
- [3.1 提取 so 库文件](#31-提取-so-库文件)
- [3.2 配置加载路径](#32-配置加载路径)
5. [快速开始](#快速开始)
- [开通服务](#开通服务)
- [使用命令行录制](#使用命令行录制)
- [前提条件](#前提条件)
- [编译](#编译)
- [设置录制选项](#设置录制选项)
- [开始录制](#开始录制)
- [结束录制](#结束录制)
- [调用 API 录制](#调用-api-录制)
- [前提条件](#前提条件-1)
- [调用 API 实现录制](#调用-api-实现录制)
- [初始化服务](#初始化服务)
- [加入频道](#加入频道)
- [开始录制](#开始录制-1)
- [结束录制](#结束录制)
- [跑通 Maven 工程](#跑通-maven-工程)
6. [API 参考](#api-参考)
7. [更新日志](#更新日志)
8. [其他参考](#其他参考)
## 简介
Agora Recording Java SDK (v4.4.150.5) 为您提供了强大的实时音视频录制能力,可无缝集成到 Linux 服务器端的 Java 应用程序中。借助此 SDK,您的服务器可以作为一个哑客户端加入 Agora 频道,实时拉取、订阅和录制频道内的音视频流。录制文件可用于内容存档、审核、分析或其他业务相关的高级功能。
## 开发环境要求
### 硬件环境
- **操作系统**:Ubuntu 14.04+ 或 CentOS 6.5+(推荐 7.0)
- **CPU 架构**:x86-64,arm64
### 网络要求
- **公网 IP**
- **域名访问**:允许访问 `.agora.io` 和 `.agoralab.co`
### 带宽需求
根据需要同时录制的频道数量和频道内情况确定所需带宽。以下数据可供参考:
- 录制一个分辨率为 640 × 480 的画面需要的带宽约为 500 Kbps
- 录制一个有两个人的频道则需 1 Mbps
- 同时录制 100 个这样的频道,需要带宽为 100 Mbps
### 软件环境
- **构建工具**:Apache Maven 或其他构建工具
- **JDK**:JDK 8+
## SDK 下载
### Maven 下载
#### x86_64 平台
```xml
io.agora.rtc
linux-recording-java-sdk
4.4.150.5
```
#### arm64 平台
```xml
io.agora.rtc
linux-recording-java-sdk
4.4.150.5-aarch64
```
### CDN 下载
#### x86_64 平台
[Agora-Linux-Recording-Java-SDK-v4.4.150.5-x86_64-762876-ee62852ef2-20250630_105128](https://download.agora.io/sdk/release/Agora-Linux-Recording-Java-SDK-v4.4.150.5-x86_64-762876-ee62852ef2-20250630_105128.zip)
#### arm64 平台
[Agora-Linux-Recording-Java-SDK-v4.4.150.5-aarch64-762913-03b1b3da07-20250630_115505](https://download.agora.io/sdk/release/Agora-Linux-Recording-Java-SDK-v4.4.150.5-aarch64-762913-03b1b3da07-20250630_115505.zip)
## 集成 SDK
SDK 集成有两种方式:通过 Maven 集成和本地 SDK 集成。
### 1. Maven 集成
Maven 集成是最简单的方式,可以自动管理 Java 依赖关系。
#### 1.1 添加 Maven 依赖
在项目的 `pom.xml` 文件中添加以下依赖:
```xml
io.agora.rtc
linux-recording-java-sdk
4.4.150.5
io.agora.rtc
linux-recording-java-sdk
4.4.150-aarch64
```
#### 1.2 集成 so 库文件
Maven 依赖包含了所需的 JAR 文件,但仍需手动处理 `.so` 库文件才能运行。请参考下面的 **加载原生库 (.so 文件)** 部分。
### 2. 本地 SDK 集成
本地 SDK 是一个包含所有必要文件的完整包,适合需要更灵活控制的场景。
#### 2.1 SDK 包结构
从官网下载的 SDK 包(zip 格式)包含以下内容:
- **doc/** - JavaDoc 文档,详细的 API 说明
- **examples/** - 示例代码和项目
- **sdk/** - 核心 SDK 文件
- `agora-recording-sdk.jar` - Java 类库
- `agora-recording-sdk-javadoc.jar` - JavaDoc 文档
#### 2.2 集成 JAR 文件
你可以通过两种方式集成 JAR 文件:
###### 本地 Maven 仓库方法
方法一:只安装 SDK JAR
```sh
mvn install:install-file \
-Dfile=sdk/agora-recording-sdk.jar \
-DgroupId=io.agora.rtc \
-DartifactId=linux-recording-java-sdk \
-Dversion=4.4.150.5 \
-Dpackaging=jar \
-DgeneratePom=true
```
方法二:同时安装 SDK JAR 和 JavaDoc JAR
```sh
mvn install:install-file \
-Dfile=sdk/agora-recording-sdk.jar \
-DgroupId=io.agora.rtc \
-DartifactId=linux-recording-java-sdk \
-Dversion=4.4.150.5 \
-Dpackaging=jar \
-DgeneratePom=true \
-Djavadoc=sdk/agora-recording-sdk-javadoc.jar
```
安装后,在 `pom.xml` 中添加依赖:
```xml
io.agora.rtc
linux-recording-java-sdk
4.4.150.5
```
###### 直接引用方法
1. 将 JAR 文件复制到项目的 `libs` 目录:
```sh
mkdir -p libs
cp sdk/agora-recording-sdk.jar libs/
cp sdk/agora-recording-sdk-javadoc.jar libs/ # 可选,用于 IDE 支持
```
2. 在 Java 项目中添加 classpath 引用:
```sh
# 使用 SDK JAR
java -cp .:libs/agora-recording-sdk.jar 你的主类
# 在 IDE 中配置 JavaDoc(常见的 IDE 如 IntelliJ IDEA 或 Eclipse 支持直接关联 JavaDoc JAR)
```
#### 2.3 集成 so 库文件
下载的 SDK 包中已经包含了 `.so` 文件。你需要确保 Java 程序运行时能够找到这些文件。请参考下面的 **加载原生库 (.so 文件)** 部分。
### 加载原生库 (.so 文件)
Agora Linux Recording Java SDK 依赖于底层的 C++ 原生库(`.so` 文件)。无论是通过 Maven 集成还是本地集成,都需要确保 Java 虚拟机 (JVM) 在运行时能够找到并加载这些库。
#### 3.1 提取 so 库文件
`.so` 文件包含在 `agora-recording-sdk.jar` 或 `linux-recording-java-sdk-x.x.x.x.jar` 文件内部。你需要先将它们提取出来:
1. 在你的项目或部署目录下创建一个用于存放库文件的目录,例如 `libs`:
```sh
mkdir -p libs
cd libs
```
2. 使用 `jar` 命令从 SDK 的 JAR 文件中提取内容(假设 JAR 文件位于 `libs` 目录下或 Maven 缓存中):
```sh
# 如果使用本地集成方式,JAR 文件通常在 libs 目录下
jar xvf agora-recording-sdk.jar
# 如果使用 Maven 集成方式,JAR 文件在 Maven 缓存中,例如:
# jar xvf ~/.m2/repository/io/agora/rtc/linux-recording-java-sdk/4.4.150.5/linux-recording-java-sdk-4.4.150.5.jar
```
3. 提取后,`libs` 目录下会生成 `native/linux/x86_64` 子目录,其中包含所需的 `.so` 文件:
```
libs/
├── agora-recording-sdk.jar (或者空的,如果仅用于提取)
├── io/ # Java 的 class 类所在,无需关注
├── META-INF/ # JAR 文件和应用程序相关的元数据,无需关注
└── native/ # 对应平台的 so 库文件
└── linux/
└── x86_64/ # x86_64 平台 so 库
├── libagora_rtc_sdk.so
├── libagora-fdkaac.so
├── libaosl.so
└── librecording.so
└── aarch64/ # arm64 平台 so 库 (如果存在)
├── libagora_rtc_sdk.so
├── libagora-fdkaac.so
├── libaosl.so
└── librecording.so
```
#### 3.2 配置加载路径
有两种主要方法让 JVM 找到 `.so` 文件:
**方法一:通过设置环境变量 `LD_LIBRARY_PATH` (推荐)**
这是最可靠的方式,特别是在 `.so` 文件之间存在依赖关系时。
```sh
# 确定你的 .so 文件所在的目录,假设在 ./libs/native/linux/x86_64
LIB_DIR=$(pwd)/libs/native/linux/x86_64
# 设置 LD_LIBRARY_PATH 环境变量,将库目录添加到现有路径的前面
export LD_LIBRARY_PATH=$LIB_DIR:$LD_LIBRARY_PATH
# 运行你的 Java 应用
java -jar 你的应用.jar
# 或者使用 classpath
# java -cp "你的classpath" 你的主类
```
**方法二:通过 JVM 参数 `-Djava.library.path`**
这种方法直接告诉 JVM 在哪里查找库文件。
```sh
# 确定你的 .so 文件所在的目录,假设在 ./libs/native/linux/x86_64
LIB_DIR=$(pwd)/libs/native/linux/x86_64
# 运行 Java 应用,并通过 -D 参数指定库路径
java -Djava.library.path=$LIB_DIR -jar 你的应用.jar
# 或者使用 classpath
# java -Djava.library.path=$LIB_DIR -cp "你的classpath" 你的主类
```
> **注意**:
>
> - 推荐使用方法一 (`LD_LIBRARY_PATH`),因为它能更好地处理库之间的依赖。如果仅使用 `-Djava.library.path`,有时可能因为库找不到其依赖的其他库而加载失败。
> - 确保 `$LIB_DIR` 指向包含 `libagora_rtc_sdk.so` 等文件的 **确切目录**。
> - 你可以将设置环境变量的命令放入启动脚本中,以便每次运行应用时自动配置。
参考以下脚本示例,它结合了两种方法,并设置了 classpath:
```sh
#!/bin/bash
# 获取当前脚本所在目录的绝对路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# 确定 so 库文件路径 (假设在脚本目录下的 libs/native/linux/x86_64)
LIB_PATH="$SCRIPT_DIR/libs/native/linux/x86_64"
# SDK JAR 路径 (假设在脚本目录下的 libs)
SDK_JAR="$SCRIPT_DIR/libs/agora-recording-sdk.jar"
# 你的应用主类
MAIN_CLASS="你的主类"
# 你的应用的其他依赖 classpath (如果有)
APP_CP="你的其他classpath"
# 设置库路径环境变量
export LD_LIBRARY_PATH=$LIB_PATH:$LD_LIBRARY_PATH
# 组合 classpath
CLASSPATH=".:$SDK_JAR:$APP_CP" # '.' 表示当前目录
# 执行 Java 程序
# 同时使用 LD_LIBRARY_PATH 和 -Djava.library.path 以确保兼容性
java -Djava.library.path=$LIB_PATH -cp "$CLASSPATH" $MAIN_CLASS
```
## 快速开始
### 开通服务
参考 [官网开通服务](https://doc.shengwang.cn/doc/recording/java/get-started/enable-service)
### 使用命令行录制
#### 前提条件
开始前请确保你已经完成录制 SDK 的环境准备和集成工作。
> **注意**:当录制 SDK 加入频道时,相当于一个哑客户端加入频道,因此需要跟声网 RTC SDK 加入相同的频道,并使用相同的 App ID 和频道场景。
#### 编译示例项目
在 `Examples-Cmd` 目录下执行编译脚本:
```sh
./build.sh
```
#### 配置录制参数
录制参数使用 JSON 格式配置,位于 `Examples-Cmd/config` 目录下。
1. 查看配置示例:
```sh
cat config/recorder_json.example
```
2. 创建或修改你自己的配置文件,例如 `config/my_recorder.json`,确保 JSON 格式正确。
3. 完整参数说明:
| 参数名 | 类型 | 说明 |
| ------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| appId | String | 项目的 App ID,需要和 RTC SDK 中的 App ID 一致 |
| token | String | 频道的 Token,如果频道设置了安全模式,需要传入 Token |
| channelName | String | 频道名称,需要和 RTC SDK 中的频道名称一致 |
| useStringUid | Boolean | 是否使用字符串类型的用户 ID |
| useCloudProxy | Boolean | 是否使用云代理服务 |
| userId | String | 用户 ID |
| subAllAudio | Boolean | 是否订阅所有音频。如果为 false,需要在 subAudioUserList 中填入订阅的用户 ID |
| subAudioUserList | String[] | 订阅音频的用户 ID 列表,仅在 subAllAudio 为 false 时生效 |
| subAllVideo | Boolean | 是否订阅所有视频。如果为 false,需要在 subVideoUserList 中填入订阅的用户 ID |
| subVideoUserList | String[] | 订阅视频的用户 ID 列表,仅在 subAllVideo 为 false 时生效 |
| subStreamType | String | 订阅的流类型,支持 `high`(大流)和 `low`(小流) |
| isMix | Boolean | 是否合流录制 |
| backgroundColor | Long | 合流录制的背景颜色。使用 RGB 颜色格式(0xRRGGBB),需要转为 long 类型的值。例如:红色为 0xFF0000,绿色为 0x00FF00,蓝色为 0x0000FF |
| backgroundImage | String | 合流录制的背景图片路径,支持 PNG 和 JPG 格式。当同时设置了背景颜色和背景图片时,背景图片优先生效 |
| layoutMode | String | 合流录制布局模式,支持 `default`(默认布局),`bestfit`(自适应布局),`vertical`(垂直布局) |
| maxResolutionUid | String | 在 vertical 布局中,设定显示最大分辨率的用户 ID |
| recorderStreamType | String | 录制类型,支持 `audio_only`(只录音频),`video_only`(只录视频),`both`(音视频都录) |
| recorderPath | String | 录制文件路径。合流录制时为录制的文件名;单流录制时为录制的目录,以每一个用户 ID 为名的 mp4 文件 |
| maxDuration | Integer | 录制时长,单位秒 |
| recoverFile | Boolean | 是否在录制时同时写 h264 和 aac 文件,程序 crash 后可以恢复出 mp4 |
| audio | Object | 音频设置 |
| audio.sampleRate | Integer | 音频采样率 |
| audio.numOfChannels | Integer | 音频通道数量 |
| video | Object | 视频设置 |
| video.width | Integer | 视频宽度 |
| video.height | Integer | 视频高度 |
| video.fps | Integer | 视频帧率 |
| waterMark | Object[] | 水印设置 |
| waterMark[].type | String | 水印类型,支持 `litera`(字幕水印),`time`(时间戳水印),`picture`(图片水印) |
| waterMark[].litera | String | 字幕内容,仅在 type 为 `litera` 时生效 |
| waterMark[].fontFilePath | String | 字体文件路径 |
| waterMark[].fontSize | Integer | 字体大小 |
| waterMark[].x | Integer | 水印的 X 坐标 |
| waterMark[].y | Integer | 水印的 Y 坐标 |
| waterMark[].width | Integer | 水印的宽度 |
| waterMark[].height | Integer | 水印的高度 |
| waterMark[].zorder | Integer | 水印的层级 |
| waterMark[].imgUrl | String | 图片水印的 URL,仅在 type 为 `picture` 时生效 |
| encryption | Object | 媒体流加密设置 |
| encryption.mode | String | 加密类型,支持 `AES_128_XTS`,`AES_128_ECB`,`AES_256_XTS`,`SM4_128_ECB`,`AES_128_GCM`,`AES_256_GCM`,`AES_128_GCM2`,`AES_256_GCM2` |
| encryption.key | String | 加密密钥 |
| encryption.salt | String | 加密盐,值为 32 位字符,例如串 "ABC123" |
| rotation | Object[] | 画面旋转设置 |
| rotation[].uid | String | 需要旋转画面的用户 ID |
| rotation[].degree | Integer | 旋转的角度,支持 0,90,180,270 |
> **必读注意事项**:
>
> - 执行录制前务必正确填写 JSON 中的 `appId` 和 `token` 参数
> - `appId` 和 `channelName` 的设置必须与声网 RTC SDK 中设置的完全一致
> - 单流录制模式下,`recorderPath` 指定的是文件夹路径,必须手动确保该目录存在,例如设置 `"recorderPath": "recorder_result/"`,则需确保 `Examples-Cmd/recorder_result/` 目录已创建
> - 确保 JSON 格式正确,不要漏掉逗号或引号等符号
#### 执行录制
1. 为单流录制创建输出目录:
```sh
mkdir -p Examples-Cmd/recorder_result
```
2. 选择并运行对应的测试脚本:
```sh
cd Examples-Cmd
./script/TestCaseName.sh
```
可以根据需要修改脚本或对应的 JSON 配置文件,定制录制行为。
#### 常用测试脚本
`Examples-Cmd/script` 目录下提供了多种预设的测试脚本:
| 脚本名称 | 功能描述 |
| ------------------------------------------------ | ------------------------------------------ |
| MixStreamRecordingAudioVideo.sh | 混流录制音视频 |
| MixStreamRecordingAudio.sh | 混流仅录制音频 |
| MixStreamRecordingVideo.sh | 混流仅录制视频 |
| MixStreamRecordingAudioVideoWatermarks.sh | 混流录制音视频并添加水印 |
| MixStreamRecordingAudioVideoWatermarksBg.sh | 混流录制音视频,添加水印和背景 |
| MixStreamRecordingAudioVideoWatermarksRecover.sh | 混流录制音视频,添加水印并启用录制恢复功能 |
| MixStreamRecordingAudioVideoEncryption.sh | 混流录制音视频并启用加密 |
| MixStreamRecordingAudioVideoStringUid.sh | 使用字符串用户 ID 的混流录制音视频 |
| SingleStreamRecordingAudioVideo.sh | 单流录制音视频 |
| SingleStreamRecordingAudio.sh | 单流仅录制音频 |
| SingleStreamRecordingVideo.sh | 单流仅录制视频 |
| SingleStreamRecordingAudioVideoWatermarks.sh | 单流录制音视频并添加水印 |
选择合适的脚本,或基于现有脚本创建自定义的录制配置。每个脚本都对应 `config` 目录下的同名配置文件。
#### 控制录制过程
- **开始录制**:脚本执行后自动开始录制
- **结束录制**:在命令行中输入 `1` 并按回车,程序将停止录制并退出
#### 录制输出文件
- **单流录制**:在 `Examples-Cmd/recorder_result/` 目录下生成多个 MP4 文件,以各用户的 UID 命名
- **混合录制**:在 `Examples-Cmd` 目录下生成单个 MP4 文件,文件名按 JSON 配置指定
#### 常见问题排查
- 如果录制没有输出文件,检查 AppID、Token 和频道名是否正确
- 确保频道中有活跃用户在发送媒体流
- 检查日志文件了解详细错误信息,日志通常位于 `Examples-Cmd/logs/` 目录
> **提示**:更多高级配置选项和详细参数说明,请参考 `Examples-Cmd/config/recorder_json.example` 文件中的注释。
### 调用 API 录制
#### 前提条件
开始前请确保你已经完成录制 SDK 的环境准备和集成工作,包括配置 jar 和对应平台的 so。
#### 调用 API 实现录制
以下示例代码基于 `Examples-Cmd` 目录中的实际示例项目,展示了如何使用录制 SDK API 进行录制。
##### 初始化服务
```java
// 创建 AgoraService 实例
AgoraService agoraService = new AgoraService();
// 配置本地代理,配置必须放在 initialize 之前
LocalAccessPointConfiguration localAccessPointConfig = new LocalAccessPointConfiguration();
localAccessPointConfig.setMode(Constants.LocalProxyMode.LocalOnly);
localAccessPointConfig.setDomainList(new String[] { "" });
localAccessPointConfig.setIpList(new String[] { "10.xx.xx.xx" });
localAccessPointConfig.setDomainListSize(1);
localAccessPointConfig.setIpListSize(1);
localAccessPointConfig.setVerifyDomainName("ap.xxx.agora.local");
int setGlobalLocalAccessPointRet = agoraService.setGlobalLocalAccessPoint(localAccessPointConfig);
// 创建并配置服务配置对象
AgoraServiceConfiguration config = new AgoraServiceConfiguration();
config.setEnableAudioDevice(false); // 是否启用音频设备(通常设为 false)
config.setEnableAudioProcessor(true); // 启用音频处理
config.setEnableVideo(true); // 启用视频功能
config.setAppId("您的APPID"); // 设置您的 App ID
config.setUseStringUid(false); // 是否使用字符串 UID
agoraService.initialize(config); // 初始化服务
// 可选:设置云代理
AgoraParameter parameter = agoraService.getAgoraParameter();
if (parameter != null) {
parameter.setBool("rtc.enable_proxy", true);
}
```
##### 加入频道
```java
// 创建媒体组件工厂
AgoraMediaComponentFactory factory = agoraService.createAgoraMediaComponentFactory();
// 创建并初始化录制器
AgoraMediaRtcRecorder agoraMediaRtcRecorder = factory.createMediaRtcRecorder();
// 第二个参数表示是否启用混流录制:true=混流,false=单流
agoraMediaRtcRecorder.initialize(agoraService, false);
// 创建并注册事件处理器
IAgoraMediaRtcRecorderEventHandler handler = new AgoraMediaRtcRecorderEventHandler();
agoraMediaRtcRecorder.registerRecorderEventHandler(handler);
// 加入频道
agoraMediaRtcRecorder.joinChannel(
"您的Token", // 频道 Token,如不启用 Token 验证可为 null
"您的频道名", // 频道名称
"0" // 用户 ID,如果设置为 0 将由系统自动分配
);
```
##### 配置和开始录制
```java
// 订阅音频流
if (需要订阅所有音频) {
agoraMediaRtcRecorder.subscribeAllAudio();
} else {
// 仅订阅特定用户的音频
agoraMediaRtcRecorder.subscribeAudio("用户ID");
}
// 订阅视频流
VideoSubscriptionOptions options = new VideoSubscriptionOptions();
options.setEncodedFrameOnly(false);
options.setType(VideoStreamType.VIDEO_STREAM_HIGH); // 可选:VIDEO_STREAM_LOW
if (需要订阅所有视频) {
agoraMediaRtcRecorder.subscribeAllVideo(options);
} else {
// 仅订阅特定用户的视频
agoraMediaRtcRecorder.subscribeVideo("用户ID", options);
}
// 配置混流布局(仅在混流模式下需要)
if (启用混流) {
VideoMixingLayout layout = new VideoMixingLayout();
// 配置布局参数...
agoraMediaRtcRecorder.setVideoMixingLayout(layout);
}
// 配置录制参数
MediaRecorderConfiguration mediaRecorderConfiguration = new MediaRecorderConfiguration();
mediaRecorderConfiguration.setWidth(640); // 设置录制视频宽度
mediaRecorderConfiguration.setHeight(480); // 设置录制视频高度
mediaRecorderConfiguration.setFps(15); // 设置录制帧率
mediaRecorderConfiguration.setMaxDurationMs(60 * 60 * 1000); // 最大录制时长,单位毫秒
mediaRecorderConfiguration.setStoragePath("/path/to/save/recording.mp4"); // 录制文件保存路径
// 合流录制配置
agoraMediaRtcRecorder.setRecorderConfig(mediaRecorderConfiguration);
// 或者单流录制配置
//agoraMediaRtcRecorder.setRecorderConfigByUid(mediaRecorderConfiguration, "用户ID");
// 添加水印(可选)
WatermarkConfig[] watermarks = new WatermarkConfig[1];
watermarks[0] = new WatermarkConfig();
// 配置水印参数...
agoraMediaRtcRecorder.enableAndUpdateVideoWatermarks(watermarks);
// 启用加密(可选)
if (需要加密) {
EncryptionConfig encryptionConfig = new EncryptionConfig();
encryptionConfig.setEncryptionMode(EncryptionMode.AES_128_GCM); // 设置加密模式
encryptionConfig.setEncryptionKey("加密密钥");
agoraMediaRtcRecorder.enableEncryption(true, encryptionConfig);
}
// 开始录制
if (启用混流) {
agoraMediaRtcRecorder.startRecording();
} else {
// 单流录制
agoraMediaRtcRecorder.startSingleRecordingByUid("用户ID");
}
```
##### 录制事件处理
```java
public static class AgoraMediaRtcRecorderEventHandler implements IAgoraMediaRtcRecorderEventHandler {
@Override
public void onFirstRemoteAudioDecoded(String channelId, String userId, int elapsed) {
// 首次检测到远程音频解码时触发,可在此开始单流音频录制
new Thread() {
@Override
public void run() {
MediaRecorderConfiguration mediaRecorderConfiguration = new MediaRecorderConfiguration();
// 配置录制参数...
agoraMediaRtcRecorder.setRecorderConfigByUid(mediaRecorderConfiguration, userId);
agoraMediaRtcRecorder.startSingleRecordingByUid(userId);
}
}.start();
}
@Override
public void onFirstRemoteVideoDecoded(String channelId, String userId, int width, int height, int elapsed) {
// 首次检测到远程视频解码时触发,可在此更新混流布局或开始单流视频录制
new Thread() {
@Override
public void run() {
if (启用混流) {
VideoMixingLayout layout = new VideoMixingLayout();
// 配置混流布局...
agoraMediaRtcRecorder.setVideoMixingLayout(layout);
} else {
MediaRecorderConfiguration mediaRecorderConfiguration = new MediaRecorderConfiguration();
// 配置录制参数...
agoraMediaRtcRecorder.setRecorderConfigByUid(mediaRecorderConfiguration, userId);
agoraMediaRtcRecorder.startSingleRecordingByUid(userId);
}
}
}.start();
}
@Override
public void onRecorderStateChanged(String channelId, String userId, Constants.RecorderState state,
Constants.RecorderReasonCode reason, String fileName) {
// 录制状态变化回调,可据此了解录制进程
}
// 其他事件处理方法...
}
```
##### 结束录制
```java
// 取消订阅流
agoraMediaRtcRecorder.unsubscribeAllAudio();
agoraMediaRtcRecorder.unsubscribeAllVideo();
// 停止录制
if (启用混流) {
agoraMediaRtcRecorder.stopRecording();
} else {
// 停止单流录制
agoraMediaRtcRecorder.stopSingleRecordingByUid("用户ID");
}
// 注销事件处理器
agoraMediaRtcRecorder.unregisterRecorderEventHandler(handler);
// 离开频道并释放资源
agoraMediaRtcRecorder.leaveChannel();
agoraMediaRtcRecorder.release();
// 释放服务
agoraService.release();
```
##### 获取录制文件
录制文件将根据录制类型保存在不同位置:
- **单流录制**:在 `Examples-Cmd` 目录下指定文件夹下生成单流录制的 mp4 文件,文件名是 UID 开头的,如 `uid_123456_timestamp.mp4`。
- **合流录制**:在 `Examples-Cmd` 目录下生成合流的录制 mp4 文件,文件名是通过 `MediaRecorderConfiguration` 对象的 `storagePath` 参数配置的。
在实际应用中,建议为每次录制设置唯一的文件路径,可以使用频道名、时间戳等作为文件名的一部分,以避免文件覆盖。
更多录制选项和高级功能,请参考 `MediaRecorderConfiguration` 类的 API 文档。
### 跑通 Maven 工程
本 SDK 提供了基于 Spring Boot 的 Maven 示例工程,方便你快速验证和二次开发。以下为跑通 `Examples-Mvn` 工程的基本流程:
#### 1. 编译打包
进入 `Examples-Mvn` 目录,执行:
```sh
mvn clean package
```
编译成功后,会在 `target/` 目录下生成 `agora-example.jar`。
#### 2. 配置密钥
在 `Examples-Mvn` 目录下创建 `.keys` 文件,内容如下(请替换为你的实际信息):
```
appId=你的AppId
token=你的Token
```
#### 3. 准备 so 库
确保 `libs/native/linux/x86_64/` 目录下包含所有必要的 so 文件(如 `libagora_rtc_sdk.so`、`librecording.so` 等)。
#### 4. 运行示例服务
在 `Examples-Mvn` 目录下执行:
```sh
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:libs/native/linux/x86_64" java -Dserver.port=18080 -jar target/agora-example.jar
```
- 该命令会启动 Spring Boot 服务,监听 18080 端口。
- 如需更换端口,可修改 `-Dserver.port` 参数。
#### 5. 通过 API 启动/停止录制
- 启动录制:
```
http://<服务器IP>:18080/api/recording/start?configFileName=mix_stream_recorder_audio_video_water_marks.json
```
- 停止录制:
```
http://<服务器IP>:18080/api/recording/stop?taskId=<任务ID>
```
> 录制配置文件需放在 `Examples-Mvn/src/main/resources/` 目录下。
#### 6. 常见问题
- 若服务无法启动,请检查 so 文件路径、.keys 文件内容及端口占用。
- 录制无输出时,请检查频道内有无活跃用户、AppId/Token/频道名是否正确。
---
## API 参考
有关 SDK API 的详细说明,请参考 [API-reference.zh.md](API-reference.zh.md) 文档,每个类和方法都提供了详细的参数说明、返回值解释。
## 更新日志
### v4.4.150.5(2025-06-30)
#### API 变更
- **修改**:`AgoraMediaRtcRecorder` 类中 `unregisterRecorderEventHandle` 方法名修正为 `unregisterRecorderEventHandler`,统一方法命名规范
#### 改进与优化
- **修复**:修复设置画面布局接口的线程安全问题,提升多线程环境下的稳定性
- **优化**:调整单个日志文件最大大小限制至 1GB,改善日志管理和磁盘空间利用
### v4.4.150.4(2025-06-11)
#### API 变更
- **新增**:`AgoraMediaRtcRecorder` 类新增 `renewToken` 方法,支持动态更新频道 Token,避免 Token 过期导致录制中断
- **修改**:将 `Constants.WaterMaskFitMode` 重命名为 `Constants.WatermarkFitMode`,修正拼写错误并保持命名一致性
#### 改进与优化
- **修复**:修复 `MixerLayoutConfig` 类中 `imagePath` 属性设置问题,确保背景图片路径正确配置
### v4.4.150.3(2025-05-20)
#### API 变更
- **新增**:`IAgoraMediaRtcRecorderEventHandler` 新增 `onError`、`onTokenPrivilegeWillExpire`、`onTokenPrivilegeDidExpire` 回调方法,支持错误上报及 Token 即将过期/已过期通知。
### v4.4.150.2(2025-05-09)
#### API 变更
- **新增**:`AgoraService` 类中添加 `setGlobalLocalAccessPoint` 函数,用于配置全局本地接入点。
#### 改进与优化
- **修复**:修复 SpringBot 打包回调处理问题
### v4.4.150.1(2025-03-28)
#### API 变更
- **新增**:`IAgoraMediaRtcRecorderEventHandler` 类中添加 `onEncryptionError` 回调函数,支持加密错误通知
- **新增**:`AgoraMediaRtcRecorder` 类中添加 `setAudioVolumeIndicationParameters` 方法,用于配置远端用户音量回调间隔
- **重构**:优化 `IAgoraMediaRtcRecorderEventHandler` 类中 `onAudioVolumeIndication` 回调函数的参数结构
#### 改进与优化
- **增强**:改进 `VideoMixingLayout` 类,修复 `backgroundColor` 属性
- **新功能**:`VideoMixingLayout` 类新增 `backgroundImage` 属性,支持设置背景图片
### v4.4.150-aarch64(2025-02-24)
#### API 变更
- **兼容**:与 v4.4.150 版本保持 API 兼容
#### 改进与优化
- **平台**:首次支持 ARM64 架构
### v4.4.150(2025-01-21)
#### API 变更
- **初始版本**:发布基础 API 结构
#### 改进与优化
- **性能**:基础功能和性能优化
## 其他参考
详细参考官网()