# Simple Video Analyer **Repository Path**: johnzchgrd/simple-video-analyer ## Basic Information - **Project Name**: Simple Video Analyer - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-16 - **Last Updated**: 2026-09-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Simple Video Analyzer · 本地视频分析工具 一个完全本地运行的视频分析 Web 应用:支持**本地视频上传**与**网页链接(Bilibili/YouTube 等)**, 自动完成**镜头分割、目标检测、场景分类、语音转写、画面文字 OCR**,并调用本地 **Ollama 多模态模型** 生成结构化的内容总结。所有分析在浏览器中以**可交互时间轴**呈现,点击任意标记即可跳转到对应画面。 > 📦 开源地址:https://gitee.com/johnzchgrd/simple-video-analyer > 📄 协议:MIT ## 功能 | 模块 | 实现 | 说明 | | --- | --- | --- | | 视频来源 | 本地文件上传 / yt-dlp 链接下载 / 内嵌播放器解析 | 支持 Bilibili、YouTube、通用直链及小站内嵌 m3u8 播放器(自动跳过广告);Bilibili DASH 音视频流自动合并 | | 镜头切换/场景分割 | PySceneDetect(回退 ffmpeg select 场景分) | 输出镜头起止时间 + 关键帧 | | 画面内容识别 | Ultralytics YOLO(默认 yolov8n) | 物体/人物检测,输出类别、置信度、位置 | | 场景分类 | open_clip(多语言 CLIP 零样本) | 对采样帧打中文场景标签 | | 语音转写 | faster-whisper(默认 small) | 带时间戳的分段转写,中英日韩等 | | 画面文字 OCR | PaddleOCR 3.x(兼容 2.x) | 识别画面中的文字,相邻帧去重加速 | | 内容总结 | Ollama 多模态模型(qwen3-vl / gemma3 / minicpm-v…) | 结合转写/OCR/检测结果 + 关键帧生成结构化总结 | | 模型管理 | 页面内拉取/删除 Ollama 模型 | 进度条实时显示,各阶段可独立选模型(每任务可配) | | 任务管理 | 批量操作 + 标签分组 + 断点续分析 | 批量删除/打标签、标签筛选、中断任务复用缓存续跑 | ## 架构 ``` ┌───────────────────────── 浏览器 (React + Vite) ─────────────────────────┐ │ 上传表单 · 任务列表 · 视频播放器 · 时间轴(镜头/转写/检测/OCR 轨道) │ └───────────────┬───────────────────────────────┬─────────────────────────┘ │ REST /api/*(上传、结果、帧图) │ WebSocket /ws/*(进度推送) ┌───────────────▼───────────────────────────────▼─────────────────────────┐ │ FastAPI 后端(Python 3.10+) │ │ main.py ── REST/WS 接口 jobs.py ── 任务编排(asyncio 管线) │ │ db.py ── SQLite 任务持久化 progress.py ── 阶段加权进度事件总线 │ │ pipeline/:download(yt-dlp,链接任务) → probe(ffprobe) → scenes → frames │ │ → transcribe → detect → classify → ocr → summarize(Ollama) │ │ 每个 AI 模块惰性加载:未安装时自动降级跳过并记录 warning,不影响其他结果 │ └───────────────┬──────────────────────────────────────────────────────────┘ │ 本地进程 ┌───────┴────────┐ ┌──────────────────┐ │ ffmpeg/ffprobe │ │ Ollama 服务(:11434)│ └────────────────┘ │ qwen2.5vl / llava │ └──────────────────┘ ``` 数据布局(默认 `backend/data/`,可用 `SVA_DATA_DIR` 修改): ``` data/ ├── jobs.db # 任务元数据 └── jobs// ├── video.mp4 # 原始视频 ├── audio.wav # 提取的音轨 ├── frames/ # 采样帧与关键帧 jpg └── result.json # 完整分析结果 ``` 设计要点: - **渐进式降级**:ffmpeg 是唯一硬依赖;YOLO / CLIP / PaddleOCR / Whisper / Ollama 各自独立,缺哪个就跳过哪个,其余结果照常产出。 - **任务化处理**:每个视频一个后台任务,WebSocket 实时推送阶段进度,支持取消与删除; 每阶段结束即落盘 `result.json`,崩溃也能拿到部分结果。 - **阶段加权进度**:转写/检测等耗时阶段按权重映射到 0~100% 总进度。 - **Range 请求**:视频与帧图经后端静态服务,播放器可自由拖动。 ## 快速开始 ### 0. 依赖 - Python 3.10+,Node.js 18+ - [ffmpeg](https://ffmpeg.org/)(含 ffprobe):Ubuntu/Debian `sudo apt install ffmpeg`,macOS `brew install ffmpeg` - (可选,用于总结)[Ollama](https://ollama.com/) + 多模态模型 ### 1. 后端 ```bash cd backend python3 -m venv .venv && source .venv/bin/activate pip install -e . # 核心依赖(FastAPI) # 按需安装分析模块(也可直接安装全部): pip install -e ".[all]" # 全部:yt-dlp/scenedetect/ultralytics/open-clip/paddleocr/faster-whisper/ollama # 或选择性安装,例如只要转写与链接下载: # pip install -e ".[transcribe,url]" uvicorn app.main:app --host 127.0.0.1 --port 8000 ``` 启动后访问 http://127.0.0.1:8000/api/health 可查看各模块可用性。 ### 2. Ollama(可选,用于内容总结) ```bash ollama serve # 如未随系统启动 ollama pull qwen2.5vl:7b # 推荐(7B,显存约 6~8GB);或 llava:7b ``` ### 3. 前端 ```bash cd frontend npm install npm run dev # 开发模式 http://localhost:5173(已代理 /api 与 /ws 到 8000) ``` **生产模式**:`npm run build` 后,后端检测到 `frontend/dist` 会自动托管,直接访问 http://127.0.0.1:8000 即可,无需单独启动前端。 ### 4. 冒烟测试 不安装任何 AI 依赖即可验证核心管线(用 ffmpeg 生成 6 秒合成视频): ```bash python scripts/smoke_test.py ``` ## 配置(环境变量) | 变量 | 默认 | 说明 | | --- | --- | --- | | `SVA_DATA_DIR` | `backend/data` | 数据目录 | | `SVA_PORT` / `SVA_HOST` | 8000 / 127.0.0.1 | 服务地址 | | `SVA_CORS` | `http://localhost:5173,...` | 允许的跨域来源 | | `SVA_SAMPLE_INTERVAL` | 2.0 | 默认抽帧间隔(秒) | | `SVA_SCENE_THRESHOLD` | 27.0 | 镜头检测灵敏度(越小越敏感) | | `SVA_DETECT_MODEL` | `yolov8n.pt` | YOLO 权重 | | `SVA_DETECT_CONF` | 0.35 | 检测置信度阈值 | | `SVA_WHISPER_MODEL` | `small` | tiny/base/small/medium/large-v3 | | `SVA_CPU_THREADS` | 16 | 各推理引擎线程数(核数全开反而线程颠簸;whisper/CLIP/YOLO/OCR 共用) | | `SVA_WHISPER_BEAM` | 1 | 转写 beam:1 最快,5 更准但慢 3~5 倍 | | `SVA_DETECT_BATCH` | 8 | YOLO 批量帧数(批量推理摊薄开销) | | `SVA_CLIP_BATCH` | 16 | CLIP 批量帧数 | | `SVA_OCR_BATCH` | 4 | PaddleOCR 批量帧数 | | `SVA_OCR_DET_MODEL` / `SVA_OCR_REC_MODEL` | `PP-OCRv5_mobile_*` | OCR 模型(v5 mobile 比默认 v6 medium 快约 2 倍) | | `SVA_OCR_DEDUP_THRESH` | 0.012 | OCR 相邻帧去重阈值(近似帧复用上一帧结果,固定字幕视频大幅提速) | | `SVA_OCR_LANG` | `ch` | PaddleOCR 语言 | | `SVA_CLIP_MODEL` | `xlm-roberta-base-ViT-B-32` | 场景分类模型(多语言 CLIP) | | `SVA_OLLAMA_MODEL` | `qwen2.5vl:7b` | 总结用多模态模型(纯 CPU 环境建议 `qwen3-vl:4b`) | | `SVA_OLLAMA_NUM_CTX` | 16384 | Ollama 上下文窗口(多图需要更大窗口) | | `SVA_OLLAMA_TIMEOUT` | 1800 | Ollama 请求超时(秒);大模型纯 CPU 推理较慢,可继续调大 | | `SVA_OLLAMA_KEEPALIVE` | `1h` | 模型生成后在 Ollama 内存驻留时长(避免重复加载大模型) | | `OLLAMA_BASE_URL` | `http://127.0.0.1:11434` | Ollama 地址 | | `SVA_YTDLP_COOKIES` | 空 | cookies.txt 路径(Bilibili 1080p+/会员画质需登录 cookie) | | `SVA_YTDLP_FORMAT` | `bestvideo*+bestaudio/best` | 下载格式选择,如 `bestvideo[height<=720]+bestaudio/best[height<=720]/best` 限 720p | | `SVA_HLS_WORKERS` | 8 | 内嵌播放器 HLS 分段并行下载数 | | `SVA_HLS_COOKIES` | 空 | HLS 分段/密钥请求的 Cookie(如 `sid=xxx; token=yyy`) | | `SVA_HF_DISABLE_XET` | 1 | 禁用 HuggingFace Xet 加速(部分网络环境会 401),设 0 启用 | | `SVA_MAX_UPLOAD_MB` | 2048 | 上传大小上限 | | `SVA_FFMPEG_BIN` / `SVA_FFPROBE_BIN` | ffmpeg / ffprobe | 可执行文件路径 | ## API 一览 | 方法 | 路径 | 说明 | | --- | --- | --- | | POST | `/api/jobs` | 上传本地视频(multipart:`file` + `options` JSON) | | POST | `/api/jobs/url` | 链接任务(JSON:`url` + `options`),yt-dlp 服务端下载后分析 | | POST | `/api/jobs/{id}/rerun` | 重新分析(JSON:`options`):复用已保存视频、新配置创建新任务,原结果保留 | | POST | `/api/jobs/{id}/resume` | 继续分析(JSON:`options`):被中断任务复用已完成阶段缓存,只补算缺失部分 | | POST | `/api/jobs/batch` | 批量操作(JSON:`action`=delete/tag、`ids`、`tags`、`mode`=set/add/remove) | | PATCH | `/api/jobs/{id}` | 更新任务标签(JSON:`tags`) | | GET | `/api/tags` | 全部标签及任务数统计 | | GET | `/api/models/ollama` | 模型管理:已安装模型详情 + 进行中的拉取任务 | | POST | `/api/models/pull` | 拉取模型(JSON:`name`),后台任务带进度 | | DELETE | `/api/models/{name}` | 删除已安装模型 | | GET | `/api/jobs` | 任务列表 | | GET | `/api/jobs/{id}` | 任务详情(含结果) | | DELETE | `/api/jobs/{id}` | 取消并删除任务 | | GET | `/api/jobs/{id}/video` | 视频流(支持 Range) | | GET | `/api/jobs/{id}/frames/{name}` | 抽帧图片 | | WS | `/ws/jobs/{id}` | 进度推送(progress / terminal 事件) | | GET | `/api/models` | 模型目录:各阶段可选模型、默认值与 Ollama 已安装模型 | | GET | `/api/health` | 环境与模块可用性 | ### options JSON 字段(上传/链接任务通用) | 字段 | 类型 | 说明 | | --- | --- | --- | | `detect` / `classify` / `ocr` / `transcribe` / `summarize` / `scenes` | bool | 各模块开关 | | `sample_interval` / `scene_threshold` / `detect_conf` | number | 分析参数 | | `language` | string\|null | 转写语言提示(zh/en/ja/ko,null 自动) | | `summarize_model` | string\|null | Ollama 视觉模型(qwen3-vl:8b、gemma3:12b、minicpm-v:8b…) | | `transcribe_model` | string\|null | tiny/base/small/medium/large-v3 | | `detect_model` | string\|null | yolov8n.pt / yolo11s.pt 等 | | `clip_model` | string\|null | xlm-roberta-base-ViT-B-32 / nllb-clip-base / ViT-B-32 | | `ocr_model` | string\|null | PP-OCRv5_mobile / PP-OCRv6_medium / PP-OCRv4_mobile,或 `"det,rec"` 自定义 | 均为可选:传 `null` 或不传时使用服务默认(环境变量)。不同任务可混用不同模型, 模型按需惰性加载并缓存。 ## 已知限制与后续方向 - 本地视频需通过浏览器上传(或使用 API),暂不支持直接指定服务器本地路径。 - Bilibili 未登录时通常只能下载 480p/720p;1080p 及以上或会员内容需要 cookie:`yt-dlp --cookies-from-browser chrome --cookies cookies.txt`, 再设置 `SVA_YTDLP_COOKIES` 指向该文件。 - 内嵌播放器站点的 **AES-128 加密 m3u8 自动解密**(密钥/IV 自动拉取,参考 [N_m3u8DL-CLI](https://github.com/nilaoda/N_m3u8DL-CLI) 的处理思路); SAMPLE-AES/CENC(DRM)需额外密钥暂不支持,站内播放器若带 token 签名也无法直接解析。 - 抽帧采用固定间隔(fps 滤镜),变帧率视频的时间戳可能有轻微漂移;关键帧为镜头中点近似帧。 - 检测/OCR 只作用于采样帧,密集逐帧分析可用 `SVA_SAMPLE_INTERVAL=0.5` 提高密度。 - 长视频转写无进度细分(阶段内进度为估计值);后续可接入 faster-whisper 回调做细分。 - 可扩展方向:任务队列上限与并发控制、说话人分离、视频摘要直接抽取精彩片段、 检测结果在播放画面上叠加标注框、结果导出 SRT/JSON/Markdown。 ## 目录结构 ``` backend/app/ main.py # FastAPI 路由 + WebSocket + 静态托管 + 批量/标签/模型管理接口 jobs.py # 任务编排(JobRunner 管线 / 断点续分析 / JobManager 取消) config.py # 环境变量配置 models.py # Pydantic 数据模型 db.py # SQLite 持久化 progress.py # 加权进度 + 事件总线 ollama_mgr.py # Ollama 模型拉取任务注册表 pipeline/ # 各分析模块(download/probe/scenes/frames/detect/classify/ocr/transcribe/summarize) frontend/src/ App.tsx # 布局:侧栏任务列表 + 批量管理 + 标签筛选 + 主区 components/ # UploadForm/JobDetail/VideoPlayer/Timeline/ModelManager/各结果面板 scripts/smoke_test.py ``` ## 开源与贡献 - 协议:[MIT](./LICENSE) - 仓库:https://gitee.com/johnzchgrd/simple-video-analyer - 欢迎提 Issue / PR。开发模式后端 `uvicorn app.main:app --reload`、前端 `npm run dev`; 提交前请运行 `python scripts/smoke_test.py` 与 `npm run build` 验证。 - 说明:分析所用的视频、模型、任务数据均位于 `backend/data/`(已 gitignore),不会入库。