# Your own live video

Send keyframes and captions from your own video pipeline to the Check API. Use entity type `external:call`. The same live video rules that run on Stream-hosted calls (`stream:v1:call`) run on these checks. Create those rules on [Live video and audio](https://getstream.io/moderation/docs/ruby/integrations/live-video-and-audio/).

1. Extract keyframes (images) and closed captions (text) in your pipeline.
2. Send them to Check with `entity_type: "external:call"`.
3. Stream evaluates them against your keyframe and closed-caption rules.
4. A match sends `moderation_rule.triggered` and `review_queue_item.new`.

`content_published_at` is the time the frame or caption was produced. Stream stores it on the flag so a reviewer can line it up with your timeline.

## Send a keyframe

```js label="Node.js"
const response = await client.moderation.check({
  entity_type: "external:call",
  entity_id: "my-room-12345",
  entity_creator_id: "user-abc",
  content_published_at: new Date(),
  moderation_payload: {
    images: ["https://your-cdn.com/keyframe-001.jpg"],
  },
});
```

## Send a caption

```js label="Node.js"
const response = await client.moderation.check({
  entity_type: "external:call",
  entity_id: "my-room-12345",
  entity_creator_id: "user-abc",
  content_published_at: new Date(),
  moderation_payload: {
    texts: ["transcribed audio segment"],
  },
});
```

## Handling actions

Stream does not join your video session, so it cannot mute, blur, or kick a participant. Use `flag_content` or `webhook_only` on the rule, and enforce the decision on your own infrastructure when the webhook arrives.

---

For the most recent version of this documentation, visit [https://getstream.io/moderation/docs/ruby/integrations/your-own-video/](https://getstream.io/moderation/docs/ruby/integrations/your-own-video/).