# MOSS-Transcribe-Diarize 转写服务部署 基于 [OpenMOSS/MOSS-Transcribe-Diarize](https://github.com/OpenMOSS/MOSS-Transcribe-Diarize) 0.9B 的端到端语音转写服务。单模型联合完成转写与说话人分离,输出带 `[S01]`、`[S02]` 等说话人标签和精确时间戳的结构化转写结果,适合多人对话、 会议、播客、访谈等多说话人场景。 与 Whisper 的区别:Whisper 只做语音转文字,不区分说话人;MOSS 在转写的 同时输出说话人标签,`sentence_api` 无需额外集成即可自动按说话人分句。 ## 目录结构 ```text moss/ README.md 本文档 systemd/moss-transcribe.service systemd 服务模板 verify.sh 部署验证脚本 ``` ## 硬件与系统要求 | 项目 | 要求 | |------|------| | GPU | NVIDIA,显存 ≥ 8 GB(推荐 16 GB 以上) | | CUDA | 12.9+(vLLM 方案)或 13.0+(SGLang Omni 方案) | | 驱动 | ≥ 535(支持 CUDA 12.x)或 ≥ 570(支持 CUDA 13) | | 系统 | Ubuntu 22.04 / 24.04 | | Python | 3.12 | | 其他 | FFmpeg、Git、curl | 模型权重约 2 GB(bf16),推理时加上音频编码器和 KV 缓存实际占用约 3–6 GB。 如果与其他 GPU 服务共存,需确保剩余显存充足。 ## 推理后端选择 MOSS 官方提供两种推理后端,按 CUDA 版本选择: | 后端 | CUDA 要求 | 适用场景 | |------|-----------|----------| | **SGLang Omni**(推荐) | CUDA 13.0+ | 官方推荐后端,长音频性能更好 | | **vLLM** | CUDA 12.x / 13.x | CUDA 12 环境或 SGLang 安装遇到问题时使用 | 两者提供相同的 OpenAI 兼容接口(`POST /v1/audio/transcriptions`), 切换后端不需要改 `sentence_api` 的任何配置。 --- ## 方案 A:SGLang Omni 部署(CUDA 13,推荐) ### 前置条件 确认驱动支持 CUDA 13: ```bash nvidia-smi # 查看 CUDA Version 列,需 ≥ 13.0 ``` ### 安装系统依赖 ```bash sudo apt update sudo apt install -y ffmpeg git curl ``` ### 安装 uv ```bash curl -LsSf https://astral.sh/uv/install.sh | sh # 重新加载 shell 或执行 source ~/.bashrc 使 uv 命令生效 ``` ### 创建目录和虚拟环境 ```bash sudo mkdir -p /opt/moss-transcribe sudo chown "$USER":"$USER" /opt/moss-transcribe cd /opt/moss-transcribe git clone https://github.com/OpenMOSS/MOSS-Transcribe-Diarize.git cd MOSS-Transcribe-Diarize uv venv --python 3.12 .venv source .venv/bin/activate ``` ### 安装推理框架 ```bash uv pip install -e ".[torch-runtime]" --torch-backend=auto uv pip install sglang-omni ``` ### 下载模型 ```bash # 国内服务器使用 HF 镜像加速 export HF_ENDPOINT=https://hf-mirror.com hf download OpenMOSS-Team/MOSS-Transcribe-Diarize ``` 模型下载到 `~/.cache/huggingface/hub/`,约 2 GB。 ### 启动服务 ```bash source /opt/moss-transcribe/MOSS-Transcribe-Diarize/.venv/bin/activate sgl-omni serve \ --model-path OpenMOSS-Team/MOSS-Transcribe-Diarize \ --host 127.0.0.1 \ --port 8001 \ --max-running-requests 4 \ --cuda-graph-max-bs 4 \ --mem-fraction-static 0.35 ``` **参数说明:** | 参数 | 默认值 | 说明 | |------|--------|------| | `--host` | `127.0.0.1` | 只监听本机,不要暴露公网 | | `--port` | `8001` | 服务端口(Whisper 用 9000,避免冲突) | | `--max-running-requests` | `4` | 最大并发请求数;显存充足可调大 | | `--cuda-graph-max-bs` | `4` | CUDA Graph 批大小上限,与并发数一致 | | `--mem-fraction-static` | `0.80` | 静态显存分配比例;与其他 GPU 服务共存时调低 | > 与 llama-server、Whisper 等其他 GPU 服务共存时,将 > `--mem-fraction-static` 设为 `0.30`–`0.40`(约 7–10 GB),避免 OOM。 > 独占 GPU 时可设为 `0.80` 获得最大并发能力。 首次启动会加载模型到 GPU,等待日志出现 `Uvicorn running on ...` 即启动完成。 --- ## 方案 B:vLLM 部署(CUDA 12 / 13 兼容) 如果 CUDA 版本低于 13.0 或 SGLang Omni 安装遇到兼容性问题,改用 vLLM。 ### 前置条件 同方案 A,但不要求 CUDA 13。 ### 安装系统依赖和 uv 与方案 A 相同(见上文)。 ### 创建目录和虚拟环境 ```bash sudo mkdir -p /opt/moss-transcribe sudo chown "$USER":"$USER" /opt/moss-transcribe cd /opt/moss-transcribe uv venv --python 3.12 .venv source .venv/bin/activate ``` ### 安装 vLLM vLLM 从 0.27.1 起包含 MOSS-Transcribe-Diarize 的模型注册。 ```bash # CUDA 13 环境 uv pip install -U "vllm[audio]" --torch-backend=auto ``` 如果安装的 vLLM 版本不支持 MOSS 模型(启动时报 `model not found`), 需要使用官方指定的 pinned nightly 构建: ```bash # CUDA 12 环境(cu129) uv pip install -U vllm \ --torch-backend=auto \ --extra-index-url https://wheels.vllm.ai/68b4a1d582818e67adc903bf1b8fc5a5447da2fa/cu129 ``` > 上游构建地址可能随版本更新,正式部署前对照 > [MOSS 官方仓库](https://github.com/OpenMOSS/MOSS-Transcribe-Diarize) Quickstart。 ### 启动服务 ```bash source /opt/moss-transcribe/.venv/bin/activate vllm serve OpenMOSS-Team/MOSS-Transcribe-Diarize \ --host 127.0.0.1 \ --port 8001 \ --trust-remote-code ``` > `--trust-remote-code` 是必需的:模型使用自定义 HuggingFace processor 代码。 首次启动会自动从 HuggingFace 下载模型权重。国内服务器建议在启动前设置: ```bash export HF_ENDPOINT=https://hf-mirror.com ``` --- ## 注册为 systemd 服务 ### SGLang Omni 版本 复制服务文件到系统目录并修改实际路径: ```bash sudo cp /path/to/repo/moss/systemd/moss-transcribe.service /etc/systemd/system/ ``` 确认 `ExecStart` 路径与实际安装位置一致: ```ini ExecStart=/opt/moss-transcribe/MOSS-Transcribe-Diarize/.venv/bin/sgl-omni serve ... ``` ### vLLM 版本 将 `ExecStart` 改为: ```ini ExecStart=/opt/moss-transcribe/.venv/bin/vllm serve OpenMOSS-Team/MOSS-Transcribe-Diarize --host 127.0.0.1 --port 8001 --trust-remote-code ``` 并删除 `Environment=HF_ENDPOINT=...` 以外的 SGLang 特有参数。 ### 启用并启动 ```bash sudo systemctl daemon-reload sudo systemctl enable --now moss-transcribe sudo journalctl -u moss-transcribe -f # 观察启动日志 ``` 首次启动会下载模型权重,看到 `running on ...` 表示服务就绪。 --- ## 验证部署 使用仓库自带的验证脚本: ```bash cd /opt/moss-transcribe bash verify.sh # 用真实语音文件验证(推荐) bash verify.sh --file /path/to/multi-speaker.wav # 同时检查 sentence_api 集成状态 bash verify.sh --api-url http://127.0.0.1:8000 ``` 或手动发起转写请求: ```bash curl -X POST http://127.0.0.1:8001/v1/audio/transcriptions \ -F model=OpenMOSS-Team/MOSS-Transcribe-Diarize \ -F file=@/path/to/test.wav \ -F response_format=verbose_json \ -F temperature=0 \ -F max_new_tokens=65536 ``` **正常响应**应包含: - `text`:完整转写文本 - `segments`:分段数组,每段包含 `start`、`end`、`text`、`speaker` ```json { "text": "大家好,今天我们讨论项目进度。 好的,我先汇报我这边的进展。", "segments": [ {"start": 0.48, "end": 2.12, "text": "大家好,今天我们讨论项目进度。", "speaker": "S01"}, {"start": 2.55, "end": 5.80, "text": "好的,我先汇报我这边的进展。", "speaker": "S02"} ] } ``` **说话人标签说明:** `S01`、`S02` 等由模型自动分配,是匿名编号。 同一说话人在同一段音频中标签一致;不同音频之间标签无关联。 --- ## 接入 sentence_api 在 `sentence_api/.env` 中确认以下配置: ```dotenv MOSS_TRANSCRIBE_URL=http://127.0.0.1:8001/v1/audio/transcriptions MOSS_MODEL=OpenMOSS-Team/MOSS-Transcribe-Diarize ``` 然后重建 API 容器: ```bash cd /opt/oral-trainer/sentence_api docker compose up -d --build curl http://127.0.0.1:8000/healthz # 确认 moss_configured 为 true ``` 已上传的视频可在管理后台点击"重新处理",重新转写后会带上说话人标签。 --- ## 从 Whisper 切换到 MOSS 如果服务器上同时部署了 Whisper(Speaches)和 MOSS,切换步骤: 1. **停止 Whisper 服务**(释放约 4 GB 显存): ```bash cd /opt/whisper docker compose down sudo systemctl disable --now whisper-transcribe # 如果注册了 systemd ``` 2. **修改 `sentence_api/.env`**: ```dotenv MOSS_TRANSCRIBE_URL=http://127.0.0.1:8001/v1/audio/transcriptions MOSS_MODEL=OpenMOSS-Team/MOSS-Transcribe-Diarize ``` 3. **重建 API**: ```bash cd /opt/oral-trainer/sentence_api docker compose up -d --build ``` 4. **验证**: ```bash curl http://127.0.0.1:8000/healthz ``` 不需要删除 Whisper 的部署文件,后续切回只需恢复 `.env` 并重新启动。 --- ## 显存分配参考 以 NVIDIA L4(24 GB)为例,MOSS 与其他服务共存的显存分配: | 服务 | 显存占用 | 说明 | |------|----------|------| | llama-server | 8.4 GB | 保留 | | MOSS (SGLang, mem-fraction=0.35) | ~8 GB | 新增 | | Speaches (Whisper) | 4 GB | 停掉后释放 | | **MOSS + llama-server** | ~16 GB / 24 GB | 安全 | 独占 GPU 时可将 `--mem-fraction-static` 调到 `0.80`(约 19 GB), `--max-running-requests` 调到 `16`,支持更多并发。 --- ## API 参数 | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `file` | file | 必填 | 上传的音频/视频文件 | | `model` | string | 服务端默认 | 模型标识符 | | `language` | string | 未设置 | 可选的语言提示(如 `zh`、`en`) | | `response_format` | string | `json` | `json`(原始文本)、`verbose_json`(分段)或 `text` | | `temperature` | float | `0.0` | 采样温度,转写建议保持 `0` | | `max_new_tokens` | int | `5120` | 最大生成 token 数;长音频/多人对话调大到 `65536` | | `prompt` | string | 未设置 | 可选的自定义指令或热词提示 | ### 热词提示 通过 `prompt` 参数为专有名词、人名、产品名等提供提示,可提高识别准确率: ```bash curl -X POST http://127.0.0.1:8001/v1/audio/transcriptions \ -F model=OpenMOSS-Team/MOSS-Transcribe-Diarize \ -F file=@meeting.wav \ -F response_format=verbose_json \ -F prompt="热词提示:MOSS, Transcribe, Diarize, vLLM" \ -F temperature=0 ``` --- ## 常见问题 ### 模型下载慢或失败 ```bash # 方法一:使用 HF 镜像 export HF_ENDPOINT=https://hf-mirror.com hf download OpenMOSS-Team/MOSS-Transcribe-Diarize # 方法二:配置 HTTP 代理 export HTTP_PROXY=http://your-proxy:port export HTTPS_PROXY=http://your-proxy:port ``` ### 启动报 CUDA out of memory 与其他 GPU 服务共存时,降低 `--mem-fraction-static`(如 `0.30`); 或停掉暂时不需要的服务(如 Whisper)释放显存。 ### 启动报 model not found vLLM 版本过低,不包含 MOSS 模型注册。使用官方指定的 pinned nightly (见方案 B 安装部分),或升级到 vLLM ≥ 0.27.1。 ### 长音频转写截断 请求时添加 `-F max_new_tokens=65536`,确保解码器能完整生成整段转写。 ### 说话人标签偶尔混淆 多人重叠说话(同时说话)时 0.9B 模型可能偶尔混淆,这是模型本身的局限。 MOSS 采用端到端 joint diarization,比 Whisper + pyannote 拼接方案更稳定, 但如果场景对说话人准确率要求极高,可以考虑使用在线的 MOSS Pro 版本。 ### 服务只监听 127.0.0.1,外部怎么访问 这是有意设计——转写服务不应暴露公网。`sentence_api` 通过 Docker 内部 网络或宿主机 `127.0.0.1` 访问即可。如果 `sentence_api` 运行在 Docker 容器里且无法访问宿主机的 `127.0.0.1:8001`,将 `MOSS_TRANSCRIBE_URL` 改为 `http://host.docker.internal:8001/v1/audio/transcriptions`(Linux 需在 `docker-compose.yml` 中添加 `extra_hosts: ["host.docker.internal:host-gateway"]`)。 --- ## 更新与回滚 ### 更新模型 ```bash export HF_ENDPOINT=https://hf-mirror.com hf download OpenMOSS-Team/MOSS-Transcribe-Diarize sudo systemctl restart moss-transcribe ``` ### 更新推理框架 ```bash cd /opt/moss-transcribe/MOSS-Transcribe-Diarize source .venv/bin/activate uv pip install -U sglang-omni # 或 vllm sudo systemctl restart moss-transcribe ``` ### 回滚 ```bash # 回滚到上一个 systemd 配置 sudo systemctl revert moss-transcribe # 或手动恢复备份的服务文件 sudo cp /path/to/backup/moss-transcribe.service.bak /etc/systemd/system/moss-transcribe.service sudo systemctl daemon-reload sudo systemctl restart moss-transcribe ```