Recording API

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:

Creating Recording Engine (createAgoraRecordingEngine)

public static IRecordingEngine* createAgoraRecordingEngine(const char * appId, IRecordingEngineEventHandler *eventHandler);

This method creates the Agora recording engine object.

Name Description
appID App ID. For details, see Security Keys
eventHandler Agora Recording SDK notifies the application of its triggered events according to IRecordingEngineEventHandler

Joining a Channel (joinChannel)

virtual int joinChannel(const char * token, const char *channelId, uid_t uid, const RecordingConfig &config) = 0;

This method lets the recording application join the channel.

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, refer to Security Keys
channelId Name of the channel: a string within 64 bytes that works as the only identifier of the channel
uid User ID: a 32-bit unsigned integer ranging from 1 to (2^32-1) that is different from any other ID
config See detailed definition in the table below
return value
  • 0: Method call succeeded
  • < 0: Method call failed

Note

The current Recording SDK has requestToken and renewToken as private interfaces. Make sure that you set the expireTimestamp as 0 when generating a Token, which means that the privilege, once generated, never expires.

The following shows the structure 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;

    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)
    {}

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

It 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 [1]

It sets whether to record audio only:

  • true: enable audio recording only
  • false: record both audio and video (default)
isVideoOnly [1]

It sets whether to record video only:

  • true: enable video recording only
  • false: record both audio and video (default)
mixResolution [2] If you have enabled the video mixing mode, this parameter sets the resolution in format width, high, fps, kbps, representing the width, height, framerate and bitrate of the video stream
isMixingEnabled

It sets whether to enable audio-mixing or/and video-mixing mode. The parameters are disabled by default:

  • If isAudioOnly is enabled, this parameter sets whether to enble audio mixing
  • If isAudioOnly is disabled, this parameter sets whether to enable audio mixing and video mixing respectively
  • If isVideoOnly is enabled, this parameter sets whether to enable video mixing
  • If isVideoOnly is disabled, this parameter sets whether to enable audio mixing and video mixing respectively
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 The decryption password in case you have enabled the decryotion mode
mixedVideoAudio

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

  • false: mix audio and video respectively (default)
  • true: mix audio and video in realtime into an mp4 file. See the table below for supported players
idleLimitSec [3] 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 3 seconds, and the default value is 300 seconds
captureInterval The time interval for screen capture that ranges from 1 second to 5 seconds. Need to be used with decodeVideo = 3/4 when joining the channel. See details at Joining a Channel (joinChannel)
streamType This parameter takes effect only when the Agora Native SDK has enabled the 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 as you wish, then choose manually

  • 0: automatically
  • 1: manually
appliteDir It sets the directory to store the Linux SDK built-in applite application
recordFilrRootDir [4] It sets the root directory to store the recording files
cfgFilePath [4] It sets 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 For example, {“Recording_Dir” :”<recording path>”}, where Recording_Dir is fixed
lowUdpPort [5] It sets the lowest UDP port
highUdpPort [5] It sets the highest UDP port
decodeAudio [6]
  • 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 [6]
  • 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

Footnotes

[1](1, 2) Parameters isAudioOnly and isVideoOnly are disabled by default, and do not set isAudioOnly and isVideoOnly as true at the same time.
[2]For recommended mixed resolution, see the table below.
[3]Parameter idleLimitSec is 300 seconds by default. Set this value no less than 3 seconds.
[4](1, 2) Do not set recordFileRootDir and cfgFilePath at the same time.
[5](1, 2) Make sure that all ports are positive intergers, and the value of highUdpPort - lowUdpPort be no less than 4.
[6](1, 2) Once raw data is enabled, video mixing is not supported. Web currently supports audio raw data but not video.

Video Profile for Communication:

