# 开始录制音视频 (/zh-CN/realtime-media/local-server-recording/get-started/start-recording)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="cpp" platform="cpp" />
## 前提条件 [#前提条件]

本文介绍如何使用声网服务端 SDK 在实时音视频频道中实现录制功能。开始前请确保你的本地开发环境满足以下条件：

* 参考[开通本地服务端录制服务](/zh-CN/realtime-media/local-server-recording/build/recording-preparation/enable-service)在控制台创建一个声网项目，并获取项目的 App ID。
* 在项目中实现了基础的音视频互动场景。
* 服务器硬件条件：
  * 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]

1. 前往[下载](/zh-CN/realtime-media/local-server-recording/reference/downloads)获取最新的声网本地服务端录制 SDK 软件包。解压后的 SDK 包目录结构如下：

    ```shell
    .
    ├── agora_sdk
    │   ├── include
    │   ├── libagora-fdkaac.so
    │   ├── libagora_rtc_sdk.so
    │   └── libaosl.so
    └── example
        ├── CMakeLists.txt
        ├── build.sh
        ├── out
        ├── recorder
        ├── recorder.json
        ├── singleVideo.json
        ├── scripts
        └── third-party
    ```

2. 将下载下来的 SDK 文件集成到你的项目中：
    - 将 `agora_sdk/include` 目录中的头文件导入到你的开发工程中
    - 将 `agora_sdk/` 目录下的如下动态库文件链接到你的工程：
      - `libagora-fdkaac.so`
      - `libagora_rtc_sdk.so`
      - `libaosl.so`

