# audio2text 音频 / 视频转双语字幕服务。上传视频 → ffmpeg 提取音频 → faster-whisper 识别英语 → 断句 + 时间戳重算 → NLLB 翻译为中文 → 输出双语 SRT。全程跑在 Docker 容器里,自带 网页上传界面,支持大文件分片上传与断点续传。 仿照 zikai 的 `server/` 风格分层(`controllers → services`),**CPU 开发 / GPU 生产 同一份代码**,仅靠 `config.yaml` 的 `device` + `model` + `compute_type` 三项切换。 --- ## 功能特性 - **网页上传**:拖拽 / 选择文件,多文件并发、4 MiB 分片、断点续传 - **双语字幕**:英文在上、中文在下,亦可单独下载英文 / 中文字幕 - **faster-whisper 转写**:词级时间戳,断句精确(取首末词时间戳) - **NLLB-200 英译中**:ASR 与翻译模型不共驻,翻译时独占显存跑大 batch - **设置页**:运行时调整 batch_size / beam_size,保存后对后续任务生效(DB 持久化) - **任务管理**:删除已完成/失败任务及其产物,进度条按批次细分 - **任务状态机**:`queued -> uploading -> extracting -> transcribing -> segmenting -> translating -> done` - **实时日志页**:按级别分层(debug=详细子步骤 / info=阶段转换 / error=完整 traceback) - **定时缓存清理**:任务产物默认保留 7 天,超期连同 DB 记录一并删除 - **SQLite 持久化**(自包含,无需外部 DB) - **离线运行**:模型缓存就位后完全离线,无需访问 HuggingFace - `/docs`(Swagger UI)公开访问 --- ## 架构 Spring 风格分层,HTTP 边界(controllers)与业务逻辑(services)分离: ``` audio2text/ ├── Dockerfile # 一份 Dockerfile,ARG VARIANT=cpu|gpu 出两个镜像 ├── docker-compose.yml # cpu / gpu / dev 三个 profile ├── setup.sh / start.sh / stop.sh # 安装 / 启动 / 停止(包装 docker 命令) ├── scripts/ │ └── prefetch_models.{sh,py} # 预拉模型权重到 ./models volume(避免首次启动下载) ├── requirements.txt ├── config.example.yaml # 配置模板(复制为 config.yaml 后填值) ├── docs/ # 详细文档(见下方索引) └── app/ ├── main.py # FastAPI 应用工厂 ├── config.py # 从 config.yaml 加载的类型化 Settings(pydantic) ├── database.py # SQLite 引擎 / Session / Base / get_db ├── security.py # /docs 的 Basic Auth(常量时间比较) ├── controllers/ # FastAPI 路由 —— HTTP 边界 │ ├── upload_router.py # 分片上传(建会话/查状态/传片/complete) │ └── task_router.py # 任务列表 / 状态 / 下载字幕 ├── services/ # 业务逻辑 │ ├── types.py # 共享 DTO(Word/Segment/Subtitle,纯 dataclass) │ ├── upload_service.py # 分片上传会话 + 拼接 + 创建任务 │ ├── ffmpeg_service.py # 提取音频 16k mono pcm │ ├── asr_service.py # faster-whisper 转写 │ ├── segmenter.py # 断句 + 时间戳重算(纯算法,零模型依赖) │ ├── translate_service.py # NLLB 翻译 │ ├── model_manager.py # 模型加载/卸载(不共驻核心) │ ├── scheduler.py # ffmpeg 串行队列 + GPU 调度线程 │ ├── pipeline.py # 编排:提取→识别→断句→翻译→写SRT │ ├── srt_writer.py # SRT 写入 + 双语合并 │ ├── log_buffer.py # 内存日志缓冲(供 /logs 页面查询) │ ├── reaper.py # 清理被放弃的上传会话(短 TTL) │ └── cache_cleaner.py # 定时清理超期任务产物 + 孤儿目录(长保留期) ├── models/ # SQLAlchemy ORM │ ├── task.py # Task(转写任务,状态机) │ └── upload_session.py # UploadSession(分片会话,含 task_id FK) ├── schemas/ # pydantic 请求/响应 DTO │ └── task.py └── views/ ├── _shared.py # 共享前端资产(BASE_CSS + SHARED_JS + 上传协议 + 页面骨架) ├── home_html.py # 主页(上传入口 + 最近任务卡片) ├── history_html.py # 历史任务分页表格(含搜索) └── logs_html.py # 实时日志页 ``` ### 数据流 ``` 浏览器 /(主页) │ 分片上传 (4 MiB/片, 可断点续传) ▼ upload_router ──► upload_service ──► UploadSession(SQLite) + 分片落盘 │ complete ▼ 创建 Task(queued) ──► scheduler │ ├─ ffmpeg 串行队列(最多 1 个并发,其余排队)→ 16k mono wav │ (按配置删原始视频) ├─ GPU 调度线程(单线程,模型复用): │ get_asr → asr_service.transcribe → segments(带词级时间戳) │ unload_asr → get_translator │ translate_service.translate → 中文译文(独占显存大 batch) └─ srt_writer → en.srt / zh.srt / bilingual.srt 更新 Task(done) + 写 output_dir ``` --- ## 快速开始 ### CPU 开发环境(2GB 内存即可) ```bash ./setup.sh # 构建镜像 + 生成 config.yaml ./start.sh # 启动容器(端口 8000) ``` ### GPU 生产环境(需 NVIDIA GPU + nvidia runtime) ```bash AUDIO2TEXT_VARIANT=gpu ./setup.sh ./start.sh # 自动检测 GPU 镜像 + nvidia-smi,端口 8001 ``` 启动后打开 `http://127.0.0.1:8000/`,拖入视频即可。详细部署流程、模型选型、CPU↔GPU 切换 见 [部署指南](./docs/DEPLOYMENT.md)。 --- ## 离线部署(导入预构建镜像) 已有 `audio2text-gpu.tar` 镜像文件时,新机器无需构建,直接导入即可启动(仍需 NVIDIA 驱动 + nvidia container runtime + 模型缓存 `./models`): ```bash # 1. 导入镜像 docker load -i audio2text-gpu.tar # 2. 准备配置 + 数据目录 mkdir -p data-gpu/uploads data-gpu/.work data-gpu/outputs models # 3. 启动容器(config.gpu.yaml 需自行准备,或从项目仓库取) docker run -d --name audio2text-gpu \ --gpus all \ -p 8001:8000 \ -v "$(pwd)/data-gpu:/data" \ -v "$(pwd)/models:/models" \ -v "$(pwd)/config.gpu.yaml:/app/config.yaml:ro" \ --restart unless-stopped \ audio2text:gpu ``` > **模型缓存**:`./models` 目录需包含 Whisper `large-v3-turbo` + NLLB `distilled-1.3B` 权重 > (约 5.5GB)。首次部署时从源机器拷贝 `models/` 目录,或联网用 `prefetch_models.sh` 预拉。 > 镜像内置 `HF_HUB_OFFLINE=1`,模型就位后完全离线运行,无需访问 HuggingFace。 详细步骤见 [Docker 说明 - 导入预构建镜像](./docs/DOCKER.md#导入预构建镜像离线部署)。 --- ## 入口 | 入口 | 地址 | |---|---| | 主页(上传 + 最近任务) | `http://127.0.0.1:8000/` | | 历史任务 | `http://127.0.0.1:8000/history` | | 实时日志 | `http://127.0.0.1:8000/logs` | | API 文档 | `http://127.0.0.1:8000/docs`(Basic Auth) | | 健康检查 | `http://127.0.0.1:8000/health` | --- ## 文档索引 详细文档按主题拆分,主页只保留核心速览: | 文档 | 内容 | |---|---| | [部署指南](./docs/DEPLOYMENT.md) | CPU / GPU 完整部署流程、前置要求、模型选型、CPU↔GPU 切换、自定义端口 | | [配置文件说明](./docs/CONFIG.md) | CPU/GPU 配置差异表、全部字段说明(server/storage/asr/translation/...)、配置示例 | | [Docker 说明](./docs/DOCKER.md) | 镜像构建、新建/重建/改配置/改依赖四种场景、**缓存分层与删除边界**、⚠️ until filter 失效根因、Volume 挂载 | | [HTTP 接口](./docs/API.md) | 接口一览表、分片上传协议、请求/响应示例 | | [架构与原理](./docs/ARCHITECTURE.md) | 断句算法、模型不共驻显存策略、GPU 利用率优化、缓存清理机制 | | [常见问题](./docs/FAQ.md) | CPU 跑 NLLB、模型下载、断点续传、保留原始视频、自动清理等 | --- ## 依赖 - **Python**:FastAPI + uvicorn + SQLAlchemy + faster-whisper + transformers(torch 按 VARIANT 分叉,CPU/GPU 装不同 wheel)。完整列表见 `requirements.txt` - **系统**:ffmpeg(镜像内 apt 装)、patchelf(修复 ctranslate2 可执行栈)。GPU 需宿主 NVIDIA 驱动 + nvidia container runtime 镜像构建与依赖安装细节见 [Docker 说明](./docs/DOCKER.md)。