Resolution FPS MinBR MaxBR Recommended
3840x2160 15 3000 9000 6000
2560x1440 15 1600 4800 3200
1920x1080 15 1000 3000 2000
1280x720 15 600 1800 1200
960x720 15 480 1440 960
848x480 15 300 900 600
640x480 15 250 750 500
480x480 15 200 600 400
640x360 15 200 600 400
360x360 15 130 390 260
424x240 15 110 330 220
320x240 15 90 270 180
240x240 15 70 210 140
320x180 15 70 210 140
240x180 15 60 180 120
180x180 15 50 150 100
160x120 15 30 90 60
120x120 15 25 75 50

Video Profile for Live Broadcast:

Resolution FPS MinBR MaxBR Recommended
3840x2160 15 6000 18000 12000
2560x1440 15 3200 9600 6400
1920x1080 15 2000 6000 4000
1280x720 15 1200 3600 2400
960x720 15 960 2880 1920
848x480 15 600 1800 1200
640x480 15 500 1500 1000
480x480 15 400 1200 800
640x360 15 400 1200 800
360x360 15 260 780 520
424x240 15 220 660 440
320x240 15 180 540 360
240x240 15 140 420 280
320x180 15 140 420 280
240x180 15 120 360 240
180x180 15 100 300 200
160x120 15 60 180 120
120x120 15 50 150 100

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

Setting Video Mixing Layout (setVideoMixingLayout)

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

This method sets the video mixing layout. See below for 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): bottom most, 100: top most

       //  Optional
       //  [0, 1.0] where 0 denotes throughly 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]: the horizontal position of the region on the screen
    • y[0.0,1.0]: the vertical position of the region on the screen
    • width[0.0,1.0]: the actual width of the region
    • height[0.0,0.1]: the actual height of the region
  • zOrder[0, 100】: defines the layer of the picture: 0 means the bottom layer, and 100 means the top
  • alpha[0.0, 1.0]: defines 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

Leaving the Channel (leaveChannel)

virtual int leaveChannel() = 0;

The recording application leaves the channel and releases the occupied thread resources.

Return value
  • 0: Method call succeeded
  • < 0: Method call failed

Releasing the IRecordingEngine Object (release)

virtual int release() = 0;

This method releases the IRecordingEngine object.

Return value
  • 0: Method call succeeded
  • < 0: Method call failed

Getting Properties (getProperties)

virtual const RecordingEngineProperties* getProperties() = 0;

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

Starting recording (startService)

virtual int startService() = 0;

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

Return value
  • 0: Method call succeeded
  • < 0: Method call failed

Stopping recording (stopService)

virtual int stopService() = 0;

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

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)

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

This callback indicates that an error occurred during the runtime of the SDK. In most cases reporting an error means that the SDK cannot fix the issue and resume running, and therefore requires interventions from the application or informs the user on the issue.

Name Description
error

The 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 mane includes illegal characters
  • ERR_INTERNAL_FAILED = 3: Internal error
stat_code

The 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_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_POLL_ERR = 0x8,
    STAT_POLL_HANG_UP = 0x10,
    STAT_POLL_NVAL = 0x20,
};

Warning Reported Callback (onWarning)

virtual void onWarning(int warn) = 0;

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

Name Description
warn

Warning code:

  • WARN_NO_AVAILABLE_CHANNEL = 103: No available channel resource, probably because the server cannot allocate channel resource
  • WARN_LOOKUP_CHANNEL_TIMEOUT = 104: Time out for the SDK looking for the specified channel before joining it, generally due to poor network connection
  • 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: Time out for the SDK opening the channel after finding it, generally due to poor network connection
  • 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 Channel Callback (onJoinChannelSuccess)

virtual void onJoinChannelSuccess(const char * channelId, uid_t uid) = 0;

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

Name Description
channelId The channel ID assigned based on the channel name specified in the joinChannel() API
uid The User ID as specified in the joinChannel() method; if no such uid has been previously assigned, the Agora server allocates an ID automatically

Leave Channel Callback (onLeaveChannel)

