Skip to main content
Glama
README.md
# nichescan — Douyin/TikTok Short-Video Hook & Transcript Analysis

> **抖音 / TikTok 短视频转录、爆款开头分析与收藏意图排序工具。**

> **You are ranking by likes, so you are studying the wrong videos.**
> Short-video search APIs never return play counts. nichescan ranks a whole niche
> by **save intent** and reads what creators **actually said** — not their captions.

**Search terms:** Douyin ASR · Douyin transcript · TikTok transcript · short-video hook analysis · viral hook analysis · competitor content research · save-ratio analysis

[English](#english) · [中文](#中文)

```bash
uvx nichescan rank ./data/*.jsonl        # no API key, no ffmpeg, runs now
```

<p align="center">
  <img src="docs/images/report-card.png" width="88%" alt="nichescan report: openings ranked by save intent">
</p>

<p align="center">
  <em>Real output on 60 clips. Highest reach was <code>money-opportunity</code>;
  highest save intent was <code>named-deliverable</code> — copying the
  most-liked clip would have been the wrong move.</em>
</p>

---

## English

### What users search for

nichescan is a **Douyin/TikTok short-video transcript and hook analysis tool**.
It helps you:

- transcribe Douyin videos with ASR / speech-to-text
- analyse TikTok and short-video hooks
- rank competitors by save ratio and engagement intent
- find reusable opening structures from real speech
- generate niche-level competitor content research reports

中文:支持**抖音视频语音转文字、抖音爆款开头分析、短视频竞品分析、短视频文案结构拆解、收藏率 / 藏赞比分析、TikTok短视频内容研究**。

### The two mistakes almost every content tool makes

**1. Ranking by likes measures reach, not usefulness.**
A like is one tap. A save means *"I want this again later"* — and revisiting is
what precedes buying. Measured on a real 55-clip cohort in the enterprise-AI
niche:

| Opening style | Mean likes | Mean saves per like |
|---|---:|---:|
| Tutorial / method | 147,336 | **0.81** |
| Money opportunity | 362,146 | 0.49 |
| Direct question | 119,011 | 0.24 |
| Trend prediction | 52,701 | 0.18 |
| Workplace comedy | 12,950 | 0.46 |

The money-opportunity clips won on likes by 2.5x — and lost on save intent.
Six clips in that cohort were **saved more often than liked** (ratio above 1.0).
Like counts cannot see any of this.

**2. Captions are not speech.** The title and the spoken first three seconds are
routinely different. Analysing titles means analysing the wrong object, so
nichescan transcribes the audio.

### Install

```bash
uvx nichescan --help              # zero install
pipx install nichescan            # or keep it around
pip install "nichescan[mcp]"      # with MCP server
```

The core package has **no dependencies**. `rank` works immediately.
`scan` additionally needs `ffmpeg` and an ASR key.

### Use it

nichescan does not crawl. Point it at whatever your crawler produced —
JSONL or CSV, from [MediaCrawler](https://github.com/NanmiCoder/MediaCrawler)
or anything else.

```bash
# 1. Metrics only. No key, no ffmpeg.
nichescan rank ./data/*.jsonl --days 60 --top 60

# 2. Rank by intent rather than reach
nichescan rank ./data/*.jsonl --sort save_ratio

# 3. Full pipeline: download, transcribe, aggregate
export DASHSCOPE_API_KEY=sk-...
nichescan scan ./data/*.jsonl --days 60 --top 60

# 4. Re-render without re-downloading
nichescan report -o ./nichescan-out

# 5. Render the shareable card shown above
nichescan render -o ./nichescan-out
```

Output:

```
nichescan-out/
├── shortlist.csv      ranked, with save_ratio and intent_band
├── transcripts.jsonl  resumable; interrupted runs pick up where they stopped
└── report.md          openings aggregated by save intent
```

### What the report tells you

```
| Opening pattern     | Clips | Mean likes | Mean save/like | What it promises        |
|---------------------|------:|-----------:|---------------:|-------------------------|
| method-promise      |     8 |    147,336 |           0.81 | A repeatable method     |
| already-happening   |     4 |    362,146 |           0.49 | An existing fact        |
| abstract-concept    |     3 |     88,120 |           0.08 | Opens on abstraction    |
```

Plus two lists that matter more than the table: **openings saved more than
expected**, and **popular but disposable** — structures to avoid even though
their like counts look good.

### ASR providers

| Provider | Flag | Key | Notes |
|---|---|---|---|
| Alibaba Qwen ASR | `--provider dashscope` | `DASHSCOPE_API_KEY` | Best Chinese accuracy in our tests |
| OpenAI-compatible | `--provider whisper` | `OPENAI_API_KEY` | Any compatible endpoint |
| FunASR (local) | `--provider funasr` | none | Free, heavier, weaker on proper nouns |

Long clips are segmented automatically (API duration caps) and oversized
payloads are compressed (base64 inflates bytes by a third).

### MCP server

Works in Claude Desktop, Cursor, Cherry Studio — anything speaking MCP.

```json
{
  "mcpServers": {
    "nichescan": {
      "command": "uvx",
      "args": ["--from", "nichescan[mcp]", "nichescan-mcp"],
      "env": { "DASHSCOPE_API_KEY": "sk-..." }
    }
  }
}
```

| Tool | Needs a key | Does |
|---|:--:|---|
| `rank_niche` | no | Rank records by save intent |
| `explain_metrics` | no | Explain the bands and why likes mislead |
| `classify_opening` | no | Label one opening line |
| `transcribe_clips` | yes | Download and transcribe real speech |
| `analyse_niche` | no | Aggregate openings across the cohort |

Then just ask: *"rank this niche by save intent and tell me which openings to copy"*.

### Claude Code skill

```bash
git clone https://github.com/JustinXai/nichescan
cd nichescan && bash install_skill.sh
```

### Python API

```python
from nichescan import load_records, shortlist, analyse, render_markdown

records = load_records(["data/*.jsonl"])
picked = shortlist(records, top=60, sort_by="save_ratio")
print(render_markdown(analyse(picked, transcripts)))
```

### Honest limits

- The engagement score is a **proxy**, not a play count. Nothing here can
  reconstruct plays, and any tool claiming otherwise is guessing.
- Pattern labels are lexical heuristics. They point you at cohorts worth
  reading; they do not judge quality.
- Save ratios vary by platform and niche. Recompute yours instead of importing
  the numbers above.
- Respect each platform's terms and each creator's rights. Study structure;
  do not republish other people's words.

---

## 中文

### 几乎所有内容工具都在犯的两个错

**第一,按点赞排序衡量的是传播,不是有用。**
点赞只是一次点击,收藏意味着「我以后还要用」——而反复回看才是成交的前置行为。
在企业AI赛道 55 条真实样本上实测:

| 开头类型 | 平均点赞 | 平均藏赞比 |
|---|---:|---:|
| 教程 / 给方法 | 147,336 | **0.81** |
| 财富机会 | 362,146 | 0.49 |
| 直接提问 | 119,011 | 0.24 |
| 趋势预测 | 52,701 | 0.18 |
| 职场段子 | 12,950 | 0.46 |

财富机会型点赞高出 2.5 倍,但收藏意图明显更低。这批样本里有 **6 条收藏数超过点赞数**。
只看点赞,这些全都看不见。

**第二,标题不等于口播。** 标题和真实前三秒经常完全不同。
只分析标题等于分析错了对象,所以 nichescan 直接转录音频。

### 安装

```bash
uvx nichescan --help              # 免安装直接跑
pipx install nichescan
pip install "nichescan[mcp]"      # 带 MCP server
```

核心包**零依赖**,`rank` 立刻能用。`scan` 需要 `ffmpeg` 和一个语音识别 key。

### 使用

nichescan **不做爬取**,它读你爬虫的产出(JSONL 或 CSV),
配合 [MediaCrawler](https://github.com/NanmiCoder/MediaCrawler) 等工具使用。

```bash
# 只算指标,不需要 key 和 ffmpeg
nichescan rank ./data/*.jsonl --days 60 --top 60

# 按收藏意图排序,而不是按传播
nichescan rank ./data/*.jsonl --sort save_ratio

# 完整流水线:下载 → 转录 → 汇总
export DASHSCOPE_API_KEY=sk-...
nichescan scan ./data/*.jsonl --days 60 --top 60
```

报告除了统计表,还会给两个更重要的清单:**收藏率异常高的开头**,
以及**点赞高但收藏极低的结构**——后者是即使数据好看也不该抄的写法。

### 说明与边界

- 互动分是**代理指标**,不是播放量。任何声称能还原播放量的工具都在猜。
- 开头分类是词法启发式,用于定位值得细读的样本,不构成质量评判。
- 藏赞比因平台和赛道而异,请用自己的数据重新计算。
- 遵守平台规则与创作者权益:学结构,不要搬运原文。

---

## License

MIT