# YouTube Live Chat Highlights — Stream Peak & Clip Finder (`hitokawa/youtube-livechat-highlights`) Actor

Give it a YouTube live stream archive URL and get chat-based highlight peaks, clip-ready timestamps, per-minute heatmap, engagement dips, and optional AI mood/sentiment analysis as structured JSON. Built for clip makers, VTuber analysts and AI agent workflows.

- **URL**: https://apify.com/hitokawa/youtube-livechat-highlights.md
- **Developed by:** [hitohito](https://apify.com/hitokawa) (community)
- **Categories:** AI, Videos
- **Stats:** 1 total users, 0 monthly users, 66.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $690.00 / 1,000 analysis-fulls

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## YouTube Live Chat Highlights — Stream Peak & Clip Finder

### What does YouTube Live Chat Highlights do?

Give it the URL of a **finished YouTube live stream** (archive with chat replay) and it returns, as **structured JSON**:

- 🔥 **Highlight peaks** — the moments where live chat exploded, detected from a 5-minute rolling window over the full chat replay
- ✂️ **Clip-ready timestamps** — each peak comes with a `youtu.be/...?t=` link and a YouTube-chapter-format label, pre-shifted (default −15s) because chat reacts *after* the moment happens
- 📊 **Per-minute heatmap** of chat activity and **engagement dips** (the boring parts)
- 🔍 **Keyword hits** — find viewers saying "clip this!", a character name, anything you specify
- 🤖 **AI analysis** (full mode) — per-peak **mood**, **event hypothesis** ("what probably happened on stream here"), **sentiment ratios** (pos/neg/neu) and up to 5 **representative comments**, powered by Claude

It analyzes the **viewers' actual reactions**, not the video pixels — which makes it fast, cheap, and language-aware (built and tested on Japanese VTuber streams: 草, w, 888, てぇてぇ are understood; English chat works too).

No video is ever downloaded — only the public chat replay.

### Why use it?

| You are... | You get... |
|---|---|
| A **clip maker** (切り抜き師) or their AI agent | The best 10 moments of a 5-hour stream in ~10 minutes, with ready-to-seek URLs — instead of scrubbing the whole VOD |
| A **VTuber agency / MCN analyst** | Automated per-stream engagement reports: peaks, dips, sentiment, superchat counts |
| A **streamer** | "Where did yesterday's stream hit?" for planning, thumbnails and chapters |
| An **AI agent builder** | Clean JSON via Apify API/MCP — pipe peaks into a clip-cutting Actor or an LLM summarizer |

### How to use it

1. Paste a YouTube URL of a **finished** live stream (chat replay must be enabled)
2. Pick a mode: `stats` (fast, cheap) or `full` (adds AI mood & sentiment)
3. Run — results land in the dataset as one JSON object (download as JSON, CSV, Excel...)

Works out of the box from the Apify Console, API, CLI, or as an MCP tool from Claude, Cursor and other AI agents.

### Input

```json
{
  "video_url": "https://www.youtube.com/watch?v=XXXXXXXXXXX",
  "mode": "full",
  "peak_count": 10,
  "clip_shift_seconds": -15,
  "keywords": ["clip this", "切り抜き"],
  "language_hint": "ja"
}
````

### Output (dataset item, abridged)

```json
{
  "video": {
    "id": "XXXXXXXXXXX",
    "title": "【World Cup】Watch-along!",
    "duration_s": 11380,
    "total_messages": 67597,
    "superchat_count": 14
  },
  "heatmap_per_min": [{ "min": 0, "count": 12 }, ...],
  "peaks": [
    {
      "rank": 1,
      "start_s": 10800,
      "end_s": 11100,
      "message_count": 3631,
      "mood": "熱戦の終了に沸く興奮と拍手喝采",
      "hypothesis": "接戦の名勝負が終了し、視聴者が賞賛コメントを大量に送っている",
      "sentiment": { "pos": 70, "neg": 12, "neu": 18 },
      "representative_comments": [
        { "text": "最高の試合だった", "sentiment": "pos" }
      ],
      "clip_recommendation": {
        "start_s": 10785,
        "end_s": 11115,
        "url": "https://youtu.be/XXXXXXXXXXX?t=10785",
        "chapter_format": "2:59:45 ピーク#1（3631コメント/5分）"
      }
    }
  ],
  "sentiment_overall": { "pos": 72, "neg": 7, "neu": 21 },
  "keyword_hits": [{ "time_s": 4735.9, "author": "...", "text": "切り抜き楽しみ‼" }],
  "dips": []
}
```

### Pricing — how much does it cost to analyze a stream?

Pay per analyzed video, not per chat message:

| Event | Price | What you get |
|---|---|---|
| Stats analysis | $0.19 / video | Heatmap + peaks + clip timestamps + keywords + dips |
| Full analysis | $0.69 / video | Everything above + AI mood, event hypothesis, sentiment, representative comments |
| Long video surcharge (>4h) | +$0.10 | Covers the extra processing for marathon streams |

A 3-hour stream with 67,000 chat messages costs **$0.69 flat** in full mode. Per-message pricing elsewhere can cost tens of dollars for the same stream.

### Tips

- **Chat reacts late**: keep `clip_shift_seconds` at −15 for gameplay, try −30 for slow-burn reactions
- **`peak_count`**: 10 is right for 2–5h streams; use 5 for short streams, up to 30 for marathons
- **Language**: `language_hint: "en"` makes AI labels English; chat itself can be any language
- Live streams still in progress are rejected (`live_status` check) — run it after the stream ends

### FAQ & limitations

- **Does it download the video?** No. Only the public live chat replay (the same data you see when watching the VOD with chat open).
- **What if chat replay is disabled?** The run fails with a clear error — the streamer turned off chat replay for that VOD.
- **Concurrent viewer counts?** Not available — YouTube does not expose them in chat replay. Chat velocity is the engagement proxy.
- **Membership/limited streams?** Not supported — public archives only.
- Comment texts in output are limited to statistics plus a handful of representative quotes per peak, out of respect for commenters' content.

Found a bug or want a feature (Twitch? multi-video compare?) — open an issue on the **Issues tab**.

***

### 日本語での説明

**配信終了後のYouTubeライブのURLを渡すと、チャット反応ベースで「盛り上がりピーク・切り抜き推奨タイムスタンプ・ヒートマップ・中だるみ区間」を構造化JSONで返す**Actorです。fullモードではさらに、ピークごとのムード・「何が起きたかの推測」・ポジネガ比率・代表コメントをAI（Claude）が付与します。

- 5時間のアーカイブを見返さずに、切り抜きポイントTOP10が約10分で手に入ります
- `youtu.be/...?t=` 形式のURLとYouTubeチャプター形式のラベル付き。チャットの反応遅延を見越して開始位置を前倒し済み
- 日本語チャット文化（草・w・888・てぇてぇ・スパチャ）を理解した感情判定
- 動画本体はダウンロードしません（公開チャットリプレイのみ）
- 料金は動画1本単位: stats $0.19 / full $0.69（4時間超は+$0.10）

Claude や Cursor から MCP ツールとしてもそのまま呼べます。

# Actor input Schema

## `video_url` (type: `string`):

URL (or video ID) of a **finished** YouTube live stream archive with chat replay enabled.

## `mode` (type: `string`):

`stats` = heatmap + peaks + clip timestamps (fast, cheap). `full` = adds LLM mood, event hypothesis, sentiment ratios and representative comments per peak.

## `peak_count` (type: `integer`):

How many top peaks to return.

## `clip_shift_seconds` (type: `integer`):

Shift applied to clip start timestamps. Negative = start the clip earlier than the chat peak (chat reacts AFTER the moment happens).

## `keywords` (type: `array`):

Optional keywords to extract from chat (e.g. clip requests, character names).

## `language_hint` (type: `string`):

Language for generated labels.

## `proxyConfiguration` (type: `object`):

Proxy for the metadata extraction step. RESIDENTIAL is required in practice; the bulky chat download always uses cheap datacenter proxy automatically.

## Actor input object example

```json
{
  "video_url": "https://www.youtube.com/watch?v=_dvQpqoJkc4",
  "mode": "stats",
  "peak_count": 10,
  "clip_shift_seconds": -15,
  "language_hint": "ja",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "video_url": "https://www.youtube.com/watch?v=_dvQpqoJkc4"
};

// Run the Actor and wait for it to finish
const run = await client.actor("hitokawa/youtube-livechat-highlights").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "video_url": "https://www.youtube.com/watch?v=_dvQpqoJkc4" }

