Recording API

There is a new release of the Developer Center! If you'd like to check it out, please click  here

Recording API

C++ Interface Class description
IRecordingEngine The IRecordingEngine class provides the main methods that can be invoked by your application
IRecordingEngineEventHandler The IRecordingEngineEventHandler class enables callback event notifications to your application

IRecordingEngine

The IRecordingEngine class provides the main methods that can be invoked by your application. It consists of the following methods:

Create a Recording Engine (createAgoraRecordingEngine)

This method creates the Agora recording engine object.

public static IRecordingEngine* createAgoraRecordingEngine(const char * appId, IRecordingEngineEventHandler *eventHandler);
Name Description
appID App ID. For details, see Security Keys.
eventHandler The Agora Recording SDK notifies the application of its triggered events according to IRecordingEngineEventHandler.

Join a Channel (joinChannel)

This method allows the recording application to join a channel.

virtual int joinChannel(const char * token, const char *channelId, uid_t uid, const RecordingConfig &config) = 0;
Name Description
token
  • For low-security requirements, set it as NULL.
  • For high-security requirements, set it as Token. If an App Certificate is enabled, you must use a Token. For details, see Security Keys.
channelId Name of the channel: A string within 64 bytes.
uid User ID: a 32-bit unsigned integer ranging from 1 to (2^32-1) that is unique in a channel
config See the definition in the table below.
return value
  • 0: Method call succeeded.
  • < 0: Method call failed.

Note

  • The Recording SDK has requestToken and renewToken as private interfaces. Make sure that you set expireTimestamp as 0 when generating a Token, which means that the privilege, once generated, never expires.
  • A channel does not accept duplicate UIDs, otherwise there will be unpredictable behaviors.

The struct of RecordingConfig:

typedef struct RecordingConfig {
    bool isAudioOnly;
    bool isVideoOnly;
    bool isMixingEnabled;
    bool mixedVideoAudio;
    char * mixResolution;
    char * decryptionMode;
    char * secret;
    char * appliteDir;
    char * recordFileRootDir;
    char * cfgFilePath;
    agora::linuxsdk::VIDEO_FORMAT_TYPE decodeVideo;
    agora::linuxsdk::AUDIO_FORMAT_TYPE decodeAudio;
    int lowUdpPort;
    int highUdpPort;
    int idleLimitSec;
    int captureInterval;
    agora::linuxsdk::CHANNEL_PROFILE_TYPE channelProfile;
    agora::linuxsdk::REMOTE_VIDEO_STREAM_TYPE streamType;
    agora::linuxsdk::TRIGGER_MODE_TYPE triggerMode;
    agora::linuxsdk::LANGUAGE_TYPE lang;
    char * proxyserver;

    RecordingConfig(): channelProfile(agora::linuxsdk::CHANNEL_PROFILE_COMMUNICATION),
        isAudioOnly(false),
        isVideoOnly(false),
        isMixingEnabled(false),
        mixResolution(NULL),
        decryptionMode(NULL),
        secret(NULL),
        idleLimitSec(300),
        appliteDir(NULL),
        recordFileRootDir(NULL),
        cfgFilePath(NULL),
        lowUdpPort(0),
        highUdpPort(0),
        captureInterval(5),
        decodeAudio(agora::linuxsdk::AUDIO_FORMAT_DEFAULT_TYPE),
        decodeVideo(agora::linuxsdk::VIDEO_FORMAT_DEFAULT_TYPE),
        mixedVideoAudio(false),
        streamType(agora::linuxsdk::REMOTE_VIDEO_STREAM_HIGH),
        triggerMode(agora::linuxsdk::AUTOMATICALLY_MODE)
        proxyserver(NULL)
    {}

    virtual ~RecordingConfig() {}
 } RecordingConfig;
Name Description
channelProfile

Sets the channel mode:

  • CHANNEL_PROFILE_COMMUNICATION: Communication (default) mode, including one-to-one chat and group chat where any user in the channel can talk
  • CHANNEL_PROFILE_LIVE_BROADCAST: Live broadcast mode which contains two roles - host and viewer (enabled by calling setClientRole)
