# 本地课堂录音批量转文字（混合引擎）

把课堂录音（iOS 语音备忘录的 m4a 等）在**本地**批量转成 Markdown 纯文本，事后自己整理成笔记和考点。
不联网调用任何云端 API；中文主导的录音走 **FunASR SeACo-Paraformer**（中文最准 + 原生土木术语热词），
英语/法语等走 **faster-whisper**。按整个文件自动路由引擎，全程 CPU 推理，无需 GPU、无需 sudo。

## 用法（三步）

```bash
./setup.sh        # ① 首次配置：装依赖 + 预下载约 3GB 模型（联网一次，之后离线可用）
# ② 把录音文件丢进 input_audio/
./run.sh          # ③ 转写：output_text/ 里出现同名 .md 文件
```

> 也可以跳过 ① 直接 `./run.sh`：检测到依赖未就绪（如刚克隆本仓库）会**自动执行
> `setup.sh`，装完接着转写**；`requirements.txt`/`setup.sh` 有更新时同样会自动补装。
> `models/` 被删除也没关系，转写时按需自动重新下载。

## CLI 参数

| 命令 | 作用 |
|---|---|
| `./run.sh` | 全自动：探测语言 → 路由引擎 → 转写 |
| `./run.sh --language zh` | 强制语言：`zh`→Paraformer；`en`/`fr`/…→Whisper |
| `./run.sh --engine paraformer` | 强制引擎：`paraformer` 或 `whisper`（优先级高于 `--language`） |
| `./run.sh --model large-v3` | 换更准的 Whisper 模型（默认 `large-v3-turbo`，更准但更慢） |
| `./run.sh --dry-run` | 只解码+探测+打印每个文件路由到哪个引擎（依据），不转写 |
| `./run.sh --download-only` | 只预下载/校验模型到 `models/`，可重复运行 |

## 特性

- **断点续传**：`output_text/<同名>.md` 已存在且比音频新 → 自动跳过。重新录制/替换音频后自动重转。
- **失败隔离**：单个文件损坏/转写失败不中断批次，结束打印「成功 N / 跳过 N / 失败 N」及原因。
- **热词纠错**：Paraformer 原生词级偏置，土木术语识别更准（见下节）。
- **长录音**：VAD 自动切分，几小时的录音无需手动分段。
- **输出格式**：`# 文件名` + 正文（无时间戳），UTF-8 纯文本 Markdown，可直接整理。

## 添加课程专属热词

编辑 `hotwords.txt`，**一行一个词**，保存即生效（下次运行自动加载）。
`#` 开头的行为注释/分组标题，会被自动忽略，可按课程分区管理。
Paraformer 用全部热词做词级偏置；Whisper 的 initial_prompt 取前 50 个。
课程里新出现的术语（老师名字、教材名词、规范编号等）都值得加进去。
现有分组：基础土木词 + 桥梁工程 / 结构鉴定和加固 / 基础工程 / 土木防灾减灾 + 通用易错词。
若发现某个热词「抢词」（如把别的词错误识别成它），直接删掉该行再重转即可。

## 想更准 / 想强制引擎

- 更准（慢）：`./run.sh --model large-v3`
- 整段中文但夹杂英文术语的录音，若被误路由到 Whisper：`./run.sh --language zh`
- 反之，英语课里想走 Paraformer 是不支持的（Paraformer 只适合中文主导）；
  英语/法语主导请用默认路由或 `--engine whisper`。

## 网络问题备选

HuggingFace 下载慢/失败时，先设置国内镜像再重跑：

```bash
export HF_ENDPOINT=https://hf-mirror.com
./setup.sh
```

FunASR（Paraformer/VAD/标点）走 ModelScope（国内直连，一般无需镜像）。

## 将来有 NVIDIA GPU

```bash
uv pip install torch torchaudio          # 换回默认源（CUDA 版）
A2T_DEVICE=cuda ./run.sh                 # 代码保留了 device 参数位，环境变量即可切换
```

（同时把 `setup.sh` 里的 `--index-url https://download.pytorch.org/whl/cpu` 去掉重装 torch。）

## 分享 / 克隆

仓库**不含**模型（约 3GB）、虚拟环境（约 1.8GB）以及录音/转写数据（隐私，见 `.gitignore`），
克隆后直接 `./run.sh` 即可：自动安装依赖、下载模型，然后转写。

## 目录结构

```
audio_to_text/
├── setup.sh          # 首次一键配置（幂等；--check 供 run.sh 校验就绪状态）
├── run.sh            # 日常入口（依赖未就绪时自动先执行 setup.sh）
├── transcribe.py     # 主程序
├── hotwords.txt      # 土木工程热词表（一行一个，即改即生效）
├── requirements.txt
├── input_audio/      # ← 录音放这里（内容不入库）
├── output_text/      # ← 转写结果在这里（同名 .md，内容不入库）
├── models/           # 模型缓存（不入库；可整体删除，运行时自动重新下载）
└── .venv/            # 项目内 Python 3.12 环境（不入库；不动系统 Python）
```

## 常见问题

- **内存**：两套引擎严格分时加载（先 Whisper 组 → 释放 → Paraformer 组），15GB 内存机器可放心用。
- **m4a 解码失败**：优先 PyAV 直接解码；异常时自动回退 `ffmpeg` 转码，仍失败则该文件记为失败并继续其余文件。
- **重复转写**：只想强制重转某个文件，删掉 `output_text/` 里对应的 `.md` 再运行即可（或 `touch` 音频文件）。
- **转写质量评估**：本次验证用的是 piper TTS 合成音；真实课堂录音的准确率请以实际录音为准，
  遇到专业词识别不准时优先往 `hotwords.txt` 加词。
