Skip to main content
Glama

mcp-video-learn

让大模型**真的“看”**视频和动图:画面抽帧 + 字幕 + 一张网格图。

模型只认识文本和图片。你丢给它一个视频链接,它通常只能读到网页标题;丢给它一个表情包, 它只看到一串文件名。这个 MCP 服务把「视频 / 动图 / 图片」统一变成模型一次就能读完的东西: 一张按时间抽帧拼成的网格图,加上能拿到的字幕文本。


它提供三个工具

工具

做什么

输入

bili_video_info

只看元信息,不下载

B 站链接

bili_video_watch

看 B 站视频:下载 → 抽帧 → 字幕

B 站链接

media_frames

看任意动的东西:本地文件 / 直链 / B 站

路径、URL、B 站链接

判断值不值得看 → bili_video_info
看视频讲什么   → bili_video_watch
识别表情包     → media_frames("C:/stickers/怼脸.gif")
看视频结尾     → media_frames("D:/clips/live.mp4", strategy="recent")

Related MCP server: claude-real-video

30 秒上手

# 1. 依赖:ffmpeg 必须在 PATH 里
ffmpeg -version

# 2. 安装
npm install -g mcp-video-learn

# 3. 接到你的 MCP 客户端(以 DSH 为例)
- id: mcp-video-learn
  name: '@deepseek-ai/dsh-mcp'
  config:
    command: npx
    args: ['-y', 'mcp-video-learn']
    env:
      VIDEO_FFMPEG: /usr/bin/ffmpeg

其它客户端(Claude Desktop 等)同理:command + args 指向本服务即可。


支持哪些格式(先看这张表)

格式

能不能看

需要额外装东西吗

视频 .mp4 .mkv .webm .mov .flv

✅ 能

不需要

GIF 动图 .gif

✅ 能(完全没问题)

不需要

静态图 .png .jpg .webp(单帧)

✅ 能

不需要

动图 WebP .webp(多帧)

⚠️ 看情况

需要装 sharp(或系统 ffmpeg 6.x)

一句话:GIF 和视频开箱即用;只有「动图 WebP」需要额外装一个 sharp。

为什么动图 WebP 特殊:它是 Google 的格式,系统自带的 ffmpeg 4.x 只能读第一帧。 装上 sharp 就能逐帧看(npm i sharp);装不上也没关系——其它格式照常工作, 只是动图 WebP 会明确告诉你缺什么,而不是给你一张黑图。


原理:九宫格不是“随便抽 9 帧”

底层是一个容量固定的 FIFO 队列:

画面进来 → 只有「画面发生明显变化」才入队 → 队列满了淘汰最旧的一帧(先进先出)

为什么这么做:一段 5 分钟的视频里可能 4 分钟是静止画面。均匀抽 9 帧会把 7 格 浪费在重复画面上;按“变化才入队”,这 9 格覆盖的是全程最有代表性的 9 个瞬间。

队列的两种取用方式(strategy 参数):

策略

取什么

用来回答

overview(默认)

把变化点均匀摊开取 N 个

“这视频讲了什么”

recent

队列最终快照(最近 N 个变化,FIFO 淘汰语义)

“现在在干嘛 / 结尾发生了什么”

同一套队列,同一个网格,换一个参数就是另一种视角。

拿不到场景变化时(纯色画面、极短片段),自动退回均匀采样——两种路径对调用方透明, 返回文本里会写清楚这次用的是哪种(mode=scene / mode=uniform)。

同一套逻辑覆盖所有媒体

输入

帧数

取样方式

视频

9(3×3)

画面变化 → FIFO 队列

动图 GIF

6(3×2)

按时长均分(一个循环正好铺满)

静态图

1

原样

调用方不需要知道自己拿到的是哪种媒体。


三种输入,一个入口

media_frames 接受任意一种:

输入

例子

处理方式

本地文件

C:/stickers/怼脸.gif

必须在白名单目录内(见下方安全)

媒体直链

https://x.com/a.gif

只接受媒体扩展名,限体积

B 站链接

https://b23.tv/xxxx

走官方 API(见下节)


B 站:走官方 API,机房 IP 也能用

云服务器/机房 IP 抓 www.bilibili.com 会被 412 拦(cookie 也救不了,拦的是网页请求)。 所以本服务不抓网页,直接用官方接口:

view 接口   → 标题 / UP 主 / 时长 / cid
wbi 签名    → playurl 拿视频流地址
player/v2   → 字幕列表 → 下载字幕 JSON
直接下流    → ffmpeg 抽帧拼网格

