dsh-vidora
IdentifiedVidora(DSH 插件)
本地优先的音视频知识文档化工具。 给 Vidora 一个本地 MP4/MKV/MP3/WAV,它会在本机完成 FFmpeg 解码、VAD 分段、Qwen3-ASR 转写、Qwen3-ForcedAligner 时间戳对齐,并调用 Harness 已配置的模型生成可追溯来源的 Markdown 讲义与译文。
DeepSeek Harness(DSH)是 Vidora 的交互入口,不是业务核心。Vidora Core 的 Transcript / Document JSON 不依赖 Harness 私有接口,可供未来的 Chrome 扩展和 GPUI 桌面端复用。
本地音视频
→ FFmpeg 解码 / 16kHz 单声道
→ VAD + 静音感知分段(不把完整长音频放进模型内存)
→ Qwen3-ASR-0.6B(可切换 1.7B)
→ Qwen3-ForcedAligner-0.6B(独立对齐阶段)
→ transcript.json(毫秒时间戳 / 稳定 segment id)
→ Harness 模型分窗口提取 → 全局合并 → 确定性 Markdown 渲染
→ notes.md + document.json + exports/
文档索引
当前状态
- Phase 1–5 的最小可运行链路已经实现。
- 已在 macOS Apple Silicon(M1 Pro,32GB,MPS)上完成真实推理测试:
- 5 分钟中文教学音频:15 段,对齐 15 段,RTF 0.100,峰值内存约 3.4GB。
- 10 分钟中英混合音频:31 段,RTF 0.096,峰值内存约 3.5GB。
- 60 分钟中文长音频:157 段,RTF 0.092,峰值内存约 3.3GB。
- 取消、检查点恢复、缓存命中、Harness 模型讲义生成均已实际执行。
- 测试音频由 macOS
say(Tingting)合成;这是真实语音推理,但不是人类课堂录音。CER 是按已知脚本计算的,不代表真实课堂准确率。详见 docs/test-report.md。 - Linux / Windows 与 Intel Mac 尚未在本机验证;代码包含 CPU fallback 和跨平台路径处理,但请将它们视为兼容目标而不是已验证结果。
能力
| 工具 | 功能 |
|---|---|
vidora_transcribe | 创建本地转写任务(本地 path 或 Bilibili/YouTube url);默认等待完成(wait=true),也可 wait=false 异步轮询 |
vidora_task_status | 查询阶段、真实已处理音频时长、总时长、片段数、错误 |
vidora_cancel_task | 取消任务;检查点保留,可恢复 |
vidora_get_transcript | 分页读取转写正文(默认可见;开启 blockHarnessContent 后仅受信任会话可见) |
vidora_generate_notes | 用 Harness 模型生成精简/详细/可读转写/复习提纲 |
vidora_translate | 用 Harness 模型把转写或讲义逐句翻译成中文/英文/日文,保留片段与来源 |
vidora_get_document | 读取讲义正文(默认可见;开启 blockHarnessContent 后仅受信任会话可见) |
vidora_export | 导出 Markdown / JSON / TXT / SRT(不返回正文) |
vidora_list_models | 查询模型、设备、FFmpeg、Worker、Harness 模型和隐私状态 |
插件同时提供一个 Harness 输入框上方的图形面板:选择/拖入媒体或粘贴 Bilibili/YouTube 链接、查看真实进度、最近项目、转写预览、Harness 模型讲义生成、中/英/日翻译与 Markdown/SRT 导出。它只在 DSH Web/Desktop profile 中挂载;headless profile 只注册工具。
支持 MP3、WAV、FLAC、M4A、MP4、MKV、WebM、OGG、Opus、AAC、MOV、AVI、FLV、M4B。
还可以在界面里粘贴 Bilibili / YouTube 单视频链接,由本机 yt-dlp 下载后自动进入同一条本地转写链路。下载只使用你已有权访问的内容,不绕过 DRM、付费墙、登录或地区限制;不支持播放列表、直播和多 P 视频。
快速安装(macOS Apple Silicon)
前提:Node.js >= 22、Python >= 3.9、FFmpeg/ffprobe、DSH >= 0.2.2-rc.1 <0.3.0。要在界面/工具中导入 Bilibili 或 YouTube 链接,还需要本机安装 yt-dlp(例如 brew install yt-dlp 或 pipx install yt-dlp)。已在 DSH 0.2.2-rc.1 上实测。
git clone <this-repo> dsh-vidora
cd dsh-vidora
# 1. 构建 TypeScript 插件
npm install
npm run build
# 2. 安装独立 Python Worker 虚拟环境(不会修改全局 Python)
node scripts/install-worker.mjs --yes
# 3. 显式确认后下载模型权重(默认写入 OS 用户数据目录)
node scripts/prepare-models.mjs --model qwen3-asr-0.6b --yes
node scripts/prepare-models.mjs --model qwen3-forced-aligner-0.6b --yes
模型来源、大小和目标目录会在下载前显示;prepare-models 也支持 --endpoint https://hf-mirror.com、--dest 和 --data-dir。Worker 自身始终以 HF_HUB_OFFLINE=1、local_files_only=True 运行,不会在推理时下载权重。
安装到 DSH profile:
dsh plugin --profile desktop add link:/absolute/path/to/dsh-vidora
然后编辑 ~/.dsh/profiles/desktop/cordis.patch.yml,为 vidora 行添加配置:
- id: vidora
config:
dataDir: /Users/you/Library/Application Support/Vidora
worker:
pythonPath: /absolute/path/to/dsh-vidora/python-worker/.venv/bin/python
asr:
modelsDir: /Users/you/Library/Application Support/Vidora/models
device: auto
align: true
llm:
mode: harness-current # harness-current(默认)| off
privacy:
strictLocal: true
blockHarnessContent: false # 默认允许 Harness 模型读取正文
trustedLocalProviders: []
重启 DSH(或让 profile HMR 重新加载)。在对话中输入:
请把
/Users/you/Videos/os-lecture.mp4转换成文字,并整理成一份精简的 Markdown 教学讲义。
也可以只转写:
只转文字,不需要总结。
也可以直接给链接:
把这个 Bilibili/YouTube 链接下载下来并转成文字。
或者复用已有转写生成详细讲义:
使用刚才的 Transcript 重新生成一份详细讲义。
把这段英文转写翻译成中文,并导出中英双语 SRT。
Harness 模型
Vidora 不再自带 Ollama、OpenAI 兼容端点或任何独立推理服务,也不会请求用户自己的 LLM 服务端。讲义和翻译统一调用 Harness 已配置的模型:
- 工具调用:使用当前 Agent 的模型(
exec.agent.model.current())。 - Web UI:使用 profile 的
agent-default-model当前选择。 - 模型可能是云端模型(例如 DeepSeek)。Vidora 不会偷偷换模型,也不会自动降级到其他服务。
llm.mode: "off":ASR、缓存、导出仍然可用;AI 讲义和翻译明确不可用。
因此不需要配置 baseUrl、apiKey、ollama 或 openai。只需要:
- id: vidora
config:
llm:
mode: harness-current
如果 Web 面板要生成讲义/翻译,profile 还需要一个默认模型:
- id: agent-default-model
config:
provider: deepseek-account
model: deepseek-flash
隐私与正文保护
这里的“严格本地”指 Vidora 不请求用户自己搭建的推理服务器,而不是禁止使用 Harness 模型。ASR/FFmpeg/VAD 始终本机执行;讲义和翻译使用 Harness 模型,因此如果该模型是云端的,转写正文会发送给该 provider。
默认 privacy.blockHarnessContent: false,即允许 Harness 模型读取正文:
vidora_get_transcript/vidora_get_document默认可见。vidora_generate_notes和vidora_translate正常使用当前 Harness 模型。- 工具返回的标题、正文和警告按正常方式返回。
如果需要额外的正文保护,可显式开启:
privacy:
blockHarnessContent: true
trustedLocalProviders: [your-local-provider]
trustedLocalModels: [your-local-model]
开启后:
vidora_get_transcript/vidora_get_document只对信任列表中的 provider/model 可见。- 工具内部会用
exec.agent.model.current()再检查一次。 ctx.tools.guard()会拦截非 Vidora 文件/Shell 工具对 Vidora 数据目录和已登记媒体路径的访问。untrustedFileToolPolicy可为block-data-path、block-all或off。- 讲义/翻译结果在不可信会话中只返回元数据,隐藏标题、章节名和详细警告。
这是运行时访问限制,不是 OS 文件系统沙箱。详见 docs/security.md。
数据目录
默认使用操作系统用户数据目录:
| 平台 | 默认位置 |
|---|---|
| macOS | ~/Library/Application Support/Vidora |
| Linux | $XDG_DATA_HOME/vidora 或 ~/.local/share/vidora |
| Windows | %APPDATA%\Vidora |
可用 dataDir 或环境变量 VIDORA_DATA_DIR 覆盖。
Vidora/
├── meta.json
├── models/
├── projects/
│ └── prj-<source-hash>/
│ ├── source.json
│ ├── transcript.json # 最近一次转写的便捷副本
│ ├── transcripts/<id>.json # 规范转写文件
│ ├── document.json # 最近一次讲义
│ ├── documents/<id>.json
│ ├── notes/<id>.md
│ └── exports/
├── uploads/ # Web 面板上传的临时媒体
├── downloads/ # 在线链接下载的媒体与 metadata.json
├── tasks/<task-id>/
│ ├── task.json
│ ├── checkpoint.json # 中断/取消后可恢复
│ └── work/audio.wav
├── cache/index.json
└── logs/worker.log
同一个音视频按 SHA-256 + 模型 + 语言 + 对齐 + VAD 参数判断缓存;命中时不会重新执行 ASR。vidora cleanup --older-than 7 可清理旧任务的临时 WAV、检查点和失效缓存项。
Transcript / Document 契约
见 docs/data-format.md。核心约束:
- 时间戳统一毫秒,对应原始媒体时间轴。
- Segment ID 稳定且唯一。
timing_status为aligned/chunk/uncertain。- 原始
transcript.json不会被 LLM 润色结果覆盖;讲义是独立的document.json。 - DocumentBlock 通过
source_segment_ids关联转写片段;Markdown 渲染时由程序生成时间戳和相对链接,LLM 不能编造时间戳。
任务恢复与 Worker 生命周期
- Python Worker 由 Node
child_process.spawn()启动,不在 Harness 主进程内做推理。 - Worker 按需启动、复用已加载模型、空闲可卸载(默认 900 秒)。
- 任务状态持久化在
tasks/<id>/task.json,Worker 在每个 ASR 片段后写checkpoint.json。 - 插件重启/Worker 崩溃/任务取消后,状态变为
interrupted或cancelled,resumable=true;用vidora_transcribe的resumeTaskId参数恢复。 - 插件卸载时先标记未完成任务为 interrupted,再发送
worker.shutdown;超时后终止子进程。不会因为切换会话而取消转写。 - 重复提交相同任务会返回已有 task 或已完成缓存,不会重复执行。
配置
完整字段与默认值见 docs/configuration.md。常用字段:
- id: vidora
config:
dataDir: /path/to/Vidora
worker:
pythonPath: /path/to/python-worker/.venv/bin/python
idleUnloadSeconds: 900
asr:
defaultModel: qwen3-asr-0.6b
modelsDir: /path/to/models
device: auto # auto | cpu | mps | cuda
dtype: auto # auto | float16 | bfloat16 | float32
language: auto
align: true
diarize: false # 实验性本地说话人聚类
alignerModel: qwen3-forced-aligner-0.6b
maxChunkSeconds: 30
vad:
thresholdDb: null # null = 自适应
minSilenceMs: 400
minSpeechMs: 250
paddingMs: 150
frameMs: 20
llm:
mode: harness-current
privacy:
strictLocal: true
blockHarnessContent: false # true = 只允许信任列表读取正文
trustedLocalProviders: []
trustedLocalModels: []
untrustedFileToolPolicy: block-data-path # block-data-path | block-all | off
tasks:
autoResume: false
maxTaskHours: 8
keepTempFiles: false
paths:
mode: explicit # explicit | roots
allowedRoots: []
maxFileSizeBytes: 21474836480
maxDurationMinutes: 480
document:
defaultMode: concise
maxCharsPerWindow: 10000
maxWindows: 300
urlImport:
enabled: true
ytDlpPath: "" # 空 = PATH 中的 yt-dlp
cookiesFile: "" # 可选;Netscape cookies.txt
cookiesFromBrowser: "" # 或 chrome/safari/firefox/edge/brave
timeoutMs: 1800000
Harness 内界面
安装到 Web/Desktop profile 后,输入框上方会出现 Vidora 面板。它支持本机文件选择、拖入/上传、路径输入、Bilibili/YouTube 链接、模型与语言选择、真实进度、最近项目、转写预览、Harness 模型讲义生成、项目问答、逐句翻译、媒体播放与时间戳跳转、全文搜索/讲义目录、环境初始化、批量导入队列、项目/术语表管理、说话人分离(实验)和多格式导出。转写完成后,来源选择会自动收起,结果横幅提供“模式 + 一键生成讲义”;转写结果里可直接播放源音视频、点击时间戳跳转,当前句自动高亮;也可选择目标语言并“逐句翻译”,译文显示在每句转写下方。顶部有“搜索”“问答”“环境”页,分别用于全文检索/讲义目录、基于转写的引用问答、环境初始化。在线链接支持播放列表/多 P 展开和批量队列;项目可重命名、打标签、收藏、归档、删除,并查看/清理存储占用。讲义页只保留一个主按钮和四个模式切换,不再需要在多个表单之间来回操作。浏览器只调用 DSH 自己的 /vidora 回环路由;详细路由和限制见 docs/ui.md。
开发与测试
npm run build # TypeScript -> dist
npm test # Node 单元/集成测试(64 项)
npm run test:python # Python Worker 单元测试(需先安装 venv)
npm run check # build + node --check + tests
# 真实推理(需要模型和 venv)
node scripts/real-asr-test.mjs testdata/audio/lecture-5m-zh.m4a --device mps
# 生成真实测试语音(macOS say;仅用于可重复测试)
node scripts/generate-test-audio.mjs --minutes 5 --name lecture-5m-zh
详细测试方法、CER 结果、取消/恢复结果见 docs/test-report.md。
已知限制
- 支持本地文件与 Bilibili/YouTube 链接;播放列表/多 P 可展开为批量队列,不支持直播、DRM/付费墙/登录绕过。
- 第一版以 片段级 时间戳为可靠交付;字符/词级时间戳来自 ForcedAligner,作为增强字段
words。对齐失败时标记为chunk或uncertain,不会伪造精确时间。 - 在线导入对播放列表/多 P 先展开成独立视频队列;不支持直播、DRM/付费墙/登录绕过。部分视频会触发 YouTube 人机验证,需要在界面选择已登录浏览器的 Cookies,或配置
cookiesFile。 - 在线导入依赖本机
yt-dlp和目标站点可访问性;网络被阻断时会失败,不会改用云端下载服务。 - 说话人分离是实验性的 MFCC + KMeans 聚类,只适合双人/少数说话人场景;不是 pyannote 级别的 diarization。
- Web 面板使用安全 Markdown 渲染(标题、列表、表格、代码块、讲义目录),支持预览/源码切换,不注入 HTML。
- Windows 原生文件选择已接入 PowerShell;仍需在真实 Windows 上验证。媒体播放依赖浏览器支持的容器/编码。
- MPS 已在 M1 Pro 上实测可用;CUDA 未在本机验证;CPU fallback 可用但更慢。
- Linux/Windows 的路径、进程和安装流程已做代码适配,但未在本机实测;详见 docs/cross-platform.md。
- 1.7B ASR 模型、真实 GPU、Intel Mac 未实测。
- 讲义/翻译质量取决于当前 Harness 模型。历史测试使用过 1.5B/3B 本地模型;小模型的章节合并和术语解释质量明显更弱。
- 长音频的 ASR 片段是 VAD 边界;跨边界句子采用静音感知切分 + 边界重复抑制,但不做强制重切/全文重对齐。
- 首次使用可在“环境”页安装 Python Worker、下载 ASR/对齐模型;模型权重下载需要网络和用户显式确认。
- 环境初始化任务使用本机脚本,不会自动安装 FFmpeg 或 yt-dlp,缺项会在“环境”页给出命令提示。
许可证
插件代码:MIT。第三方模型、Python 包、FFmpeg 的许可证与来源见 THIRD_PARTY_NOTICES.md。Qwen3-ASR / ForcedAligner 权重为 Apache-2.0。
Comments
Loading…