Skip to content

Latest commit

 

History

History
166 lines (123 loc) · 6.71 KB

File metadata and controls

166 lines (123 loc) · 6.71 KB

FunASR OpenAI 兼容 API 低代码工作流配方

English

当你希望让 Dify、n8n、HTTP 节点、webhook worker 或其他低代码工作流引擎调用私有 FunASR 语音 API 时,可以从这份配方开始。建议先在本目录跑通本地 smoke test,再把 localhost 换成工作流运行环境能够访问到的服务名或内网地址。

服务预检

cd examples/openai_api
python server.py --model sensevoice --device cuda --port 8000

在工作流所在主机或容器中执行:

export FUNASR_BASE_URL=http://<funasr-host>:8000
curl -fsS "$FUNASR_BASE_URL/health"
curl -fsS "$FUNASR_BASE_URL/v1/models"

如果工作流引擎运行在 Docker 中,localhost 通常指的是工作流容器自身。请改用 Docker Compose service name、Kubernetes service name 或内网主机名。

Postman smoke test

在配置低代码工具前,可以先导入 Postman collection,从图形界面跑通 health、模型列表和转写请求;需要按 schema 导入时可使用 OpenAPI spec。设置 FUNASR_BASE_URL,在 multipart file 字段选择本地音频文件,第一次测试建议保持 MODEL_ALIAS=sensevoice

Multipart HTTP 请求

所有工作流引擎最终都需要发出下面这种请求:

字段
Method POST
URL http://<funasr-host>:8000/v1/audio/transcriptions
Body type multipart/form-data
File field file
Text field model=sensevoice
Text field response_format=verbose_json
Timeout 根据最长音频时长设置,例如长录音可先设为 300 秒。

等价 curl 命令:

curl "$FUNASR_BASE_URL/v1/audio/transcriptions" \
  -F file=@meeting.wav \
  -F model=sensevoice \
  -F response_format=verbose_json

常用响应字段映射:

路径 用途
text 纯文本转写结果,可传给聊天机器人、工单、知识库或后续摘要节点。
segments 请求 verbose_json 时返回的时间戳、说话人等分段信息。
duration API 返回的音频处理时长,适合写入日志和监控。
model 本次请求使用的模型别名。

Dify 自定义工具或 HTTP 节点

当 Dify 应用接收上传音频文件,或收到内部音频存储 URL 时,可以使用下面两种模式。

直接上传文件

在 HTTP request 节点或自定义工具中配置:

  • Method: POST
  • URL: http://<funasr-host>:8000/v1/audio/transcriptions
  • Body: multipart/form-data
  • File part: file,绑定到上传音频变量
  • Text parts: model=sensevoiceresponse_format=verbose_json
  • Output variable: 把 text 映射为转写文本;需要时间戳或说话人信息时保留 segments

音频 URL 转写

有些工作流工具只能传文件 URL,而不能直接传 multipart 二进制。此时建议加一个内网 worker:

  1. Dify 将音频 URL 和元数据发送给 worker。
  2. worker 从可信存储下载音频。
  3. worker 使用 multipart 请求调用 FunASR。
  4. worker 将 textsegments 和运行日志返回给 Dify。
import requests

FUNASR_URL = "http://funasr-api:8000/v1/audio/transcriptions"

def transcribe_from_url(audio_url: str) -> dict:
    audio_response = requests.get(audio_url, timeout=120)
    audio_response.raise_for_status()
    files = {"file": ("audio.wav", audio_response.content, "audio/wav")}
    data = {"model": "sensevoice", "response_format": "verbose_json"}
    response = requests.post(FUNASR_URL, files=files, data=data, timeout=300)
    response.raise_for_status()
    return response.json()

请把这个 worker 放在可信内网中,并在下载用户提供的链接前校验允许访问的域名或存储桶。

n8n HTTP Request 节点

一个常见 n8n 流程是:触发器 -> 二进制音频数据 -> HTTP Request -> 转写结果消费节点。

推荐 HTTP Request 配置:

n8n 设置
Method POST
URL http://<funasr-host>:8000/v1/audio/transcriptions
Send Body enabled
Body Content Type Form-Data / multipart
Binary file field file
Additional form fields model=sensevoiceresponse_format=verbose_json
Response Format JSON
Timeout 长录音场景需要调大。

请求之后,使用 {{$json.text}} 作为转写文本。如果启用了 verbose_json,可以把 {{$json.segments}} 传给字幕、说话人分析或质检节点。

Webhook worker 模式

当工作流引擎不能稳定发送 multipart 文件,或音频需要预处理时,可以把转写封装成一个内部 webhook worker。

from pathlib import Path
import tempfile
import requests

FUNASR_URL = "http://localhost:8000/v1/audio/transcriptions"

def transcribe_bytes(filename: str, payload: bytes, content_type: str = "audio/wav") -> dict:
    with tempfile.NamedTemporaryFile(suffix=Path(filename).suffix or ".wav") as tmp:
        tmp.write(payload)
        tmp.flush()
        with open(tmp.name, "rb") as audio:
            response = requests.post(
                FUNASR_URL,
                files={"file": (filename, audio, content_type)},
                data={"model": "sensevoice", "response_format": "verbose_json"},
                timeout=300,
            )
    response.raise_for_status()
    return response.json()

这个 worker 也适合集中做音频转码、文件大小限制、请求 ID、鉴权、重试和审计日志。

生产环境护栏

  • 在跨团队共享 FunASR 服务前,先加好鉴权、TLS、上传大小限制和限流;代理和网关模式见 安全与网关指南
  • 使用 /health 做工作流 readiness check,使用 /v1/models 校验模型别名。
  • 记录 request id、音频时长、模型别名、响应格式、设备、延迟和错误类型。
  • 按最长音频时长设置工作流超时;超长录音建议先切分,再交给低代码工具处理。
  • 私有音频放在可信存储中,避免把签名 URL、凭据或转写文本写入公开日志。
  • 上生产前,至少用一个公开 smoke 样例和一个真实业务样例完整跑通同一条工作流。

故障排查

现象 处理方式
工作流能访问 /health,但转写失败 确认请求是 multipart/form-data,且二进制字段名是 file
Dify 或 n8n 访问 localhost 失败 换成工作流运行时可访问的主机名、Compose service name 或 Kubernetes service name。
响应中没有 segments 设置 response_format=verbose_json
请求超时 调大 HTTP timeout,或先切分长录音。
第一次请求很慢 使用 --model sensevoice 预加载模型,并用 /health 做 readiness check。
模型别名未知 调用 /v1/models,使用返回列表中的别名。