Aureum01/streamscribe

GitHub: Aureum01/streamscribe

一款纯本地 CPU 运行的实时新闻直播流转录与分析工具,支持多流监控、磁盘缓存和本地 AI 查询,全程不依赖云服务。

Stars: 2 | Forks: 0

# streamscribe 在普通 CPU 上进行实时广播转录与分析,完全依赖本地 AI,无云服务依赖。 streamscribe 可以同时转录多个实时新闻流,将每个片段缓存到磁盘,并允许你使用自己的本地模型查询结果。音频永远不会离开你的设备。它专为记者、OSINT 从业者、研究人员和分析师而设计,满足他们在无需将任何数据发送至第三方 API 的情况下监控广播媒体的需求。 ``` YouTube live streams ---> capture engine ---> accurate captions (any count) (faster-whisper, | CPU-only) +--> quad monitor UI +--> session cache (disk) +--> local AI analyst (Ollama) +--> MCP server (agents) ``` ## 为什么会有这个项目 大多数转录工具在近实时传输片段时会破坏句子的完整性,或者需要 GPU 或云 API 的支持。streamscribe 做出了不同的取舍。字幕会比实时播放滞后固定的约 10 秒,但每一段都是包含完整上下文、一次转录完成的完整段落。所有内容都会被持久化存储到一个结构化缓存中,可供本地 LLM 或任何 MCP 客户端查询。仅限 CPU 的限制是刻意为之:目标用户使用的是普通笔记本电脑,而不是 GPU 阵列。 ## 功能 - **捕获与处理引擎。** 录制完整的音频窗口,在自然停顿处进行切分,结合完整上下文对每个窗口进行一次转录,并自动对拼接处进行去重。不会出现半个单词的碎片。 - **多流监控。** 每个流使用一个引擎进程,支持任意数量的订阅源,提供可同时显示最多六个面板的 CCTV 风格 UI。上方为静音视频,下方为实时转录文本。 - **会话缓存。** 每个已确认的片段都会作为机器可读的 JSONL 和纯文本格式存入 `cache///`,并按写入实时刷新。 - **本地 AI 分析师。** 侧边栏可汇总选定订阅源的近期转录内容,并将问题发送给你自己的 Ollama 模型。 - **MCP 服务器。** 将缓存(`list_feeds`、`get_recent_transcript`、`search_transcript`、`get_session_info`)暴露给 ollmcp、Claude Desktop、LangChain 或任何其他使用 Model Context Protocol 的客户端。 - **专为长时间无人值守运行而构建。** 具备退避机制的自动重连、实时摄取节奏控制、幻觉防护、广告时段空闲模式、WebSocket 保活,以及可选的音频快照自动清理。 - **支持本地视频。** 将订阅源指向任何 YouTube URL。VOD 将以正常速度通过处理流水线播放。 ## 快速开始 环境要求:Python 3.10+,PATH 中需包含 [ffmpeg](https://ffmpeg.org),分析师功能可选安装 [Ollama](https://ollama.com)。 ``` git clone https://github.com/Aureum01/streamscribe.git && cd streamscribe python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\Activate.ps1 pip install -r requirements.txt python quad.py ``` 该单一命令会为 `feeds.json` 中的每个条目启动一个转录引擎(首次运行时会生成一个初始配置文件),在 `http://localhost:8080/ui/quad.html` 提供监控 UI 服务,并自动在浏览器中打开。 如需使用 AI 分析师,请在另一个终端中运行: ``` ollama serve ollama pull llama3.2:3b # once; a good CPU-sized analyst model ``` ## 准确度阶梯 streamscribe 默认配置针对普通硬件进行了优化。每一层都有文档记录的升级路径。以下是升级收益从高到低的顺序。 ### 1. Whisper 模型(影响最大的单一因素) 默认的 `tiny.en` 可以在普通 CPU 上同时运行四个订阅源。每提升一个级别,对名称、数字和口音的识别能力都会增强,而这些通常是分析工作中最关键的细节。 | 模型 | 参数量 | 每个订阅源内存占用 | 相对速度 | 适用场景 | |---|---|---|---|---| | `tiny.en` | 39M | ~0.5 GB | 1.0x | 普通 CPU 上运行 4 个及以上订阅源 | | `base.en` | 74M | ~0.7 GB | ~0.6x | 推荐的首选升级方案 | | `distil-small.en` | 166M | ~1.0 GB | ~0.5x | CPU 周期利用率最佳的质量 | | `small.en` | 244M | ~1.5 GB | ~0.25x | 接近广播级质量,支持 1-2 个订阅源 | | `large-v2` | 1.5B | ~4 GB+ | 建议使用 GPU | 多语言及翻译 | ``` python quad.py --model base.en # every feed ``` 或者也可以在 `feeds.json` 中(或 UI 的配置抽屉中)为每个订阅源单独设置,这样就可以让一个高优先级的订阅源运行比其他订阅源更大的模型: ``` { "feed_id": "bloomberg", "url": "...", "port": 8765, "model": "distil-small.en" } ``` ### 2. 捕获窗口 更长的窗口能为模型在每次处理时提供更多的句子上下文,但也会导致相应程度的延迟增加。使用 `--window 8`(默认值)大约会比实时延迟 10 秒。在密集语音场景下,`--window 12` 的阅读体验会有显著提升。 ### 3. 分析师模型 支持任何 Ollama 模型。在 CPU 上,`llama3.2:3b` 和 `qwen3:4b` 可以在一分钟内给出回答。8B 模型更智能,但每个问题需要几分钟时间。如果有 GPU,70B 级别的模型可以直接接入,其他设置无需任何更改。 ### 4. 路线图 丰富化处理器(基于缓存的 NER、声明提取、监视列表警报)、会话配置文件构建器(每个订阅源的运行叙述上下文)、跨订阅源分歧检测、多语言 large-v2 翻译以及直接广播站点音频提取器。缓存 schema 是所有这些功能赖以构建的稳定接口。 ## 监控 UI - **订阅源列(左侧)。** 显示所有已配置的订阅源,采用 CCTV 风格,并带有实时状态指示点。点击订阅源可将其显示在屏幕上;当已显示六个面板时,最早加载的会被替换。下载图标可获取该订阅源的纯文本或 JSONL 格式的转录内容。 - **面板。** 上方为静音的 YouTube 嵌入视频(仅供人工监视;转录音频直接来源于流),下方为实时转录文本,支持自动滚动及滚动时暂停。 - **配置订阅源。** 添加、删除或编辑订阅源、端口和每个订阅源专属的模型。保存后立即生效:面板会立即切换到新视频,并且只有流、端口或模型发生更改的引擎才会重启。无需重启脚本,无需编辑文件。 - **AI 分析师。** 选择一个 Ollama 模型,选定订阅源和回溯窗口,然后进行提问。回答基于缓存的转录内容生成,并格式化为带有订阅源和时间戳引用的结构化纯文本。 - **清除会话。** 每日结束时的重置操作。删除整个缓存,并以全新的会话重启每个引擎。请先下载并保留你需要的内容。 ## 会话缓存 ``` cache/ └── bloomberg/ └── 20260611-134941/ ├── meta.json # stream URL, model, language; written once ├── session.json # live counters, rewritten as the session runs ├── segments.jsonl # one JSON record per confirmed segment └── chunks.txt # plain-text transcript, one segment per line ``` 每条 `segments.jsonl` 记录都包含 ISO 时间戳、实际时间、流偏移量、订阅源 ID 和文本。这是任何分析层的原始素材。`--keep-audio-minutes 30` 会在转录文本旁额外保存每次捕获的音频作为 WAV 快照,并自动删除超过保留期限的旧快照。 ## MCP 服务器 `mcp_server.py` 是一个零依赖的 stdio MCP 服务器,可将会话缓存暴露给任何 MCP 客户端。它提供四个工具: | 工具 | 参数 | 返回内容 | |---|---|---| | `list_feeds` | 无 | 所有包含已缓存会话的订阅源 | | `get_recent_transcript` | `feed_id`, `minutes` | 最近 N 分钟内带时间戳的片段 | | `search_transcript` | `query`, `feed_id?`, `minutes?` | 跨订阅源匹配关键词的片段 | | `get_session_info` | `feed_id` | 最新会话的元数据和计数器 | 如果缓存存储在 `./cache` 以外的位置,请设置 `STREAMSCRIBE_CACHE`。 根据你的具体环境,有以下三种使用方式。 ### 选项 1:Claude Desktop(最简单) 在 Windows 上将此内容添加到 `%APPDATA%\Claude\claude_desktop_config.json`。如果你使用的是 WSL,请像启动任何其他基于 WSL 的 MCP 服务器一样使用 `wsl.exe` 来启动它: ``` { "mcpServers": { "streamscribe": { "command": "wsl.exe", "args": [ "bash", "-ic", "/mnt/c/path/to/streamscribe/.venv/bin/python /mnt/c/path/to/streamscribe/mcp_server.py" ], "env": { "STREAMSCRIBE_CACHE": "/mnt/c/path/to/streamscribe/cache" } } } } ``` 保存后完全退出并重启 Claude Desktop。聊天输入框中会出现一个锤子图标,确认工具已成功加载。请确保 `quad.py` 已经提前运行,这样缓存中才有可供查询的内容。 ### 选项 2:ollmcp 终端客户端(完全本地,无云服务) 这会运行一个终端聊天会话,在此会话中,本地 Ollama 模型会直接调用 streamscribe 工具。不会向任何外部服务发送任何数据。 安装客户端: ``` pip install mcp-client-for-ollama ``` 在 Windows 上,Ollama 必须监听所有网络接口,以便 WSL 能够访问它。从系统托盘停止 Ollama,然后执行: ``` $env:OLLAMA_HOST = "0.0.0.0:11434" ollama serve ``` 若要在重启后永久保留此设置: ``` [System.Environment]::SetEnvironmentVariable("OLLAMA_HOST", "0.0.0.0:11434", "User") ``` 在 WSL 中查找 Windows 主机的 IP: ``` ip route | grep default | awk '{print $3}' ``` 然后启动客户端,指向该 IP: ``` ollmcp -s mcp_server.py -m qwen3:8b -H http://:11434 ``` 当它启动时,请禁用思考模式,以便模型直接触发工具调用,而不仅仅是对其进行推理: ``` /thinking-mode ``` 然后在第一次要求确认工具调用时输入 `s`,以允许该会话中的所有工具调用。查询示例: ``` What feeds does streamscribe have cached? Get me the last 30 minutes from bloomberg. Search for "iran" across all feeds from the last hour. ``` 适合用于工具调用的模型包括:`qwen3:8b`、`qwen3:14b`、`mistral:latest`、`qwen2.5:3b`。参数量小于 7B 的模型有时无法可靠地生成工具调用。 ### 选项 3:mcpo REST 桥接 mcpo 将 stdio MCP 服务器封装为 REST API,这使得任何 HTTP 客户端(包括脚本、curl 和 Invoke-WebRequest)都可以查询缓存。 ``` pip install mcpo mcpo --port 8200 -- python mcp_server.py ``` 然后直接调用工具: ``` Invoke-WebRequest -Uri "http://localhost:8200/list_feeds" -Method POST -ContentType "application/json" -Body "{}" -UseBasicParsing Invoke-WebRequest -Uri "http://localhost:8200/get_recent_transcript" -Method POST -ContentType "application/json" -Body '{"feed_id":"bloomberg","minutes":30}' -UseBasicParsing ``` 自动生成的 API 文档位于 `http://localhost:8200/docs`。 ## 控制 API UI 的所有操作都是通过同一端口上的标准 HTTP 请求实现的。 | Endpoint | Method | 用途 | |---|---|---| | `/api/feeds` | GET | 订阅源和引擎状态 | | `/api/feeds` | POST | 替换订阅源;仅重启发生变更的部分 | | `/api/restart` | POST | 重启单个引擎(`{"feed_id": "..."}`) | | `/api/transcript` | GET | 最近的片段(`?feed_id=&minutes=`) | | `/api/download` | GET | 转录文件(`?feed_id=&format=txt\|jsonl`) | | `/api/models` | GET | 已安装的 Ollama 模型 | | `/api/analyze` | POST | 基于事实的问题,返回结构化的纯文本回答 | | `/api/cache/clear` | POST | 清空缓存,重新启动全新的引擎 | ## 单一订阅源 CLI `pipeline.py` 可以脱离管理服务独立运行: ``` python pipeline.py --url "https://www.youtube.com/watch?v=..." \ --mode transcribe --model base.en --language en \ --feed-id myfeed --reconnect ``` 重要参数:`--window N`(捕获窗口秒数)、`--engine stream`(旧版低延迟滚动缓冲区)、`--serve --port N`(WebSocket 输出)、`--keep-audio-minutes N`、`--no-cache`、`--mode captions`(在可用时使用 YouTube 自动字幕,CPU 消耗为零)、`--debug`。 ## 配置参考 | 设置 | 位置 | 默认值 | 备注 | |---|---|---|---| | 订阅源、端口、每个订阅源的模型 | `feeds.json` / UI | 4 个初始订阅源 | 引擎在变更时进行差异化重启 | | whisper 模型 | `--model` / 单个订阅源 | `tiny.en` | 参见准确度阶梯 | | 捕获窗口 | `--window` | 8 s | 准确度更高,延迟更大 | | UI 端口 | `--ui-port` | 8080 | | | Ollama 主机 | `OLLAMA_HOST` 环境变量 | `http://localhost:11434` | | | 分析师超时时间 | `STREAMSCRIBE_OLLAMA_TIMEOUT` 环境变量 | 600 s | CPU 模型处理较慢 | | 缓存根目录 | `--cache-dir` | `cache/` | 由引擎、API、MCP 共享 | ## 故障排除 **视频面板显示“Error 153”。** 页面必须通过 HTTP 提供服务。YouTube 嵌入内容需要 referrer,而 `file://` 页面无法发送。请使用 quad.py 打印出的 URL,而不是文件路径。 **“inference behind capture”警告。** CPU 的转录速度跟不上订阅源传输音频的速度。请使用更小的 `--model`、更大的 `--window`,或者减少订阅源数量。 **分析师超时。** 第一次提问时会将模型加载到内存中(之后会保持加载状态 30 分钟)。请重新提问、选择更小的模型,或者缩短回溯窗口。上下文上限约为 12k 个,并使用 8k token 的上下文窗口发送,因此不会有内容被静默截断。 **连续几分钟没有字幕。** 可能是插播了广告或音乐垫音。引擎会刻意以接近零的 CPU 消耗跳过非语音片段,并在检测到语音恢复后的一个数据块内继续工作。 ## 测试 ``` python -m pytest tests -q ``` 该套件涵盖了对捕获引擎(窗口几何结构、静音点切分、拼接去重、幻觉防护、快照清理)、旧版流引擎、去重逻辑、缓存层的测试,以及一个 90 秒的脚本化广播模拟(要求在有限的缓冲区下一字不差地还原其播放脚本)。 ## 架构说明 每个订阅源使用一个独立的 OS 进程(一个引擎就是一个 `pipeline.py` 实例),各自拥有独立的 WebSocket 服务器和缓存会话。订阅源之间互不干扰,并且彼此独立崩溃。`quad.py` 充当监督者:它生成引擎,通过单一端口提供 UI 和控制 API 服务,并将分析师请求代理给 Ollama,因此浏览器不需要配置 CORS 例外。捕获引擎会根据实际时间协调摄取节奏(YouTube 直播流会提供长达数小时的 DVR 窗口,如果不加限制,这些数据会以最大下载速度涌入),并且最多在运行队列中保留四个已完成的窗口,当超出限制时,它会丢弃最旧的窗口并发出警告,而不是无限制地占用内存。 ## 许可协议与贡献 基于 [Apache 2.0 License](LICENSE) 发布。 尊重仅限 CPU 基准环境的贡献是最有价值的。每一项功能都必须确保能在笔记本电脑上优雅降级。如果你添加了 GPU 加速、多语言支持或更庞大的模型,请清楚地记录下 CPU 的兜底方案,以便让没有专用硬件的分析师依然能够正常使用该工具。
标签:AI风险缓解, ESC4, LLM评估, Ollama, OSINT, Whisper, 人工智能, 实时流媒体, 时序数据库, 本地部署, 用户模式Hook绕过, 逆向工具, 音频转录