Files
mediaplayer/moss/README.md
2026-09-11 09:14:51 +08:00

461 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```