关于 framefetch
framefetch 是将社交视频 URL 转为字幕、元数据、抽样帧、OCR 等结构化结果的 API 和 MCP 服务,面向需要搜索或分析多个平台视频的 Agent 与应用。
主要功能
- 01提取字幕、元数据和视频帧
- 02基于视频内容回答问题
- 03通过 OCR 识别画面文字
- 04按关键词搜索并批量处理最多 10 个 URL
- 05生成摘要、结构化数据和评论分析
适用场景
- 01回答有关社交视频的问题
- 02提取前按关键词查找视频
- 03分析视频画面和屏幕文字
- 04一次批量处理多个视频 URL
MCP 相关
通过 Streamable HTTP 提供 MCP 服务,包含 `framefetch_extract`、`framefetch_platform_capabilities`、`framefetch_search` 和 `framefetch_account` 工具。另有本地 stdio 桥接程序,将调用转发至托管服务。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://framefetch.net/mcpclaude mcp add --transport http marvinrey7879-framefetch https://framefetch.net/mcp{"mcpServers":{"marvinrey7879-framefetch":{"type":"http","url":"https://framefetch.net/mcp"}}}在 Cursor 中打开{"servers":{"marvinrey7879-framefetch":{"type":"http","url":"https://framefetch.net/mcp"}}}在 VS Code 中打开{"mcpServers":{"marvinrey7879-framefetch":{"type":"http","url":"https://framefetch.net/mcp"}}}{"mcpServers":{"marvinrey7879-framefetch":{"serverUrl":"https://framefetch.net/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
4| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| ask | string | 否 | 关于视频的问题(3–500 个字符);答案最多 500 个 token,包含带时间戳的引文,并以转录文本为依据(自动提取)。绝不缓存;如果不可用则降级处理(不收费)。对于较长的视频,答案取自按相关性选择/抽样的部分,而不只是开头——参见响应中的 `ask.coverage`。没有转录文本(例如 Pinterest)时,改用帧,并设置 `based_on`:["frames"]。 |
| url | string | 是 | 受支持平台上的公开视频 URL。 |
| cache | boolean | 否 | 设为 false 可强制重新提取并收费。 |
| voice | enum | 否 | "audio_digest" 的语音:OpenAI 语音(alloy/echo/fable/onyx/nova/shimmer)以及 Groq "Fritz-PlayAI";默认值为 "alloy"。alloy | echo | fable | onyx | nova | shimmer | Fritz-PlayAI |
| fields | array | 否 | 要返回的数据;默认值为 ["metadata"]。依赖项:digest→transcript;audio_digest→digest→transcript;structured→transcript;comment_sentiment→comments。digest/audio_digest/structured/comment_sentiment 失败时降级为警告,绝不收费。digest:通过 LLM 生成概要和主题。audio_digest:将 digest 生成为 mp3(签名 URL,有效期 24 小时);通过 `voice` 指定语音;其他语言的音频需使用 +`translate`。structured:通过视觉 LLM 提取章节/实体/展示的产品/声明/关键时刻。comments:最多返回 comments_cap 条;仅支持 YouTube(否则返回警告;参见 GET /v1/platforms)。comment_sentiment:汇总受众情绪(positive_pct/neutral_pct/negative_pct/summary/top_themes);至少需要 5 条评论;同样仅支持 YouTube。text_overlay:逐帧 OCR;需要 "frames";超过 200 帧时跳过。delta:与上次获取相比的变化速度;首次调用会初始化基准。文档:https://framefetch.net/docs。 |
| frames | object | 否 | 帧采样规格;请求 "frames" 或 "text_overlay" 时必填。 |
| frames.n | number | 否 | every_n:每隔 N 个源帧采样一帧 |
| frames.to | number | 否 | range:结束秒数 |
| frames.fps | number | 否 | fps/range:每秒帧数(最多 60) |
| frames.from | number | 否 | range:开始秒数 |
| frames.mode | enum | 是 | all | every_n | fps | range |
| frames.width | number | 否 | 缩放后的宽度,单位为 px(16–7680) |
| frames.format | enum | 否 | jpg | png | webp |
| translate | string | 否 | ISO-639-1 目标语言(例如 "es");添加 `transcript_translated`(保留时间信息)。需要 "transcript"(或 "digest")。按音频分钟计费。 |
| comments_cap | integer | 否 | 顶层评论的最大数量(1–200,默认值为 30);仅与 "comments" 一起使用。 |
| subtitle_format | enum | 否 | 将转录文本渲染为 `subtitles` 字幕(srt/vtt)。需要 "transcript"(或 "digest");如果设置了 "translate",则使用翻译后的字幕条目。srt | vtt |
详细介绍
FrameFetch
任意社交视频 URL → 答案、转录文本、元数据、洞察、帧和屏幕文字(OCR)。
面向 Agent 的优先视频数据 API + MCP 服务。按次付费,或使用 x402(USDC)付款——无需账户。
FrameFetch 可将一个 YouTube、YouTube Shorts、TikTok、Instagram Reels、Pinterest 或 Reddit 视频 URL 转换为单个 JSON 响应,其中包含:对视频问题的直接回答、元数据、互动洞察、转录文本(字幕或 Whisper)、大模型摘要(文本或语音 mp3)、结构化 JSON(章节/实体/产品/声明)、评论 + 情感分析、按参数采样的帧(每 N 帧/每秒 1 帧/指定时间范围,可设任意宽度),以及这些帧中嵌入的屏幕文字(OCR——字幕、价格标签、标牌)。此外,还提供关键词搜索(尚无 URL 时使用)和批量处理(单次调用最多处理 10 个 URL)。专为 AI Agent 打造,API 和 MCP 优先。
此仓库包含开源客户端 + 文档。服务本身运行于 framefetch.net——你只需准备一个免费的 API 密钥(或通过 x402 按次付费);后端由服务托管。
原因
大模型无法观看视频。若要对视频进行推理,必须先将其转换为文本和图像——包括答案、转录文本、元数据和若干帧。FrameFetch 可通过统一的架构,从六个平台的 URL 获取所有这些内容。
安装
npm install framefetch
Node 18+(使用内置的 fetch)。获取免费密钥:framefetch.net。
版本说明。 此仓库的版本为 0.4.0。目前 npm 上的最新版本是 0.3.0——
npm install framefetch安装的仍是该版本,且仅支持extract/metadata/transcript/frames/platforms/status/demo/createKey。下文记录的其他功能现已在 API 上提供,也可通过此仓库使用;使用 npm 0.3.0 时,可通过extract({ fields: [...] })获取相同数据。
提问——获取答案,而不是一大段转录文本
针对视频提问,可获得简短且有依据的回答,并附带时间戳引用;无需自行解析 25,000-token 的转录文本。
import { FrameFetch } from 'framefetch';
const ff = new FrameFetch({ apiKey: process.env.FRAMEFETCH_API_KEY });
const { ask } = await ff.ask(
'https://www.youtube.com/watch?v=jNQXAC9IVRw',
'What does the presenter say to do first?',
);
console.log(ask.answer); // short, direct answer
console.log(ask.confidence); // 'high' | 'medium' | 'low'
for (const q of ask.quotes) { // verbatim, timestamped supporting quotes
console.log(`[${q.t_sec}s] ${q.text}`);
}
console.log(ask.coverage); // which part of the transcript was analyzed
只有实际生成答案时才会收费。对于已提取过的视频,重复提问会复用缓存的转录文本,因此无需重新下载或转录即可快速回答;但答案本身始终会重新生成,不会从缓存中提供。
基于帧的回答: 当视频没有转录文本(例如 Pinterest 视频,或转录失败)时,回答会基于采样的关键帧图像生成。此时 coverage.mode 为 "frames",quotes 为 [](没有可供引用的转录文本),且 confidence 最高为 "medium"。
快速开始
import { FrameFetch } from 'framefetch';
const ff = new FrameFetch({ apiKey: process.env.FRAMEFETCH_API_KEY });
const r = await ff.extract({
url: 'https://www.youtube.com/watch?v=jNQXAC9IVRw',
fields: ['metadata', 'transcript', 'frames', 'text_overlay'],
frames: { mode: 'fps', fps: 1, width: 480 },
});
console.log(r.metadata.title); // "Me at the zoo"
console.log(r.transcript.text); // "All right, so here we are, in front of the elephants…"
console.log(r.frames.length); // 19 — frames is an array
console.log(r.textOverlay?.[0]?.text); // on-screen text detected in the first frame, if any
注意两种拼写:text_overlay 是请求字段名,textOverlay 是响应键名。
专用辅助函数
await ff.metadata(url); // title, author, duration, views, likes…
await ff.transcript(url); // captions, else Whisper
await ff.frames(url, { mode: 'fps', fps: 1, width: 512 });
await ff.ask(url, 'What product is being reviewed?'); // grounded Q&A, see above
await ff.digest(url); // LLM summary of the transcript
await ff.audioDigest(url, { voice: 'nova' }); // spoken mp3 briefing (signed URL, 24h)
await ff.structured(url); // chapters/entities/products/claims/key_moments
await ff.comments(url, { comments_cap: 50 }); // top-level comments
await ff.commentSentiment(url); // aggregated audience-mood rollup (+ the comments)
await ff.platforms(); // capability matrix (no key)
await ff.status(); // live service health (no key)
// on-screen text (OCR) — requires "frames" alongside it, use extract() directly:
await ff.extract({ url, fields: ['frames', 'text_overlay'], frames: { mode: 'fps', fps: 1 } });
上面的每个辅助函数都是对 extract() 的轻量封装,因此 extract() 接受的任何参数(translate、
format、额外的 fields 等)都可以作为最后一个参数传入,并会原样转发。
搜索视频并一次提取多个视频
// Find something to extract when you don't have a URL yet
const s = await ff.search('how to make sourdough', { limit: 5 });
for (const hit of s.results) {
console.log(hit.title, hit.url, hit.durationSec);
}
// Then extract up to 10 of them in ONE call. Shared options apply to every url.
const b = await ff.batch(s.results.slice(0, 3).map((r) => r.url), {
fields: ['metadata', 'digest'],
});
for (const item of b.results) {
if (!item.ok) { console.error(item.url, item.error?.code); continue; }
console.log(item.metadata.title, '→', item.digest.gist);
}
单个 URL 失败不会导致整个批次失败——每个条目都带有自己的 ok 标志;当 ok 为 false
时,还会附带包含 code/message/hint 的 error。批量处理中不接受针对单个 URL 的 frames 规格;此类情况请使用
extract()。
翻译转录文本,导出字幕
// translate the transcript into 1 of 25 languages (surfaced as transcript_translated)
const r = await ff.transcript(url, { translate: 'ja' });
console.log(r.transcript_translated.text);
// export subtitles directly — format is sent as a query param, response comes back as a string
const srt = await ff.transcript(url, { format: 'srt' }); // source-language subtitles
const vttJa = await ff.transcript(url, { translate: 'ja', format: 'vtt' }); // translated subtitles
无需注册
const ff = new FrameFetch(); // no key
await ff.demo('https://youtu.be/jNQXAC9IVRw'); // instant metadata, rate-limited
const { key } = await ff.createKey('[email protected]'); // self-serve key + free credit
在 MCP Agent 中使用
FrameFetch 附带一个 MCP 服务(Streamable HTTP),包含四个工具:framefetch_extract、
framefetch_platform_capabilities、framefetch_search 和 framefetch_account。将其添加到 Claude、
Cursor 或任何 MCP 客户端中:
{
"mcpServers": {
"framefetch": {
"url": "https://framefetch.net/mcp",
"headers": { "Authorization": "<YOUR_FRAMEFETCH_KEY>" }
}
}
}
也可以用一行命令:
claude mcp add --transport http framefetch https://framefetch.net/mcp \
--header "Authorization: <YOUR_FRAMEFETCH_KEY>"
MCP 位于 https://framefetch.net/mcp,使用 Streamable HTTP 传输 JSON-RPC。REST 接口位于
/v1/* 下,接受纯 JSON({"url": "…"})。混淆两者是首次调用时最常见的错误,因此两个接口都会明确回应:
将 REST 请求体 POST 到 /mcp 会返回 JSON-RPC 解析错误;将 JSON-RPC 请求体 POST 到 /v1/extract 则会返回
400 WRONG_ENDPOINT,并指出客户端应使用的正确 URL。
本地 stdio 桥接
更倾向于使用本地 stdio 服务(Claude Desktop、沙箱或不需要入站 HTTP)?此程序包
附带 framefetch-mcp,这是一个零依赖的 stdio↔HTTP 桥接程序,可提供相同的工具,
并将调用转发到 framefetch.net:
{
"mcpServers": {
"framefetch": {
"command": "npx",
"args": ["-y", "framefetch-mcp"],
"env": { "FRAMEFETCH_API_KEY": "<YOUR_FRAMEFETCH_KEY>" }
}
}
}
无需密钥即可使用 tools/list;调用工具时需使用 FRAMEFETCH_API_KEY(或 x402)。使用
FRAMEFETCH_MCP_URL 可覆盖端点。
无账户付费(x402)
自主 Agent 可通过 Base 上的 x402 按次使用 USDC 付费,无需注册,也无需人工介入。可在 x402 Bazaar 和 /.well-known/x402.json 中发现。个人用户可使用免费额度、预付费点数或 Stripe 卡付款。
错误
调用失败时会抛出 FrameFetchError,包含 .status、.code 和 .hint:
import { FrameFetchError } from 'framefetch';
try {
await ff.transcript(url);
} catch (e) {
if (e instanceof FrameFetchError && e.status === 402) {
// out of credit — top up at framefetch.net or via x402
}
}
API 接口
| 方法 | 端点 | 身份验证 |
|---|---|---|
extract({ url, fields, frames, … }) | POST /v1/extract | 密钥 |
ask(url, question) | POST /v1/extract(ask 参数) | 密钥 |
metadata(url) | POST /v1/metadata | 密钥 |
transcript(url, { translate, format }) | POST /v1/transcript | 密钥 |
frames(url, spec) | POST /v1/frames | 密钥 |
digest(url) | POST /v1/extract(digest) | 密钥 |
audioDigest(url, { voice }) | POST /v1/extract(audio_digest) | 密钥 |
structured(url) | POST /v1/extract(structured) | 密钥 |
comments(url, { comments_cap }) | POST /v1/extract(comments) | 密钥 |
commentSentiment(url) | POST /v1/extract(comment_sentiment) | 密钥 |
search(query, { limit }) | POST /v1/search | 密钥 |
batch(urls, { fields }) | POST /v1/batch | 密钥 |
platforms() | GET /v1/platforms | — |
status() | GET /v1/status | — |
demo(url) | POST /v1/demo | — |
createKey(email) | POST /v1/keys | — |
完整的 extract() 请求格式
ff.extract({
url: string,
fields?: Field[], // 'metadata' | 'insights' | 'transcript' | 'frames' | 'text_overlay'
// | 'digest' | 'audio_digest' | 'structured' | 'comments'
// | 'comment_sentiment' | 'delta'
frames?: { mode, n, fps, from, to, format, width },
translate?: string, // ISO-639-1 target language (25 supported)
voice?: string, // TTS voice for audio_digest
comments_cap?: number, // 1-200, default 100
ask?: string, // 3-500 char question — see ff.ask() above
publish?: boolean, // opt in to a public per-video SEO page
format?: 'md' | 'markdown' | 'srt' | 'vtt', // alternate egress rendering (returns a string, not JSON)
});
完整的类型化响应格式(ExtractResult、Ask、
VideoStructured、VideoComments、CommentSentiment、AudioDigest、SearchResult、
BatchResult 等)请参阅 index.d.ts。
完整的 OpenAPI 文档:framefetch.net/openapi.json · 文档:framefetch.net/docs
链接
网站 · 文档 · 定价 · 状态 · 指南:为 Agent 提供视频数据 · 与替代方案比较
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。