# Run the Actor and wait for it to finish
run = client.actor("hitokawa/youtube-livechat-highlights").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "video_url": "https://www.youtube.com/watch?v=_dvQpqoJkc4"
}' |
apify call hitokawa/youtube-livechat-highlights --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=hitokawa/youtube-livechat-highlights",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "YouTube Live Chat Highlights — Stream Peak & Clip Finder",
        "description": "Give it a YouTube live stream archive URL and get chat-based highlight peaks, clip-ready timestamps, per-minute heatmap, engagement dips, and optional AI mood/sentiment analysis as structured JSON. Built for clip makers, VTuber analysts and AI agent workflows.",
        "version": "0.1",
        "x-build-id": "6SEODN6QnlR5o9aw6"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/hitokawa~youtube-livechat-highlights/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-hitokawa-youtube-livechat-highlights",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/hitokawa~youtube-livechat-highlights/runs": {
            "post": {
                "operationId": "runs-sync-hitokawa-youtube-livechat-highlights",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/hitokawa~youtube-livechat-highlights/run-sync": {
            "post": {
                "operationId": "run-sync-hitokawa-youtube-livechat-highlights",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "video_url"
                ],
                "properties": {
                    "video_url": {
                        "title": "Video URL",
                        "type": "string",
                        "description": "URL (or video ID) of a **finished** YouTube live stream archive with chat replay enabled."
                    },
                    "mode": {
                        "title": "Analysis mode",
                        "enum": [
                            "stats",
                            "full"
                        ],
                        "type": "string",
                        "description": "`stats` = heatmap + peaks + clip timestamps (fast, cheap). `full` = adds LLM mood, event hypothesis, sentiment ratios and representative comments per peak.",
                        "default": "stats"
                    },
                    "peak_count": {
                        "title": "Number of peaks",
                        "minimum": 1,
                        "maximum": 30,
                        "type": "integer",
                        "description": "How many top peaks to return.",
                        "default": 10
                    },
                    "clip_shift_seconds": {
                        "title": "Clip start shift (seconds)",
                        "minimum": -120,
                        "maximum": 120,
                        "type": "integer",
                        "description": "Shift applied to clip start timestamps. Negative = start the clip earlier than the chat peak (chat reacts AFTER the moment happens).",
                        "default": -15
                    },
                    "keywords": {
                        "title": "Keywords",
                        "type": "array",
                        "description": "Optional keywords to extract from chat (e.g. clip requests, character names).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "language_hint": {
                        "title": "Output language",
                        "enum": [
                            "ja",
                            "en"
                        ],
                        "type": "string",
                        "description": "Language for generated labels.",
                        "default": "ja"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration (metadata fetch)",
                        "type": "object",
                        "description": "Proxy for the metadata extraction step. RESIDENTIAL is required in practice; the bulky chat download always uses cheap datacenter proxy automatically.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
