Skip to main content

Video screenshot upload

To meet the needs of video content supervision, Agora Video SDK enables you to take screenshots of the video stream in a channel and then upload these images to third-party cloud storage.

Understand the tech

When you enable screenshot upload, you set the interval between screenshots. After each interval Video SDK takes a screenshot of the video stream sent by local users, and uploads the image to Agora SD-RTN™. Agora SD-RTN™ uploads each screenshot to your third-party cloud storage and sends a callback notification to your server in the form of an HTTPS request.


In order to follow this procedure you must have:

  • Android Studio 4.1 or higher.
  • Android SDK API Level 24 or higher.
  • A mobile device that runs Android 4.1 or higher.
  • An Agora account and project.

  • A computer with Internet access.

    Ensure that no firewall is blocking your network communication.

Project setup

Take the following steps to set up your project for screenshot upload:

  • Configure a third-party cloud storage account for storing screenshots.

  • Implement a webhook to receive HTTP message notifications from Agora SD-RTN™.

  • Take the following steps to enable and configure the Agora video screenshot upload service:

    • In Agora Console, go to the Project Management tab and click Configure against the project for which you want to enable Video screenshot upload.

    • On the configuration page, find Video screenshot upload and select Enable. You see the Video Screenshot Upload Configuration page.

    • On the configuration page, fill in the following information:

      • Callback Url: The URL where your webhook receives and handles incoming notifications.
      • Storage: The name of your cloud storage service.
      • Region: The geographical location of the data center where the storage is located.
      • Access key: The key used to authenticate and access the storage service.
      • Secret key: A secure key paired with the access key for secure access.
      • Bucket name: Name of the bucket for storing files within the storage service.
      • Endpoint: The URL to access the storage service.
      • Filename prefix: A string added to the beginning of file names.

  • Add the Video screenshot and upload dynamic library to your project.

Implement screenshot upload

You call the enableContentInspect method to enable the video screenshot upload function, and set the type in ContentInspectConfig to CONTENT_INSPECT_TYPE_SUPERVISE. After the video screenshot upload function is successfully enabled, your app takes screenshots according to the frequency specified by the interval and uploads the screenshots to your third-party storage. The sample code is as follows:

fun startSrcreenshotUpload() {
val config = ContentInspectConfig()
config.extraInfo = "YourExtraInfo"
config.moduleCount = 1
config.modules[0].type = ContentInspectConfig.CONTENT_INSPECT_TYPE_SUPERVISE
// Set the upload frequency of screenshots in seconds
config.modules[0].interval = 5
// Enable screenshot upload
agoraEngine!!.enableContentInspect(true, config)


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

Video screenshot upload dynamic library

For details about the Video screenshot upload dynamic library and the increase in size of the integrated app for each architecture, see App size optimization.

HTTP message notification

After a screenshot is successfully uploaded to Agora SD-RTN™, the Agora service sends a message notification callback to your application server in the form of an HTTPS POST request. The data format is JSON, and the character encoding is UTF-8.

After receiving a message notification, your application server responds with a status code of 200. The response packet body format is JSON. Agora considers the notification to have failed under any of the following circumstances:

  • The Agora service does not receive a response from your server within 5 seconds after sending the message notification.

  • The HTTP status code of the response is not 200, or the response body format is not JSON.

The Agora service retries immediately after the first notification failure, and sends a message notification again. It makes a total of three notification attempts.

HTTP Request

Request header

Field namevalue

Request body

The request body is a JSON Object that contains the following fields:

requestIdStringCallback notification ID that identifies an event notification from the Agora server.
callbackParamJSON ObjectCustomize the incoming fields in the callback. Currently only includes the cname field, which is the channel name.
callbackDataStringThe string data transmitted by the SDK video screenshot upload module.
checksumStringThe MD5 value calculated from the four parameter values ​​of callbackAddr, code, object and requestId. It is used to verify that this callback notification comes from the video screenshot upload service.
objectStringThe name of the screenshot file.
The naming convention for this file is: <OSS prefix>/<year month day>/<sid>_<cname>__uid_s_<uid>__uid_e_<type>_utc.jpg. The meaning of each field in the file name is as follows:
  • <sid>: Screenshot ID. The ID is a unique identifier for a screenshot.
  • <cname>: The channel name of the screenshot user.
  • <uid>: User ID. The user ID set when joining the channel.
  • <type>: File type, only supported video.
  • <utc>: The Unix timestamp of this screenshot. UTC time, consisting of year, month, day, hour, minute, second, and millisecond. For example, utc equals 20190611073246073 means that the start time of the slice file is 07:32:46:73 milliseconds on June 11, 2019 UTC.
codeNumberThe status code of this screenshot. 200 indicates that the screenshot is complete.
msgStringThe status of this screenshot. Supervise complete indicates that the screenshot is complete.
channelNameStringThe name of the channel to which the screenshot user belongs. Consistent with object.cname.
userIdStringThe user ID of the user whose screenshot was taken this time. Consistent with object.uid.
timestampIntUnix timestamp (in milliseconds) for this screenshot. UTC time, consistent with object.utc.

Example request

"requestId": "38f8e3cfdcXXXXXXXXX1ceba380d7e1a_1652693284_b5813fe2ae4fa5cdfe5abd8fef82526f",
"callbackParam": {
"cname": "httpClient463224"
"callbackData": "",
"checksum": "75ee988XXXXXXc2ad4ec2aef58f178fd8",
"object": "test/20201216/38f8e3cfdc474cd56fc1ceba380d7e1a_httpClient463224__uid_s_91__uid_e_video_20200413081128672.jpg",
"code": 200,
"msg": "Supervise complete",
"channelName": "httpClient463224",
"userId": "91",
"timestamp": 20190611073246070

HTTP status codes

Status codeDescription
200The request was successful.
201A new resource was successfully requested and created.
206During the entire screenshot process, no user sent a stream, or some screenshot files were not uploaded to the third-party cloud storage.
400The syntax of the request is incorrect and the server cannot understand it. For example, a wrong parameter.
401Unauthorized. App ID/Customer Certificate mismatch.
404The server could not find the resource (web page) according to the request.
500An internal server error prevented the request from being completed.
504Internal server error. The server acting as a gateway or proxy is not getting the request from the remote server.


The following prices apply when you use screenshot upload as a feature under Video Calling and Interactive Live Streaming products:​

Billing itemsPricing*Free Usage
SDK side screenshot$0.3/10,000 imagesFirst 10,000 images per month are free
Additional charge for SDK side screenshot
when QPS > 500
$1.5/QPSFirst 500 QPS per month are free

*The fee is waived for customers using the Active Fence content moderation extension.​