buvid3 会自动向 /x/frontend/finger/spi 申请,不登录也能取元信息。

需要登录态时(可选)

想要更高码率、或视频有权限限制时,配一个小号 cookie(务必用小号,不要用主号):

# 方式一:Netscape 格式的 cookies.txt
export BILI_COOKIES=/root/bili-cookies.txt

# 方式二:一行 cookie 串(脚本只保留必要的几个字段)
export BILI_COOKIE="$(node scripts/cookies-to-env.mjs /root/bili-cookies.txt)"

怎么拿到 cookies:

  1. 用 Chrome / Edge 登录 B 站小号,打开 bilibili.com;

  2. 装扩展 Get cookies.txt LOCALLY,点 Export → 得到 cookies.txt;

  3. 传到服务器并收紧权限:

scp cookies.txt root@<host>:/root/bili-cookies.txt
ssh root@<host> "chmod 600 /root/bili-cookies.txt"

cookie 等于登录态:不要提交到 git、不要发到聊天里。 没有 cookie 时元信息与大部分下载仍可用(qn=32,约 480p)。


动图 WebP 支持矩阵

情况

行为

静态 WebP

✅ ffmpeg 直接处理

动图 WebP + 装了 sharp

✅ 逐帧解码后拼网格(mode=webp-sharp)

动图 WebP + 没装 sharp

❌ 明确报错,告诉你装什么

动图 WebP + ffmpeg 6.x

✅ 走 ffmpeg 正常路径

坏掉的 WebP

❌ 识破并报错(不会输出一张空白图)

装 sharp(可选依赖,不装也能用其它格式):

npm i sharp
# 或者复用宿主里已装的 sharp:
export SHARP_MODULE=/path/to/node_modules/sharp

为什么值得装:QQ / 微信里的表情包很多是动图 WebP;不装的话这类表情只能看到报错。


配置项

全部通过环境变量,没有配置文件:

变量

默认

说明

VIDEO_FFMPEG

ffmpeg

ffmpeg 可执行文件

VIDEO_YTDLP

yt-dlp

仅作为 B 站 API 失败时的兜底

VIDEO_COOKIES

—

兼容旧名;等同 BILI_COOKIES

BILI_COOKIES

—

B 站 cookies.txt(Netscape 格式)

BILI_COOKIE

—

B 站 cookie 串(SESSDATA=...; bili_jct=...)

VIDEO_AUDIT

~/.cache/mcp-video-learn/audit.jsonl

审计日志

VIDEO_MAX_MB

60

单次下载体积上限(MB)

VIDEO_ALLOW_ROOTS

当前目录 + 临时目录

media_frames 允许读取的本地目录(路径分隔符分隔)

SHARP_MODULE

—

复用宿主已装的 sharp


实测数据与验证

这个插件的“能跑”不是推测,是分层跑出来的:

层

命令

覆盖

结果

单元

npm test

FIFO 队列语义、URL 校验、网格计算、cookie 头拼装

20/20

真实媒体矩阵

npm run selftest:matrix

mp4/gif/webp/png、1s40s、横竖屏、frames 112、tileWidth 64~640、坏文件、白名单

69/69

MCP 协议

npm run selftest:mcp

真实拉起服务、列工具、调工具、拒非法输入、真实 B 站 watch

8/8

性能(服务器实测,5 分钟 640×360 视频):场景检测 3.1 秒,生成九宫格 9.2 秒。 B 站真实视频:3 分 33 秒的 MV,下载 10 MB / 10.5 秒,9 帧网格 + 522 字字幕。

踩过并修掉的坑(写给后来的人)

  1. ffmpeg 4.4 没有 -fps_mode —— 会报 Unrecognized option,必须用 -vsync vfr;插件自动探测版本。

  2. select=gt(scene,…) 只比亮度 —— 红→绿这种“亮度接近、色度差异大”的切换会整段漏掉。 改用 tblend 差分 + signalstats 取 Y/U/V 最大值。

  3. tile 必须凑满 cols×rows 才输出 —— 场景点不足时要补均匀时间点,否则一张图都出不来。

  4. 机房 IP 抓 B 站网页 412 —— 元信息与下载都改走官方 API(带 buvid3)。

  5. ffmpeg 4.4 解不开动图 WebP —— 用 sharp 兜底;坏文件会被识破(libvips 会把残缺文件解成空白页却不报错)。

  6. 同一功能写了两份实现 —— 测试测的是 A 文件、服务跑的是 B 文件;现在统一到 src/pipeline.js。