isAudioOnly

Sets whether to record audio only:

  • True: Enable audio recording only
  • False: Record both audio and video (default)
isVideoOnly

Sets whether to record video only:

  • True: Enable video recording only
  • False: Record both audio and video (default)
isMixingEnabled

Sets whether to enable audio-mixing or/and video-mixing mode:

  • False (default): Enable individual mode
  • True: Enable composite mode

If composite mode is enabled:

  • If isAudioOnly is true and isVideoOnly is false, this parameter sets to record audio only.
  • If isAudioOnly is false and isVideoOnly is true, this parameter sets to record video only.
  • If both isAudioOnly and isVideoOnly are false, this parameter sets to enable voice mixing and video mixing, that is, to record the audio and video of all uids respectively.
  • isVideoOnly and isVideoOnly cannot be set to true at the same time.
mixResolution [1] If you have enabled the video mixing mode, this parameter sets the resolution in format: width, height, fps, and kbps, representing the width, height, frame rate, and bitrate of the video stream.
decryptionMode

When the whole channel is encrypted, the recording SDK uses this parameter to enable the built-in decryption function:

  • “aes-128-xts”: AES-128, XTS mode
  • “aes-128-ecb”: AES-128, ECB mode
  • “aes-256-xts”: AES-256, XTS mode
secret (Default: NULL) The decryption password when decryption mode is enabled.
idleLimitSec If the user calls leaveChannel() to stop recording, then the recording file ends with a period of silence which is decided by the value set for this parameter. The value must be no less than three seconds, and the default value is 300 seconds.
appliteDir (Default: NULL) The directory to store the Linux SDK built-in applite application.
recordFilrRootDir (Default: NULL) The root directory to store the recording files. Do not set recordFileRootDir and cfgFilePath at the same time.
cfgFilePath (Default: NULL) The path of the configuration file. In this configuration file, you can set the absolute path of the recording file, and the content in the configuration file must be in JSON format. Do not set recordFileRootDir and cfgFilePath at the same time. For example, {“Recording_Dir” :”<recording path>”}, where Recording_Dir is fixed
lowUdpPort (Default: 0) The lowest UDP port. Ensure the value of highUdpPort - lowUdpPort is no less than 4.
highUdpPort (Default: 0) The highest UDP port. Ensure the value of highUdpPort - lowUdpPort is no less than 4.
captureInterval Time interval for the screen capture that ranges from one second to five seconds. Need to be used with decodeVideo = 3/4 when joining the channel. See details at Join a Channel (joinChannel).
decodeAudio [2]
  • AUDIO_FORMAT_DEFAULT_TYPE = 0: Default audio format
  • AUDIO_FORMAT_AAC_FRAME_TYPE = 1: AAC format
  • AUDIO_FORMAT_PCM_FRAME_TYPE = 2: PCM format
  • AUDIO_FORMAT_MIXED_PCM_FRAME_TYPE = 3: PCM audio-mixing format
decodeVideo [2]
  • VIDEO_FORMAT_DEFAULT_TYPE = 0: Default video format
  • VIDEO_FORMAT_H264_FRAME_TYPE = 1: H.264 format
  • VIDEO_FORMAT_YUV_FRAME_TYPE = 2: YUV format
  • VIDEO_FORMAT_JPG_FRAME_TYPE = 3: JPG format
  • VIDEO_FORMAT_JPG_FILE_TYPE = 4: JPG file format
  • VIDEO_FORMAT_JPG_VIDEO_FILE_TYPE = 5: JPG + video file format
mixedVideoAudio

If you have set isMixingEnabled as true, this parameter allows you to mix audio and video in real time:

  • False: Mix audio and video respectively (default)
  • True: Mix audio and video in real time into an MP4 file. See the table below for the supported players.
streamType This parameter takes effect only when the Agora Native SDK has enabled dual-stream mode (high stream by default).
triggerMode

Choose to record automatically or manually upon joining the channel. If you wish to call startRecording and stopRecording, then choose manually.

  • 0: automatically
  • 1: manually
proxyserver You can set the parameter to record the content with intranet server. For details, please contact sales@agora.io .

