1. 项目概述一个全能的本地化音视频转录与智能分析平台如果你经常需要处理会议录音、访谈、播客或者视频内容并且厌倦了手动整理、标记说话人和提炼重点的繁琐工作那么今天聊的这个项目绝对能让你眼前一亮。Transcription Stream Community Edition我们姑且叫它“转录流”社区版是一个开箱即用的、完全自托管的音视频转录与说话人分离服务。它的核心魅力在于“一体化”和“离线化”从你扔给它一个音频/视频文件开始到最终拿到一份带时间戳、区分了不同说话人、甚至附带了AI智能摘要和全文检索的转录稿整个过程都在你自己的服务器上完成数据不出本地隐私和安全完全可控。这个项目巧妙地将几个顶尖的开源工具焊接在了一起用 OpenAI 的 Whisper及其增强版 WhisperX负责高精度语音转文字用 whisper-diarization 项目实现说话人分离即判断“谁在什么时候说了话”用轻量级大模型框架 Ollama 搭载 Mistral-7B 模型来生成内容摘要再用 Meilisearch 这个闪电般快速的搜索引擎为所有转录稿建立索引。最后它用一个简洁的 Web 界面和一个支持拖放的 SSH 文件夹把所有这些复杂的技术包装成了像使用网盘一样简单的操作体验。无论是技术极客想搭建自己的媒体处理流水线还是内容团队需要一个内部的高效转录工具这个项目都提供了一个近乎完美的起点。2. 核心架构与组件选型解析2.1 为什么选择这套技术栈当你决定自己搭建一个转录服务时会面临一堆选择。Transcription Stream 的选型背后是一套非常务实的工程思维核心目标是在保证最佳效果的前提下最大化利用现有成熟组件并确保整个流程能无缝衔接。2.1.1 语音转文字引擎Whisper 与 WhisperX 的黄金组合项目没有使用商业 API而是选择了 OpenAI 开源的 Whisper 模型。原因很简单第一免费且效果顶尖尤其在多语言和带口音的语音识别上表现惊人第二完全离线彻底杜绝了数据泄露风险。但原生 Whisper 有个问题它不区分说话人一段对话会变成一整块文本。所以项目引入了whisper-diarization。这并非一个单独的模型而是一个处理流水线。它先用 Whisper 进行转录然后使用一个专门的声学模型如 PyAnnote 的模型来分析音频识别出不同的语音片段并聚类判断这些片段属于几个不同的说话人最后将说话人标签与 Whisper 生成的字幕时间戳进行对齐。这个过程就是“说话人分离”Diarization。而WhisperX的加入则是为了进一步提升效率和精度。WhisperX 优化了 Whisper 的推理过程并引入了更精准的强制对齐Forced Alignment技术能将转录文本中的每个词与音频时间戳更精确地对应起来。在这个项目中它被用来做后处理确保最终输出中每个词的时间戳和对应的说话人都准确无误。注意这套组合拳对 GPU 内存有一定要求。虽然项目通过调整批次大小batch size进行了优化但如果你同时运行转录和后面的 LLM 摘要12GB 显存可能依然捉襟见肘。原作者就因此将 Ollama 服务分到了另一台机器上。这是部署时需要重点考量的点。2.1.2 智能摘要引擎Ollama Mistral-7B转录出文字只是第一步从长篇文字中快速抓取重点才是提升效率的关键。项目选择了 Ollama 来本地运行大语言模型。Ollama 的优势极其明显它把 LLM 的部署和运行简化到了极致一条命令就能拉取并启动一个模型并且提供了统一的 API 接口。模型方面选择了 Mistral-7B。这是一个 70 亿参数的模型在开源模型中以其出色的性能和高效率平衡而闻名。7B 的规模意味着它对硬件的要求相对友好可以在消费级 GPU 甚至足够内存的 CPU 上运行同时又在理解、总结和遵循指令方面有足够的能力。用它来总结会议纪要、提取行动项、归纳话题完全够用且响应速度很快。2.1.3 全文检索引擎Meilisearch当你的转录稿积累到成百上千份时如何快速找到某次会议上提到的某个关键词或话题逐份打开查找是噩梦。项目集成了 Meilisearch一个用 Rust 写的、速度极快的搜索引擎。它能为所有转录稿建立实时索引支持复杂的搜索查询、过滤和高亮显示。这意味着你可以在几毫秒内从海量录音资料中定位到需要的信息这对于知识管理和内容回溯来说价值巨大。2.1.4 交互层SSH 与 Web 的双重接口这是项目在易用性上的点睛之笔。它提供了两种极其符合工程师习惯的文件提交方式SSH 文件夹投递在服务器上通过 SSH 挂载两个特殊文件夹transcribe仅转录和diarize转录说话人分离。你只需要用任何 SFTP 工具如scp,rsync或图形化的 FileZilla把文件拖进去后台服务就会自动处理结果输出到transcribed文件夹。这完美融入了自动化脚本和流水线。Web 图形界面对于临时、单次的操作或者需要预览、审阅的场景一个直观的 Web 界面ts-web提供了上传、播放、实时高亮字幕、下载等全套功能。它还会在处理完成后发送浏览器通知。这种设计覆盖了从全自动后台处理到人工交互审查的所有场景。2.2 服务架构与数据流整个系统由多个 Docker 容器组成通过 Docker Compose 编排ts-gpu核心工作容器。包含 Whisper, WhisperX, whisper-diarization 等所有音频处理流水线。它监听transcribe和diarize目录的文件变动执行繁重的 GPU 计算任务。ts-web前端 Web 应用容器。提供用户界面与 ts-gpu 和 Ollama 通信管理任务状态和文件展示。ollama运行 Mistral-7B 模型的容器。接收 ts-web 传来的转录文本执行摘要生成任务。meilisearch搜索引擎容器。接收并索引每一份完成的转录稿。一个 SSH 服务器通常集成在 ts-gpu 或单独容器中提供 SFTP 服务用于文件投递。数据流大致如下用户通过 Web 上传或 SSH 放入音频文件。ts-gpu 监听到新文件根据目标文件夹决定调用whisper仅转录或whisper-diarization转录说话人分离管道。处理完成后生成.srt(字幕)、.txt(纯文本)、.json(结构化数据) 等文件存入带日期时间戳的专属文件夹。ts-web 更新任务状态并可选地将纯文本发送给 ollama 容器进行摘要。摘要生成后保存为summary.txt。同时转录文本被发送到 meilisearch 建立索引。用户可以在 ts-web 上播放音频、查看同步高亮的字幕、下载所有文件或者通过未来集成的界面搜索所有历史转录稿。3. 从零开始的部署与配置实战3.1 硬件与基础环境准备在动手之前请确保你的环境符合要求这能避免后续绝大部分问题。3.1.1 硬件要求GPU强烈推荐这是最大的性能瓶颈。你需要一块 NVIDIA GPU因为依赖 CUDA。显存至少 8GB如果要同时流畅运行转录和 Ollama 摘要建议 16GB 或以上。项目作者提到 12GB 都可能不够所以做好规划。可以使用nvidia-smi命令检查显卡信息。CPU 与内存现代的多核 CPU如 Intel i5/R5 及以上和至少 16GB 的系统内存是基础保障。处理长音频文件时内存消耗较大。存储Docker 镜像本身巨大ts-gpu 约 26GB加上模型文件和生成的转录稿建议预留 50GB 以上的 SSD 空间以获得最佳体验。3.1.2 软件基础操作系统Ubuntu 22.04 LTS 或 20.04 LTS 是最稳定、社区支持最好的选择。其他 Linux 发行版也可行但可能需要调整部分依赖安装命令。NVIDIA 驱动确保已安装最新版的、与你的 CUDA 版本匹配的官方驱动。可以去 NVIDIA 官网根据显卡型号下载。Docker 与 Docker Compose这是项目的运行基石。# 安装 Docker sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod ar /etc/apt/keyrings/docker.asc echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release echo $VERSION_CODENAME) stable | \ sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # 将当前用户加入 docker 组避免每次用 sudo sudo usermod -aG docker $USER # 退出终端重新登录生效 # 验证安装 docker --version docker compose versionNVIDIA Container Toolkit让 Docker 容器能使用宿主机的 GPU。distribution$(. /etc/os-release;echo $ID$VERSION_ID) curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \ sed s#deb https://#deb [signed-by/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g | \ sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list sudo apt-get update sudo apt-get install -y nvidia-container-toolkit sudo nvidia-ctk runtime configure --runtimedocker sudo systemctl restart docker # 验证 GPU 在 Docker 中可用 docker run --rm --runtimenvidia --gpus all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi如果最后一条命令能成功输出显卡信息说明环境配置正确。3.2 项目获取与快速启动最省心的方式是使用项目提供的“免构建”脚本它会直接从 Docker Hub 拉取预构建好的镜像。# 1. 克隆项目代码仓库 git clone https://github.com/transcriptionstream/transcriptionstream.git cd transcriptionstream # 2. 直接运行快速启动脚本这会拉取镜像并启动所有服务 chmod x start-nobuild.sh ./start-nobuild.sh这个脚本背后其实就是调用了docker compose up -d。首次运行需要下载总计约 30GB 的多个镜像请保持网络通畅并耐心等待。完成后你可以用docker ps查看运行中的容器。3.3 自定义构建与深度配置如果你想修改代码、使用特定的模型版本或者想了解背后的构建过程则需要从源码构建。3.3.1 构建前的关键配置.env文件项目根目录下的.env文件是全局配置的核心。在运行构建脚本前最好先审视并修改它。# 查看并编辑 .env 文件 cp .env.example .env # 如果不存在先复制示例文件 nano .env你需要关注以下几个关键变量WHISPER_MODEL指定使用的 Whisper 模型大小如large-v3。模型越大精度越高但速度越慢显存占用越大。medium是精度和速度的一个较好平衡点。OLLAMA_HOST如果你的 Ollama 服务运行在其他机器上修改这里的 IP 地址。MEILI_MASTER_KEYMeilisearch 的主密钥用于 API 访问。务必修改为一个强密码。TS_WEB_SECRETts-web 应用的密钥用于会话安全。同样务必修改。INCLUDE_MODELS控制构建 ts-gpu 镜像时预下载哪些语音模型。如果磁盘空间紧张可以只保留你需要的模型如large-v3。3.3.2 执行自动化构建与运行脚本项目提供了两个主要的脚本# 1. 安装脚本构建 Docker 镜像这个过程非常耗时取决于网络和机器性能 chmod x install.sh ./install.sh # 这会构建 ts-gpu 等镜像可能需要数小时 # 2. 运行脚本启动所有容器服务 chmod x run.sh ./run.sh实操心得构建ts-gpu镜像是最耗时的环节因为它需要下载并编译许多深度学习依赖。建议在夜间或网络条件好时进行。如果构建失败通常是网络超时导致可以尝试更换 Docker 镜像源或分段执行 Dockerfile 中的命令进行排查。3.3.3 修改默认 SSH 密码出于安全考虑必须修改默认的 SSH 用户密码。默认密码nomoresaastax是公开的。 找到ts-gpu目录下的Dockerfile搜索nomoresaastax修改RUN echo transcriptionstream:nomoresaastax | chpasswd这一行将nomoresaastax替换为你自己的强密码。然后重新构建ts-gpu镜像。4. 核心功能使用详解与避坑指南4.1 两种文件提交方式实战4.1.1 SSH/SFTP 投递适合自动化这是最高效的批量处理方式。服务启动后会在 SSH 服务器上暴露两个目录transcribe和diarize。连接信息主机你的服务器 IP端口22222(注意不是默认的22)用户名transcriptionstream密码你修改后的密码或默认的nomoresaastax操作方法使用任何 SFTP 客户端如命令行sftp、scp或图形化工具 WinSCP、FileZilla连接上述信息。你会看到根目录下有transcribe、diarize和transcribed文件夹。将你的音频/视频文件支持 mp3, wav, m4a, mp4, mov 等常见格式直接拖入transcribe文件夹仅进行语音转文字不区分说话人。diarize文件夹进行语音转文字并区分说话人。文件放入后后台服务会自动检测并开始处理。处理完成后原始文件会被移动到transcribed目录下的一个以时间戳和文件名命名的子文件夹中例如transcribed/2024-05-27_14-30-22_my_meeting.mp3/。该文件夹内包含所有输出文件。注意事项通过 SSH 放入的文件其处理状态无法在 ts-web 界面中直接看到。你需要到transcribed目录下查看是否生成了结果文件夹来判断是否完成。对于超长文件如超过2小时的会议处理时间可能很长请耐心等待。4.1.2 Web 界面上传适合交互式操作在浏览器中访问http://你的服务器IP:5006即可打开 ts-web 界面。上传点击上传按钮选择文件并选择任务类型Transcribe 或 Diarize。任务队列上传后文件会出现在任务列表中。你可以实时看到处理状态等待中、处理中、完成、失败。结果查看与播放处理完成后任务项会变成可点击的链接。点击进入详情页你会看到一个内嵌的 HTML5 音频播放器以及同步滚动和高亮的转录文本区域。播放音频时对应的文本行会高亮点击文本音频也会跳转到对应时间点。这非常适合校对和审阅。下载在详情页可以下载原始的音频文件、.srt字幕文件、.txt纯文本文件、.json结构化数据文件以及生成的summary.txt摘要文件。4.2 自定义摘要提示词Prompt项目默认的摘要提示词已经很有结构但你可以根据自己行业或场景的需求进行定制让 AI 输出更符合你要求的摘要。修改位置ts-gpu/ts-summarize.py文件中的prompt_text变量。prompt_text f 请你作为专业的会议纪要助手分析以下转录文本。 请严格按照以下格式输出摘要 【与会人员】列出所有发言者的标识如 Speaker 0, Speaker 1及其在会议中扮演的角色如果能从上下文推断例如主持人、项目经理、开发代表。 【核心议题】归纳会议讨论的 3-5 个核心主题按重要性降序排列。 【关键结论与决定】逐条列出会议达成的明确结论、做出的决策以及相关责任人。 【待办事项Action Items】以表格形式列出包含“事项描述”、“负责人”、“截止日期”如果提及。 【后续步骤】简述会议确定的下一步计划。 转录文本如下 {transcription_text} 修改后需要保存ts-summarize.py文件。重新构建ts-gpuDocker 镜像因为该文件被打包进了镜像内cd /path/to/transcriptionstream docker compose build ts-gpu docker compose up -d --force-recreate ts-gpu如果你也希望 ts-web 界面上“Summary”按钮显示的文字随之改变还需要修改ts-web/templates/transcription.html中对应的按钮或标题文字。实操心得设计提示词时指令越清晰、格式要求越严格LLM 的输出就越规整、越有用。可以尝试让模型以 Markdown 格式输出这样在 ts-web 中查看时会更加美观。另外Mistral-7B 对中文提示词的理解也很好你可以直接使用中文来要求它生成中文摘要。4.3 利用 Meilisearch 进行全文检索虽然 ts-web 界面尚未集成搜索功能但你可以直接通过 Meilisearch 强大的 API 来查询你的转录库。获取搜索密钥Meilisearch 启动后你需要一个具备搜索权限的 API Key。默认情况下你可以使用MEILI_MASTER_KEY在.env文件中设置的那个进行所有操作但在生产环境应该创建一个仅具有搜索权限的密钥。# 使用 curl 创建一个搜索密钥假设 Meilisearch 运行在本地 7700 端口 curl \ -X POST http://localhost:7700/keys \ -H Content-Type: application/json \ -H Authorization: Bearer 你的MEILI_MASTER_KEY \ --data-binary { name: Search Key, description: Used for searching transcripts, actions: [search], indexes: [transcripts], expiresAt: null }响应中会包含key字段这就是你的搜索密钥。执行搜索# 搜索所有包含“项目里程碑”和“风险”的转录稿 curl \ -X POST http://localhost:7700/indexes/transcripts/search \ -H Content-Type: application/json \ -H Authorization: Bearer 你的搜索KEY \ --data-binary { q: 项目里程碑 风险, highlightPreTag: em, highlightPostTag: /em, attributesToHighlight: [text] }返回的结果会包含匹配的转录文档并且text字段中匹配的关键词会被em标签包裹便于高亮显示。你还可以添加过滤器比如按日期、文件名或说话人进行筛选。5. 常见问题排查与性能优化实录5.1 部署与启动问题问题1运行./start-nobuild.sh或docker compose up时提示端口冲突。原因默认端口22222, 5006, 11434, 7700可能已被你机器上的其他服务占用。解决修改docker-compose.yml文件中各服务的ports映射。例如将5006:5006改为8080:5006这样外部就通过 8080 端口访问 ts-web。记得同时更新.env文件中TS_WEB_HOST等相关的配置如果存在并通知所有使用者新的访问地址。问题2容器启动后立刻退出查看日志docker logs 容器名显示 CUDA 错误或显存不足Out of Memory。原因ANVIDIA Container Toolkit 未正确安装或配置。排查在宿主机运行nvidia-smi正常吗运行测试命令docker run --rm --runtimenvidia --gpus all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi能在容器内看到 GPU 吗解决重新按照前文步骤安装和配置 NVIDIA Container Toolkit并重启 Docker 服务。原因BGPU 显存确实不足。尤其是同时运行转录大模型和 Ollama 的 Mistral-7B。解决分而治之将负载重的服务分到不同主机。这是最彻底的方案。例如在一台 GPU 服务器上只运行ts-gpu和meilisearch在另一台内存充足的机器甚至可以是 Apple Silicon Mac上运行ollama。然后修改.env中的OLLAMA_HOST指向另一台机器的 IP。降低模型规格在.env中将WHISPER_MODEL从large-v3改为medium或small显著减少显存占用。对于 Ollama可以考虑换用更小的模型如llama3.2:3b但摘要质量会下降。调整批处理大小项目作者已为了兼容性将批处理大小batch size从 8 调到了 16。你可以在ts-gpu相关的代码或配置中寻找调整参数的地方进一步调小如调到 4 或 2以在显存不足时也能运行但会降低处理速度。问题3Web 界面可以访问但上传文件后任务一直处于“等待中”或处理失败。排查查看相关容器的日志是第一步。# 查看 ts-gpu 容器的日志 docker logs transcriptionstream-ts-gpu-1 --tail 100 -f # 查看 ts-web 容器的日志 docker logs transcriptionstream-ts-web-1 --tail 100 -f常见原因网络问题ts-web无法连接到ts-gpu或ollama的服务。检查docker-compose.yml中服务间的网络配置确保它们在同一自定义网络下并且使用服务名如ts-gpu而非localhost进行通信。权限问题Docker 容器内用户对挂载的卷volume没有写入权限。检查宿主机上./data等目录的权限确保 Docker 进程通常是 root 或特定用户有读写权。依赖模型未下载首次处理时Whisper 需要下载对应模型。如果网络不畅可能卡住或超时。可以进入ts-gpu容器手动触发下载或使用国内镜像源。5.2 功能使用问题问题4处理后的转录文本中说话人标签全是“Speaker 0”、“Speaker 1”无法区分具体是谁。原因说话人分离Diarization技术本质上是无监督的声纹聚类它只能区分出音频中有几个不同的声音并给它们编号但无法知道这些编号对应现实中的哪个人。解决这是所有 Diarization 系统的共同“局限”。在实际工作流中通常需要人工后期校对。你可以在 ts-web 的播放界面结合音频手动修改文本前的说话人标签。导出.json文件里面包含了每个片段的时间戳和说话人 ID你可以用脚本批量替换。例如如果你知道 Speaker 0 是“张三”Speaker 1 是“李四”写一个简单的 Python 脚本将对应的 ID 替换为名字即可。问题5生成的摘要质量不高或者格式不符合要求。原因主要取决于提示词Prompt和模型能力。解决优化提示词如前文所述仔细设计你的prompt_text。明确指令、指定格式、给出例子Few-shot能极大提升输出质量。尝试不同模型Ollama 支持众多模型。你可以停止默认的ollama容器换用其他可能更擅长总结的模型例如llama3.2或qwen2.5:7b。只需修改docker-compose.yml中ollama服务的启动命令或通过 Ollama 的 API 在运行时拉取和切换模型。后处理如果摘要只是格式有点乱可以写一个简单的后处理脚本对summary.txt的内容进行清洗和格式化。问题6通过 SSH 放入的文件在 ts-web 里看不到。这是预期行为。SSH 投递和 Web 上传是两个独立的入口。SSH 处理的文件其状态和结果不通过 ts-web 的数据库管理因此不会在 Web 任务列表显示。你需要直接到服务器文件系统的transcribed目录下去查找结果。5.3 性能与稳定性优化为长音频文件启用分段处理Whisper 本身能处理长音频但一次性加载超长文件到内存可能不稳定。whisper-diarization通常内置了分段逻辑。你可以检查其配置确保chunk_length_s参数设置合理例如 30秒。这能在处理数小时长的文件时提高稳定性。使用更快的存储确保 Docker 的数据卷./data和模型缓存目录位于 SSD 上。机械硬盘的 IO 速度会成为整个流水线的瓶颈尤其是在加载大型模型时。监控 GPU 使用情况使用nvidia-smi -l 1命令实时监控 GPU 显存占用和利用率。这能帮助你判断瓶颈是在计算还是数据加载上并据此调整批处理大小或并发任务数。定期清理转录生成的中间文件和缓存可能会占用大量空间。可以设置一个定时任务cron job定期清理./data目录下超过一定天数的临时文件夹或者只保留最终的输出文件。这个项目将一个复杂的多模态 AI 应用栈封装成了几乎可以一键部署的解决方案。它最大的价值在于提供了一个完整、可复现的参考架构。你可以直接用它作为生产力工具更可以将其作为蓝图根据自身需求裁剪、增强或集成到更大的系统中。例如将其转录结果自动同步到 Notion、钉钉文档或者与你的客户关系管理系统CRM打通自动生成客户访谈报告。想象空间就此打开。