已知限制

  • 动图 WebP 需要 sharp 或 ffmpeg ≥ 6.x。

  • B 站:走 API 可下 480p;更高清晰度/会员内容需要登录 cookie。

  • 抽帧是采样,不是逐帧分析:极长的视频只能看到代表点。

  • 字幕只反映台词/讲解;纯语音或音乐视频拿不到内容。

  • 只读:不下载到用户目录、不上传、不发布任何内容。


安全边界

措施

目的

本地路径白名单(VIDEO_ALLOW_ROOTS)

防止变成任意文件读取器

直链只认媒体扩展名

防止变成通用下载器

体积上限(VIDEO_MAX_MB)

防止磁盘/带宽被打满

步骤超时

防止卡死

审计日志(本地)

每次调用留痕

只接受 bilibili.com / b23.tv

链接白名单


开发

src/index.js      MCP 服务:工具注册与参数校验
src/pipeline.js   抽帧管线:场景检测 / FIFO 队列 / 网格生成(可独立测试)
src/filmstrip.js  固定容量队列与两种取用策略(纯函数)
src/media.js      格式判定、网格计算、ffprobe 结果归一(纯函数)
src/bili-api.js   B 站官方 API:wbi 签名、playurl、字幕(机房 IP 可用)
src/webp-sharp.js 动图 WebP 的 sharp 解码(可选依赖)
src/lib.js        URL 校验、字幕清洗、时长格式化(纯函数)
scripts/          三层自测 + cookie 转换工具
test/             node:test
npm test                    # 单元测试
npm run selftest:matrix     # 真实媒体矩阵(需要 ffmpeg)
npm run selftest:mcp        # MCP 协议层(需要依赖已装)

许可

MIT © 2026 HOHOLI

Available Tools

3 tools
bili_video_infoA

看一个 B 站视频的元信息(不下载):标题、UP 主、时长、简介摘要、有没有字幕。用于判断值不值得看。

NameRequiredDescriptionDefault
urlYesB 站链接(含 b23.tv 短链)

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations supplied, the description carries the full behavioral burden. It does disclose that nothing is downloaded (an implicit read-only/no-side-effect signal) and that the description is only a summary ('简介摘要'), which usefully implies truncated content. It says nothing about authentication, rate limits, failure modes for invalid or region-locked links, or whether subtitle presence means availability versus fetchability.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short clauses with zero waste: the returned fields are front-loaded, the 'not a download' qualifier appears immediately after the verb, and the use case closes the sentence. Nothing could be removed without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter lookup tool with no output schema, the description compensates by enumerating the concrete return fields, which is exactly what an agent needs to decide whether to call it. Absence of annotations means the safety/error profile is left unstated, which is the only meaningful gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is exactly one parameter with 100% schema description coverage, and the schema already explains it takes a Bilibili URL including b23.tv short links. The description adds no further meaning about accepted URL forms or normalization, so the baseline of 3 applies when the schema does all the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource ('看一个 B 站视频的元信息') and enumerates exactly what comes back: title, uploader, duration, description summary, subtitle presence. The parenthetical '(不下载)' implicitly contrasts it with the download/watch sibling, but does not name bili_video_watch outright, so the differentiation requires a small inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'用于判断值不值得看' states a concrete use case, establishing clear context for when to reach for this tool rather than a downloading one. It stops short of explicitly routing the agent to bili_video_watch when full playback or media retrieval is wanted, so there are no stated exclusions or named alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

bili_video_watchA

真正“看”一个 B 站视频:走官方 API 下载低清流(机房 IP 也可用)→ 抽 N 帧拼成网格 + 字幕文本。适合回答“这个视频讲了什么”。注意:只有字幕能反映台词/讲解,纯语音内容会缺失。

NameRequiredDescriptionDefault
urlYesB 站链接
framesNo抽几帧,默认 9

TDQS

A3.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are supplied, so the description carries the full behavioral burden. It does disclose useful traits — official API, low-resolution stream, works from datacenter IPs, frame count 4–12, and the subtitle-only limitation for speech. However, it says nothing about latency/cost of downloading a full video, failure modes for unavailable or subtitle-less videos, or what the returned payload looks like, leaving significant gaps for a network-heavy tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and workflow are front-loaded in a single arrow-chained sentence, followed by a use case and a caveat — no filler. The arrow-chain is slightly dense to parse, but every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with no annotations and no output schema, the description covers the essential mechanics, the use case, and the main limitation. It would be stronger with a note on runtime cost and on behavior when a video has no subtitles, but nothing critical for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already documented. The description adds a small amount of meaning by explaining that the extracted frames are tiled into a grid, but it does not clarify tradeoffs of choosing more vs fewer frames beyond the schema's 4–12 bounds.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource — actually 'watching' a Bilibili video by downloading the official low-bitrate stream and extracting N frames into a grid plus subtitle text. It also names the concrete question it answers ('what is this video about'), which separates it from bili_video_info (metadata) and media_frames (generic extraction).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear use condition ('适合回答"这个视频讲了什么"') and a caveat that only subtitles carry spoken/dialogue content, which implicitly steers speech-only content elsewhere. It stops short of explicitly naming the sibling tools or stating exclusions, so it falls just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

