Live video and audio

Live video and audio moderation watches a livestream or a call as it happens and acts when a rule matches. The rules read video keyframes and audio transcriptions (closed captions).

How it works

Live video and audio rules differ from user and content rules:

  1. Real-Time Analysis: Video keyframes and audio transcriptions are analyzed in real-time during active sessions (calls, livestreams, etc.)
  2. Consecutive Violations: Rules track consecutive violations within a single session (not across time windows)
  3. Escalating Actions: Actions escalate based on violation number (1st violation, 2nd violation, etc.)
  4. Immediate Execution: Actions are executed immediately when conditions are met, affecting the live session

Configure via API

Create a live video rule with the server-side SDKs:

client.moderation.upsert_moderation_rule(GetStream::Generated::Models::UpsertModerationRuleRequest.new(
  name: "Inappropriate Content Detection",
  description: "Detects and responds to inappropriate content in live video and audio",
  rule_type: "call",
  enabled: true,
  cooldown_period: "5m",
  logic: "OR",
  conditions: [
    GetStream::Generated::Models::RuleBuilderCondition.new(
      type: "keyframe_rule",
      keyframe_rule_params: GetStream::Generated::Models::KeyframeRuleParams.new(
        harm_labels: ["NUDITY", "VIOLENCE"], threshold: 3, min_confidence: 0.75
      )
    ),
    GetStream::Generated::Models::RuleBuilderCondition.new(
      type: "closed_caption_rule",
      closed_caption_rule_params: GetStream::Generated::Models::ClosedCaptionRuleParams.new(
        threshold: 2, llm_harm_labels: { "HATE_SPEECH" => "Content that promotes hatred, discrimination, or violence" }
      )
    ),
  ],
  action_sequences: [
    GetStream::Generated::Models::CallRuleActionSequence.new(violation_number: 1, actions: ["mute_video", "call_warning"], call_options: GetStream::Generated::Models::CallOptions.new(warning_text: "Please keep your video appropriate")),
    GetStream::Generated::Models::CallRuleActionSequence.new(violation_number: 2, actions: ["mute_audio", "mute_video"]),
    GetStream::Generated::Models::CallRuleActionSequence.new(violation_number: 3, actions: ["kick_user"]),
  ]
))

Video Keyframe Condition

Keyframe rules analyze video frames captured during live sessions to detect visual content violations.

Parameters:

  • harm_labels: Array of harm labels to detect (e.g., ["NUDITY", "VIOLENCE", "WEAPONS"])
  • threshold: Number of consecutive violations required before triggering (e.g., 3)
  • min_confidence: Optional minimum confidence, from 0 to 1. 0.75 means 75%. Omit it to use the image-engine default of 50 on the 0–100 scale.

Example:

{
  "type": "keyframe_rule",
  "keyframe_rule_params": {
    "harm_labels": ["NUDITY", "VIOLENCE"],
    "threshold": 3,
    "min_confidence": 0.75
  }
}

This rule triggers when a user's video contains 3 consecutive keyframes with nudity or violence detected, with a minimum confidence score of 75%. A keyframe that does not match resets that count to 0.

Closed Caption Condition

Closed caption rules analyze audio transcriptions from live sessions to detect spoken content violations.

LLM Harm Labels (Configurable):

When LLM configurability is enabled, you can use detailed harm labels with custom descriptions:

Example with LLM Labels:

{
  "type": "closed_caption_rule",
  "closed_caption_rule_params": {
    "threshold": 2,
    "llm_harm_labels": {
      "HATE_SPEECH": "Content that promotes hatred, discrimination, or violence against groups",
      "THREAT": "Content containing threats of violence or harm against individuals or groups"
    }
  }
}

NLP Harm Labels:

With the AI Text (NLP) engine, you can use simple string arrays: ["HATE_SPEECH", "THREAT", "SPAM"]

Example with NLP Labels:

{
  "type": "closed_caption_rule",
  "closed_caption_rule_params": {
    "threshold": 2,
    "harm_labels": ["HATE_SPEECH", "THREAT"]
  }
}

This rule triggers when a user's speech contains 2 consecutive violations of hate speech or threats. A caption that does not match resets that count to 0.

Action Sequences (Escalation)

Call rules use action sequences to define escalating responses based on violation number. Unlike user and content rules that use a single action, call rules can have different actions for each violation level.

Key Concepts:

  • Violation Number: Tracks how many times this specific rule has been triggered for a user in the current session
  • Action Sequences: Define different actions for each violation number (1st violation, 2nd violation, etc.)
  • Simultaneous Actions: Multiple actions within the same sequence execute at the same time
  • Rule-Level Cooldown: Prevents the same rule from triggering repeatedly within the cooldown period

Example Action Sequence:

{
  "action_sequences": [
    {
      "violation_number": 1,
      "actions": ["mute_video", "call_warning"],
      "call_options": {
        "warning_text": "Please keep your video appropriate"
      }
    },
    {
      "violation_number": 2,
      "actions": ["mute_audio", "mute_video"]
    },
    {
      "violation_number": 3,
      "actions": ["kick_user"]
    }
  ]
}

How Escalation Works:

  1. First Violation: User receives a warning and video is muted
  2. Second Violation: User's audio and video are muted
  3. Third Violation: User is kicked from the call

Rule-Level Cooldown:

