final call = streamVideo.makeCall(
callType: StreamCallType.defaultType(),
id: 'my-call-id',
preferences: DefaultCallPreferences(
videoModerationConfig: VideoModerationConfig.mute(
duration: Duration(seconds: 5),
),
),
);Call Moderation
Handle moderation events in video call applications. Stream's moderation system automatically emits events when content violates configured policies. Configure policies via the Stream Dashboard or moderation API.
Best Practices
- Display warnings clearly - Show moderation warnings prominently to users
- Handle blur gracefully - Apply blur filters without disrupting call flow
- Inform about termination - Explain why a call ended due to violations
- Log moderation events - Track violations for review and policy adjustment
Stream API moderation events:
- call.moderation_warning - Warning issued to user
- call.moderation_blur - Blur effect should be applied to camera
- call.ended - Call terminated (with
reason: PolicyViolationModerationfor violations)
Video Moderation Configuration
The Flutter SDK handles call.moderation_blur events through VideoModerationConfig, set via CallPreferences when creating a call:
| Flag / Callback | Description |
|---|---|
muteAudio | Mutes the local user's microphone and prevents re-enabling it for the configured duration. |
muteVideo | Mutes the local user's camera and prevents re-enabling it for the configured duration. |
applyBlur | Applies a full-frame native blur on the camera track visible to all participants. Requires the stream_video_filters package. |
duration | How long the moderation action lasts. null means it persists until call.clearModerationBlur() is called. |
onWarning | Callback invoked when a call.moderation_warning event is received. |
onApply | Callback invoked when the moderation blur action fires (after built-in actions). |
onClear | Callback invoked when the moderation blur action is cleared (after built-in clear actions). |
Convenience constructors cover the most common presets:
| Constructor | Equivalent to |
|---|---|
VideoModerationConfig.disabled() | Default. No automatic action. The event is still emitted on callEvents. |
VideoModerationConfig.mute() | muteAudio: true, muteVideo: true |
VideoModerationConfig.blur() | applyBlur: true |
Setting the Configuration
Pass videoModerationConfig in DefaultCallPreferences when creating a call:
Combining Behaviors
Flags are composable. For example, mute audio and video while also running a custom callback:
final call = streamVideo.makeCall(
callType: StreamCallType.defaultType(),
id: 'my-call-id',
preferences: DefaultCallPreferences(
videoModerationConfig: VideoModerationConfig(
muteAudio: true,
muteVideo: true,
duration: Duration(seconds: 10),
onWarning: (message) {
// Show a warning snackbar
},
onApply: () {
// Show a moderation banner in the UI
},
onClear: () {
// Hide the moderation banner
},
),
),
);Or combine mute with native blur:
VideoModerationConfig(
muteAudio: true,
muteVideo: true,
applyBlur: true,
duration: Duration(seconds: 10),
)Moderation Blur
To use applyBlur: true (or VideoModerationConfig.blur()), you need the stream_video_filters package. This applies a full-frame native blur on the outgoing camera track before encoding, so the blur is visible to all participants.
Behavior
- With
stream_video_filterspackage - Full-screen blur applied to outgoing video, auto-removed after the configured duration - Without the package - The blur handlers will not be registered and the blur effect will not be applied
Usage
final call = streamVideo.makeCall(
callType: StreamCallType.defaultType(),
id: 'my-call-id',
preferences: DefaultCallPreferences(
videoModerationConfig: VideoModerationConfig.blur(
duration: Duration(seconds: 5),
),
),
);Custom Moderation Handling
For full control over what happens when a moderation blur event is received, pass onApply and onClear callbacks directly in the config:
final call = streamVideo.makeCall(
callType: StreamCallType.defaultType(),
id: 'my-call-id',
preferences: DefaultCallPreferences(
videoModerationConfig: VideoModerationConfig(
duration: Duration(seconds: 5),
onWarning: () {
// Called when a moderation warning is received
},
onApply: () {
// Called when moderation blur fires
},
onClear: () {
// Called when moderation blur is cleared
},
),
),
);The callbacks run after any built-in actions, so you can add them alongside muteAudio, muteVideo, or applyBlur for additional side effects.
Listening to Call Events
All moderation events are also emitted on call.callEvents, regardless of the VideoModerationConfig setting. For moderation warnings you can use either the onWarning callback in the config or listen to StreamCallModerationWarningEvent on callEvents directly.
Moderation Warning
Display a notification when the user receives a moderation warning:
call.callEvents.on<StreamCallModerationWarningEvent>((event) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Moderation Warning'),
content: Text(event.message),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('OK'),
),
],
),
);
});Moderation Blur
Listen to blur events directly when using VideoModerationConfig.disabled() or when you need additional side effects alongside the config:
call.callEvents.on<StreamCallModerationBlurEvent>((event) {
// Handle the blur event manually
});Handling Moderation Policy Violation
Multiple policy violations may terminate the call. The StreamCallEndedEvent carries a reason field with the value PolicyViolationModeration when the call was ended due to moderation:
call.callEvents.on<StreamCallEndedEvent>((event) {
if (event.reason == 'PolicyViolationModeration') {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Call Terminated'),
content: Text(
'The video call was terminated due to multiple policy violations.',
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('OK'),
),
],
),
);
}
});Checking Moderation State
You can check whether the local user is currently under moderation via the call state:
final isModerated = call.state.value.isVideoModerated;To programmatically clear the moderation action (for example, from an admin UI):
call.clearModerationBlur();