# Moderation

This cookbook shows how to handle moderation events in your video call application. These events are automatically emitted by Stream's moderation system when content violates your configured moderation policies. You can configure moderation policies through the [Stream Dashboard](https://getstream.io/moderation/docs/node/) or via the moderation API.

The Stream API emits the following moderation events:

- `call.moderation_warning` - Emitted when a moderation warning is issued to the user
- `call.moderation_blur` - Emitted when a blur effect should be applied to the user's camera
- `call.ended` - Emitted when a call ends, with `reason: PolicyViolationModeration` when the call is terminated due to a moderation policy violation

## Moderation Notification

The following is an example of a custom `ModerationNotification` component that listens for moderation warning events and displays a notification to the user. It also handles cases where a call is ended due to policy violations.

```tsx
import { useEffect, useRef, useState } from "react";
import { Notification, useCall } from "@stream-io/video-react-sdk";

export const ModerationNotification = () => {
  const call = useCall();
  const [isVisible, setVisible] = useState(false);
  const [message, setMessage] = useState("");
  const warningTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);

  useEffect(() => {
    if (!call) return;

    const unsubscribe = call.on("call.moderation_warning", (event) => {
      setVisible(true);
      setMessage(event.message);
      clearTimeout(warningTimeoutRef.current);
      warningTimeoutRef.current = setTimeout(() => {
        setVisible(false);
        warningTimeoutRef.current = undefined;
      }, 3000);
    });

    return () => {
      unsubscribe();
      clearTimeout(warningTimeoutRef.current);
      warningTimeoutRef.current = undefined;
    };
  }, [call]);

  useEffect(() => {
    if (!call) return;
    return call.on("call.ended", (event) => {
      if (event.reason === "PolicyViolationModeration") {
        /* call ended due to policy violation logic */
      }
    });
  }, [call]);

  return <Notification message={message} isVisible={isVisible} />;
};
```

## Moderation Blur

The `useModeration` hook is provided by `@stream-io/video-react-sdk` and handles moderation blur events automatically. When a `call.moderation_blur` event is emitted, the hook applies a blur effect to the user's camera.

### Behavior

The hook behaves differently depending on whether the `@stream-io/video-filters-web` package is available:

- If `@stream-io/video-filters-web` is available: A full-screen blur effect is applied to the user's camera on the outgoing video track. The blur is automatically removed after the configured timeout.
- If `@stream-io/video-filters-web` is not available or an error occurs: The camera will be disabled as a fallback measure to ensure content moderation.

### Usage

To enable moderation in your application, import the `useModeration` hook from `@stream-io/video-react-sdk` and call it in your custom call UI component.

```tsx
import {
  StreamCall,
  StreamVideo,
  useModeration,
} from "@stream-io/video-react-sdk";

export const App = () => {
  return (
    <StreamVideo client={client}>
      <StreamCall call={call}>
        <CustomCallUI />
      </StreamCall>
    </StreamVideo>
  );
};

export const CustomCallUI = () => {
  // Enable moderation by plugging in the useModeration hook
  useModeration({ duration: 2000 }); // leave empty for default 5000ms

  // Render the actual component tree
};
```

![Blurred Screen](https://getstream.io/docs-assets/images/7b24fe89e2a3.png)

## Handling Moderation Policy Violation

After the applied moderation policies are violated multiple times, the call may be terminated by the moderation system.
This is signaled through a `call.ended` event carrying `PolicyViolationModeration` as the reason.

Here is a minimalistic example:

```tsx
import { useCall } from "@stream-io/video-react-sdk";

export const MyComponent = () => {
  const call = useCall();
  useEffect(() => {
    if (!call) return;
    return call.on("call.ended", (event) => {
      if (event.reason === "PolicyViolationModeration") {
        alert("Call terminated due to multiple policy violations.");
      }
    });
  }, [call]);
};
```

---

For the most recent version of this documentation, visit [https://getstream.io/video/docs/react/v2/ui-cookbook/moderation/](https://getstream.io/video/docs/react/v2/ui-cookbook/moderation/).