The cooldown period prevents the same rule from triggering repeatedly. Once a rule triggers and executes an action sequence, it enters a cooldown period (configurable: 5s, 10s, 1m, 5m, or 10m). During this cooldown, the rule will not trigger again, even if conditions are met.

Cross-Call Violation Tracking

While action sequences handle escalation within a single call, you may also want to take action against users who accumulate violations across multiple calls. The call_violation_count condition lets you create a user rule that triggers when a user reaches a threshold of call rule violations within a time window.

For example, you can ban a user who triggers these rules 5 times across any calls within a 24-hour period.

Configure via API

client.moderation.upsert_moderation_rule(GetStream::Generated::Models::UpsertModerationRuleRequest.new(
  name: "Ban Repeat Call Offenders",
  rule_type: "user",
  enabled: true,
  cooldown_period: "24h",
  logic: "AND",
  conditions: [
    GetStream::Generated::Models::RuleBuilderCondition.new(
      type: "call_violation_count",
      call_violation_count_params: GetStream::Generated::Models::CallViolationCountParams.new(threshold: 5, time_window: "24h")
    ),
  ],
  action: GetStream::Generated::Models::RuleBuilderAction.new(type: "ban_user")
))

Parameters:

  • threshold: Number of call rule violations required to trigger (e.g., 5)
  • time_window: Time window to track violations. Supported values: "30m", "1h", "24h", "7d", "30d"

How It Works:

  • Every time a call rule's action sequence executes (any violation number), a global counter is incremented for the user
  • The counter tracks violations across all calls and all call rules, not just a single session
  • When a user rule with call_violation_count is evaluated, it checks whether the user's total call violations within the time window meet or exceed the threshold
  • This allows combining in-call escalation (action sequences) with cross-call enforcement (user rules)

Available Call Actions

Call rules support the following actions:

Mute Video

Disables the user's video stream.

{
  "actions": ["mute_video"]
}

Note: The mute_video action automatically mutes only video (audio remains unmuted). No additional options are required or used.

Mute Audio

Disables the user's audio/microphone.

{
  "actions": ["mute_audio"]
}

Note: The mute_audio action automatically mutes only audio (video remains unmuted). No additional options are required or used.

Mute User (Audio and Video)

Mutes both audio and video simultaneously by specifying both actions.

{
  "actions": ["mute_audio", "mute_video"]
}

Note: To mute both audio and video, include both mute_audio and mute_video in the actions array. Each action is executed independently with its default behavior.

Blur Video

Blurs the user's video feed (visual censorship).

{
  "actions": ["call_blur"]
}

Note: The call_blur action blurs the video feed. No additional options are required or used.

End Call

Terminates the entire call for all participants.

{
  "actions": ["end_call"]
}

Note: The end_call action terminates the call for all participants. No additional options are required or used.

Kick User

Removes the user from the call (others continue).

{
  "actions": ["kick_user"]
}

Note: The kick_user action removes the user from the call. No additional options are required or used.

Warning

Sends a warning message to the user.

{
  "actions": ["call_warning"],
  "call_options": {
    "warning_text": "Please follow community guidelines"
  }
}

Options:

  • warning_text: Warning message to display to the user (required)

Webhook Only

Sends a webhook event without executing any call actions. Useful for logging or external integrations.

{
  "actions": ["webhook_only"]
}

Webhook Events

When a call rule is triggered, a webhook event is automatically sent. To configure webhook URL and subscribe to events, navigate to Moderation > Advanced Filters > Preferences > Webhook & Event Configuration. Select the moderation_rule.triggered event to receive call rule trigger events.

Event Type: moderation_rule.triggered

Event Structure:

{
  "type": "moderation_rule.triggered",
  "created_at": "2026-01-20T23:45:04.485362361Z",
  "rule": {
    "id": "0450e7d6-9386-4eb9-a720-f3999979989c",
    "name": "Nudity or hate speech not allowed from men",
    "type": "call",
    "description": "Detects inappropriate content in video calls"
  },
  "violation_number": 1,
  "entity_id": "default:default_test-4013",
  "entity_type": "stream:v1:call",
  "user_id": "test-user-2025b49e-ef45-473f-bb90-4f8f679c8581",
  "triggered_actions": ["mute_video", "call_warning"],
  "review_queue_item_id": "abc123"
}

Fields:

  • type: Always "moderation_rule.triggered" for rule builder events
  • created_at: ISO 8601 timestamp when the event was created
  • rule: Object containing rule information
    • id: Unique identifier for the rule
    • name: Human-readable rule name
    • type: Rule type ("call", "user", or "content")
    • description: Rule description
  • violation_number: (Call rules only) The violation number that triggered this event (1st violation, 2nd violation, etc.)
  • entity_id: The ID of the entity that triggered the rule (for call rules, this is the call CID)
  • entity_type: The type of entity (for call rules, this is "stream:v1:call")
  • user_id: The ID of the user who triggered the rule
  • triggered_actions: Array of action types that were executed (e.g., ["mute_video", "call_warning"])
  • review_queue_item_id: (Optional) The review queue item ID if the violation was flagged for review

Note: Webhook events are sent once per rule per violation number per entity. If multiple keyframes or closed captions trigger the same rule with the same violation number, only one webhook event is sent.

Your own video

If Stream does not host the video, send keyframes and captions yourself. See Your own live video.