Footnotes

[1]The isAudioOnly and isVideoOnly parameters are disabled by default, and do not set isAudioOnly and isVideoOnly as true at the same time.
[2](1, 2) Once the raw data is enabled, video mixing is not supported. The Web currently supports raw audio data but not raw video data.

Video Profile for Communication:

Video Profile for Live Broadcast:

Supported Players:

Platform Player mixedVideoAudio=false mixedVideoAudio=true
Linux Default Player Supported Supported
Linux VLC Media Player Supported Supported
Linux ffplay Supported Supported
Windows Media Player Supported Audio Supported
Windows KMPlayer Supported Supported
Windows VLC Player Supported Supported
macOS QuickTime Player Supported Audio Supported
macOS Movist Supported Supported
macOS MPlayerX Supported Supported
macOS KMPlayer Do not Support Do not Support
iOS iOS Default Player Supported Audio Supported
iOS VLC Do not Support Do not Support
iOS KMPlayer Supported Audio Supported
Android Android Default Player Supported Audio Supported
Android MXPlayer Supported Audio Supported
Android VLC for Android Supported Supported
Android KMPlayer Supported Supported

Set the Video Mixing Layout (setVideoMixingLayout)

This method sets the video mixing layout.

virtual int setVideoMixingLayout(const agora::linuxsdk::VideoMixingLayout &layout) = 0;

The struct of VideoMixingLayout:

 typedef struct VideoMixingLayout
 {
     struct Region {
       uid_t uid;
       double x;//[0,1]
       double y;//[0,1]
       double width;//[0,1]
       double height;//[0,1]
       int zOrder; //Optional, [0, 100] //0 (Default): Min, 100: Max

       //  Optional
       //  [0, 1.0] Where 0 = transparent, 1.0 = opaque
       double alpha;

       int renderMode;//RENDER_MODE_HIDDEN: Crop, RENDER_MODE_FIT: Zoom to fit
       Region()
           :uid(0)
            , x(0)
            , y(0)
            , width(0)
            , height(0)
            , zOrder(0)
            , alpha(1.0)
            , renderMode(1)
      {}

   };
   int canvasWidth;
   int canvasHeight;
   const char* backgroundColor;//e.g. "#C0C0C0" in RGB
   uint32_t regionCount;
   const Region* regions;
   const char* appData;
   int appDataLength;
   VideoMixingLayout()
       :canvasWidth(0)
        , canvasHeight(0)
        , backgroundColor(NULL)
        , regionCount(0)
        , regions(NULL)
        , appData(NULL)
        , appDataLength(0)
   {}
} VideoMixingLayout;
Name Description
canvasWidth Width of the entire canvas (the display window or screen).
canvasHeight Height of the entire canvas (the display window or screen).
backgroundColor The background color of the canvas (the display window or screen). Enter any of the 6-digit symbols defined in RGB.
regions

