开始录制音视频
本文介绍如何使用声网服务端 SDK 在实时音视频频道中实现录制功能。
前提条件
开始前请确保你的本地开发环境满足以下条件:
- 参考开通服务在控制台创建一个声网项目,并获取项目的 。
- 在项目中实现了基础的音视频互动场景。
- 服务器硬件条件:
- CPU:8 核,1.8 GHz 主频
- 内存:推荐 4 GB 或更高
- 服务器软件环境:
- 操作系统:Ubuntu(18.04 版本及以上)或 CentOS(7.0 版本及以上)
- CPU 架构:arm64 或 x86-64
- glibc 2.18 或更高版本
- gcc 4.8 或更高版本
- 网络要求:
- 服务器接入公网,有公网 IP
- 服务器允许访问
.agora.io
以及.agoralab.co
集成 SDK
下载并添加 SDK
根据你的开发环境,选择一种方式将 SDK 下载并集成到你的项目中:
- 通过 Maven 下载并添加
- 本地下载并添加
在项目的 pom.xml
文件中添加以下依赖:
-
x86_64 平台
XML<dependency>
<groupId>io.agora.rtc</groupId>
<artifactId>linux-recording-java-sdk</artifactId>
<version>4.4.150.5</version>
</dependency> -
arm64 平台
XML<dependency>
<groupId>io.agora.rtc</groupId>
<artifactId>linux-recording-java-sdk</artifactId>
<version>4.4.150.5-aarch64</version>
</dependency>
Maven 依赖包含了所需的 JAR 文件,但仍需手动处理 .so
库文件才能运行。
-
前往下载获取最新的声网本地服务端录制 SDK 软件包。
本地 SDK 是一个包含所有必要文件的完整包,适合需要更灵活控制的场景。从官网下载的 SDK 包(zip 格式)包含以下内容:
- doc/ - JavaDoc 文档,详细的 API 说明
- examples/ - 示例代码和项目
- sdk/ - 核心 SDK 文件
agora-recording-sdk.jar
- Java 类库agora-recording-sdk-javadoc.jar
- JavaDoc 文档
-
选择一种方式将 SDK 添加到你的项目中
方法一、使用本地 Maven 仓库方法集成:
Shell# 只安装 SDK JAR
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
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<dependency>
<groupId>io.agora.rtc</groupId>
<artifactId>linux-recording-java-sdk</artifactId>
<version>4.4.150.5</version>
</dependency>方法二、直接引用 SDK:
-
将 JAR 文件复制到项目的
libs
目录:Shellmkdir -p libs
cp sdk/agora-recording-sdk.jar libs/
cp sdk/agora-recording-sdk-javadoc.jar libs/ # 可选,用于 IDE 支持 -
在 Java 项目中添加
classpath
引用:Shell# 使用 SDK JAR
java -cp .:libs/agora-recording-sdk.jar 你的主类
# 在 IDE 中配置 JavaDoc(常见的 IDE 如 IntelliJ IDEA 或 Eclipse 支持直接关联 JavaDoc JAR)
-
下载的 SDK 包中已经包含了 .so
文件。你需要确保 Java 程序运行时能够找到这些文件。
加载原生库 (.so 文件)
声网本地服务端录制 Java SDK 依赖于底层的 C++ 原生库(.so
文件)。无论是通过 Maven 集成还是本地集成,都需要确保 Java 虚拟机 (JVM) 在运行时能够找到并加载这些库。
-
提取 so 库文件
.so
文件包含在agora-recording-sdk.jar
或linux-recording-java-sdk-x.x.x.x.jar
文件内部。你需要先将它们提取出来:-
在你的项目或部署目录下创建一个用于存放库文件的目录,例如
libs
:Shellmkdir -p libs
cd libs -
使用
jar
命令从 SDK 的 JAR 文件中提取内容(假设 JAR 文件位于libs
目录下或 Maven 缓存中):Shell# 如果使用本地集成方式,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 -
提取后,
libs
目录下会生成native/linux/x86_64
子目录,其中包含所需的.so
文件:Shelllibs/
├── 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
-
-
配置加载路径
有两种主要方法让 JVM 找到
.so
文件:方法一、通过设置环境变量
LD_LIBRARY_PATH
(推荐)。这是最可靠的方式,特别是在.so
文件之间存在依赖关系时。Shell# 确定你的 .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 在哪里查找库文件。Shell# 确定你的 .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
:Shell#!/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 - 推荐使用方法一 (
调用 API 实现录制
实现录制的 API 时序如下图所示:
初始化服务资源
首先,你需要创建一个 AgoraService
服务实例,并使用 initialize
方法进行初始化,设置 App ID 和音视频相关的配置。
// 初始化 Service 资源,设置 log
AgoraService agoraService = new AgoraService();
AgoraServiceConfiguration config = new AgoraServiceConfiguration();
config.setEnableAudioDevice(false);
config.setEnableAudioProcessor(true);
config.setEnableVideo(true);
config.setAppId(recorderConfig.getAppId());
config.setUseStringUid(recorderConfig.isUseStringUid());
LogConfig logConfig = new LogConfig();
logConfig.setFileSizeInKB(1024 * 20);
logConfig.setFilePath("logs/agora_logs/agorasdk.log");
config.setLogConfig(logConfig);
int ret = agoraService.initialize(config);
创建 Recorder
调用 createAgoraMediaComponentFactory
和 createMediaRtcRecorder
创建录制实例,然后使用 AgoraMediaRtcRecorder.initialize
方法初始化录制实例。
// 创建 recorder
AgoraMediaComponentFactory factory = agoraService.createAgoraMediaComponentFactory();
AgoraMediaRtcRecorder agoraMediaRtcRecorder = factory.createMediaRtcRecorder();
// 初始化 recorder
// enableMix 设置录制模式
// - false 表示分开录制每个用户的音视频流,即单流录制
// - true 表示将所有用户的音视频混合录制,即合流录制
boolean enableMix = false;
// service 为上一步初始化的 AgoraService 对象
agoraMediaRtcRecorder.initialize(agoraService, enableMix);
注册事件处理器
使用 registerRecorderEventHandler
注册录制事件的回调处理器,以便接收和处理录制过程中的事件通知。
// 注册回调
private IAgoraMediaRtcRecorderEventHandler eventHandler = new IAgoraMediaRtcRecorderEventHandler() {
@Override
public void onConnected(String channelId, String userId) {
}
@Override
public void onDisconnected(String channelId, String userId, Constants.ConnectionChangedReasonType reason) {
}
// 其他事件回调
};
agoraMediaRtcRecorder.registerRecorderEventHandler(eventHandler);
订阅音视频流
调用 subscribeAllAudio
和 subscribeAllVideo
方法来订阅频道内的所有音频和视频流。
// 订阅流
agoraMediaRtcRecorder.subscribeAllAudio();
VideoSubscriptionOptions options = new VideoSubscriptionOptions();
options.setEncodedFrameOnly(false);
options.setType(Constants.VideoStreamType.VIDEO_STREAM_HIGH);
agoraMediaRtcRecorder.subscribeAllVideo(options);
配置录制参数
使用 setRecorderConfig
方法设置录制的相关配置,包括视频分辨率、帧率、存储路径等。
请确保你设置的录制文件存储路径 storagePath
存在。如果指定的目录不存在,会导致录制失败。
// 设置录制相关配置
MediaRecorderConfiguration mediaRecorderConfiguration = new MediaRecorderConfiguration();
mediaRecorderConfiguration.setWidth(width != 0 ? width : recorderConfig.getVideo().getWidth());
mediaRecorderConfiguration.setHeight(height != 0 ? height : recorderConfig.getVideo().getHeight());
mediaRecorderConfiguration.setFps(recorderConfig.getVideo().getFps());
mediaRecorderConfiguration.setMaxDurationMs(recorderConfig.getMaxDuration() * 1000);
mediaRecorderConfiguration.setStoragePath(recorderConfig.getRecorderPath());
mediaRecorderConfiguration.setSampleRate(recorderConfig.getAudio().getSampleRate());
mediaRecorderConfiguration.setChannelNum(recorderConfig.getAudio().getNumOfChannels());
mediaRecorderConfiguration.setStreamType(Constants.MediaRecorderStreamType.STREAM_TYPE_BOTH);
mediaRecorderConfiguration.setVideoSourceType(Constants.VideoSourceType.VIDEO_SOURCE_CAMERA_SECONDARY);
agoraMediaRtcRecorder.setRecorderConfig(mediaRecorderConfiguration);
加入频道并开始录制
调用 joinChannel
加入指定的频道,然后使用 startRecording
开始录制。
// 加入频道并开始录制
agoraMediaRtcRecorder.joinChannel(recorderConfig.getToken(),
recorderConfig.getChannelName(),
recorderConfig.getUserId());
agoraMediaRtcRecorder.startRecording();
结束录制和释放资源
录制完成后,需要调用相应的方法来取消订阅流、停止录制、退出频道并释放资源。你会在配置录制参数时指定的存储路径下找到 MP4 格式的录制文件。
// 结束录制 清理资源 退出频道
agoraMediaRtcRecorder.unsubscribeAllAudio();
agoraMediaRtcRecorder.unsubscribeAllVideo();
agoraMediaRtcRecorder.stopRecording();
agoraMediaRtcRecorder.unregisterRecorderEventHandler(eventHandler);
agoraMediaRtcRecorder.leaveChannel();
agoraMediaRtcRecorder.release();
factory.release();
agoraService.release();
完整示例代码
以下是使用声网服务端 SDK 进行视频录制的完整示例代码:
// 初始化 Service 资源,设置 log
AgoraService agoraService = new AgoraService();
AgoraServiceConfiguration config = new AgoraServiceConfiguration();
config.setEnableAudioDevice(false);
config.setEnableAudioProcessor(true);
config.setEnableVideo(true);
config.setAppId(recorderConfig.getAppId());
config.setUseStringUid(recorderConfig.isUseStringUid());
LogConfig logConfig = new LogConfig();
logConfig.setFileSizeInKB(1024 * 20);
logConfig.setFilePath("logs/agora_logs/agorasdk.log");
config.setLogConfig(logConfig);
int ret = agoraService.initialize(config);
// 创建 recorder
AgoraMediaComponentFactory factory = agoraService.createAgoraMediaComponentFactory();
AgoraMediaRtcRecorder agoraMediaRtcRecorder = factory.createMediaRtcRecorder();
// 初始化 recorder
boolean enableMix = false;
agoraMediaRtcRecorder.initialize(agoraService, enableMix);
// 注册回调
IAgoraMediaRtcRecorderEventHandler eventHandler = new IAgoraMediaRtcRecorderEventHandler() {
@Override
public void onConnected(String channelId, String userId) {
}
@Override
public void onDisconnected(String channelId, String userId, Constants.ConnectionChangedReasonType reason) {
}
// 其他事件回调
};
agoraMediaRtcRecorder.registerRecorderEventHandler(eventHandler);
// 订阅流
agoraMediaRtcRecorder.subscribeAllAudio();
VideoSubscriptionOptions options = new VideoSubscriptionOptions();
options.setEncodedFrameOnly(false);
options.setType(Constants.VideoStreamType.VIDEO_STREAM_HIGH);
agoraMediaRtcRecorder.subscribeAllVideo(options);
// 设置录制相关配置
MediaRecorderConfiguration mediaRecorderConfiguration = new MediaRecorderConfiguration();
mediaRecorderConfiguration.setWidth(width != 0 ? width : recorderConfig.getVideo().getWidth());
mediaRecorderConfiguration.setHeight(height != 0 ? height : recorderConfig.getVideo().getHeight());
mediaRecorderConfiguration.setFps(recorderConfig.getVideo().getFps());
mediaRecorderConfiguration.setStoragePath(recorderConfig.getRecorderPath());
mediaRecorderConfiguration.setSampleRate(recorderConfig.getAudio().getSampleRate());
mediaRecorderConfiguration.setChannelNum(recorderConfig.getAudio().getNumOfChannels());
mediaRecorderConfiguration.setStreamType(Constants.MediaRecorderStreamType.STREAM_TYPE_BOTH);
mediaRecorderConfiguration.setMaxDurationMs(recorderConfig.getMaxDuration() * 1000);
agoraMediaRtcRecorder.setRecorderConfig(mediaRecorderConfiguration);
// 加入频道并开始录制
agoraMediaRtcRecorder.joinChannel(recorderConfig.getToken(),
recorderConfig.getChannelName(),
recorderConfig.getUserId());
agoraMediaRtcRecorder.startRecording();
// 结束录制 清理资源 退出频道
agoraMediaRtcRecorder.unsubscribeAllAudio();
agoraMediaRtcRecorder.unsubscribeAllVideo();
agoraMediaRtcRecorder.stopRecording();
agoraMediaRtcRecorder.unregisterRecorderEventHandler(eventHandler);
agoraMediaRtcRecorder.leaveChannel();
agoraMediaRtcRecorder.release();
factory.release();
agoraService.release();
后续步骤
完成基本录制功能后,你可以进一步探索以下功能:
参考信息
编译示例项目并运行
声网在 GitHub 上提供了完整的录制示例项目供你参考,你可以前往下载或查看其中的源代码。
下文提供了基于 Spring Boot 的 Maven 示例工程,方便你快速验证和二次开发。以下为跑通 Examples-Mvn
工程的基本流程:
1. 编译打包
进入 Examples-Mvn
目录,执行:
mvn clean package
编译成功后,会在 target/
目录下生成 agora-example.jar
。
2. 配置密钥
在 Examples-Mvn
目录下创建 .keys
文件,内容如下(请替换为你的实际信息):
appId={你的 App ID}
token={你的 Token}
3. 准备 so 库
确保 libs/native/linux/x86_64/
目录下包含所有必要的 so 文件(如 libagora_rtc_sdk.so
、librecording.so
等)。
4. 运行示例服务
在 Examples-Mvn
目录下执行:
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 启动/停止录制
-
启动录制:
Shellhttp://<服务器IP>:18080/api/recording/start?configFileName=mix_stream_recorder_audio_video_water_marks.json
-
停止录制:
Shellhttp://<服务器IP>:18080/api/recording/stop?taskId=<任务ID>
录制配置文件需放在 Examples-Mvn/src/main/resources/
目录下。
相关文档
本文介绍实现一个极简的录制任务需要调用的核心 API。你可以参考录制 API 了解完整的功能列表和对应的 API。