内容
# 视频镜头
> 通用的视频智能分析工具。给它一个视频和一个提示,获取一个带有时间戳的时间线、基于证据的发现、建议和结构化的报告 —— 准备好供人类审查或 AI 代理使用。
[](LICENSE)
[](https://www.python.org/downloads/)
[]()
视频镜头将任何视频 —— 错误记录、会议、演示、教程、参考视频、会话重放 —— 转化为结构化的产物,AI 代理(或您)可以对其进行推理。它通过解析器 → 提取 → 时间线 → 分析的流水线来实现这一点,该流水线生成人类可读的 Markdown 报告和机器可读的 JSON 分析。
```bash
videolens analyze ./bug-recording.mov \
--mode bug \
--prompt "Identify the bug and create reproduction steps."
```
或启动网页 UI:
```bash
videolens ui
```
---
## 为什么选择视频镜头
大多数“视频摘要”工具只是封装了 Whisper 就了事。视频镜头是为需要对视频进行推理的 AI 代理而构建的:带有时间戳的证据、特定模式的分析、结构化的输出,以及一个缓存的中间时间线,以便您可以针对一个提取结果提出多个问题。该流水线是模块化的 —— 解析器、处理器、模式和输出都是独立且易于扩展的。
## 状态
**v0.1 —— alpha.** 端到端工作正常:本地文件 + 直接 URL + YouTube → 时间线 → 模式驱动的分析 → Markdown/JSON 报告。包含 UI。尚未在生产环境中进行大规模测试。
## 功能
- **多源输入** —— 本地文件(`.mp4` / `.mov` / `.webm` / `.mkv`)、直接视频 URL、YouTube
- **仅限云端处理** —— OpenAI 用于转录、帧描述(+ OCR)和合成
- **带有时间戳的时间线** —— 每个发现都引用视频中特定秒数的证据
- **四种分析模式** 在 v0.1 中:`general`、`bug`、`meeting`、`production_recipe`(UX / 教程 / 产品演示 / 内容 / 隐私等功能正在规划中)
- **本地网页 UI** (Streamlit)—— 拖放上传、模式/帧滑块、标签式结果(报告 / 时间线 / 帧 / 转录 / 缓存)
- **每步缓存** —— 重新运行成本较低;每个提示的分析缓存意味着在第一次提取后,“询问一个提取结果的多个问题” 是免费的
- **成本感知帧预算** —— `--max-frames` 控制视觉 API 调用;自适应间隔
## 架构
```
源 URL 或文件
│
▼
┌──────────┐ 对本地文件 / youtube / 直接 URL / 网页进行分类,
│ 解析器 │ 并清楚地报告限制
└──────────┘
│
▼
┌────────────┐ yt-dlp(远程时),ffprobe 元数据,ffmpeg 音频
│ 处理器 │ 提取 + 30 秒分段,ffmpeg 帧采样,
└────────────┘ OpenAI 转录(每个分段并行),OpenAI 视觉帧描述 + OCR(每个帧并行)
│ 合并
▼
┌──────────┐ 将帧摘要 + 转录合并为时间窗口分段;
│ 时间线 │ 每个分段的 OCR、视觉、转录、置信度
└──────────┘
│
▼
┌──────────┐ 一个 GPT-5.5 调用,带有时间线 + 用户提示 + 模式
│ 分析 │ 指导 → 结构化分析(摘要、发现及带有时间戳的证据、建议、任务、限制)
└──────────┘
│
▼
┌──────────┐
│ 输出 │ report.md + analysis.json + 缓存的中间产物
└──────────┘
```
每个步骤都缓存在 `.videolens/cache/<source-hash>/`,因此重新运行成本较低。缓存键包括源内容(哈希)加上提取设置(帧间隔、最大帧数)。
## 安装
需要 **Python 3.12+** 和 **ffmpeg** + **ffprobe** 在 `PATH` 中。
```bash
# 安装 ffmpeg(macOS)
brew install ffmpeg
# 克隆并使用 uv 安装
git clone https://github.com/shadoprizm/videolens.git
cd videolens
uv sync --extra ui
```
设置您的 OpenAI API 密钥:
```bash
export OPENAI_API_KEY=sk-...
```
(网页 UI 也接受密钥作为密码样式输入,如果您不想将其放在环境中。)
## 用法
### 网页 UI(推荐)
```bash
uv run videolens ui
```
打开 http://localhost:8501。拖放视频,设置提示和模式,点击分析。
### Vercel 部署
Vercel 运行 `pyproject.toml` 中声明的根 FastAPI 入口点:
```toml
[tool.vercel]
entrypoint = "app:app"
```
Vercel 部署在 `/` 和 `/api/health` 处暴露一个轻量级 HTTP 接口。
完整的上传/分析 Streamlit UI 仍然是一个本地应用,通过 `uv run videolens ui` 启动。
在 Vercel 上保留 UI 依赖项在可选的 `ui` 额外依赖中,防止 Vercel 的 Python 函数包拉入 Streamlit、pandas、pyarrow 和 PDF 渲染包。
### Railway 部署
Railway 是全功能的 Streamlit UI 的推荐托管路径。仓库中包含:
- `Dockerfile` —— 安装 Python 依赖项、`ffmpeg` 和 PDF 渲染系统库
- `railway.json` —— 告诉 Railway 使用 Dockerfile 和健康检查 Streamlit
- `.dockerignore` —— 将本地缓存、视频和虚拟环境排除在镜像之外
在 Railway 上:
1. 从 `github.com/shadoprizm/videolens` 创建一个新项目。
2. 部署。Railway 将使用根 `Dockerfile` 进行构建。
3. 在 Networking 中,生成一个目标端口为 `8501` 的公共域名。
不要为托管应用设置共享的 `OPENAI_API_KEY`。视频镜头是自带密钥的:
用户将自己的 OpenAI 密钥粘贴到 UI 中,使用该工具,并在该浏览器会话中仅保留密钥。
可选:添加一个挂载在 `/app/.videolens` 的 Railway 卷,以便在重新部署时保留上传的文件和已处理视频的缓存。
### 命令行界面
```bash
uv run videolens analyze <source> --prompt "<your question>" [--mode general|bug|meeting|production_recipe]
```
有用的标志:
| 标志 | 默认值 | 目的 |
|---|---|---|
| `--mode`, `-m` | `general` | 分析模式 |
| `--max-frames` | `40` | 视觉模型帧数的上限(成本控制) |
| `--frame-interval` | `5.0` | 采样帧之间的秒数(自适应 —— 如有需要,将增长以尊重最大帧数) |
| `--output-dir`, `-o` | `./output/videolens` | 写入 `report.md` + `analysis.json` 的位置 |
| `--force` | 关闭 | 跳过缓存并重新处理 |
| `--json` | 关闭 | 跳过终端摘要打印 |
| `--verbose`, `-v` | 关闭 | 詳細日志 |
### 示例
```bash
# 检查损坏的 UI 屏幕录像
videolens analyze ./broken.mov --mode bug \
--prompt "What's broken, how do I reproduce it, and what's the severity?"
# 从会议记录中提取决策和后续行动
videolens analyze ./standup.mp4 --mode meeting \
--prompt "List the decisions made and any open follow-up actions."
# 常规审查教程或演示
videolens analyze "https://www.youtube.com/watch?v=..." \
--prompt "What does this demo show and what are the strengths and weaknesses?"
```
## v0.1 中的模式
| 模式 | 使用场景 |
|---|---|
| `general` | 广泛审查:正在发生什么,有什么值得注意的,有什么值得了解的 |
| `bug` | 错误记录 → 复现步骤、严重性提示、适合提交的摘要 |
| `meeting` | 会议/电话/简报 → 决策、异议、承诺、后续行动(使用说话人识别) |
| `production_recipe` | 参考视频 → 视频本身的制作方式:脚本主线、镜头清单、编辑节奏、可能使用的工具、资产清单和重建配方 |
每个模式都是一个小的提示片段文件,位于 `src/videolens/analysis/modes/` 下。添加新模式大约需要 30 行代码。
## 模型(可配置)
默认值位于 `src/videolens/config.py`:
| 阶段 | 模型 |
|---|---|
| 转录(general/bug) | `gpt-4o-mini-transcribe` |
| 转录(meeting) | `gpt-4o-transcribe-diarize` |
| 帧描述 + OCR(每个帧) | `gpt-5.4-mini` |
| 最终分析合成 | `gpt-5.5` |
通过编辑 `Models` 数据类可以替换它们。
## 成本指南
大致数量级:
- 30 秒视频,5 帧 → 远低于 $0.05
- 5 分钟视频,20 帧 → 通常低于 $0.20
- 30 分钟会议,40 帧 → 通常 $0.50–$1.50
每个提示的分析缓存意味着对已经提取的视频提出第二个问题仅需支付合成费用(几美分)。
## 会话重放(PostHog / Hotjar / Clarity / FullStory / LogRocket / OpenReplay)
这些服务存储用户会话事件,而不是视频 —— yt-dlp 无法提取它们。视频镜头提供了一个可选的 **浏览器捕获** 回退方案,通过 headless Chromium 打开重放 URL,启动播放并实时录制视口:
```bash
uv sync --extra capture
uv run playwright install chromium
```
安装后,粘贴任何 PostHog/Hotjar 等共享 URL,视频镜头会自动通过 Chromium 路由。可以通过 `--capture-duration <seconds>` 调整录制窗口(默认为 60 秒)。
> **目前仅限自托管使用。** 实时捕获与重放本身一样长,这与托管 PaaS 部署上的请求生命周期相冲突。在 app.videolens.io 上托管的实例会回退到现有的“手动录制屏幕并上传”的工作流程,用于重放服务。
## MCP 服务器(Claude Code / Cursor / Windsurf)
视频镜头提供了一个 [Model Context Protocol](https://modelcontextprotocol.io) 服务器,以便 AI 代理可以将视频作为一流工具进行分析。
```bash
uv sync --extra mcp
```
可用工具:
| 工具 | 功能 |
|---|---|
| `analyze_video` | 对源 + 提示 + 模式运行完整流水线 |
| `ask_video` | 对已分析的视频提出后续问题 |
| `get_timeline` | 获取缓存的时间线(分段与视觉/OCR/转录) |
| `get_transcript` | 获取缓存的转录 |
| `get_frames` | 获取帧摘要 |
| `list_cached` | 列出所有具有缓存提取产物的视频 |
将其添加到 Claude Code:
```bash
claude mcp add videolens -- videolens-mcp
```
或将其连接到 Cursor / Windsurf / 任何 MCP 感知主机,方法与任何 stdio MCP 服务器相同。
## 路线图
- **鲁棒性:** 软故障转录,以便仅限帧的视频仍能生成报告;在 UI 中提供更清晰的错误界面
- **更多来源:** 网页渲染的嵌入式视频(Playwright)、会话重放 JSON 导出(PostHog / Clarity / Hotjar / FullStory / LogRocket / OpenReplay)、Zoom/Meet/Teams 记录
- **场景变化帧选择:** 比 v0.1 中使用的自适应间隔更智能
- **嵌入 + 语义搜索** 在处理过的时间线上的
## 贡献
欢迎提出问题和 PR。该架构的设计是模块化的 —— 大多数新增功能都位于 `resolvers/`、`processors/`、`analysis/modes/` 或 `outputs/` 下的独立文件中,不会影响其他部分。
## 许可证
MIT —— 见 [LICENSE](LICENSE)。