virtual void onLeaveChannel(agora::linuxsdk::LEAVE_PATH_CODE code) = 0;

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

 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 Channel Callback (onUserJoined)

virtual void onUserJoined(uid_t uid, agora::linuxsdk::UserJoinInfos &infos) = 0;

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

typedef struct UserJoinInfos {
    const char* storageDir;
    //new attached info add below

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


}
}
Name Description
uid The User ID as specified in the joinChannel() method; if no such uid has been previously assigned, the Agora server allocates an ID automatically
recordingDir The directory of the recorded files

Other User Offline Callback (onUserOffline)

virtual void onUserOffline(uid_t uid, agora::linuxsdk::USER_OFFLINE_REASON_TYPE reason) = 0;

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

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

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

Name Description
uid The User ID as specified in the joinChannel() method; if no such uid has been previously assigned, the Agora server allocates an ID automatically
reason

Reasons for user gone offline:

  • USER_OFFLINE_QUIT = 0: The user has quit the channel
  • USER_OFFLINE_DROPPED = 1: The user drops offline because the SDK has received no data package of this user for too long [7]
  • USER_OFFLINE_BECOME_AUDIENCE = 2: It 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()

Footnotes

[7]Considering the unreliable channel, the SDK can also mistake a user quitting the channel for gone offline because it has not received the user’s offline message.

Audio Raw Data Received Callback (audioFrameReceived)

virtual void audioFrameReceived(unsigned int uid, const agora::linuxsdk::AudioFrame *frame) const = 0;

This callback is triggered when the audio raw data is received.

Name Description
uid The User ID as specified in the joinChannel() method; if no such uid has been previously assigned, the Agora server allocates an ID automatically
frame The received audio raw data on pcm or aac format
struct AudioFrame {
    AUDIO_FRAME_TYPE type;
    union {
        AudioPcmFrame *pcm;
        AudioAacFrame *aac;
    } frame;

    AudioFrame();
    ~AudioFrame();

    MEMORY_TYPE mType;
};

AudioPcmFrame

See below for the struct of the received audio raw 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 The timestamp of the frame
channels The number of the sound channels
sample_bits The sampling data width
sample_rates The sampling rate
samples The number of samples
pcmBuf The audio frame buffer
pcmBufSize The size of the audio frame buffer

AudioAacFrame

See below for 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_;
};
名称 描述
frame_ms The timestamp of this frame
aacBuf The audio frame buffer
aacBufSize The size of the audio frame buffer

Video Raw Data Received Callback (videoFrameReceived)

virtual void videoFrameReceived(unsigned int uid, const agora::linuxsdk::VideoFrame *frame) const = 0;

This callback is triggered when the video raw data is received. And since we have callback for every frame of the video, you can also conduct pornography detection if necessary.

Agora recommends that you capture the i frame only and neglect the rest. Set the capture interval to suit your needs: each captured data means screenshot from which you can tell if it contains sensitive contents.

Name Description
uid The User ID as specified in the joinChannel() method; if no such uid has been previously assigned, the Agora server allocates an ID automatically
frame The received video data in YUV, H264 or JPG
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

See below for the struct of the video raw data in the 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 The timestamp of the frame
ybuf Pointer to the Y buffer pointer in the YUV data
ubuf Pointer to the U buffer pointer in the YUV data
vbuf Pointer to the V buffer pointer in the YUV data
width Video pixel width
height Video pixel height
ystride Line span of Y buffer in YUV data
ustride Line span of U buffer in YUV data
vstride Line span of V buffer in YUV data
buf The video frame buffer
bufSize The size of the video frame buffer

VideoH264Frame

See below for 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 The timestamp of the frame
buf The video frame buffer
bufSize The size of the video frame buffer

VideoJpgFrame

See below for 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 The timestamp of the frame
buf The video fram buffer
bufSize The size of the video frame buffer
Is this page helpful?