The user list of VideoMixingLayout. Each host in the channel has a region to display the video on the screen with the following parameters to be set:

  • uid: UID of the user whose video is displayed in the region.
  • x[0.0,1.0]: Horizontal position of the region on the screen.
  • y[0.0,1.0]: Vertical position of the region on the screen.
  • width[0.0,1.0]: Actual width of the region.
  • height[0.0,1.0]: Actual height of the region.
  • zOrder[0, 100】: The layer of the picture: 0 means the bottom layer, and 100 means the top layer.
  • alpha[0.0, 1.0]: The transparency of the image: 0 means transparent, and 1 means opaque.
  • renderMode:
    • RENDER_MODE_HIDDEN(1): Cropped
    • RENDER_MODE_FIT(2): Proportionate
appData Data that defines the application.
Return value
  • 0: Method call succeeded
  • < 0: Method call failed

Here is an example to show the position and size of the host’s head portrait:

../_images/sei_overview.png

Leave the Channel (leaveChannel)

This method allows the recording application to leave the channel and release thread resources.

virtual int leaveChannel() = 0;
Return value
  • 0: Method call succeeded
  • < 0: Method call failed

Release the IRecordingEngine Object (release)

This method releases the IRecordingEngine object.

virtual int release() = 0;
Return value
  • 0: Method call succeeded
  • < 0: Method call failed

Get the Properties (getProperties)

This method allows you to get a series of recording properties. For example, you can get the recording path immediately after the recording has started, even before joining a channel. This method differs from onUserJoined in that onUserJoined returns you the recording path only after you have joined the channel.

virtual const RecordingEngineProperties* getProperties() = 0;

Start the Recording (startService)

This method manually starts recording. A prerequisite for calling this method is that you need to set triggermode to manually when joining the channel. For more information, see Join a Channel (joinChannel) about triggerMode.

virtual int startService() = 0;
Return value
  • 0: Method call succeeded
  • < 0: Method call failed

Stop the Recording (stopService)

This method manually stops recording. A prerequisite for calling this method is that you need to set triggermode to manually when joining the channel. For more information, see Join a Channel (joinChannel) about triggerMode.

virtual int stopService() = 0;
Return value
  • 0: Method call succeeded
  • < 0: Method call failed

IRecordingEngineEventHandler Class

The IRecordingEngineEventHandler class provides callback methods for the recording engine. It consists of the following callbacks:

Error Reported Callback (onError)

This callback indicates that an error occurred during SDK runtime. The SDK cannot fix the issue and resume running, and requires intervention from the application and informs the user on the issue.

virtual void onError(int error, agora::linuxsdk::STAT_CODE_TYPE stat_code) = 0;
Name Description
error

Error codes:

  • ERR_OK = 0: No error.
  • ERR_FAILED = 1: General error (the reason is not specifically classified).
  • ERR_INVALID_ARGUMENT = 2: Invalid parameter called. For example, the specific channel name includes illegal characters.
  • ERR_INTERNAL_FAILED = 3: Internal error.
stat_code

State codes:

  • STAT_OK = 0: Everything is normal.
  • STAT_ERR_FROM_ENGINE = 1: Error from the engine.
  • STAT_ERR_ARS_JOIN_CHANNEL = 2: Failure to join the channel.
  • STAT_ERR_CREATE_PROCESS = 3: Failure to create a process.
  • STAT_ERR_MIXED_INVALID_VIDEO_PARAM = 4: Failure to mix video.
  • STAT_ERR_NULL_POINTER = 5: Null pointer.
  • STAT_ERR_PROXY_SERVER_INVALID_PARAM = 6: Invalid parameters of the proxy server.
  • STAT_POLL_ERR = 0x8: Error in polling.
  • STAT_POLL_HANG_UP = 0x10: Polling hangs up.
  • STAT_POLL_NVAL = 0x20: Invalid polling request.
enum ERROR_CODE_TYPE {
    ERR_OK = 0,
    //1~1000
    ERR_FAILED = 1,
    ERR_INVALID_ARGUMENT = 2,
    ERR_INTERNAL_FAILED = 3,
};

enum STAT_CODE_TYPE {
    STAT_OK = 0,
    STAT_ERR_FROM_ENGINE = 1,
    STAT_ERR_ARS_JOIN_CHANNEL = 2,
    STAT_ERR_CREATE_PROCESS = 3,
    STAT_ERR_MIXED_INVALID_VIDEO_PARAM = 4,
    STAT_ERR_NULL_POINTER = 5,
    STAT_ERR_PROXY_SERVER_INVALID_PARAM = 6,

    STAT_POLL_ERR = 0x8,
    STAT_POLL_HANG_UP = 0x10,
    STAT_POLL_NVAL = 0x20,
};

Warning Reported Callback (onWarning)

This callback indicates that some warning occurred during SDK runtime. In most cases, the application can ignore the warnings reported by the SDK because the SDK can usually fix the issue and resume running.

virtual void onWarning(int warn) = 0;
Name Description
warn

Warning codes:

  • WARN_NO_AVAILABLE_CHANNEL = 103: No available channel resource, probably because the server cannot allocate any channel resource.
  • WARN_LOOKUP_CHANNEL_TIMEOUT = 104: Timeout for the SDK looking for the specified channel before joining it, generally due to poor network connections.
  • WARN_LOOKUP_CHANNEL_REJECTED = 105: The request for finding the channel has been rejected, probably because the server cannot handle this request or this request is illegal.
  • WARN_OPEN_CHANNEL_TIMEOUT = 106: Timeout for the SDK opening the channel after finding it, generally due to poor network connections.
  • WARN_OPEN_CHANNEL_REJECTED = 107: The request for opening the channel has been rejected, probably because the server cannot handle this request or this request is illegal.

Join the Channel Callback (onJoinChannelSuccess)

This callback indicates that the user has successfully joined the specified channel.

virtual void onJoinChannelSuccess(const char * channelId, uid_t uid) = 0;
Name Description
channelId Channel ID assigned based on the channel name specified in the joinChannel() API.
uid User ID as specified in the joinChannel() method; if no uid is previously assigned, the Agora server automatically assigns a uid.

Leave the Channel Callback (onLeaveChannel)

This callback indicates that the SDK has successfully left the channel.

virtual void onLeaveChannel(agora::linuxsdk::LEAVE_PATH_CODE code) = 0;
 enum LEAVE_PATH_CODE {
   LEAVE_CODE_INIT = 0,
   LEAVE_CODE_SIG = 1<<1,
   LEAVE_CODE_NO_USERS = 1<<2,
   LEAVE_CODE_TIMER_CATCH = 1<<3,
   LEAVE_CODE_CLIENT_LEAVE = 1 << 4,
};

Other User Joined the Channel Callback (onUserJoined)

This callback indicates that another user has joined the channel. If some other user is already in the channel, the SDK reports to the app on these users as well.

virtual void onUserJoined(uid_t uid, agora::linuxsdk::UserJoinInfos &infos) = 0;
typedef struct UserJoinInfos {
    const char* storageDir;
    //new attached info add below

    UserJoinInfos():
        storageDir(NULL)
    {}
}UserJoinInfos;


}
}
Name Description
uid User ID as specified in the joinChannel() method; if no uid is previously assigned, the Agora server automatically assigns a uid.
recordingDir Directory of the recorded files.

