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)
- Join a Channel (joinChannel)
- Set the Video Mixing Layout (setVideoMixingLayout)
- Leave the Channel (leaveChannel)
- Release the IRecordingEngine Object (release)
- Get the Properties (getProperties)
- Start the Recording (startService)
- Stop the Recording (stopService)
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 |
|
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 |
|
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:
|
isAudioOnly | Sets whether to record audio only:
|
isVideoOnly | Sets whether to record video only:
|
isMixingEnabled | Sets whether to enable audio-mixing or/and video-mixing mode:
If composite mode is enabled:
|
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:
|
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] |
|
decodeVideo [2] |
|
mixedVideoAudio | If you have set isMixingEnabled as true, this parameter allows you to mix audio and video in real time:
|
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.
|
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:
|
appData | Data that defines the application. |
Return value |
|
Here is an example to show the position and size of the host’s head portrait:

Leave the Channel (leaveChannel)¶
This method allows the recording application to leave the channel and release thread resources.
virtual int leaveChannel() = 0;
Return value |
|
Release the IRecordingEngine Object (release)¶
This method releases the IRecordingEngine object.
virtual int release() = 0;
Return value |
|
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 |
|
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 |
|
IRecordingEngineEventHandler Class¶
The IRecordingEngineEventHandler class provides callback methods for the recording engine. It consists of the following callbacks:
- Error Reported Callback (onError)
- Warning Reported Callback (onWarning)
- Join the Channel Callback (onJoinChannelSuccess)
- Leave the Channel Callback (onLeaveChannel)
- Other User Joined the Channel Callback (onUserJoined)
- Other User Offline Callback (onUserOffline)
- Raw Audio Data Received Callback (audioFrameReceived)
- Raw Video Data Received Callback (videoFrameReceived)
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:
|
stat_code | State codes:
|
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:
|
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:
|
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. |