# Quickstart (/en/realtime-media/on-premise-recording/quickstart)

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

<_PlatformTabsGroup groupMode="structured" canonicalPlatform="linux-cpp" platforms="[&#x22;linux-cpp&#x22;,&#x22;linux-java&#x22;]" showTabs="true">
  <_PlatformPanel platform="linux-cpp">
    <_PlatformProcessedMarker groupMode="structured" canonicalPlatform="linux-cpp" platform="linux-cpp" />

    This article describes how to use the On-Premise Recording SDK to record real-time audio and video.

    ## Understand the tech [#understand-the-tech]

    Recording audio and video in a channel using the On-Premise Recording SDK works by adding a special user to the Video SDK channel. This special user captures the audio and video from the channel, transcodes it, and stores it on your Linux server.

    ![On-Premise Recording SDK recording workflow](https://assets-docs.agora.io/images/on-premise-recording/quickstart.svg)

    <CalloutContainer type="info">
      <CalloutDescription>
        Integrate the On-Premise Recording SDK into your Linux server, not your client app. To record audio and video without deploying a Linux server, use Agora [Cloud Recording](/en/realtime-media/cloud-recording).
      </CalloutDescription>
    </CalloutContainer>

    ## Prerequisites [#prerequisites]

    Before you begin, complete the following steps and ensure your environment meets the required specifications:

    * [Create an Agora project](/en/realtime-media/on-premise-recording/manage-agora-account#generate-temporary-token) in the Agora Console and obtain an App ID and a temporary token.
    * Implement a Video SDK project that includes basic audio and video interaction.

    **Server hardware requirements:**

    * **CPU**: 8 cores, 1.8 GHz
    * **Memory**: At least 4 GB (recommended)

    **Server software requirements:**

    * **Operating system**: Ubuntu 18.04 or later, or CentOS 7.0 or later
    * **CPU architecture**: arm64 or x86-64
    * **glibc**: version 2.18 or later
    * **gcc**: version 4.8 or later

    **Network requirements:**

    * The server is connected to the public internet and has a public IP address.
    * The server allows access to the following domains:

      * `*.agora.io`
      * `*.agoralab.co`

    ## Project setup [#project-setup]

    This section shows how to integrate the On-Premise Recording SDK into your app.

    ### Integrate the SDK [#integrate-the-sdk]

    1. Download the latest On-Premise Recording SDK package from the [SDKs](/en/api-reference/sdks?product=on-premise-recording\&platform=linux) page.

    2. Extract the package. The directory structure should look like this:

       ```text
       .
       ├── 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
       ```

    3. Integrate the SDK into your project:

       * Import the header files from `agora_sdk/include` into your project.
       * Link the following dynamic library files from the `agora_sdk` directory:

         * `libagora-fdkaac.so`
         * `libagora_rtc_sdk.so`
         * `libaosl.so`

    <CalloutContainer type="info">
      <CalloutDescription>
        The `example` directory contains a complete sample project for local recording. To run it, see [Test the project](#test-the-project).
      </CalloutDescription>
    </CalloutContainer>

    ## Implement On-Premise Recording [#implement-on-premise-recording]

    This section shows how to implement On-Premise recording in your app, step by step.

    The following figure illustrates the essential steps:

    <details>
      <summary>
        Quickstart sequence diagram
      </summary>

      ![On-Premise Recording quickstart sequence diagram](https://assets-docs.agora.io/images/on-premise-recording/on-premise-recording-quickstart-logic-cpp.svg)
    </details>

    ### Initialize the service [#initialize-the-service]

    Create the Agora service using `createAgoraService`. Then initialize it with media configuration options and logging settings.

    ```cpp
    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);
    ```

    ### Create the recorder instance [#create-the-recorder-instance]

    Call `createAgoraMediaComponentFactory` and use it to create a `IAgoraMediaRtcRecorder` instance. Then initialize the recorder with the service and recording mode.

    ```cpp
    agora::rtc::IMediaComponentFactory* factory = createAgoraMediaComponentFactory();
    agora::agora_refptr<agora::rtc::IAgoraMediaRtcRecorder> recorder = factory->createMediaRtcRecorder();

    // Set the recording mode
    // - false: Record each user's audio and video stream separately (single stream recording)
    // - true: Record all users' audio and video streams together (composite recording)

    bool isMix = false;
    // Initialize recorder
    recorder->initialize(service, isMix);
    ```

    ### Register the event handler [#register-the-event-handler]

    Call `registerRecorderEventHandle` to register a user-defined event handler that receives recorder callbacks.

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

    ### Subscribe to audio and video streams [#subscribe-to-audio-and-video-streams]

    Call `subscribeAllAudio` and `subscribeAllVideo` to receive all audio and video streams in the channel.

    ```cpp
    recorder->subscribeAllAudio();
    recorder->subscribeAllVideo(options);
    ```

    ### Configure recording [#configure-recording]

    Call `setRecorderConfig` to define recording parameters such as resolution, frame rate, audio settings, and the storage location.

    <CalloutContainer type="info">
      <CalloutDescription>
        Ensure that the directory specified in `storagePath` exists. If not, the recording will fail.
      </CalloutDescription>
    </CalloutContainer>

    ```cpp
    // Set recording configuration
    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;
    // Set recording stream type: audio stream, video stream, or audio and video stream
    recorder_config.streamType = static_cast<agora::media::MediaRecorderStreamType>(config.recorderStreamType);
    // Set the maximum recording duration
    recorder_config.maxDurationMs = config.maxDuration * 1000;

    recorder->setRecorderConfig(recorder_config);
    ```

    ### Join the channel and start recording [#join-the-channel-and-start-recording]

    Call `joinChannel` to join the specified channel and `startRecording` to begin recording.

    ```cpp
    recorder->joinChannel(config.token.c_str(), config.ChannelName.c_str(), config.UserId.c_str());
    recorder->startRecording();
    ```

    ### Stop recording and release resources [#stop-recording-and-release-resources]

    Call the cleanup methods to end recording, unsubscribe from streams, and release memory.

    ```cpp
    recorder->unsubscribeAllAudio();
    recorder->unsubscribeAllVideo();
    recorder->stopRecording();

    recorder->unregisterRecorderEventHandle(eventHandler.get());
    eventHandler = nullptr;

    recorder->leaveChannel();
    recorder = nullptr;

    service->release();
    ```

    ### Complete sample code [#complete-sample-code]

    The following example shows the full implementation of an On-Premise Recording workflow.

    <details>
      <summary>
        Complete sample code for On-Premise Recording
      </summary>

      ```cpp
      // Create and initialize the Agora service, and configure logging
      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);

      // Create the media recorder instance
      agora::rtc::IMediaComponentFactory* factory = createAgoraMediaComponentFactory();
      agora::agora_refptr<agora::rtc::IAgoraMediaRtcRecorder> recorder = factory->createMediaRtcRecorder();

      // Initialize the recorder
      // Set to true for mixed recording or false for individual streams
      bool isMix = false;
      recorder->initialize(service, isMix);

      // Register the event handler for recorder callbacks
      std::unique_ptr<RecorderEventHandler> eventHandler{new RecorderEventHandler(recorder, config)};
      recorder->registerRecorderEventHandle(eventHandler.get());

      // Subscribe to all audio and video streams
      recorder->subscribeAllAudio();
      recorder->subscribeAllVideo(options); // 'options' should be properly defined before use

      // Configure recorder settings
      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);

      // Join the channel and start recording
      recorder->joinChannel(config.token.c_str(), config.ChannelName.c_str(), config.UserId.c_str());
      recorder->startRecording();

      // Stop recording and clean up
      recorder->unsubscribeAllAudio();
      recorder->unsubscribeAllVideo();
      recorder->stopRecording();

      recorder->unregisterRecorderEventHandle(eventHandler.get());
      eventHandler = nullptr;

      recorder->leaveChannel();
      recorder = nullptr;

      service->release();
      ```
    </details>

    ## Test the project [#test-the-project]

    Agora provides a complete sample project in the SDK download package. After downloading and extracting the package, follow these steps to build and run it:

    1. Navigate to the sample project directory:

       ```sh
       cd agora_rtc_sdk/example
       ```

    2. Build the sample project:

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

    3. Add the SDK library path to the `LD_LIBRARY_PATH` environment variable:

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

    4. Choose a configuration file for your recording mode:

       * Use `recorder.json` for composite recording.
       * Use `singleVideo.json` for individual recording.

       <CalloutContainer type="info">
         <CalloutDescription>
           For more information on the differences between mixed and individual recording modes, see [Individual recording](/en/realtime-media/on-premise-recording/build/record-audio-and-video/individual-mode) and [Composite recording](/en/realtime-media/on-premise-recording/build/record-audio-and-video/composite-mode).
         </CalloutDescription>
       </CalloutContainer>

    5. Run the sample recorder with the selected configuration file:

       ```sh
       # Example: Run individual recording
       ./out/sample_recorder singleVideo.json
       ```

    ## Reference [#reference]

    This section contains content that completes the information on this page, or points you to documentation that explains other aspects to this product.

    ### API reference [#api-reference]

    * [`createAgoraService`](/en/api-reference/api-ref/on-premise-recording#createagoraservice)
    * [`initialize`](/en/api-reference/api-ref/on-premise-recording#initialize)
    * [`setLogFile`](/en/api-reference/api-ref/on-premise-recording#setlogfile)
    * [`createAgoraMediaComponentFactory`](/en/api-reference/api-ref/on-premise-recording#createagoramediacomponentfactory)
    * [`registerRecorderEventHandle`](/en/api-reference/api-ref/on-premise-recording#registerrecordereventhandle)
    * [`subscribeAllAudio`](/en/api-reference/api-ref/on-premise-recording#subscribeallaudio)
    * [`subscribeAllVideo`](/en/api-reference/api-ref/on-premise-recording#subscribeallvideo)
    * [`setRecorderConfig`](/en/api-reference/api-ref/on-premise-recording#setrecorderconfig)
    * [`joinChannel`](/en/api-reference/api-ref/on-premise-recording#joinchannel)
    * [`startRecording`](/en/api-reference/api-ref/on-premise-recording#startrecording)
    * [`unsubscribeAllAudio`](/en/api-reference/api-ref/on-premise-recording#unsubscribeallaudio)
    * [`unsubscribeAllVideo`](/en/api-reference/api-ref/on-premise-recording#unsubscribeallvideo)
    * [`stopRecording`](/en/api-reference/api-ref/on-premise-recording#stoprecording)
    * [`unregisterRecorderEventHandle`](/en/api-reference/api-ref/on-premise-recording#unregisterrecordereventhandle)
    * [`leaveChannel`](/en/api-reference/api-ref/on-premise-recording#leavechannel)
    * [`release`](/en/api-reference/api-ref/on-premise-recording#release)

    <_PlatformProcessedMarker close="true" />
  </_PlatformPanel>

  <_PlatformPanel platform="linux-java">
    <_PlatformProcessedMarker groupMode="structured" canonicalPlatform="linux-cpp" platform="linux-java" />

    This article describes how to use the On-Premise Recording SDK to record real-time audio and video.

    ## Understand the tech [#understand-the-tech-1]

    Recording audio and video in a channel using the On-Premise Recording SDK works by adding a special user to the Video SDK channel. This special user captures the audio and video from the channel, transcodes it, and stores it on your Linux server.

    ![On-Premise Recording SDK recording workflow](https://assets-docs.agora.io/images/on-premise-recording/quickstart.svg)

    <CalloutContainer type="info">
      <CalloutDescription>
        Integrate the On-Premise Recording SDK into your Linux server, not your client app. To record audio and video without deploying a Linux server, use Agora [Cloud Recording](/en/realtime-media/cloud-recording).
      </CalloutDescription>
    </CalloutContainer>

    ## Prerequisites [#prerequisites-1]

    Before you begin, complete the following steps and ensure your environment meets the required specifications:

    * [Create an Agora project](/en/realtime-media/on-premise-recording/manage-agora-account#generate-temporary-token) in the Agora Console and obtain an App ID and a temporary token.
    * Implement a Video SDK project that includes basic audio and video interaction.

    **Server hardware requirements:**

    * **CPU**: 8 cores, 1.8 GHz
    * **Memory**: At least 4 GB (recommended)

    **Server software requirements:**

    * **Operating system**: Ubuntu 18.04 or later, or CentOS 7.0 or later
    * **CPU architecture**: arm64 or x86-64
    * **glibc**: version 2.18 or later
    * **gcc**: version 4.8 or later

    **Network requirements:**

    * The server is connected to the public internet and has a public IP address.
    * The server allows access to the following domains:

      * `*.agora.io`
      * `*.agoralab.co`

    ## Project setup [#project-setup-1]

    This section shows how to integrate the On-Premise Recording SDK into your app.

    <Tabs defaultValue="maven">
      <TabsList>
        <TabsTrigger value="maven">
          Add using Maven
        </TabsTrigger>

        <TabsTrigger value="manual">
          Add manually
        </TabsTrigger>
      </TabsList>

      <TabsContent value="maven">
        Add the following dependencies to your project’s` pom.xml` file based on your platform:

        * **For x86\_64**:

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

        * **For arm64**:

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

      <TabsContent value="manual">
        ### Download and unzip [#download-and-unzip]

        1. Download the latest On-Premise Recording SDK package from the [SDKs](/en/api-reference/sdks?product=on-premise-recording\&platform=linux) page.

        2. Unzip the SDK and you see the following contents:
           ```txt
           doc/                            JavaDoc documentation
              examples/                       Sample projects and code
              sdk/                            Core SDK files
                sdk/agora-recording-sdk.jar     Java class library
                sdk/agora-recording-sdk-javadoc.jar  JavaDoc (optional, for IDE support)
           ```

        ### Integrate the SDK [#integrate-the-sdk-1]

        Choose one of the following methods to add the SDK to your project.

        #### Use a local maven repository [#use-a-local-maven-repository]

        1. Install the SDK JAR using Maven:

           To install only the SDK JAR:

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

        To install both the SDK JAR and JavaDoc:

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

        1. Add the dependency to your `pom.xml`:
           ```xml
           <dependency>
                 <groupId>io.agora.rtc</groupId>
                 <artifactId>linux-recording-java-sdk</artifactId>
                 <version>4.4.150.5</version>
               </dependency>
           ```

        #### Reference the JAR directly [#reference-the-jar-directly]

        1. Create a `libs` directory and copy the JAR files:
           ```bash
           mkdir -p libs
              cp sdk/agora-recording-sdk.jar libs/
              cp sdk/agora-recording-sdk-javadoc.jar libs/  # Optional, for IDE JavaDoc support
           ```

        2. Add the JAR file to your classpath when compiling or running:
           ```xml
           java -cp .:libs/agora-recording-sdk.jar YourMainClass
           ```

        <CalloutContainer type="info">
          <CalloutTitle>
            info
          </CalloutTitle>

          <CalloutDescription>
            To enable JavaDoc support in your IDE (such as IntelliJ IDEA or Eclipse), attach `agora-recording-sdk-javadoc.jar` to the library reference.
          </CalloutDescription>
        </CalloutContainer>

        ### Load native libraries [#load-native-libraries]

        The SDK depends on native `.so` libraries written in C++. Whether you integrate the SDK using Maven or manually, you must ensure the Java Virtual Machine (JVM) can locate and load these libraries at runtime.

        #### Extract native `.so` files [#extract-native-so-files]

        The native `.so` files are bundled inside the `agora-recording-sdk.jar` or `linux-recording-java-sdk-<version>.jar` file. You need to extract them manually:

        1. Create a directory to store the native library files:
           ```bash
           mkdir -p libs
              cd libs
           ```

        2. Use the `jar` command to extract contents:

           If you're using the local SDK:

        ```bash
        jar xvf agora-recording-sdk.jar
        ```

        If you're using the Maven-installed SDK:

        ```bash
        jar xvf ~/.m2/repository/io/agora/rtc/linux-recording-java-sdk/4.4.150.5/linux-recording-java-sdk-4.4.150.5.jar
        ```

        After extraction, you'll find a directory structure like this:

        ```txt
        libs/
           ├── agora-recording-sdk.jar
           ├── native/
           │   └── linux/
           │       ├── x86_64/
           │       │   ├── libagora_rtc_sdk.so
           │       │   ├── libagora-fdkaac.so
           │       │   ├── libaosl.so
           │       │   └── librecording.so
           │       └── aarch64/   (if available for arm64)
           │            ├── libagora_rtc_sdk.so
           │            ├── libagora-fdkaac.so
           │            ├── libaosl.so
           │            └── librecording.so
        ```

        #### Configure the library load path [#configure-the-library-load-path]

        The JVM must be configured to locate the extracted `.so` files. You can do this in one of two ways:

        * **Option 1: Use `LD_LIBRARY_PATH` (Recommended)**

          1. Set the environment variable before launching your app:
             ```bash
             # Assuming the .so files are in ./libs/native/linux/x86_64
                    LIB_DIR=$(pwd)/libs/native/linux/x86_64
                    export LD_LIBRARY_PATH=$LIB_DIR:$LD_LIBRARY_PATH
             ```

          2. Run your application:
             ```xml
             java -jar your-app.jar
                    # Or with classpath:
                    java -cp "your-classpath" YourMainClass
             ```

        * **Option 2: Use JVM option `-Djava.library.path`**

          This method directly tells the JVM where to find the native libraries:

        ```xml
        java -Djava.library.path=./libs/native/linux/x86_64 -jar your-app.jar
          # Or with classpath:
          java -Djava.library.path=./libs/native/linux/x86_64 -cp "your-classpath" YourMainClass
        ```

        <CalloutContainer type="info">
          <CalloutTitle>
            info
          </CalloutTitle>

          <CalloutDescription>
            Using `LD_LIBRARY_PATH` is more reliable, especially when native libraries depend on each other.
          </CalloutDescription>
        </CalloutContainer>

        #### Automate with a startup script (Optional) [#automate-with-a-startup-script-optional]

        You can create a shell script to automate the setup:

        ```bash
        #!/bin/bash

        # Get the directory of this script
        SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

        # Define paths
        LIB_PATH="$SCRIPT_DIR/libs/native/linux/x86_64"
        SDK_JAR="$SCRIPT_DIR/libs/agora-recording-sdk.jar"
        MAIN_CLASS="your.main.Class"
        APP_CP="your-other-classpaths"

        # Set environment variable
        export LD_LIBRARY_PATH=$LIB_PATH:$LD_LIBRARY_PATH

        # Build full classpath
        CLASSPATH=".:$SDK_JAR:$APP_CP"

        # Run Java program
        java -Djava.library.path=$LIB_PATH -cp "$CLASSPATH" $MAIN_CLASS
        ```

        Make the script executable:

        ```bash
        chmod +x run.sh
        ./run.sh
        ```
      </TabsContent>
    </Tabs>

    ## Implement On-Premise Recording [#implement-on-premise-recording-1]

    This section shows how to implement On-Premise recording in your app, step by step.

    The following figure illustrates the essential steps:

    <details>
      <summary>
        Quickstart sequence diagram
      </summary>

      ![On-Premise Recording quickstart sequence diagram](https://assets-docs.agora.io/images/on-premise-recording/on-premise-recording-quickstart-logic-cpp.svg)
    </details>

    ### Initialize the service [#initialize-the-service-1]

    Create an `AgoraService` instance and initialize it with your App ID and feature flags.

    ```java
    // Create and configure the service
    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());

    // Set up log configuration
    LogConfig logConfig = new LogConfig();
    logConfig.setFileSizeInKB(1024 * 20);
    logConfig.setFilePath("logs/agora_logs/agorasdk.log");
    config.setLogConfig(logConfig);

    // Initialize the Agora service
    int ret = agoraService.initialize(config);
    ```

    ### Create a recorder instance [#create-a-recorder-instance]

    Call `createMediaRtcRecorder` to create a recorder instance,and then use `AgoraMediaRtcRecorder.initialize` to initialize it.

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

    // Initialize recorder
    // enableMix sets the recording mode
    // - false: Record each user’s audio and video stream separately (individual stream recording)
    // - true: Record all users’ audio and video as a mixed stream (mixed recording)
    boolean enableMix = false;
    // service is the AgoraService object initialized in the previous step
    agoraMediaRtcRecorder.initialize(agoraService, enableMix);
    ```

    ### Register event handlers [#register-event-handlers]

    Register an event handler to receive recording callbacks.

    ```java
    // Define the event handler
    private IAgoraMediaRtcRecorderEventHandler eventHandler = new IAgoraMediaRtcRecorderEventHandler() {
        @Override
        public void onConnected(String channelId, String userId) {
            // Handle connection event
        }

        @Override
        public void onDisconnected(String channelId, String userId, Constants.ConnectionChangedReasonType reason) {
            // Handle disconnection event
        }

        // Add more overrides as needed
    };

    // Register the event handler
    agoraMediaRtcRecorder.registerRecorderEventHandler(eventHandler);
    ```

    ### Subscribe to audio and video streams [#subscribe-to-audio-and-video-streams-1]

    Subscribe to all audio streams and high-quality video streams in the channel.

    ```java
    // Subscribe to audio
    agoraMediaRtcRecorder.subscribeAllAudio();

    // Subscribe to video
    VideoSubscriptionOptions options = new VideoSubscriptionOptions();
    options.setEncodedFrameOnly(false);
    options.setType(Constants.VideoStreamType.VIDEO_STREAM_HIGH);
    agoraMediaRtcRecorder.subscribeAllVideo(options);
    ```

    ### Configure the recorder [#configure-the-recorder]

    Set the resolution, frame rate, duration, and file path for the recording.

    ```java
    // Configure the recorder
    MediaRecorderConfiguration recorderConfig = new MediaRecorderConfiguration();
    recorderConfig.setWidth(width != 0 ? width : recorderConfig.getVideo().getWidth());
    recorderConfig.setHeight(height != 0 ? height : recorderConfig.getVideo().getHeight());
    recorderConfig.setFps(recorderConfig.getVideo().getFps());
    recorderConfig.setMaxDurationMs(recorderConfig.getMaxDuration() * 1000);
    recorderConfig.setStoragePath(recorderConfig.getRecorderPath());
    recorderConfig.setSampleRate(recorderConfig.getAudio().getSampleRate());
    recorderConfig.setChannelNum(recorderConfig.getAudio().getNumOfChannels());
    recorderConfig.setStreamType(Constants.MediaRecorderStreamType.STREAM_TYPE_BOTH);
    recorderConfig.setVideoSourceType(Constants.VideoSourceType.VIDEO_SOURCE_CAMERA_SECONDARY);

    agoraMediaRtcRecorder.setRecorderConfig(recorderConfig);
    ```

    <CalloutContainer type="info">
      <CalloutDescription>
        Ensure that the `storagePath` exists before you start recording. If the directory does not exist, the recording fails.
      </CalloutDescription>
    </CalloutContainer>

    ### Join the channel and start recording [#join-the-channel-and-start-recording-1]

    Use the following code to join a channel and begin recording:

    ```java
    agoraMediaRtcRecorder.joinChannel(
        recorderConfig.getToken(),
        recorderConfig.getChannelName(),
        recorderConfig.getUserId()
    );
    agoraMediaRtcRecorder.startRecording();
    ```

    ### Stop and release resources [#stop-and-release-resources]

    Unsubscribe from streams, stop the recording, and release resources.

    ```java
    agoraMediaRtcRecorder.unsubscribeAllAudio();
    agoraMediaRtcRecorder.unsubscribeAllVideo();
    agoraMediaRtcRecorder.stopRecording();
    agoraMediaRtcRecorder.unregisterRecorderEventHandler(eventHandler);
    agoraMediaRtcRecorder.leaveChannel();
    agoraMediaRtcRecorder.release();
    agoraService.release();
    ```

    The recorded MP4 file is saved to the storage path you specified in the recording configuration.

    ### Complete sample code [#complete-sample-code-1]

    <details>
      <summary>
        Complete sample code for On-Premise Recording
      </summary>

      ```java
      // Initialize Service resources and set 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);

      // Create recorder
      AgoraMediaRtcRecorder agoraMediaRtcRecorder = agoraService.createMediaRtcRecorder();
      // Initialize recorder
      boolean enableMix = false;
      agoraMediaRtcRecorder.initialize(agoraService, enableMix);
      // Register callbacks
      IAgoraMediaRtcRecorderEventHandler eventHandler = new IAgoraMediaRtcRecorderEventHandler() {
          @Override
          public void onConnected(String channelId, String userId) {

          }

          @Override
          public void onDisconnected(String channelId, String userId, Constants.ConnectionChangedReasonType reason) {
          }

          // Other event callbacks
      };
      agoraMediaRtcRecorder.registerRecorderEventHandler(eventHandler);
      // Subscribe to streams
      agoraMediaRtcRecorder.subscribeAllAudio();
      VideoSubscriptionOptions options = new VideoSubscriptionOptions();
      options.setEncodedFrameOnly(false);
      options.setType(Constants.VideoStreamType.VIDEO_STREAM_HIGH);
      agoraMediaRtcRecorder.subscribeAllVideo(options);

      // Set recording-related configurations
      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);
      // Join channel and start recording
      agoraMediaRtcRecorder.joinChannel(recorderConfig.getToken(),
                      recorderConfig.getChannelName(),
                      recorderConfig.getUserId());
      agoraMediaRtcRecorder.startRecording();

      // Stop recording, clean up resources, and leave channel
      agoraMediaRtcRecorder.unsubscribeAllAudio();
      agoraMediaRtcRecorder.unsubscribeAllVideo();
      agoraMediaRtcRecorder.stopRecording();
      agoraMediaRtcRecorder.unregisterRecorderEventHandler(eventHandler);
      agoraMediaRtcRecorder.leaveChannel();
      agoraMediaRtcRecorder.release();
      agoraService.release();
      ```
    </details>

    ## Test the project [#test-the-project-1]

    Agora provides an open source sample project on GitHub for your reference. Download or view the [Agora Recording Java SDK](https://github.com/AgoraIO-Extensions/Agora-Recording-Java-SDK) project for a more detailed example.

    Follow these steps to compile, configure, and run the Agora recording sample using the Spring Boot project.

    1. **Compile the project**

       Open a terminal and navigate to the `Examples-Mvn` directory. Run the following command to build the project:

       ```bash
       mvn clean package
       ```

       After the build completes successfully, the output JAR file appears in the `target/generated` directory as `agora-example.jar`.

    2. **Configure your App ID and token**

       In the `Examples-Mvn` directory, create a `.keys` file and add your Agora credentials:

       ```text
       appId=YOUR_APP_ID
       token=YOUR_TOKEN
       ```

       Replace `YOUR_APP_ID` and `YOUR_TOKEN` with your actual values.

    3. **Prepare native libraries**

       Ensure that the `libs/native/linux/x86_64/` directory contains the following `.so` files:

       * `libagora_rtc_sdk.so`
       * `librecording.so`
       * `libagora-fdkaac.so`
       * `libaosl.so`

       <CalloutContainer type="info">
         <CalloutDescription>
           These libraries must be available at runtime. If any are missing, the application will fail to load the native dependencies.
         </CalloutDescription>
       </CalloutContainer>

    4. **Run the sample application**

       From the `Examples-Mvn` directory, run the following command:

       ```bash
       LD_LIBRARY_PATH="$LD_LIBRARY_PATH:libs/native/linux/x86_64" \
       java -Dserver.port=18080 -jar target/agora-example.jar
       ```

       The Spring Boot server starts and listens on port `18080`. To use a different port, update the `-Dserver.port` parameter.

    5. **Start and stop a recording session**

       * **Start recording**

         Send an HTTP request to the following endpoint:

         ```text
         http://<your-server-ip>:18080/api/recording/start?configFileName=mix_stream_recorder_audio_video_water_marks.json
         ```

       * **Stop recording**

         Replace `<taskId>` with the value returned from the start response:

         ```text
         http://<your-server-ip>:18080/api/recording/stop?taskId=<taskId>
         ```

       <CalloutContainer type="info">
         <CalloutDescription>
           Place all configuration files (such as `mix_stream_recorder_audio_video_water_marks.json`) in the `Examples-Mvn/src/main/resources/` directory.
         </CalloutDescription>
       </CalloutContainer>

    ## Reference [#reference-1]

    This section contains content that completes the information on this page, or points you to documentation that explains other aspects to this product.

    ### API reference [#api-reference-1]

    * [`AgoraService`](/en/api-reference/api-ref/on-premise-recording#agoraservice)
    * [`AgoraServiceConfiguration`](/en/api-reference/api-ref/on-premise-recording#agoraserviceconfiguration)
    * [`LogConfig`](/en/api-reference/api-ref/on-premise-recording#logconfig)
    * [`initialize`](/en/api-reference/api-ref/on-premise-recording#initialize)
    * [`AgoraMediaRtcRecorder`](/en/api-reference/api-ref/on-premise-recording#agoramediartcrecorder)
    * [`registerRecorderEventHandler`](/en/api-reference/api-ref/on-premise-recording#registerrecordereventhandler)
    * [`subscribeAllAudio`](/en/api-reference/api-ref/on-premise-recording#subscribeallaudio)
    * [`subscribeAllVideo`](/en/api-reference/api-ref/on-premise-recording#subscribeallvideo)
    * [`setRecorderConfig`](/en/api-reference/api-ref/on-premise-recording#setrecorderconfig)
    * [`joinChannel`](/en/api-reference/api-ref/on-premise-recording#joinchannel)
    * [`startRecording`](/en/api-reference/api-ref/on-premise-recording#startrecording)
    * [`unsubscribeAllAudio`](/en/api-reference/api-ref/on-premise-recording#unsubscribeallaudio)
    * [`unsubscribeAllVideo`](/en/api-reference/api-ref/on-premise-recording#unsubscribeallvideo)
    * [`stopRecording`](/en/api-reference/api-ref/on-premise-recording#stoprecording)
    * [`unregisterRecorderEventHandler`](/en/api-reference/api-ref/on-premise-recording#unregisterrecordereventhandler)
    * [`leaveChannel`](/en/api-reference/api-ref/on-premise-recording#leavechannel)
    * [`release`](/en/api-reference/api-ref/on-premise-recording#release)

    <_PlatformProcessedMarker close="true" />
  </_PlatformPanel>
</_PlatformTabsGroup>
