中文 | English
一个本地运行的录音转文字桌面 App:macOS 可安装为双击 App,Windows/Linux 提供源码引导安装与启动脚本。 全程离线,不调用任何云 API,音频与文字都不出本机。
以转写准确性为根基,之上提供三种专业模式:
| 模式 | 场景 | 产出 |
|---|---|---|
| 通用转写 | 会议、访谈、自言自语、任意音频文件 | 忠实原文的逐字稿(中英混合自动识别) |
| 课堂录音 | 空旷、有回声、老师离得远、旁边有人闲聊 | 降噪 + 只留主讲人的逐字稿 + 自动重点总结 |
| 雅思口语教官 | 教官与考生一对一练习(中英夹杂) | 区分教官/考生 + 疑似读音/语法/表达问题标注 + 反馈报告 |
代码主体在
lecture_intel/(历史目录名,App 名为 Recorder)。
市面上的录音转文字应用有一个共同的默认行为:它会悄悄把你说错的话改对。 语法修好、句子理顺、口音抹平——对"记录会议内容"是优点,对"我想知道我说得 怎么样"是灾难,因为诊断价值恰恰在那些错误里。
Recorder 的第一原则是:
任何模式都不改写说话人的措辞选择。说错的原样保留。
需要提示的地方(读音存疑、语法问题、中式表达)只做标注,不动正文。 可选的本地大模型增强也只在"听不清导致的转写错字"上工作,不做润色改写。
边界同样要说清:Whisper 解码时本身就会丢弃部分语气词(上游
faster-whisper#901、whisper.cpp#965 报告后均未修复)。50 条评测集实测
(TTS 合成、large-v3 通用模式):英文填充词召回 92%、中文 90%,
半截话保留 100%;丢失以吞掉(如 "er"/"呃")或误写近音字("嗯"→"恨")为主,
均属上游解码固有损耗。详情与决策门见 lecture_intel/eval/README.md。
课堂模式是唯一会清理正文信号的模式,且清理一律留痕:降噪参数与门控
决策、被剔除的时间区间、被折叠的疑似循环,全部写入输出目录的 meta.json——
每条都可回查,原话永远在标注里。通用与雅思模式对疑似伪影只标注、不动正文。
- 完全离线。Whisper 模型跑在本机,首次下载后可以断网使用。没有账号、没有上传。
- Apple Silicon GPU 加速。默认
mlx-whisper(Metal);不可用时自动回退faster-whisper(CPU)。纯 CPU 推理依赖已按平台整理,CPU 设备的自动档使用small模型,且支持预下载后离线运行。 - 跨平台与加速后端:Windows/Linux 的核心、GUI 离屏测试和上传音频转录 smoke test 已加入 GitHub 托管 runner。App/CLI 已接入可选 whisper.cpp Vulkan(兼容的 Intel/AMD GPU)和 Intel OpenVINO GPU;未配置或未能确认 GPU 执行时回退 faster-whisper CPU。真实 GPU 验收通过自托管硬件 workflow 执行,在对应 Intel/AMD 作业通过前 不宣称 GPU 已实机验证。Apple Silicon 使用 MLX/Metal;Intel Mac 使用 CPU。见 GPU 后端实测指南。
- 中英混合(code-switching)不偏科。中文段落保持中文、英文段落保持英文, 不会被"翻译"成单一语言(实现见下方"工程要点")。
- 录音来源:各平台支持麦克风和已有音频文件;系统声音链路已接入 macOS (ScreenCaptureKit)、Windows(WASAPI loopback)和 Linux(PipeWire/PulseAudio monitor)。 macOS 的电脑内部声音及麦克风混录可直接使用;Windows/Linux 的系统声音仍需在对应真机上 播放声音并确认生成的 WAV 非静音后,才能视为验收通过。
- 逐词置信度始终开启——这是雅思模式识别"疑似发音问题"的依据。
- 长录音稳。2 小时录音在 16GB 机器上按静音分块处理,内存有界、进度真实。
- 崩溃安全。转写在独立子进程中运行,即使模型进程被系统杀掉,界面不会崩、 已录下的音频不会丢。
- 导出 txt / md / docx,带时间戳与说话人标签;json 导出附带忠实度标注;旧版
.doc转换仅 macOS 可用。 - 深浅色主题,跟随系统。
- 可选本地大模型(Ollama)。装本机后可做校对 / 课堂总结 / 雅思点评;按语言选用模型。
选型与安装见 lecture_intel/docs/LLM_MODELS.md。
- 麦克风按 48 kHz / 16-bit / 单声道 裸 PCM 采集。擦音(s/sh/th/f)的对立频段在
8 kHz 以上,16 kHz 采集会在录音瞬间永久丢失它们——而"疑似读音问题"诊断恰恰依赖这些
频段。一切降采样只发生在派生副本上(引擎内部归一化到 16 kHz 供 ASR),输出目录里的
original.wav终身保持采集原样,并带 SHA-256 哈希。 - macOS 麦克风模式(菜单栏麦克风图标/控制中心可选 标准 / 语音突显 / 宽谱):建议保持
标准。要验证当前模式的影响,用同一句话分别在两种模式下各录一段,对比两个输出目录的
original.wav即可(语音突显的 DSP 会改变信号,诊断场景以标准模式为准)。 - 蓝牙耳机慎用于发音诊断:进入 HFP 通话模式后硬件只输出 16 kHz,且其回声消除/降噪 DSP 不可关闭。要诊断发音,请用有线或模拟麦克风。
- 每个输出目录自带
meta.json:原始音频哈希、处理链逐步参数(归一化、降噪门控、仲裁、 剔段)、导出文件哈希——逐字稿可证明来自哪版音频。
加载 → 整文件转写 → 导出。中英自动识别,逐字忠实。
ffmpeg 预处理(高通去低频隆隆 + 自适应降噪 + 响度归一,按噪声底门控,参数与决策写入
meta.json)→ 转写 → 疑似重复仲裁(真口吃保留,确认伪影才折叠,原话留在标注)→
说话人聚类后只保留说话时长最长的主讲人(被剔除区间写入 meta.json)→
自动提取重点(强调句式、定义句、高频术语、讲解最久的片段)生成 *.summary.md。
转写 → 免 token 的两人分离(声纹嵌入 + 聚类,自动判定教官/考生, 界面可一键对调)→ 分析 → 反馈报告。
分析包含四类,全部只标注不改写:
- 疑似读音问题:Whisper 逐词置信度异常低的词——声学模型"没听准"的地方, 通常就是读不清、读错或口音偏差的词。已做多重降噪处理(跳过段首伪影、 过滤常用词、要求词长 ≥4)以减少误报。
- 语法问题:时态、主谓一致、冠词等;本机有 LanguageTool 服务时用它, 否则走内置规则。
- 表达问题:中式英语、搭配不自然。
- 教官的纠正:教官现场给出的正确说法,作为参考一并列出。
最后按雅思四项维度(流利度与连贯 / 词汇 / 语法 / 发音)汇总成报告, 报告里嵌入完整逐字稿。
需要 Python 3.10+ 与 ffmpeg。进入 lecture_intel/ 后按平台安装:
uv venv
uv pip install -r requirements.txt
./make_app.sh # 安装到 /Applications/Recorder.apppowershell -NoProfile -ExecutionPolicy Bypass -File .\install_windows.ps1 -DownloadCpuModel
powershell -NoProfile -ExecutionPolicy Bypass -File .\run_windows.ps1bash install_linux.sh --download-cpu-model
./run_linux.shWindows/Linux 当前发布形式是源码引导安装,不是签名的独立可执行安装包。已有音频文件上传转录
在各平台共用同一离线流水线;系统声音采集的 Windows/Linux 真机验收不由 CI 的编译和
--capabilities 检查替代;系统声音采集仍需对应设备的真机播放和非静音 WAV 验收。
Vulkan/OpenVINO 的真实 GPU 状态见验收指南。
cd lecture_intel
.venv/bin/python3 download_models.py # 走 hf-mirror.com 镜像,落到本地模型目录模型分三档,界面里可选:最准 large-v3 / 均衡 large-v3-turbo /
最快 small。下好之后运行时完全不联网。
窗口收窄(紧凑档)时模型下拉只显示图标,对应含义:🎯 = 最准(一箭中靶心)、 ⚖️ = 均衡(天平)、⚡ = 最快(闪电);展开下拉仍是完整名称,收起态悬停也有完整名称的提示。
.venv/bin/python3 transcribe.py 录音.m4a # 通用
.venv/bin/python3 transcribe.py 课堂.mp3 -m classroom # 课堂
.venv/bin/python3 transcribe.py 雅思.webm -m ielts # 雅思反馈
.venv/bin/python3 transcribe.py a.wav --model large-v3-turbo -f txt -f docx
.venv/bin/python3 transcribe.py 讲座.m4a -l ja # 指定语言(默认自动检测)语言选择器列出 13 种语言(中/英/日/韩/法/德/西/乌克兰/阿/泰/越/印尼/印地语), 但**「自动检测」不限于此**——Whisper 本身支持 100 种语言(mlx-whisper 与 faster-whisper 实测为同一张语言表), 列表之外的语音照常识别转写,只是无法在界面或命令行手动指定。
支持 m4a / mp3 / wav / webm / flac / aac / ogg / opus。
第一次点「开始转写」会弹一次保存位置确认框(就像浏览器下载那样):默认落在你 git 下来 / 解压的那个文件夹下的 output/——
路径在运行时向上找 .git 定位,所以每个人都是自己的目录,不写死任何人的本机路径。
从已安装的 App 启动、周围没有仓库时,退回 ~/Documents 下的数据目录,
绝不默认写到 ~/Library/Application Support 或 /Applications 这类系统目录——用户不会去那儿找自己的文件。
确认后按录音文件名建子文件夹存放结果。选择会被记住,之后不再弹;要改用菜单「文件 → 更改输出文件夹…」,
随时查看用「显示输出文件夹」。命令行默认写到音频旁边的 <文件名>_output,可用 -o 指定。
装了 Ollama 之后可在界面打开「AI 增强」:修正听不清导致的错字、生成课堂总结、补充雅思考官点评。关掉则走离线规则。模型跑在本机,权重不要提交进 Git。
「不改写」的边界:主转写逐字忠实、永不改写;可选 AI 增强只额外生成一份校对版(补标点、修识别错别字),原文文件保持不变;说话人自己的语言错误只被标注,不被修改。
默认路由:中文录音推荐 Qwen(qwen3 / qwen2.5:7b),其余语言默认 Mistral;
候选链只收可在 Ollama 下载的大语言模型(Ollama 库中目前不存在可下载且真能喂音频的多模态大语言模型,而本 App 本就不向 Ollama 送音频)。
这只是默认值,具体装哪个、装多大由你自行选择。未安装 Ollama 或没装任何匹配模型时,增强自动跳过。安装步骤、内存档位与中国镜像见:
lecture_intel/docs/LLM_MODELS.md
lecture_intel/
├── app.py GUI 入口(双击目标)
├── transcribe.py CLI 入口
├── make_app.sh 构建并安装 /Applications/Recorder.app
├── download_models.py Whisper 模型预下载(镜像直连)
├── docs/LLM_MODELS.md 硬件档位 × Ollama(Qwen/Mistral)选型
│
├── core/ 引擎
│ ├── engine.py 唯一编排入口:run(input, output, mode)
│ ├── modes.py general / classroom / ielts 三套参数预设
│ ├── transcriber.py Whisper 封装(mlx → faster-whisper 回退、分块、逐词置信度)
│ ├── provenance.py meta.json 留痕:原始哈希、处理链逐步参数、导出哈希
│ ├── repeat_arbitration.py 口吃 vs ASR 循环三级仲裁(时间轴 → silencedetect → 孤立重解码)
│ ├── denoise.py ffmpeg 降噪(课堂,噪声底门控)
│ ├── diarize.py 免 token 说话人分离(声纹嵌入 + 聚类 + 时序平滑)
│ ├── ielts.py 发音 / 语法 / 表达分析与报告
│ ├── classroom.py 重点提取与总结
│ ├── llm.py 可选的本地 LLM 增强(Ollama)
│ ├── sysaudio.py 系统内录驱动
│ ├── runner.py 子进程执行器(崩溃隔离)
│ ├── paths.py 用户数据目录(唯一真源)
│ └── export.py txt / md / doc / docx 导出
│
├── gui/ PySide6 界面(首页 / 录音 / 处理 / 结果 + 主题)
├── native/ SystemAudioRecorder.swift(ScreenCaptureKit 内录)
├── dictionaries/ 课堂术语词典(旧流水线存档,core 引擎未接入)
└── tests/ 无需模型即可跑的单元测试(python -m pytest)
数据流:
音频 →[课堂: 降噪]→ 按静音分块转写(GPU) →[分离说话人 / 只留主讲人]
→[雅思分析 | 课堂总结]→ 导出
这些是把"能跑"做到"准且稳"过程中真正起作用的决定:
整文件送 Whisper,而不是自己切 30s 小段。 早期版本先用 VAD 切段再逐段转写,切口处丢词、重叠处重复、上下文断裂。 Whisper 自带 30s 窗口与跨窗上下文,直接喂整段最准。超长音频只在静音处 分大块,不在句子中间下刀。
分块 + 逐块语言检测,解决中英混说。 单次全局语言判定会把少数语言"翻译"掉(英文模式吃掉中文,中文模式吃掉英文)。 按静音切块后每块独立检测语言,中英各自保真,同时仍然全程在 GPU 上跑。
分块也顺带解决了内存与进度。 2 小时录音不再构建一张巨图(16GB 机器不会 OOM),进度条按块推进, 不会卡在某个百分比不动。转写幻觉产生的重复循环由专门的抑制逻辑收敛。
转写跑在子进程,不是线程。 模型编译时递归很深,会撑爆工作线程的小栈;应用退出时若线程仍在运行会直接 abort。改成 multiprocessing 子进程 + 主线程轮询结果队列后:子进程崩溃只是 子进程崩溃,界面照常、录音文件安全,退出时直接终止子进程即可。
说话人分离不用需要授权令牌的方案。
改用声纹嵌入 + 层次聚类,两人场景足够。同性别声音在声学上常常分不开,
因此加了一层语言混合回退:当声学分离明显失衡、且某段的语言不是考生语言时,
按语言归属分配角色(雅思考生一律答英文,说其他语言的即教官)——中文、日文、
韩文、俄文、泰文教官已用真实音频验证可分,这一步才让教官/考生分离真正可用。
法/德/西这类与英文同用拉丁字母的教官尚未可靠:逐块语种只在每个静音块恰好
只含一种语言时才够用,而真实会话的 60 秒块常混两种语言;且声学分离成功时,
角色判定(_candidate_score)目前还不看段语种。两点均已建任务跟踪。
系统内录自己写 WAV。 ScreenCaptureKit 给出的是非交错 Float32,AVAudioFile / 转换器都拒绝处理, 于是 Swift 侧手动反交错成交错 Int16 并手写 WAV 头。需要一次性授予"屏幕录制" 权限,未授权时界面会给出明确指引。
打包不用 py2app / PyInstaller。
把 torch、mlx 冻进 bundle 体积巨大且脆弱。改为构建一个轻量 .app 启动器,
指向安装好的运行副本;依赖照常可以升级。由于 macOS TCC 会阻止 Finder 启动的
App 读取 ~/Documents,安装脚本会把可运行副本与虚拟环境放到
~/Library/Application Support/Recorder,从那里启动,真正做到双击即开。
项目从 2026 年 5 月做到 7 月,大致五个阶段:
| 时间 | 阶段 |
|---|---|
| 2026-05-07 ~ 05-17 | 雅思口语批改原型:语法 / 自然度 / 发音规则 + FastAPI 接口(backend/) |
| 2026-05-30 ~ 06-01 | 转向课堂录音,搭起 11 步流水线(modules/ + pipeline.py) |
| 2026-06-13 ~ 06-14 | 推倒重来:mode 驱动的 core/ 引擎,整文件转写取代自切 VAD 段;子进程隔离崩溃 |
| 2026-06-18 ~ 06-20 | 系统内录、深浅色主题、用户数据目录统一 |
| 2026-07-05 ~ 07-07 | 界面改版为四屏,录音来源三选一 |
早期一直没有用 git 管理,2026-07-28 才导入版本库。因此所有提交的日期都是导入日期, 按上述阶段整理成 23 次提交,每条提交的正文里注明了它对应的原始开发时间。
规划分三步。当前状态:第 1、3 步已完成并经真实音频验证;第 2 步对中/日/韩/俄/泰 教官已验证可用,法/德/西等拉丁文教官尚未可靠。
- 统一语言设置(
language)+ 语言工具层——不是单独做一个「检测 App」, 而是让后续分离角色、报告、模型路由有统一参数; - 说话人分离去掉写死中文假设;
- 转写语言标签真正多语;再接分析。
实现要点:语言工具层在 core/languages.py,按 Unicode 文字系统判定语言
(假名→日语、谚文→韩语、汉字→中文;拉丁、西里尔、阿拉伯等被多种语言共用的文字
交给 Whisper 自己的检测结果区分),语言设置接入引擎、命令行(transcribe.py -l ja)
与界面「语言」选择器(默认自动检测,共 15 种常用语言)。教官角色判定以「非考生语言」
为准:日/韩/俄/泰教官按文字系统归属分角色,已用五种语言的真实音频逐一验证;
法德西等拉丁文教官要靠分块转写附带的逐块语种区分,实测尚不可靠——逐块语种
仅在单个静音块恰好只含一种语言时才足够,真实会话的 60 秒块常混两种语言,
且声学分离成功时角色判定(_candidate_score)尚未使用段语种(两点已建任务跟踪)。
可选的本地大模型增强(校对 / 课堂总结)按转写自身的语言下 prompt,
不再一律用中文指令;雅思教官点评报告保持中文说明(考生恒为英文作答,且界面为中文),
LanguageTool 保持 en-US(诊断对象即考生英文)。中英混说的判定阈值与归属规则保持
不变。规划中的可选项——教官话对照翻译——暂未实现,需要时再议。
模型路由说明见 LLM 指南。
- 模型与全部处理都在本机,没有任何网络请求(除首次下载模型)。
- 录音与转写结果写入本地数据目录(见
core/paths.py),仓库不收录任何音频。 - 可选的 LLM 增强走本地 Ollama,同样不出网。
python -m pytest # 仓库根目录运行,仅覆盖 lecture_intel/(默认验证层)
# backend/tests 为存档代码,不计入默认验证改完代码后重新运行 lecture_intel/make_app.sh 同步到已安装的 App。
完整需求与取舍记录见 REQUIREMENTS.md。
lecture_intel/— App 主体(唯一在维护的代码)。改界面前请先读lecture_intel/docs/GUI_DESIGN.md(必须保持的设计约定) 与lecture_intel/docs/LLM_MODELS.md(本地大模型选型)。aura_gui/、lecture_intel/gui_old/、pipeline.py、config.yaml与modules/中的课程分类 与结构化模块 — 被core/引擎取代的早期实现,已于 2026-09-20 删除 (modules/audio_loader.py与其中的数据类仍在使用,故modules/目录保留;aura_gui/是界面改版的设计稿源本、早已合并进lecture_intel/gui/,其设计意图已迁至lecture_intel/docs/GUI_DESIGN.md)。backend/+frontend/— 最早的 FastAPI 雅思批改原型,其分析思路 (发音置信度、语法规则、报告模板)已并入lecture_intel/core/ielts.py, 保留仅作存档,可忽略。