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)
- Joining a Channel (joinChannel)
- Setting Video Mixing Layout (setVideoMixingLayout)
- Leaving the Channel (leaveChannel)
- Releasing the IRecordingEngine Object (release)
- Getting Properties (getProperties)
- Starting Recording (startService)
- Stopping Recording (stopService)
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 |
|
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 |
|
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:
|
isAudioOnly [1] | It sets whether to record audio only:
|
isVideoOnly [1] | It sets whether to record video only:
|
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:
|
decryptionMode | When the whole channel is encrypted, the recording SDK uses this parameter to enable the built-in decryption function:
|
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:
|
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
|
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] |
|
decodeVideo [6] |
|
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:
|
appData | Data that defines the application |
Return value |
|
Here is an example to show the position and size of the host’s head portrait:

Leaving the Channel (leaveChannel)¶
virtual int leaveChannel() = 0;
The recording application leaves the channel and releases the occupied thread resources.
Return value |
|
Releasing the IRecordingEngine Object (release)¶
virtual int release() = 0;
This method releases the IRecordingEngine object.
Return value |
|
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 |
|
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 |
|
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 Channel Callback (onJoinChannelSuccess)
- Leave Channel Callback (onLeaveChannel)
- Other User Joined Channel Callback (onUserJoined)
- Other User Offline Callback (onUserOffline)
- Audio Raw Data Received Callback (audioFrameReceived)
- Video Raw Data Received Callback (videoFrameReceived)
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:
|
stat_code | The 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_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:
|
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:
|
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 |