:::info[信息]
SDK 包中的 `example` 路径下是完整的本地录制示例项目。你可以参考[编译示例项目并运行](#run-example)跑通并体验。
:::

## 调用 API 实现录制 [#调用-api-实现录制]

实现录制的 API 时序如下图所示：

<DocsImage alt="录制快速开始 API 时序" src="https://web-cdn.agora.io/docs-portal/img/recording/start-recording.svg" displayWidth="60%" />

### 初始化服务资源 [#初始化服务资源]

首先，你需要调用 [`createAgoraService`](/zh-CN/api-reference/local-server-recording/cpp/iagoraservice.cpp#createagoraservice) 创建服务实例，并使用 [`initialize`](/zh-CN/api-reference/local-server-recording/cpp/iagoraservice.cpp#initialize) 方法进行初始化，设置 App ID 和音视频相关的配置。

```cpp
// 初始化 Service 资源，设置 log
auto service = createAgoraService();
agora::base::AgoraServiceConfiguration service_config;
service_config.enableAudioDevice = false;
service_config.enableAudioProcessor = true;
service_config.enableVideo = true;
service_config.appId = config.appId.c_str();
service_config.useStringUid = config.UseStringUid;
service->initialize(service_config);
service->setLogFile("./io.agora.rtc_sdk/agorasdk.log", 1024*1024*5);
```

### 创建 Recorder [#创建-recorder]

调用 [`createAgoraMediaComponentFactory`](/zh-CN/api-reference/local-server-recording/cpp/iagoramediacomponentfactory.cpp#createagoramediacomponentfactory) 和 [`createMediaRtcRecorder`](/zh-CN/api-reference/local-server-recording/cpp/iagoramediacomponentfactory.cpp#createmediartcrecorder) 创建录制实例，然后使用 [`IAgoraMediaRtcRecorder::initialize`](/zh-CN/api-reference/local-server-recording/cpp/iagoramediartcrecorder.cpp#initialize) 方法初始化录制实例。

```cpp
// 创建 recorder
agora::rtc::IMediaComponentFactory* factory = createAgoraMediaComponentFactory();
agora::agora_refptr<agora::rtc::IAgoraMediaRtcRecorder> recorder = factory->createMediaRtcRecorder();
// 初始化 recorder
// isMix 设置录制模式
// - false 表示分开录制每个用户的音视频流，即单流录制
// - true 表示将所有用户的音视频混合录制，即合流录制
bool isMix = false;
// service 为上一步初始化的 AgoraService 对象
recorder->initialize(service, isMix);
```

### 注册事件处理器 [#注册事件处理器]

使用 [`registerRecorderEventHandler`](/zh-CN/api-reference/local-server-recording/cpp/iagoramediartcrecorder.cpp#registerrecordereventhandle) 注册录制事件的回调处理器，以便接收和处理录制过程中的事件通知。

```cpp
// 注册回调
std::unique_ptr<RecorderEventHandler> eventHandler{new RecorderEventHandler(recorder, config)};
recorder->registerRecorderEventHandle(eventHandler.get());
```

### 订阅音视频流 [#订阅音视频流]

调用 [`subscribeAllAudio`](/zh-CN/api-reference/local-server-recording/cpp/iagoramediartcrecorder.cpp#subscribeallaudio) 和 [`subscribeAllVideo`](/zh-CN/api-reference/local-server-recording/cpp/iagoramediartcrecorder.cpp#subscribeallvideo) 方法来订阅频道内的所有音频和视频流。

```cpp
// 订阅流
recorder->subscribeAllAudio();
recorder->subscribeAllVideo(options);
```

### 配置录制参数 [#配置录制参数]

使用 [`setRecorderConfig`](/zh-CN/api-reference/local-server-recording/cpp/iagoramediartcrecorder.cpp#setrecorderconfig) 方法设置录制的相关配置，包括视频分辨率、帧率、存储路径等。

:::warning[注意]
请确保你设置的录制文件存储路径 `storagePath` 存在。如果指定的目录不存在，会导致录制失败。
:::

```cpp
// 设置录制相关配置
agora::media::MediaRecorderConfiguration recorder_config;
recorder_config.width = config.video.width;
recorder_config.height = config.video.height;
recorder_config.fps = config.video.fps;
recorder_config.storagePath = config.recorderPath.c_str();
recorder_config.sample_rate = config.audio.sampleRate;
recorder_config.channel_num = config.audio.numOfChannels;
// 设置录制音频流、视频流、音视频流
recorder_config.streamType = static_cast<agora::media::MediaRecorderStreamType>(config.recorderStreamType);
// 设置最大录制时长
recorder_config.maxDurationMs = config.maxDuration * 1000;
recorder->setRecorderConfig(recorder_config);
```

### 加入频道并开始录制 [#加入频道并开始录制]

调用 [`joinChannel`](/zh-CN/api-reference/local-server-recording/cpp/legacy/classagora-1-1recording-1-1-i-recording-engine#joinchannel) 加入指定的频道，然后使用 [`startRecording`](/zh-CN/api-reference/local-server-recording/cpp/iagoramediartcrecorder.cpp#startrecording) 开始录制。

```cpp
// 加入频道并开始录制
recorder->joinChannel(config.token.c_str(), config.ChannelName.c_str(), config.UserId.c_str());
recorder->startRecording();
```

### 结束录制和释放资源 [#结束录制和释放资源]

录制完成后，需要调用相应的方法来取消订阅流、停止录制、退出频道并释放资源。你会在[配置录制参数](#配置录制参数)时指定的存储路径下找到 MP4 格式的录制文件。

```cpp
// 结束录制 清理资源 退出频道
recorder->unsubscribeAllAudio();
recorder->unsubscribeAllVideo();
recorder->stopRecording();
recorder->unregisterRecorderEventHandle(eventHandler.get());
eventHandler = nullptr;
recorder->leavelChannel();
recorder = nullptr;
service->release();
```

### 完整示例代码 [#完整示例代码]

以下是使用声网服务端 SDK 进行视频录制的完整示例代码：

```cpp
// 初始化 Service 资源，设置 log
auto service = createAgoraService();
agora::base::AgoraServiceConfiguration service_config;
service_config.enableAudioDevice = false;
service_config.enableAudioProcessor = true;
service_config.enableVideo = true;
service_config.appId = config.appId.c_str();
service_config.useStringUid = config.UseStringUid;
service->initialize(service_config);
service->setLogFile("./io.agora.rtc_sdk/agorasdk.log", 1024*1024*5);
 
 
// 创建 recorder
agora::rtc::IMediaComponentFactory* factory = createAgoraMediaComponentFactory();
agora::agora_refptr<agora::rtc::IAgoraMediaRtcRecorder> recorder = factory->createMediaRtcRecorder();
// 初始化 recorder
bool isMix = false;
recorder->initialize(service, isMix);
// 注册回调
std::unique_ptr<RecorderEventHandler> eventHandler{new RecorderEventHandler(recorder, config)};
recorder->registerRecorderEventHandle(eventHandler.get());
// 订阅流
recorder->subscribeAllAudio();
recorder->subscribeAllVideo(options);
 
// 设置录制相关配置
agora::media::MediaRecorderConfiguration recorder_config;
recorder_config.width = config.video.width;
recorder_config.height = config.video.height;
recorder_config.fps = config.video.fps;
recorder_config.storagePath = config.recorderPath.c_str();
recorder_config.sample_rate = config.audio.sampleRate;
recorder_config.channel_num = config.audio.numOfChannels;
recorder_config.streamType = static_cast<agora::media::MediaRecorderStreamType>(config.recorderStreamType);
recorder_config.maxDurationMs = config.maxDuration * 1000;
recorder->setRecorderConfig(recorder_config);
// 加入频道并开始录制
recorder->joinChannel(config.token.c_str(), config.ChannelName.c_str(), config.UserId.c_str());
recorder->startRecording();
 
// 结束录制 清理资源 退出频道
recorder->unsubscribeAllAudio();
recorder->unsubscribeAllVideo();
recorder->stopRecording();
recorder->unregisterRecorderEventHandle(eventHandler.get());
eventHandler = nullptr;
recorder->leavelChannel();
recorder = nullptr;
service->release();
```

## 后续步骤 [#后续步骤]

完成基本录制功能后，你可以进一步探索以下功能：

- [单流录制和合流录制](/zh-CN/realtime-media/local-server-recording/build/configure-recording-output/recording-mode)
- [自定义合流录制视频布局](/zh-CN/realtime-media/local-server-recording/build/configure-recording-output/set-layout)
- [配置水印](/zh-CN/realtime-media/local-server-recording/build/configure-recording-output/watermark)
- [录制崩溃后修复录制文件](/zh-CN/realtime-media/local-server-recording/build/best-practices/restore-files)

<a id="run-example"></a>
## 参考信息 [#参考信息]
### 编译示例项目并运行 [#编译示例项目并运行]

声网在 SDK 下载包中提供了完整的录制示例项目。获取并解压下载包后，你可以参考如下步骤编译并运行项目：

1. 运行如下命令行，前往示例项目所在路径：

   ```shell
   cd agora_rtc_sdk/example
   ```

2. 运行命令行，构建示例项目：

   ```shell
   ./build.sh
   ```

3. 将 SDK 包中的库文件添加到 LD_LIBRARY_PATH：

   ```shell
   export LD_LIBRARY_PATH=../../agora_sdk:$LD_LIBRARY_PATH
   ```

4. 按照场景需要填写 `recorder.json`（合流录制的配置文件）或 `singleVideo.json`（单流录制的配置文件）。单流和合流的场景区别可以参考[单流录制和合流录制](/zh-CN/realtime-media/local-server-recording/build/configure-recording-output/recording-mode)。

5. 运行如下命令行，示例程序会根据你在指定 json 文件中的配置进行录制：

   ```shell
   # 假定进行单流录制
   ./out/sample_recorder  singleVideo.json
   ```

### API 参考 [#api-参考]

本文介绍实现一个极简的录制任务需要调用的核心 API。你可以参考[录制 API](/zh-CN/api-reference/local-server-recording/cpp/api-overview) 了解完整的功能列表和对应的 API。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="cpp" platform="java" />
本文介绍如何使用声网服务端 SDK 在实时音视频频道中实现录制功能。

## 前提条件 [#前提条件-1]

开始前请确保你的本地开发环境满足以下条件：

- 参考[开通本地服务端录制服务](/zh-CN/realtime-media/local-server-recording/build/recording-preparation/enable-service)在控制台创建一个声网项目，并获取项目的 App ID。
- 在项目中实现了基础的音视频互动场景。
- 服务器硬件条件：
  - 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-1]

### 下载并添加 SDK [#下载并添加-sdk]

根据你的开发环境，选择一种方式将 SDK 下载并集成到你的项目中：

<Tabs defaultValue="maven" groupId="integrate" persist>
<TabsList>
  <TabsTrigger value="maven">通过 Maven 下载并添加</TabsTrigger>
  <TabsTrigger value="local">本地下载并添加</TabsTrigger>
</TabsList>

<TabsContent value="maven">

在项目的 `pom.xml` 文件中添加以下依赖：

- x86_64 平台

  ```xml
  <dependency>
      <groupId>io.agora.rtc</groupId>
      <artifactId>linux-recording-java-sdk</artifactId>
      <version>4.4.151.1</version>
  </dependency>
  ```

- arm64 平台

  ```xml
  <dependency>
      <groupId>io.agora.rtc</groupId>
      <artifactId>linux-recording-java-sdk</artifactId>
      <version>4.4.151</version>
  </dependency>
  ```

Maven 依赖包含了所需的 JAR 文件，但仍需手动处理 `.so` 库文件才能运行。

</TabsContent>

<TabsContent value="local">

1. 前往[下载](/zh-CN/realtime-media/local-server-recording/reference/downloads)获取最新的声网本地服务端录制 SDK 软件包。

    本地 SDK 是一个包含所有必要文件的完整包，适合需要更灵活控制的场景。从官网下载的 SDK 包（zip 格式）包含以下内容：

    - **doc/**         - JavaDoc 文档，详细的 API 说明
    - **examples/**    - 示例代码和项目
    - **sdk/**         - 核心 SDK 文件
      - `agora-recording-sdk.jar` - Java 类库
      - `agora-recording-sdk-javadoc.jar` - JavaDoc 文档

2. 选择一种方式将 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：

    1. 将 JAR 文件复制到项目的 `libs` 目录：

        ```shell
        mkdir -p libs
        cp sdk/agora-recording-sdk.jar libs/
        cp sdk/agora-recording-sdk-javadoc.jar libs/  # 可选，用于 IDE 支持
        ```

    2. 在 Java 项目中添加 `classpath` 引用：

        ```shell
        # 使用 SDK JAR
        java -cp .:libs/agora-recording-sdk.jar 你的主类

        # 在 IDE 中配置 JavaDoc（常见的 IDE 如 IntelliJ IDEA 或 Eclipse 支持直接关联 JavaDoc JAR）
        ```

下载的 SDK 包中已经包含了 `.so` 文件。你需要确保 Java 程序运行时能够找到这些文件。

</TabsContent>
</Tabs>

### 加载原生库（`.so` 文件） [#加载原生库so-文件]

声网本地服务端录制 Java SDK 依赖于底层的 C++ 原生库（`.so` 文件）。无论是通过 Maven 集成还是本地集成，都需要确保 Java 虚拟机 (JVM) 在运行时能够找到并加载这些库。

1. 提取 so 库文件

   `.so` 文件包含在 `agora-recording-sdk.jar` 或 `linux-recording-java-sdk-x.x.x.x.jar` 文件内部。你需要先将它们提取出来：

   1.  在你的项目或部署目录下创建一个用于存放库文件的目录，例如 `libs`：

        ```shell
        mkdir -p libs
        cd libs
        ```

   2.  使用 `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
        ```

   3.  提取后，`libs` 目录下会生成 `native/linux/x86_64` 子目录，其中包含所需的 `.so` 文件：

        ```shell
        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
        ```

2. 配置加载路径

    有两种主要方法让 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" 你的主类
    ```

    :::info[信息]
    - 推荐使用方法一 (`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-实现录制-1]

实现录制的 API 时序如下图所示：

<DocsImage alt="录制快速开始 API 时序" src="https://web-cdn.agora.io/docs-portal/img/recording/start-recording-java.svg" displayWidth="60%" />

### 初始化服务资源 [#初始化服务资源-1]

首先，你需要创建一个 `AgoraService` 服务实例，并使用 [`initialize`](/zh-CN/api-reference/local-server-recording/java/agoraservice.java#initialize) 方法进行初始化，设置 App ID 和音视频相关的配置。

```java
// 初始化 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 [#创建-recorder-1]

调用 [`createMediaRtcRecorder`](/zh-CN/api-reference/local-server-recording/java/agoraservice.java#createmediartcrecorder) 创建录制实例，然后使用 [`AgoraMediaRtcRecorder.initialize`](/zh-CN/api-reference/local-server-recording/java/agoramediartcrecorder.java#initialize) 方法初始化录制实例。

```java
// 创建 recorder
AgoraMediaRtcRecorder agoraMediaRtcRecorder = agoraService.createMediaRtcRecorder();

// 初始化 recorder
// enableMix 设置录制模式
// - false 表示分开录制每个用户的音视频流，即单流录制
// - true 表示将所有用户的音视频混合录制，即合流录制
boolean enableMix = false;
// service 为上一步初始化的 AgoraService 对象
agoraMediaRtcRecorder.initialize(agoraService, enableMix);
```

### 注册事件处理器 [#注册事件处理器-1]

使用 [`registerRecorderEventHandler`](/zh-CN/api-reference/local-server-recording/java/agoramediartcrecorder.java#registerrecordereventhandler) 注册录制事件的回调处理器，以便接收和处理录制过程中的事件通知。

```java
// 注册回调
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);
```

### 订阅音视频流 [#订阅音视频流-1]

调用 [`subscribeAllAudio`](/zh-CN/api-reference/local-server-recording/java/agoramediartcrecorder.java#subscribeallaudio) 和 [`subscribeAllVideo`](/zh-CN/api-reference/local-server-recording/java/agoramediartcrecorder.java#subscribeallvideo) 方法来订阅频道内的所有音频和视频流。

```java
// 订阅流
agoraMediaRtcRecorder.subscribeAllAudio();
VideoSubscriptionOptions options = new VideoSubscriptionOptions();
options.setEncodedFrameOnly(false);
options.setType(Constants.VideoStreamType.VIDEO_STREAM_HIGH);
agoraMediaRtcRecorder.subscribeAllVideo(options);
```

### 配置录制参数 [#配置录制参数-1]

使用 [`setRecorderConfig`](/zh-CN/api-reference/local-server-recording/java/agoramediartcrecorder.java#setrecorderconfig) 方法设置录制的相关配置，包括视频分辨率、帧率、存储路径等。

:::warning[注意]
请确保你设置的录制文件存储路径 `storagePath`
  存在。如果指定的目录不存在，会导致录制失败。
:::

```java
// 设置录制相关配置
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);
```

### 加入频道并开始录制 [#加入频道并开始录制-1]

调用 [`joinChannel`](/zh-CN/api-reference/local-server-recording/java/agoramediartcrecorder.java#joinchannel) 加入指定的频道，然后使用 [`startRecording`](/zh-CN/api-reference/local-server-recording/java/agoramediartcrecorder.java#startrecording) 开始录制。

```java
// 加入频道并开始录制
agoraMediaRtcRecorder.joinChannel(recorderConfig.getToken(),
                recorderConfig.getChannelName(),
                recorderConfig.getUserId());
agoraMediaRtcRecorder.startRecording();
```

### 结束录制和释放资源 [#结束录制和释放资源-1]

录制完成后，需要调用相应的方法来取消订阅流、停止录制、退出频道并释放资源。你会在[配置录制参数](#配置录制参数-1)时指定的存储路径下找到 MP4 格式的录制文件。

```java
// 结束录制 清理资源 退出频道
agoraMediaRtcRecorder.unsubscribeAllAudio();
agoraMediaRtcRecorder.unsubscribeAllVideo();
agoraMediaRtcRecorder.stopRecording();
agoraMediaRtcRecorder.unregisterRecorderEventHandler(eventHandler);
agoraMediaRtcRecorder.leaveChannel();
agoraMediaRtcRecorder.release();
agoraService.release();
```

### 完整示例代码 [#完整示例代码-1]

以下是使用声网服务端 SDK 进行视频录制的完整示例代码：

```java
// 初始化 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
AgoraMediaRtcRecorder agoraMediaRtcRecorder = agoraService.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();
agoraService.release();
```

## 后续步骤 [#后续步骤-1]

完成基本录制功能后，你可以进一步探索以下功能：

- [单流录制和合流录制](/zh-CN/realtime-media/local-server-recording/build/configure-recording-output/recording-mode)
- [自定义合流录制视频布局](/zh-CN/realtime-media/local-server-recording/build/configure-recording-output/set-layout)
- [配置水印](/zh-CN/realtime-media/local-server-recording/build/configure-recording-output/watermark)
- [录制崩溃后修复录制文件](/zh-CN/realtime-media/local-server-recording/build/best-practices/restore-files)

<a id="run-example"></a>
## 参考信息 [#参考信息-1]
### 编译示例项目并运行 [#编译示例项目并运行-1]

声网在 GitHub 上提供了完整的录制示例项目供你参考，你可以前往下载或查看其中的源代码。

<Cards>
  <Card title="Agora-Recording-Java-SDK" href="https://github.com/AgoraIO-Extensions/Agora-Recording-Java-SDK" />
</Cards>

下文提供了基于 Spring Boot 的 Maven 示例工程，方便你快速验证和二次开发。以下为跑通 `Examples-Mvn` 工程的基本流程：

#### 1. 编译打包 [#1-编译打包]

进入 `Examples-Mvn` 目录，执行：

```shell
mvn clean package
```

编译成功后，会在 `target/` 目录下生成 `agora-example.jar`。

#### 2. 配置密钥 [#2-配置密钥]

在 `Examples-Mvn` 目录下创建 `.keys` 文件，内容如下（请替换为你的实际信息）：

```xml
appId={你的 App ID}
token={你的 Token}
```

#### 3. 准备 so 库 [#3-准备-so-库]

确保 `libs/native/linux/x86_64/` 目录下包含所有必要的 so 文件（如 `libagora_rtc_sdk.so`、`librecording.so` 等）。

#### 4. 运行示例服务 [#4-运行示例服务]

在 `Examples-Mvn` 目录下执行：

```shell
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 启动/停止录制 [#5-通过-api-启动停止录制]

- 启动录制：

  ```shell
  http://<服务器IP>:18080/api/recording/start?configFileName=mix_stream_recorder_audio_video_water_marks.json
  ```

- 停止录制：

  ```shell
  http://<服务器IP>:18080/api/recording/stop?taskId=<任务ID>
  ```

:::warning[注意]
录制配置文件需放在 `Examples-Mvn/src/main/resources/` 目录下。
:::

### 相关文档 [#相关文档]

本文介绍实现一个极简的录制任务需要调用的核心 API。你可以参考[录制 API](/zh-CN/api-reference/local-server-recording/java/api-overview) 了解完整的功能列表和对应的 API。
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>
