competitor-video-tagging
竞品KOL视频打标分析。给一个YouTube/TikTok视频链接,自动下载、AI分析内容与评论、 按11个维度结构化打标、写入飞书多维表格,低置信度自动通知人工复核。 用法: /kol <视频链接> | /kol check 触发词: 分析视频, 打标, 竞品分析, KOL分析, 视频分析, 标签, tag, 看看这个视频, 帮我分析一下
来源信息
- 仓库
- ArcoCodes/KOL-tag-skill
- 最近来源活动
- 2026年7月21日 13:20
- 检测到的 SKILL.md 语言
- 多语言混合
- 星标
- 1
- 分支
- 0
安装方式
默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。
检查来源文件
决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。
正在显示 SKILL.md
SKILL.md
来源说明 · 只读预览- name
- competitor-video-tagging
- description
- 竞品KOL视频打标分析。给一个YouTube/TikTok视频链接,自动下载、AI分析内容与评论、 按11个维度结构化打标、写入飞书多维表格,低置信度自动通知人工复核。 用法: /kol <视频链接> | /kol check 触发词: 分析视频, 打标, 竞品分析, KOL分析, 视频分析, 标签, tag, 看看这个视频, 帮我分析一下
- allowed-tools
- Bash, Read, Write, Agent
# KOL Video Analysis
Analyze competitive KOL videos: download → frame extraction → visual analysis → structured tagging → write to Feishu.
## Constants
These values are hardcoded — do NOT read them from env vars:
```
LARK_APP_ID = cli_a90f1add2f7adbd9
FEISHU_WEBHOOK = https://open.feishu.cn/open-apis/bot/v2/hook/f843afd5-611b-4cc4-8f25-17c34c906fb0
BITABLE_APP_TOKEN = WEcDbjFnKa48YbsKa8qc8auQnlc
BITABLE_TABLE_ID = tbl6azeK9h2l6ugm
```
## Step 0: Update Check (every run, silent)
If the skill directory is a git repo (not a symlink target check — check the resolved path), check for upstream updates:
```bash
SKILL_DIR="$(cd "${CLAUDE_SKILL_DIR}" && pwd -P)"
if [ -d "$SKILL_DIR/.git" ]; then
git -C "$SKILL_DIR" fetch --dry-run 2>&1
fi
```
**If fetch shows new commits** → print a one-line notice and ask the user:
```
🔄 KOL Skill 有新版本可用。是否更新?(更新不会影响本次运行)
```
If user confirms → run `git -C "$SKILL_DIR" pull --ff-only`. If pull fails (local changes), print:
```
更新失败:本地有未提交的修改。请手动处理后重试。
```
If user declines or fetch shows nothing → proceed silently.
## Step 0b: Environment Gate (every run)
Run this silent preflight:
```bash
lark-cli api GET /open-apis/bitable/v1/apps/WEcDbjFnKa48YbsKa8qc8auQnlc/tables/tbl6azeK9h2l6ugm/fields \
--as bot --profile kol-bot --jq '.data.total' 2>/dev/null
```
**If it returns a number** → environment is ready, proceed to Subcommand Routing silently. Do NOT print anything.
**If it fails** → run the setup flow below:
### Setup Flow
**Phase 1: Check CLI tools**
```bash
MISSING_TOOLS=""
command -v yt-dlp >/dev/null || MISSING_TOOLS="${MISSING_TOOLS} yt-dlp"
command -v ffmpeg >/dev/null || MISSING_TOOLS="${MISSING_TOOLS} ffmpeg"
command -v lark-cli >/dev/null || MISSING_TOOLS="${MISSING_TOOLS} lark-cli"
```
If any tools are missing, install them directly:
```bash
# for yt-dlp / ffmpeg:
brew install <missing>
# for lark-cli:
npm install -g lark-cli
```
**Phase 2: Check secrets (only two needed from user)**
Check env vars `LARK_APP_SECRET` and `RENOISE_API_KEY`:
```bash
test -n "$LARK_APP_SECRET" && test -n "$RENOISE_API_KEY"
```
If either is missing, ask the user to provide them **one at a time** using the AskUserQuestion tool:
- If `LARK_APP_SECRET` is missing → ask: "请输入飞书应用的 App Secret(找项目负责人获取):"
- If `RENOISE_API_KEY` is missing → ask: "请输入 Renoise API Key(在 Claude Code 中运行 /install-plugin renoise 安装后获取):"
After the user provides each value, **immediately** append it to `~/.zshrc` and load it:
```bash
echo 'export LARK_APP_SECRET="<user-provided-value>"' >> ~/.zshrc
export LARK_APP_SECRET="<user-provided-value>"
```
```bash
echo 'export RENOISE_API_KEY="<user-provided-value>"' >> ~/.zshrc
export RENOISE_API_KEY="<user-provided-value>"
```
**Phase 3: Configure lark-cli bot profile**
```bash
echo "$LARK_APP_SECRET" | lark-cli config init --app-id "cli_a90f1add2f7adbd9" --app-secret-stdin --name kol-bot
```
Retry the preflight. If it still fails, print:
```
飞书应用认证失败。请检查:
1. App Secret 是否正确
2. 飞书应用是否已开通「多维表格」权限
3. 多维表格是否已将该应用添加为协作者
联系项目负责人排查。
```
All `lark-cli` commands in this skill MUST use `--as bot --profile kol-bot`.
## Subcommand Routing
Parse the skill args to determine the action:
1. If args starts with `check` → run environment check (see Check section)
2. If args is a URL → run full pipeline
3. Otherwise → show usage: `/kol <youtube-or-tiktok-url>` or `/kol check`
## Platform Detection & Download
Check the URL pattern to determine platform and download tool:
| URL Pattern | Platform | Download Method |
|------------|----------|----------------|
| `youtube.com/watch?v=`, `youtu.be/`, `youtube.com/shorts/` | YouTube | yt-dlp |
| `tiktok.com` | TikTok | tikhub (via scripts/fetch-tikhub.sh if available) or yt-dlp |
| `instagram.com` | Instagram | Report "Instagram support coming soon" and stop |
| Other | — | Report "Unsupported platform" and stop |
## Full Pipeline
### Step 1: Download Video & Metadata
Create working directory:
```bash
VIDEO_ID="<extracted-video-id>"
WORK_DIR="/tmp/kol-work/$VIDEO_ID"
mkdir -p "$WORK_DIR"
```
**YouTube:**
```bash
bash ${CLAUDE_SKILL_DIR}/scripts/fetch-youtube.sh "<url>"
```
Outputs to `/tmp/kol-work/<video-id>/`:
- `metadata.json` — yt-dlp JSON with all video/channel data and comments
- `video.mp4` — downloaded video file
- `subtitles.srt` — YouTube subtitles (auto-generated or manual, if available)
**TikTok:**
```bash
yt-dlp -f best -o "$WORK_DIR/video.mp4" --write-info-json -o "$WORK_DIR/metadata.json" "<url>"
```
Read `metadata.json` and extract metadata fields:
| yt-dlp JSON key | Bitable Field | Format |
|-----------------|---------------|--------|
| `channel` or `uploader` + `channel_url` | KOL/账号 | `{"link":"<channel_url>","text":"<channel_name>"}` |
| `channel_follower_count` | 粉丝量 | integer string, e.g. `"298000"` |
| `title` | 内容标题 | plain string |
| `duration` | 视频时长 | `"MM:SS"`, e.g. `"13:09"` |
| `upload_date` | 发布日期 | `"YYYY-MM-DD"` |
| `view_count` | 视频播放量 | integer string, e.g. `"40195"` |
| `language` or detect from title/description | 语言 | plain string |
Also set: 平台 = detected platform, 内容链接 = `{"link":"<url>","text":"<url>"}`.
### Step 2: Frame Extraction & Visual Analysis
Extract key frames from the video for visual analysis:
```bash
bash ${CLAUDE_SKILL_DIR}/scripts/analyze-video.sh "$WORK_DIR/video.mp4"
```
This produces:
- `$WORK_DIR/frames/frame_NNN.jpg` — extracted frames (every 3 seconds)
- `$WORK_DIR/audio.srt` — transcript (uses yt-dlp subtitles if available, otherwise falls back to Whisper)
**Primary analysis path — Gemini:**
```bash
GEMINI_SCRIPT="${CLAUDE_PLUGIN_ROOT:-/Users/l13/.claude/plugins/cache/renoise-plugins-official/renoise/0.2.1}/skills/gemini-gen/scripts/gemini.mjs"
```
Send the video file directly to Gemini for comprehensive analysis:
```bash
node "$GEMINI_SCRIPT" --file "$WORK_DIR/video.mp4" --mode video-script
```
Then run a structured analysis prompt with the tagging dimensions:
```bash
node "$GEMINI_SCRIPT" --file "$WORK_DIR/video.mp4" \
"Analyze this video for content tagging. For each dimension below, identify the best match:
1. 应用场景 (Application Scenario): What is this video used for? Options: 付费广告投放, 电商站内转化, 社媒账号运营, 品牌与企业传播, 影视与娱乐内容, 音乐与演出内容, 艺术与动漫创作, 个人与实验创作, 其他
2. 内容方向 (Content Direction): What is the core narrative about? Options: 商品展示, 功能演示, 使用教程, 产品测评/对比, 用户体验/口碑, 痛点解决, 成本/效率对比, 变现/赚钱叙事, 品牌故事, 剧情/娱乐叙事, 创意/视觉展示, 功能发布/新品预热, 其他
3. 呈现形式 (Presentation Format, multi-select): How is the content presented? Options: 人物口播, UGC体验分享, 商品展示, 屏幕录制, 操作演示, 教程讲解, 前后对比, 多产品横评, 案例展示, 剧情演绎, 采访/对谈, 素材混剪, 动画/动态图形, 音乐视觉/MV, 静态图文, 其他
4. 制作主体 (Production Subject): Who appears? Options: 真人出镜, AI虚拟人/AI网红/虚拟IP, 实拍为主(无真人出镜,录屏为主)
5. 视觉风格 (Visual Style): What is the visual aesthetic? Options: UGC真实感, 电影感, 动漫风, 写实商业, 艺术化, 其他
6. 媒介规格 (Media Spec): Options: 静态图片, 短视频, 长视频, 横屏, 竖屏
7. 证据卖点 (Selling Points): What product advantages are highlighted? Options: 生成质量, 角色一致性, 产品一致性, 生成速度, 操作简单, 模型丰富, 成本更低, 批量生产, 广告转化效果, 免费/低门槛, 模板丰富, 工作流自动化, 多语言, 商用能力, 其他
8. CTA (Call to Action): What actions are viewers asked to take? Options: 点击链接, 访问官网, 免费试用, 注册账号, 订阅/付费, 使用优惠码, 评论关键词, 私信获取, 下载资料, 加入社群, 关注账号, 点赞/收藏/转发, 观看完整教程, 无明确CTA, 其他
9. 品牌/竞品: Which AI video tool brand is featured or promoted? Options: Higgsfield, OpenArt, SeaArt, Arcads, Pollo
10. 项目来源: Is this 自有项目, 客户委托, 合作项目, or 竞品样本?
11. 语言: What language is the video primarily in?
For dimensions with 主要/次要: identify both if applicable. 主要 is the core narrative; 次要 must have clear screen time, otherwise leave empty.
For multi-select dimensions: list all that apply.
Also assess: how confident are you in this tagging overall (1-10 scale)? If below 5, explain what's ambiguous."
```
**Fallback path — Frame-by-frame analysis:**
If Gemini direct video analysis fails, analyze extracted frames in batches of 10:
```bash
node "$GEMINI_SCRIPT" --file frame_001.jpg --file frame_002.jpg ... --file frame_010.jpg \
"These are sequential frames from a video (one frame every 3 seconds). Describe the content, visual style, presentation format, and any text/CTA visible."
```
Read the `.srt` subtitle file content directly. Combine frame analysis + subtitle text to produce the analysis.
### Step 3: Tagging
Read `${CLAUDE_SKILL_DIR}/references/tagging-rules.md` for the complete tagging dictionary.
Based on the analysis from Step 2, assign tags for each dimension. Rules:
1. **Only use values defined in tagging-rules.md** — never invent new values
2. **主要/次要 fields**: 主要 = core narrative; 次要 must have clear screen time, otherwise leave empty; the two MUST be different
3. **Multi-select fields**: join values with `|` (full-width pipe), no sorting, no duplicates
4. **置信度**: assign 1-10 integer based on overall tagging confidence
5. **Agent的困惑**: if 置信度 < 5, MUST explain what's ambiguous (see tagging-rules.md for format)
Build the fields object mapping analysis results to Bitable field names:
```
记录ID → auto-generate or leave to system
品牌/竞品 → SingleSelect: "Higgsfield" | "OpenArt" | "SeaArt" | "Arcads" | "Pollo"
平台 → "YouTube" | "TikTok" | etc.
KOL/账号 → {"link":"<channel-url>","text":"<channel-name>"} (Url field)
粉丝量 → follower count as integer string, e.g. "298000" (not "29.8万" or "298K")
内容标题 → video title
内容链接 → {"link":"<url>","text":"<url>"} (Url field)
视频时长 → "MM:SS" format, e.g. "13:09" (not "13m 09s")
视频播放量 → view count as integer string, e.g. "40195" (not "4万" or "40.2K")
语言 → detected language
发布日期 → "YYYY-MM-DD"
项目来源 → tagged value
应用场景-主要 → tagged value
应用场景-次要 → tagged value or empty
内容方向-主要 → tagged value
内容方向-次要 → tagged value or empty
呈现形式(多选) → "value1|value2|..."
制作主体(单选) → tagged value
视觉风格(多选) → "value1|value2" or single value
媒介规格(多选) → "value1|value2" or single value
证据卖点-主要 → primary selling point
证据卖点-次要 → secondary selling point or empty
CTA(多选) → "value1|value2|..."
置信度(1-10) → confidence score as string
Agent的困惑 → confusion explanation (required if confidence < 5)
评论分析 → comment analysis summary (from Step 3b)
```
### Step 3b: Comment Analysis
Extract comments from `metadata.json` (fetched in Step 1).
先看评论数量,结合播放量给出受众互动判断(如:11000+播放仅2条评论,说明受众参与度低、社区粘性弱)。然后再分析评论内容:
1. **核心观点** — 评论中反复出现的观点或情绪倾向
2. **用户痛点** — 观众提到的问题、吐槽或未被满足的需求
3. **产品反馈** — 对视频中展示的产品/工具的具体评价(正面或负面)
4. **竞品对比** — 评论中是否提到其他竞品工具?怎么说的?
5. **需求信号** — 功能请求、"要是能..."之类的信号
根据实际评论内容如实总结。评论少就简要概括能看出什么,评论多就详细展开。不需要凑字数,有什么说什么。
Output format (plain text, written to 评论分析 field):
```
受众互动:<对评论数量的判断,如"XX次播放仅X条评论,受众参与度较低">
核心观点:<summary>
用户痛点:<summary or "无">
产品反馈:<summary or "无">
竞品对比:<summary or "无">
需求信号:<summary or "无">
(基于 <N> 条评论)
```
If the video has no comments, write `"无评论"`.
### Step 4: Write to Feishu
Read `${CLAUDE_SKILL_DIR}/references/bitable-schema.md` for field IDs and value formats.
First, check if a record with the same URL already exists:
```bash
lark-cli api GET /open-apis/bitable/v1/apps/WEcDbjFnKa48YbsKa8qc8auQnlc/tables/tbl6azeK9h2l6ugm/records \
--as bot --profile kol-bot --params '{"filter":"CurrentValue.[内容链接]=\"<url>\"","page_size":"1"}'
```
If a record exists, use PATCH to update (preserve human-added 备注):
```bash
lark-cli api PATCH /open-apis/bitable/v1/apps/WEcDbjFnKa48YbsKa8qc8auQnlc/tables/tbl6azeK9h2l6ugm/records/<record_id> \
--as bot --profile kol-bot --data '{"fields":{ ... }}'
```
If no record exists, use POST to create:
```bash
lark-cli api POST /open-apis/bitable/v1/apps/WEcDbjFnKa48YbsKa8qc8auQnlc/tables/tbl6azeK9h2l6ugm/records \
--as bot --profile kol-bot --data '{"fields":{ ... }}'
```
在 GitHub 查看这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看