整段评测适合录完再评的场景:作业提交,批量补评,由接入方服务端统一提交评测。一次 HTTPS 请求上传音频与评测参数,平台评完后返回结果,单次请求在服务端最长处理 600 秒。边录边评,需要读完即出分时用实时评测。
调用#
try (YuguClient client = YuguClient.builder()
.apiKey(System.getenv("YUGU_APP_KEY"), System.getenv("YUGU_SECRET_KEY"))
.build()) {
EvalResult r = client.evaluate(Path.of("audio.wav"),
new EvaluateConfig(EvaluateConfig.CORE_SENTENCE, "今天天气很好", "zh-CN"));
System.out.println("总分 " + r.getOverall());
System.out.println("发音 " + r.getDims().getPronunciation());
System.out.println("流利度 " + r.getDims().getFluency());
System.out.println("完整度 " + r.getDims().getIntegrity());
r.getWords().forEach(w -> System.out.println(w.getWord() + " " + w.getScores().getOverall()));
} catch (YuguException e) {
System.err.println(e.getCategory() + " " + e.getCode() + " " + e.getRawMessage());
}client.evaluateAsync(
EvaluateConfig(CoreType.SENTENCE, "今天天气很好", Language.ZH_CN),
AudioInput.fromFile(File(filesDir, "sample.wav")),
object : YuguCallback<EvalResult> {
override fun onSuccess(result: EvalResult) {
scoreView.text = "总分 ${result.overall}"
}
override fun onFailure(error: YuguException) {
scoreView.text = "评测失败 ${error.code} ${error.message}"
}
},
)client.evaluate(audio: .file(wavURL), config: config) { outcome in
switch outcome {
case .success(let result): print(result.overall ?? 0)
case .failure(let error): print(error.category, error.code, error.message)
}
}const audio = await readFile(process.argv[2] || 'hello.wav');
const result = await client.evaluate(audio, {
coreType: 'sentence',
referenceText: '今天天气很好',
language: 'zh-CN',
});
console.log('总分', result.overall, '各维度', result.dims);async onRecordStop() {
const recording = await recorder.stop();
const result = await client.evaluate({
coreType: 'sentence',
referenceText: '今天天气很好',
language: 'zh-CN',
audio: recording,
});
console.log('总分', result.overall, '发音', result.dims.pronunciation, '流利', result.dims.fluency);
},# 原生整段评测。被签名参数只有 config 段的 JSON 原文
CONFIG='{"coreType":"sentence","referenceText":"今天天气很好","language":"zh-CN"}'
TS=$(date +%s)
NONCE=$(openssl rand -hex 16)
SIGN=$(printf 'config=%s' "$CONFIG" | openssl dgst -sha256 -hmac "$YUGU_SECRET_KEY" -binary | base64)
curl -sS https://open.shengzhiai.com/api/v1/evaluate \
-H "X-App-Key: $YUGU_APP_KEY" \
-H "X-Timestamp: $TS" \
-H "X-Nonce: $NONCE" \
-H "X-Signature: $SIGN" \
-H "Idempotency-Key: $(openssl rand -hex 16)" \
-F "audio=@audio.wav" \
-F "config=$CONFIG;type=application/json"评测参数必填 coreType 与参考文本,language 缺省为 en-US,中文评测要传 zh-CN,可选参数与取值见评测模式。安卓的 evaluate 是阻塞调用,放在后台线程执行,evaluateAsync 的回调默认在主线程。iOS 另有 async 写法,见 iOS SDK。
音频输入#
| 端 | 接受的音频 |
|---|---|
| Java | byte[],File,Path,InputStream,AudioSource.pcm(pcm, 16000) |
| 安卓 | ByteArray,File,InputStream,AudioInput.fromPcm(pcm, 16000, 1) |
| iOS | .data(bytes),.file(url),.pcm16(pcm, sampleRate:, channels:) |
| 网页 | Blob,File,ArrayBuffer,Uint8Array 与任意 ArrayBufferView,裸 PCM 传 audioFormat: 'pcm' 与 sampleRate |
| 小程序 | ArrayBuffer,Uint8Array,临时文件路径,SDK 录音结果,裸 PCM 传 audioFormat: 'pcm' 与 sampleRate |
裸 PCM 由 SDK 加上 WAV 头后上传。推荐 WAV,PCM 16 位,16 kHz,单声道,时长不短于 1 秒,请求体不超过 50 MB,完整要求见音频与录音。
结果#
整段评测与实时评测返回同一个结果模型:总分,维度分,逐字或逐词分数,分句,音频质量警告,本地预检提示,幂等键,重放标记与尝试次数,原始 JSON 始终可取,平台新增的字段从原始 JSON 读取。连读题型的总分取 connected_overall,SDK 的总分访问器已按题型处理。字段说明见评测结果字段。
声通兼容整段评测#
evaluateCompat 调用 POST /{coreType},coreType 与参数名沿用声通命名,例如 sent.eval.cn 与 refText,适合参数体系已按声通设计的业务。result 内的字段与原生接口一致,SDK 解析为同一个结果模型,兼容接口不返回 report,asrText 与 standardAudio。请求带 attachAudioUrl=1 时另有录音下载地址,保留 7 天。兼容接口只接受签名鉴权。接口定义见声通兼容整段评测。
计费与重复提交#
每次调用自动带幂等键,网络抖动引起的重试复用同一个键,平台按键只评测一次,只计费一次。需要同一份作业只计费一次时,用作业号作为幂等键,做法见重试与幂等。