Video Moderation
Stream's video moderation engine samples frames from an uploaded video and scores each frame with the same AI categories you use for images. The video takes the strictest frame verdict. Analysis runs asynchronously so the upload is not held back.
Results are returned as ai_video. Existing video rules, the review queue, webhooks, and billing keep working.
How it works
When a video is uploaded:
- The video is accepted immediately.
- Stream samples frames evenly across the whole video (default one frame per second). If the video is long, the sample rate is thinned so the full video is still covered.
- Each frame is scored against your video policy rules (the same label and confidence model as image moderation).
- The video action is the strictest frame action. Labels from every flagged frame are combined.
- The message or post is updated when analysis finishes.
- Flagged videos appear in the content review queue. Open Moderation > Review Queue in the dashboard.
You can change how densely frames are sampled in the dashboard video policy.
Supported categories
These are the categories shown in the dashboard video policy editor. Video uses the image moderation categories, without PII and QR Code, and has no subcategories:
- Explicit
- Non-Explicit Nudity of Intimate parts and Kissing
- Swimwear or Underwear
- Violence
- Visually Disturbing
- Drugs & Tobacco
- Alcohol
- Rude Gestures
- Gambling
- Hate Symbols
Set a confidence threshold per category (1 to 100). Higher values flag less. A threshold of 90 only matches highly confident frames, which means fewer flags and fewer false positives.
Supported formats
Video moderation accepts most common video containers and codecs, including:
- MP4 (
.mp4,.m4v) - QuickTime (
.mov), including iPhone recordings in HEVC (H.265) and HDR - WebM (
.webm) - Matroska (
.mkv) - AVI (
.avi) - MPEG (
.mpg,.mpeg,.ts) - 3GP (
.3gp) - FLV (
.flv) - WMV (
.wmv)
Supported video codecs include H.264, H.265 (HEVC), VP8, VP9, AV1, MPEG-2, MPEG-4 Part 2, and ProRes.
The format is detected from the file contents, not the extension. The file must include duration metadata. Videos without it are not moderated. To keep unsupported uploads out entirely in Stream Chat, configure the app's file upload allowlist or blocklist from the dashboard. This is a Stream Chat upload setting, not part of the Moderation API; for standalone moderation, filter file types in your own upload flow.
Configuration
Set an action for each category you care about on ai_video_config, with a required min_confidence on a 0-100 scale, the same shape as image rules. Video and image are set separately in the policy, so video settings don't affect image moderation. Live calls use video_call_rule_config, not this field.
await client.moderation.upsertConfig({
key: "chat:messaging",
ai_video_config: {
rules: [
{ label: "Explicit", action: "remove", min_confidence: 70 },
{ label: "Violence", action: "flag", min_confidence: 50 },
],
},
});Actions are flag, shadow, remove, bounce, bounce_flag, and bounce_remove. Use flag for borderline frames and remove for content that should not stay up.
Send video URLs in moderation_payload.videos with the Check API. Stream Chat and Feeds send attached videos for you.
const response = await client.moderation.check({
entity_type: "listing",
entity_id: "listing-123",
entity_creator_id: "user-42",
config_key: "marketplace",
moderation_payload: {
videos: ["https://cdn.example.com/listings/123/tour.mp4"],
},
});
// response.status is "pending" until the video is analyzedLimitations
- Analysis is always asynchronous. The verdict arrives a few seconds to a few minutes after the request, depending on length. The
asyncfield onai_video_configis ignored for video, andforce_syncon Check skips video entirely, so don't use either to wait for a verdict. - Very long videos are sampled more sparsely so the whole file is still covered.
Hold a video until it's checked
Stream Chat and Feeds publish the video right away and update the message or post if it is flagged or removed. To keep a video hidden until it's confirmed safe in your own app:
- Store the video as pending and don't show it to other users.
- Call Check with the video. The response has
status: "pending". - Handle the
moderation_check.completedwebhook. It carriesentity_id,entity_type, andrecommended_action. - Publish the video when
recommended_actioniskeep, and remove or hold it for review otherwise.