p99 与 VAP — 话轮交替模型

p99 根据单路音频估计话轮结束概率。VAP 根据同步的用户与助手音频预测语音活动。应用根据这些分数决定何时回应或打断。

这些 API 需要从源码构建 SDK。Swift 使用 SpeechVAD;C++ 需要 SPEECH_CORE_WITH_ONNX=ON。Android API 使用 ONNX Runtime。这些独立 API 不改变现有流水线的默认配置。

模型

p99 turn-1-mini5.3M · CoreML · Float3216 kHz · 160 ms · 1 chApache-2.0
VAP (otoSpeech)5.8M · CoreML / ONNX · Float3216 kHz · 20 s · 2 chCC BY 4.0 / MIT

Swift API

p99 会缓冲不足一步的音频。每个 160 ms 步长返回八个 20 ms 帧。请使用 availableAfterSeconds 确定决策时间,并在不同对话之间重置会话。

import SpeechVAD

let p99 = try await P99TurnModel.fromPretrained()
let session = try p99.createSession()
let frames = try session.pushAudio(pcm16k)
for frame in frames {
    print(frame.probability, frame.availableAfterSeconds)
}
try session.reset()

let vap = try await VAPModel.fromPretrained()
let forecast = try vap.forecast(userAudio: userPcm, agentAudio: agentPcm)
print(forecast.pNow, forecast.pFuture, forecast.voiceActivity)

VAP 使用最近 20 秒、16 kHz 的音频。两路长度必须相同;助手未发声时提供零值通道。较短输入在前端补静音。每次预测会重新计算整个窗口,请根据设备选择调用间隔。

C++

#include <speech_core/models/onnx_vap.h>

speech_core::OnnxVap model("models/vap.onnx");
auto forecast = model.forecast(user.data(), agent.data(), user.size(), 16000);
// p_now[0]: user, p_now[1]: agent
// p_future and voice_activity use the same channel order.

Android

val directory = ModelManager.ensureVapModels(context)
withContext(Dispatchers.Default) {
    VoiceActivityProjection(VoiceActivityProjectionConfig(directory)).use { model ->
        val forecast = model.forecast(userPcm, agentPcm)
        println(forecast.userNearTerm)
        println(forecast.agentNearTerm)
    }
}

下载

基准测试结果

TurnBench · Soniqo

许可证