Other User Offline Callback (onUserOffline)

This callback notifies the application that a user has left the channel or gone offline.

The SDK determines that a user has left the channel (or gone offline) based on the time interval (15 seconds) during which no data package from this user is received.

False detections may occur due to poor network connections, and Agora recommends using signaling for more reliable offline detection.

virtual void onUserOffline(uid_t uid, agora::linuxsdk::USER_OFFLINE_REASON_TYPE reason) = 0;
Name Description
uid User ID as specified in the joinChannel() method; if no uid is previously assigned, the Agora server automatically assigns a uid.
reason

Reasons for the user gone offline:

  • USER_OFFLINE_QUIT = 0: The user has quit the channel.
  • USER_OFFLINE_DROPPED = 1: The user dropped offline because the SDK has received no data package from this user for a period of time.
  • USER_OFFLINE_BECOME_AUDIENCE = 2: This is triggered when the host is switched to the audience role; applicable only if you have set the channel profile as live broadcast when calling joinChannel().

Raw Audio Data Received Callback (audioFrameReceived)

This callback is triggered when raw audio data is received.

virtual void audioFrameReceived(unsigned int uid, const agora::linuxsdk::AudioFrame *frame) const = 0;
Name Description
uid User ID as specified in the joinChannel() method; if no uid is previously assigned, the Agora server automatically assigns a uid.
frame Received raw audio data in PCM or AAC format.
struct AudioFrame {
    AUDIO_FRAME_TYPE type;
    union {
        AudioPcmFrame *pcm;
        AudioAacFrame *aac;
    } frame;

    AudioFrame();
    ~AudioFrame();

    MEMORY_TYPE mType;
};

AudioPcmFrame

The struct of the received raw audio data in PCM format:

class AudioPcmFrame {
    friend class IEngine;
    public:
    AudioPcmFrame(uint_t frame_ms, uint_t sample_rates, uint_t samples);
    ~AudioPcmFrame();
    public:
    uint_t frame_ms_;
    uint_t channels_; // 1
    uint_t sample_bits_; // 16
    uint_t sample_rates_; // 8k, 16k, 32k
    uint_t samples_;