media_framesA

把任意“动的东西”变成模型能看懂的帧网格:本地 GIF/WebP/视频、媒体直链、或 B 站链接。适合识别动图表情包、看短视频、检查本地素材。返回元信息(尺寸/帧数/时长)+ 一张网格图。

NameRequiredDescriptionDefault
inputYes本地路径、媒体直链(.gif/.webp/.mp4…)或 B 站链接
framesNo抽几帧;动图默认 6,视频默认 9
strategyNo视频取帧策略:overview 均匀覆盖全程(默认);recent 取最近 N 个变化瞬间(FIFO 队列快照)
tileWidthNo每帧宽度(像素),默认 240

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are supplied, so the description must carry the full behavioral burden. It partially does: it discloses accepted input sources and the return shape (metadata plus one grid image), but it omits network/IO behavior for remote or bilibili inputs, the 12-frame cap, failure modes, and cost/latency implications.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is short: three compact clauses cover purpose, input sources, use cases, and return value. The phrasing is slightly informal, and it front-loads the core purpose, but the return-value detail at the end could be reordered to come earlier.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Because there is no output schema, the description's statement of the return value (dimensions, frame count, and duration, plus a grid image) is essential, and the description supplies it. Combined with the 100%-covered input schema, an agent has almost everything it needs, though remote fetching and failure handling remain unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents the input, frame count defaults, the strategy enum, and the tile width range. The description adds no parameter-level meaning beyond what the schema says; the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a concrete verb+resource: convert local GIF/WebP/video, media direct links, or bilibili links into a frame grid. It differs implicitly from the siblings bili_video_info and bili_video_watch by covering any media source, not just bilibili, but it never names those siblings, so the differentiation stays implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete usage scenarios: recognizing animated memes, watching short videos, checking local assets. However, it never says when to prefer bili_video_watch or bili_video_info over this tool, and it gives no exclusions or prerequisites (for example, whether bilibili downloads need auth).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.7.0
    • First observedbili_video_info
    • First observedbili_video_watch
    • First observedmedia_frames

TDQS

A3.6/5.0

Scored across 3 tools

Disambiguation3/5

bili_video_info is clearly a metadata-only check, but bili_video_watch and media_frames both accept Bilibili links and both return frame grids, creating real overlap. The descriptions do try to separate them (talking-head/subtitle use case vs. generic animated media), so an agent can usually choose correctly, but the boundary requires reading carefully.

Naming Consistency3/5

Two tools share a bili_video_ resource prefix while the third uses a generic media_ prefix, and the verb/action component varies (info = noun, watch = verb, frames = noun). Readable and domain-suggestive, but no predictable verb_noun pattern across the set.

Tool Count4/5

Three tools is on the lean side but each covers a distinct stage (triage metadata → deep watch → generic media inspection), so nothing feels redundant filler. The scope is intentionally narrow, so a small count is defensible.

Completeness4/5

The core workflow—decide whether to watch, then extract frames plus subtitles, plus a generic media path—is covered end to end. Gaps remain: no subtitle/transcript-only retrieval, no timestamp-targeted frame extraction, and pure-speech content is explicitly unsupported, which will dead-end some 'what does this say' queries.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to watch YouTube videos by extracting frames at scene changes and visual references, pairing each frame with the exact words spoken at that timestamp. Provides dense frame-transcript interleaving for any model.
    32 npm
    5
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables coding agents to turn videos from social platforms or local files into a small set of distinct frames plus a manifest, so they can answer visual questions by reading image paths. Also provides metadata lookup for captions and authors without downloading the video.
    2
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI clients to watch local video files or YouTube/Bilibili and other supported URLs, receiving timestamped transcripts, subtitles, searchable text and keyframe contact sheets. Runs fully offline with local speech recognition and bundled ffmpeg, so no API key or cloud upload is needed.
    6
    74 PyPI
    13
    MIT