Video Moderation / Workflows

Video Moderation Workflows

Introduction

Video Moderation Workflows make it easy to create your own custom rules and actions, directly from your online dashboard.

You decide how each video or stream is analyzed, and what rules should lead to a video being either accepted or rejected.

Create a Workflow

To create a new workflow, navigate to the Workflow page on your dashboard. You will be able to select the rules that should be applied, and what actions should be taken based on those rules: ACCEPT or REJECT.

For more information on the different detection models you can use, head to our Model reference.

Define your custom moderation rules directly from your dashboard

You might want to create multiple workflows if you handle different types of videos with different rules. For instance, let's say you have a dating site and your users can upload a profile video, and can do video chats with other participants. You could create a workflow for Profile videos, where you reject videos containing children or celebrities, and another workflow for videochats with different rules.

Once your workflow has been created, you will get a workflow id that you can use to submit videos for moderation.

There are two ways to moderate a Stored Video. You can choose between synchronous moderation, where the moderation happens during your API request, or asynchronous moderation. While both yield the same results, they differ in their implementations. Synchronous Moderation is quicker to setup, but will only work for short videos (up to 60s).

Submitting short stored videos sync

The synchronous moderation API is quick and easy to use. Everything happens within a single API request cycle.

Since this has to fit within a single API request cycle, this approach will only work for videos that are less than 60 seconds long. To moderate longer videos, use the Asynchronous Video Moderation.


Once you have created and saved a workflow, you can retrieve the workflow id and use it to query the API. You can then submit a video either by sending the raw bytes or by sending a public URL pointing to the video.

Moderate video by submitting the raw bytes


curl -X POST 'https://api.sightengine.com/1.0/video/check-workflow-sync.json' \
  -F 'media=@/path/to/video.mp4' \
  -F 'workflow={workflow_id}' \
  -F 'api_user={api_user}' \
  -F 'api_secret={api_secret}'


# this example uses requests
import requests
import json

params = {
  'workflow': '{workflow_id}',
  'api_user': '{api_user}',
  'api_secret': '{api_secret}'
}
files = {'media': open('/path/to/video.mp4', 'rb')}
r = requests.post('https://api.sightengine.com/1.0/video/check-workflow-sync.json', files=files, data=params)

output = json.loads(r.text)


$params = array(
  'media' => new CurlFile('/path/to/video.mp4'),
  'workflow' => '{workflow_id}',
  'api_user' => '{api_user}',
  'api_secret' => '{api_secret}',
);

// this example uses cURL
$ch = curl_init('https://api.sightengine.com/1.0/video/check-workflow-sync.json');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
curl_close($ch);

$output = json_decode($response, true);


// this example uses axios and form-data
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');

data = new FormData();
data.append('media', fs.createReadStream('/path/to/video.mp4'));
data.append('workflow', '{workflow_id}');
data.append('api_user', '{api_user}');
data.append('api_secret', '{api_secret}');

axios({
  method: 'post',
  url:'https://api.sightengine.com/1.0/video/check-workflow-sync.json',
  data: data,
  headers: data.getHeaders()
})
.then(function (response) {
  // on success: handle response
  console.log(response.data);
})
.catch(function (error) {
  // handle error
  if (error.response) console.log(error.response.data);
  else console.log(error.message);
});

Moderate video URL


curl -X GET -G 'https://api.sightengine.com/1.0/video/check-workflow-sync.json' \
  --data-urlencode 'stream_url=https://domain/path/video' \
  -d 'workflow={workflow_id}' \
  -d 'api_user={api_user}' \
  -d 'api_secret={api_secret}'


# this example uses requests
import requests
import json

params = {
  'stream_url': 'https://domain/path/video',
  'workflow': '{workflow_id}',
  'api_user': '{api_user}',
  'api_secret': '{api_secret}'
}
r = requests.get('https://api.sightengine.com/1.0/video/check-workflow-sync.json', params=params)

output = json.loads(r.text)


if output['status'] == 'failure':
  # handle failure
  print(output['error'])

if output['summary']['action'] == 'reject':
  # handle video rejection
  # the rejection probability is provided in output['summary']['reject_prob']
  # and user readable reasons for the rejection are in the array output['summary']['reject_reason']
  pass


$params = array(
  'stream_url' =>  'https://domain/path/video',
  'workflow' => '{workflow_id}',
  'api_user' => '{api_user}',
  'api_secret' => '{api_secret}',
);