    uchar_t *pcmBuf_;
    uint_t pcmBufSize_;

//    private:
    std::string buf_; // samples * sample_bits_ / CHAR_BIT * channels_
};
Name Description
frame_ms Timestamp of the frame.
channels Number of audio channels.
sample_bits Width of the sampling data.
sample_rates Sampling rate.
samples Number of samples.
pcmBuf Audio frame buffer.
pcmBufSize Size of the audio frame buffer.

AudioAacFrame

The struct of the received audio file in AAC format:

class AudioAacFrame {
    friend class IEngine;
    public:
    explicit AudioAacFrame(uint_t frame_ms);
    ~AudioAacFrame();

    uchar_t *aacBuf_;
    uint_t frame_ms_;
    uint_t aacBufSize_;
//    private:
    std::string buf_;
};
Name Description
frame_ms Timestamp of this frame
aacBuf Audio frame buffer
aacBufSize Size of the audio frame buffer

Raw Video Data Received Callback (videoFrameReceived)

This callback is triggered when the raw video data is received. Since we have callbacks for every frame of the video, you can also detect sexually explicit content, if necessary.

Agora recommends that you capture the i frame only and neglect the others. Set the capture interval according to your needs. Each captured data is a screenshot that determines whether there is any sensitive content.

virtual void videoFrameReceived(unsigned int uid, const agora::linuxsdk::VideoFrame *frame) const = 0;
Name Description
uid User ID as specified in the joinChannel() method; if no uid is previously assigned, the Agora server automatically assigns a uid.
frame Received video data in YUV, H264, or JPG format.
struct VideoFrame {
    VIDEO_FRAME_TYPE type;
    union {
        VideoYuvFrame *yuv;
        VideoH264Frame *h264;
        VideoJpgFrame *jpg;
    } frame;

    int rotation_; // 0, 90, 180, 270
    VideoFrame();
    ~VideoFrame();

    MEMORY_TYPE mType;
};

VideoYuvFrame

The struct of the raw video data in YUV format:

class VideoYuvFrame {
    friend class IEngine;
    public:
    VideoYuvFrame(uint_t frame_ms, uint_t width, uint_t height, uint_t ystride,
            uint_t ustride, uint_t vstride);
    ~VideoYuvFrame();

    uint_t frame_ms_;

    uchar_t *ybuf_;
    uchar_t *ubuf_;
    uchar_t *vbuf_;

    uint_t width_;
    uint_t height_;

    uint_t ystride_;
    uint_t ustride_;
    uint_t vstride_;

    //all
    uchar_t *buf_;
    uint_t bufSize_;


};
Name Description
frame_ms Timestamp of the frame.
ybuf Y buffer pointer.
ubuf U buffer pointer.
vbuf V buffer pointer.
width Width of the video pixel.
height Height of the video pixel.
ystride Line span of the Y buffer.
ustride Line span of the U buffer.
vstride Line span of the V buffer.
buf Video frame buffer.
bufSize Size of the video frame buffer.

VideoH264Frame

The struct of the video data in H.264 format:

struct VideoH264Frame {
    friend class IEngine;
    public:
    VideoH264Frame():
        frame_ms_(0),
        frame_num_(0),
        buf_(NULL),
        bufSize_(0)
    {}

    ~VideoH264Frame(){}
    uint_t frame_ms_;
    uint_t frame_num_;

    //all
    uchar_t *buf_;
    uint_t bufSize_;


};
Name Description
frame_ms Timestamp of the frame.
buf Video frame buffer.
bufSize Size of the video frame buffer.

VideoJpgFrame

The struct of the video data in JPG format:

struct VideoJpgFrame {
    friend class IEngine;

    public:
    VideoJpgFrame():
        frame_ms_(0),
        buf_(NULL),
        bufSize_(0){}

   ~VideoJpgFrame() {}
    uint_t frame_ms_;

    //all
    uchar_t *buf_;
    uint_t bufSize_;


};
Name Description
frame_ms Timestamp of the frame.
buf Video frame buffer.
bufSize Size of the video frame buffer.
Is this page helpful?