// this example uses cURL
$ch = curl_init('https://api.sightengine.com/1.0/video/check-workflow-sync.json?'.http_build_query($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

$output = json_decode($response, true);

if($output['summary']['action']=='reject') {
  // handle video rejection
  // the rejection probability is provided in $output['summary']['reject_prob']
  // and user readable reasons for the rejection are in the array $output['summary']['reject_reason']
}


// this example uses axios
const axios = require('axios');

axios.get('https://api.sightengine.com/1.0/video/check-workflow-sync.json', {
  params: {
    'stream_url': 'https://domain/path/video',
    'workflow': '{workflow_id}',
    'api_user': '{api_user}',
    'api_secret': '{api_secret}',
  }
})
.then(function (response) {
  // on success: handle response
  console.log(response.data);
})
.catch(function (error) {
  // handle error
  if (error.response) console.log(error.response.data);
  else console.log(error.message);
});

Response

The body of the response will be JSON-formatted. This response will contain a summary object with the moderation decision taken, along with reasons for rejection if the video has to be rejected


{
    "status": "success",
    "request": {
        "id": "req_81pP7cRqEvbdZ457WNQ2O",
        "timestamp": 1597952947.216626,
        "operations": 10
    },
    "summary": {
        "action": "reject",
        "reject_prob": 0.82,
        "reject_reason": [
            {
                "text": "Alcohol"
            }
        ]
    },
    "data": {
      "frames": [
        ...
      ]
    }
    "workflow": {
        "id": "wfl_81jOFDxdI8un4sm38y4Kw"
    }
}

Submitting long or real-time videos async

Once you have created and saved a workflow, you can retrieve the workflow id and use it to query the API.

You can submit a video either by sending the raw bytes or by sending a public URL pointing to the video.

Moderate video by submitting the raw bytes


curl -X POST 'https://api.sightengine.com/1.0/video/check-workflow.json' \
  -F 'media=@/path/to/video.mp4' \
  -F 'workflow={workflow_id}' \
  -F 'callback_url=https://your.callback/path' \
  -F 'api_user={api_user}' \
  -F 'api_secret={api_secret}'


# this example uses requests
import requests
import json

params = {
  'workflow': '{workflow_id}',
  # specify where you want to receive result callbacks (optional)
  'callback_url': 'https://your.callback/path',
  'api_user': '{api_user}',
  'api_secret': '{api_secret}'
}
files = {'media': open('/path/to/video.mp4', 'rb')}
r = requests.post('https://api.sightengine.com/1.0/video/check-workflow.json', files=files, data=params)

output = json.loads(r.text)


$params = array(
  'media' => new CurlFile('/path/to/video.mp4'),
  'workflow' => '{workflow_id}',
  // specify where you want to receive result callbacks (optional)
  'callback_url' => 'https://your.callback/path',
  'api_user' => '{api_user}',
  'api_secret' => '{api_secret}',
);

// this example uses cURL
$ch = curl_init('https://api.sightengine.com/1.0/video/check-workflow.json');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
curl_close($ch);

$output = json_decode($response, true);


// this example uses axios and form-data
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');

data = new FormData();
data.append('media', fs.createReadStream('/path/to/video.mp4'));
data.append('workflow', '{workflow_id}');
// specify where you want to receive result callbacks (optional)
data.append('callback_url', 'https://your.callback/path');
data.append('api_user', '{api_user}');
data.append('api_secret', '{api_secret}');

axios({
  method: 'post',
  url:'https://api.sightengine.com/1.0/video/check-workflow.json',
  data: data,
  headers: data.getHeaders()
})
.then(function (response) {
  // on success: handle response
  console.log(response.data);
})
.catch(function (error) {
  // handle error
  if (error.response) console.log(error.response.data);
  else console.log(error.message);
});

Moderate video URL


curl -X GET -G 'https://api.sightengine.com/1.0/video/check-workflow.json' \
    --data-urlencode 'stream_url=https://domain/path/video' \
    -d 'workflow={workflow_id}' \
    -d 'callback_url=https://your.callback.url/path' \
    -d 'api_user={api_user}' \
    -d 'api_secret={api_secret}'


# this example uses requests
import requests
import json

params = {
  'stream_url': 'https://domain/path/video',
  'workflow': '{workflow_id}',
  # specify where you want to receive result callbacks
  'callback_url': 'https://your.callback.url/path',
  'api_user': '{api_user}',
  'api_secret': '{api_secret}'
}
r = requests.get('https://api.sightengine.com/1.0/video/check-workflow.json', params=params)

output = json.loads(r.text)


if output['status'] == 'failure':
  # handle failure
  print(output['error'])


$params = array(
  'stream_url' =>  'https://domain/path/video',
  'workflow' => '{workflow_id}',
  // specify where you want to receive callbacks
  'callback_url' => 'https://your.callback.url/path',
  'api_user' => '{api_user}',
  'api_secret' => '{api_secret}',
);

// this example uses cURL
$ch = curl_init('https://api.sightengine.com/1.0/video/check-workflow.json?'.http_build_query($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

$output = json_decode($response, true);


// this example uses axios
const axios = require('axios');

axios.get('https://api.sightengine.com/1.0/video/check-workflow.json', {
  params: {
    'stream_url': 'https://domain/path/video',
    // specify where you want to receive result callbacks
    'callback_url': 'https://your.callback.url/path',
    'workflow': '{workflow_id}',
    'api_user': '{api_user}',
    'api_secret': '{api_secret}',
  }
})
.then(function (response) {
  // on success: handle response
  console.log(response.data);
})
.catch(function (error) {
  // handle error
  if (error.response) console.log(error.response.data);
  else console.log(error.message);
});

If the request is successful, the response JSON will contain the media id that you can then use to listen for events through your callback URL or poll the API for updates.


{
    "status": "success",
    "request": {
        "id": "req_81pP7cRqEvbdZ457WNQ2O",
        "timestamp": 1597952947.216626,
        "operations": 10
    },
    "media": {
        "id": "med_81pP7cDAfjdALi73ff",
        "uri": "...",
    },
    "callback": "https://your.callback/path"
}

Next steps

Once Sightengine starts analyzing your video, you can retrieve moderation results in realtime through two separate channels: either through callbacks (this is the recommended approach as it is more efficient and faster) or by polling the API.

Did you find this page helpful?

We're always looking for advice to help improve our documentation!

Let us know what you think

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more

OK