# 快速开始 用沙箱密钥完成第一次评测,读出总分,维度分与逐字分数。 来源:https://open.shengzhiai.com/sdk/v2/quickstart/ ## 准备工作 | 项 | 要求 | |---|---| | 密钥 | 开放平台签发的 appKey 与 secretKey。联调期间用沙箱密钥,每把每天 200 次,不扣套餐与余额,申请方式见[沙箱环境](https://open.shengzhiai.com/sdk/v2/sandbox/) | | 音频 | 一段 1 秒以上的 WAV 录音,16 kHz,16 位,单声道。可以直接用[示例音频](https://open.shengzhiai.com/sdk/v2/spec/fixtures/audio/zh_short.wav),朗读的参考文本为 `今天天气很好` | | 运行环境 | Java 11,安卓 5.0,iOS 13,Chrome 73,Node.js 20,微信基础库 `2.20.1`。Node.js 18 需要传入 `crypto` 选项,各端完整要求见[版本兼容](https://open.shengzhiai.com/sdk/v2/compatibility/) | > 注意:secretKey 只放在接入方服务端或可信环境。网页,小程序与移动端联调时可以用签名,例如小程序写 `auth: { appKey, secretKey }`,正式上线改用 token,做法见[鉴权](https://open.shengzhiai.com/sdk/v2/authentication/)。 ## 接入步骤 ### Java #### 五分钟快速开始 分三步执行。需要 JDK 11 或更高版本与 Maven 3.6 或更高版本,一段 3 秒左右的 16 kHz,16 位,单声道 WAV 录音,以及开放平台签发的 appKey 与 secretKey,联调期间用沙箱密钥,申请方式见 [`SANDBOX.md`](https://open.shengzhiai.com/sdk/v2/sandbox/)。 1. 新建工程目录 `yugu-quickstart`,在其中新建 `pom.xml`: ```xml 4.0.0 com.example yugu-quickstart 1.0 11 UTF-8 shengzhiai https://open.shengzhiai.com/maven/ com.shengzhiai.yugu yugu-java-sdk 2.1.0 org.apache.maven.plugins maven-compiler-plugin 3.13.0 org.codehaus.mojo exec-maven-plugin 3.5.0 QuickStart ``` 2. 新建 `src/main/java/QuickStart.java`: ```java import com.shengzhiai.yugu.YuguClient; import com.shengzhiai.yugu.errors.YuguException; import com.shengzhiai.yugu.model.EvalResult; import com.shengzhiai.yugu.model.EvaluateConfig; import java.nio.file.Path; public class QuickStart { public static void main(String[] args) { 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()); } } } ``` 3. 把录音放到工程目录,命名为 `audio.wav`,设置密钥后运行,控制台输出总分,分项与逐字分数: ```bash YUGU_APP_KEY=沙箱appKey YUGU_SECRET_KEY=沙箱secretKey mvn -q compile exec:java ``` `demos/java-cli` 是同样流程的完整工程,带命令行参数,可直接运行。 ### 安卓 #### 安装 在 `settings.gradle` 里加入优谷雅言 Maven 仓库: ```groovy dependencyResolutionManagement { repositories { google() mavenCentral() maven { url "https://open.shengzhiai.com/maven/" } } } ``` 在模块的 `build.gradle` 里声明依赖: ```groovy dependencies { implementation "com.shengzhiai.yugu:yugu-android-sdk:2.1.0" } ``` Kotlin DSL 写法: ```kotlin // settings.gradle.kts dependencyResolutionManagement { repositories { google() mavenCentral() maven { url = uri("https://open.shengzhiai.com/maven/") } } } // app/build.gradle.kts dependencies { implementation("com.shengzhiai.yugu:yugu-android-sdk:2.1.0") } ``` 工程仍在顶层 `build.gradle` 的 `allprojects` 里声明仓库时,把同一行 `maven { url "https://open.shengzhiai.com/maven/" }` 加进那里。 仓库里的每个版本发布后不再改动,依赖写成具体版本号即可锁定,需要回退时改回历史版本号。每个文件都附带 `.md5`,`.sha1`,`.sha256`,`.sha512` 校验和,另有源码包 `-sources.jar` 与接口文档包 `-javadoc.jar`。`1.x` 版本没有发布到 Maven 仓库,源码包仍可在 `https://open.shengzhiai.com/sdk/` 下载,已停止维护。 SDK 自带 R8 混淆保留规则,接入方不需要额外配置。 #### 权限 SDK 的清单文件已声明 `INTERNET`,构建时自动合并。使用录音器时,宿主应用需要声明录音权限: ```xml ``` Android 6.0 起录音权限需要在运行时申请: ```kotlin if (Build.VERSION.SDK_INT >= 23 && checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED ) { requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 1001) } ``` 把 `Context` 传给 `Recorder` 后,SDK 在开始录音前检查权限,没有权限时抛 `PermissionException`,错误码 90201。 #### 五分钟快速开始 第一步,创建客户端。整个应用共用一个实例即可。 ```kotlin val client = YuguClient.builder() .auth(Auth.appKey("YOUR_APP_KEY", "YOUR_SECRET_KEY")) .build() ``` 第二步,准备一段 16 kHz,16 位,单声道的 WAV 音频,调用整段评测。REST 方法是阻塞调用,放在后台线程执行: ```kotlin thread { val result = client.evaluate( EvaluateConfig(CoreType.SENTENCE, "今天天气很好", Language.ZH_CN), File(filesDir, "sample.wav"), ) Log.i("yugu", "总分 ${result.overall},发音 ${result.dimensions.pronunciation}") } ``` 也可以使用异步方法,回调默认在主线程执行,可以直接更新界面: ```kotlin client.evaluateAsync( EvaluateConfig(CoreType.SENTENCE, "今天天气很好", Language.ZH_CN), AudioInput.fromFile(File(filesDir, "sample.wav")), object : YuguCallback { override fun onSuccess(result: EvalResult) { scoreView.text = "总分 ${result.overall}" } override fun onFailure(error: YuguException) { scoreView.text = "评测失败 ${error.code} ${error.message}" } }, ) ``` 第三步,应用退出或不再评测时关闭客户端: ```kotlin client.close() ``` 完整的可运行工程见 demos/android-demo,包含录音评测,示例音频评测与实时评测。 ### iOS #### 安装 ##### Xcode 添加依赖 1. 在 Xcode 菜单 File 中选择 Add Package Dependencies。 2. 在搜索框输入 `https://open.shengzhiai.com/git/yugu-ios-sdk.git`。 3. Dependency Rule 选择 Up to Next Major Version,版本填 `2.1.0`。 4. 产品勾选 `YuguSDK`,点击 Add Package。 ##### Package.swift 声明 ```swift // swift-tools-version:5.9 import PackageDescription let package = Package( name: "MyApp", platforms: [.iOS(.v13)], dependencies: [ .package(url: "https://open.shengzhiai.com/git/yugu-ios-sdk.git", from: "2.1.0"), ], targets: [ .target(name: "MyApp", dependencies: [ .product(name: "YuguSDK", package: "yugu-ios-sdk"), ]), ] ) ``` 包标识取仓库地址的最后一段,所以 `package:` 参数写 `yugu-ios-sdk`。 #### 麦克风权限 使用录音器的 App 必须在 Info.plist 中声明麦克风用途,缺少这一项时 iOS 在首次录音时终止 App。 ```xml NSMicrophoneUsageDescription 录制朗读音频,用于语音评测 ``` macOS App 开启了沙盒时,另需在 entitlements 中打开 `com.apple.security.device.audio-input`。只评测已有音频时不需要麦克风权限。 #### 五分钟上手 ```swift import YuguSDK // 创建客户端,App 内复用同一个实例 let client = YuguClient(options: YuguClientOptions( auth: .appKey("", secretKey: ""))) // 评测一段 16 kHz 单声道 WAV let config = EvaluateConfig(coreType: .sentence, referenceText: "今天天气很好", language: "zh-CN") let result = try await client.evaluate(audio: .file(wavURL), config: config) // 读取分数 print("总分", result.overall ?? 0) print("流利度", result.dimensions.fluency ?? 0, "完整度", result.dimensions.integrity ?? 0) for word in result.words { print(word.word ?? "", word.overall ?? 0) } // 不再使用时释放 client.close() ``` 不使用 `async` 时用完成回调写法,回调在 `callbackQueue` 上执行,缺省为主队列: ```swift 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) } } ``` 用麦克风录音再评测: ```swift let recorder = YuguRecorder() YuguRecorder.requestPermission { granted in guard granted else { return } try? recorder.start() } // 用户读完后 if let recording = recorder.stop() { client.evaluate(audio: recording.audioInput, config: config) { outcome in // 处理结果 } } recorder.release() ``` ### 网页 #### 安装 ##### npm 仓库安装 SDK 发布在优谷雅言自建 npm 仓库 `https://open.shengzhiai.com/npm/`。仓库公开读取,安装不需要账号或令牌。在项目根目录的 `.npmrc` 写入一行: ```ini @shengzhiai:registry=https://open.shengzhiai.com/npm/ ``` 然后安装指定版本: ```bash npm install @shengzhiai/yugu-web-sdk@2.1.0 ``` `pnpm` 与 Yarn 1 读取同一个 `.npmrc`,Yarn 2 及以上版本在 `.yarnrc.yml` 的 `npmScopes` 里配置同一个地址。查看全部可用版本用 `npm view @shengzhiai/yugu-web-sdk versions`,回退到历史版本时把 `@2.1.0` 换成目标版本号。 ##### script 标签引入 安装后的 `dist` 目录带有 UMD 构建,不需要打包工具。把 `node_modules/@shengzhiai/yugu-web-sdk/dist/yugu-sdk.umd.min.js` 复制到站点静态目录后引用,全局对象为 `YuguSDK`: ```html ``` #### 五分钟快速开始 1. 准备环境:Node.js 20 或更高版本,一段 3 秒左右的 16 kHz 单声道 WAV 录音,沙箱环境的 appKey 与 secretKey。沙箱密钥的申请方式与每日额度见 [`SANDBOX.md`](https://open.shengzhiai.com/sdk/v2/sandbox/),Node.js 18 的做法见 [Node.js 用法](https://open.shengzhiai.com/sdk/v2/sdks/web/#nodejs-用法)。 2. 新建工程,安装 SDK: ```bash mkdir yugu-quickstart && cd yugu-quickstart npm init -y echo "@shengzhiai:registry=https://open.shengzhiai.com/npm/" > .npmrc npm install @shengzhiai/yugu-web-sdk@2.1.0 ``` 3. 新建 `quickstart.mjs`: ```js import { readFile } from 'node:fs/promises'; import { YuguClient } from '@shengzhiai/yugu-web-sdk'; const client = new YuguClient({ appKey: process.env.YUGU_APP_KEY, secretKey: process.env.YUGU_SECRET_KEY, }); 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); await client.close(); ``` 4. 运行脚本,查看分数: ```bash YUGU_APP_KEY=沙箱appKey YUGU_SECRET_KEY=沙箱secretKey node quickstart.mjs hello.wav ``` 5. 浏览器里试用时,在同一目录新建 `index.html`,用任意静态服务器打开,例如 `python3 -m http.server 8080` 后访问 `http://localhost:8080/`: ```html



```

包含录音,实时评测与结果展示的完整页面见仓库 `demos/web-demo` 目录。

### 小程序

#### 安装

在小程序工程的根目录,即 `project.config.json` 所在目录,执行:

```bash
echo "@shengzhiai:registry=https://open.shengzhiai.com/npm/" >> .npmrc
npm install @shengzhiai/yugu-miniprogram-sdk@2.1.0
```

工程里还没有 `package.json` 时先执行 `npm init -y`。npm 源不需要账号,已发布的版本不会被覆盖,退回历史版本时把版本号换成目标版本重新安装即可。

安装后在微信开发者工具中构建 npm:

1. 打开工程,点击菜单“工具”,选择“构建 npm”。
2. 构建完成后工程里出现 `miniprogram_npm/@shengzhiai/yugu-miniprogram-sdk` 目录。
3. 代码中按包名引用:

```js
const { YuguClient } = require('@shengzhiai/yugu-miniprogram-sdk');
```

`project.config.json` 设置了 `miniprogramRoot` 时,`package.json` 放在该目录下,或者在 `setting.packNpmRelationList` 里登记 `package.json` 与 `miniprogram_npm` 的位置。升级 SDK 后要重新构建 npm。

#### 合法域名

SDK 只通过 `wx.request` 与 `wx.connectSocket` 访问平台,上线前在小程序管理后台的“开发管理”,“开发设置”,“服务器域名”中配置:

| 类型 | 域名 |
|---|---|
| request 合法域名 | `https://open.shengzhiai.com` |
| socket 合法域名 | `wss://open.shengzhiai.com` |

SDK 2.0 不再使用 `wx.uploadFile`,不需要配置 uploadFile 合法域名。开发阶段可以在开发者工具的“详情”,“本地设置”里勾选“不校验合法域名,web-view,TLS 版本以及 HTTPS 证书”,真机预览与发布前要改回。

录音需要麦克风权限。在小程序管理后台的“用户隐私保护指引”中声明使用麦克风,首次录音时微信弹出授权框,用户拒绝后录音器报 `PermissionException`,错误码 90201。

#### 五分钟上手

整段评测:录一段音,上传评测,打印总分。

```js
const { YuguClient } = require('@shengzhiai/yugu-miniprogram-sdk');

const client = new YuguClient({
  auth: { token: '<由自有服务端下发的短期 token>' },
});
const recorder = client.createRecorder();

Page({
  onRecordStart() {
    recorder.start();
  },
  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);
  },
  onUnload() {
    client.close();
  },
});
```

实时评测:录音帧直接推入会话,停止录音时自动结束会话。

```js
const session = client.streamEvaluate(
  { coreType: 'sentence', referenceText: '今天天气很好', language: 'zh-CN' },
  {
    onResult(result) { console.log('总分', result.overall); },
    onError(err) { console.log('评测失败', err.code, err.message); },
  },
);
recorder.pipeTo(session);
recorder.start();
// 用户读完后
recorder.stop();
```

### cURL

没有 SDK 的语言直接调用 REST 接口。签名用 HMAC-SHA256,`openssl` 一行即可算出,被签名参数与拼接规则见[签名与鉴权](https://open.shengzhiai.com/sdk/v2/api/authentication/)。

```bash
export YUGU_APP_KEY=沙箱appKey YUGU_SECRET_KEY=沙箱secretKey
curl -sSO https://open.shengzhiai.com/sdk/v2/spec/fixtures/audio/zh_short.wav && mv zh_short.wav audio.wav
```

在 `audio.wav` 所在目录执行:

```snippet
docs/site/snippets/evaluate.sh
```

## 返回结果

整段评测成功时直接返回结果对象,不包信封。常用字段如下,各评测模式的完整字段见[评测结果字段](https://open.shengzhiai.com/sdk/v2/api/results/)。

| 字段 | 含义 |
|---|---|
| `recordId` | 评测记录号,报告查询与问题排查使用 |
| `result.overall` | 总分,百分制。连读题型的总分在 `result.connected_overall` |
| `result.pronunciation`,`result.fluency`,`result.integrity` | 发音,流利度,完整度 |
| `result.tone`,`result.rear_tone` | 中文声调分与句末语调 |
| `result.words` | 逐字或逐词分数,含拼音,音素与起止时间,时间单位 10 毫秒 |
| `warnings` | 音频质量警告码,例如 1002 音量过低,评分照常返回 |

```json
{
  "recordId": "eval_a31712f40cbf",
  "eof": 1,
  "result": {
    "paragraphs": [],
    "kernel_version": "1.0.0",
    "resource_version": "1.0.0",
    "overall": 88.9,
    "pronunciation": 100,
    "tone": 83,
    "fluency": 96,
    "rhythm": 78,
    "integrity": 100,
    "speed": 225,
    "rear_tone": "fall",
    "duration": "1.920",
    "numeric_duration": 1.92,
    "warning": [],
    "words": [
      {
        "word": "今",
        "pinyin": "jin",
        "rawpinyin": "jin1",
        "symbolpinyin": "jīn",
        "charType": 0,
        "readType": 0,
        "tone": "tone1",
        "scores": {
          "overall": 78,
          "pronunciation": 78,
          "tone": 100,
          "overall_pron": 78,
          "prominence": 0
        },
        "span": {
          "start": 15,
          "end": 31
        },
        "pause": {
          "type": 0,
          "duration": 0
        },
        "phonemes": [
          {
            "phoneme": "J",
            "phone": "j",
            "category": 0,
            "pronunciation": 78,
            "tone_index": "0",
            "span": {
              "start": 15,
              "end": 23
            }
          },
          {
            "phoneme": "IN",
            "phone": "in",
            "category": 1,
            "pronunciation": 78,
            "tone_index": "1",
            "span": {
              "start": 23,
              "end": 31
            }
          }
        ],
        "normalized_syllables": [
          {
            "syllables": "今",
            "pinyin": "jin",
            "tone": "tone1",
            "tone_sandhi": "tone1",
            "phoneme_span": [
              0,
              1
            ]
          }
        ],
        "word_parts": [
          {
            "part": "今",
            "charType": 0,
            "beginIndex": 0,
            "endIndex": 0
          }
        ],
        "phonics": [],
        "linkable": false,
        "syllables": [],
        "evidence": {
          "scored": false,
          "rms_db": -32.7,
          "rel_db": -0.5,
          "dur_ms": 160,
          "dur_ratio": 0.8,
          "sfgop": 0.625
        },
        "readStatus": "correct",
        "read_status": "correct"
      },
      {
        "word": "天",
        "pinyin": "tian",
        "rawpinyin": "tian1",
        "symbolpinyin": "tiān",
        "charType": 0,
        "readType": 0,
        "tone": "tone1",
        "scores": {
          "overall": 95,
          "pronunciation": 95,
          "tone": 100,
          "overall_pron": 95,
          "prominence": 0
        },
        "span": {
          "start": 31,
          "end": 57
        },
        "pause": {
          "type": 0,
          "duration": 0
        },
        "phonemes": [
          {
            "phoneme": "T",
            "phone": "t",
            "category": 0,
            "pronunciation": 95,
            "tone_index": "0",
            "span": {
              "start": 31,
              "end": 43
            }
          },
          {
            "phoneme": "IAN",
            "phone": "ian",
            "category": 1,
            "pronunciation": 95,
            "tone_index": "1",
            "span": {
              "start": 43,
              "end": 55
            }
          }
        ],
        "normalized_syllables": [
          {
            "syllables": "天",
            "pinyin": "tian",
            "tone": "tone1",
            "tone_sandhi": "tone1",
            "phoneme_span": [
              0,
              1
            ]
          }
        ],
        "word_parts": [
          {
            "part": "天",
            "charType": 0,
            "beginIndex": 0,
            "endIndex": 0
          }
        ],
        "phonics": [],
        "linkable": false,
        "syllables": [],
        "evidence": {
          "scored": false,
          "rms_db": -31.8,
          "rel_db": 0.5,
          "dur_ms": 240,
          "dur_ratio": 1.2,
          "sfgop": 0.917
        },
        "readStatus": "correct",
        "read_status": "correct"
      }
    ],
    "sentences": [
      {
        "sentence": "今天天气很好",
        "index": 0,
        "scores": {
          "overall": 89,
          "pronunciation": 100,
          "fluency": 96,
          "integrity": 100
        },
        "details": [
          {
            "word": "今",
            "pinyin": "jin",
            "rawpinyin": "jin1",
            "symbolpinyin": "jīn",
            "charType": 0,
            "readType": 0,
            "tone": "tone1",
            "scores": {
              "overall": 78,
              "pronunciation": 78,
              "tone": 100,
              "overall_pron": 78,
              "prominence": 0
            },
            "span": {
              "start": 15,
              "end": 31
            },
            "pause": {
              "type": 0,
              "duration": 0
            },
            "phonemes": [
              {
                "phoneme": "J",
                "phone": "j",
                "category": 0,
                "pronunciation": 78,
                "tone_index": "0",
                "span": {
                  "start": 15,
                  "end": 23
                }
              },
              {
                "phoneme": "IN",
                "phone": "in",
                "category": 1,
                "pronunciation": 78,
                "tone_index": "1",
                "span": {
                  "start": 23,
                  "end": 31
                }
              }
            ],
            "normalized_syllables": [
              {
                "syllables": "今",
                "pinyin": "jin",
                "tone": "tone1",
                "tone_sandhi": "tone1",
                "phoneme_span": [
                  0,
                  1
                ]
              }
            ],
            "word_parts": [
              {
                "part": "今",
                "charType": 0,
                "beginIndex": 0,
                "endIndex": 0
              }
            ],
            "phonics": [],
            "linkable": false,
            "syllables": []
          },
          {
            "word": "天",
            "pinyin": "tian",
            "rawpinyin": "tian1",
            "symbolpinyin": "tiān",
            "charType": 0,
            "readType": 0,
            "tone": "tone1",
            "scores": {
              "overall": 95,
              "pronunciation": 95,
              "tone": 100,
              "overall_pron": 95,
              "prominence": 0
            },
            "span": {
              "start": 31,
              "end": 57
            },
            "pause": {
              "type": 0,
              "duration": 0
            },
            "phonemes": [
              {
                "phoneme": "T",
                "phone": "t",
                "category": 0,
                "pronunciation": 95,
                "tone_index": "0",
                "span": {
                  "start": 31,
                  "end": 43
                }
              },
              {
                "phoneme": "IAN",
                "phone": "ian",
                "category": 1,
                "pronunciation": 95,
                "tone_index": "1",
                "span": {
                  "start": 43,
                  "end": 55
                }
              }
            ],
            "normalized_syllables": [
              {
                "syllables": "天",
                "pinyin": "tian",
                "tone": "tone1",
                "tone_sandhi": "tone1",
                "phoneme_span": [
                  0,
                  1
                ]
              }
            ],
            "word_parts": [
              {
                "part": "天",
                "charType": 0,
                "beginIndex": 0,
                "endIndex": 0
              }
            ],
            "phonics": [],
            "linkable": false,
            "syllables": []
          }
        ]
      }
    ],
    "compositeReport": {
      "compositeScore": 88.9,
      "integrityScore": 100,
      "accuracyScore": 100,
      "toneVoiceScore": 83,
      "nasalsScore": 98,
      "pronunciationScore": 100,
      "phonemeScore": 100,
      "fluencyScore": 96,
      "fluentScore": 96,
      "readSpeedScore": 85,
      "readSpeed": 225,
      "skillScore": 78,
      "stopConnScore": 85,
      "stressScore": 32,
      "intonationScore": 100,
      "emotionScore": 76,
      "literalTotal": 89,
      "toneScore": 100,
      "completenessScore": 100,
      "skillSuggest": "重音变化不够明显,关键词应当适度强调(音高提升 / 时长延长 / 加强气流)。",
      "emotionSuggest": "第三声(上声)调值偏低。练习时走 214 曲线,先降再升。推荐练习『你好/美好/小狗』等词。",
      "initialScore": 83.5,
      "finalScore": 83.5
    },
    "yuguScores": {
      "overall": 88.9,
      "integrity": 100,
      "accuracy": {
        "overall": 100,
        "tone": 100,
        "nasal": 98,
        "phoneme": 100,
        "initial": 83.5,
        "final": 83.5
      },
      "fluency": {
        "overall": 96,
        "speed_score": 85,
        "naturalness": 100
      },
      "reading_skill": {
        "overall": 78,
        "pause": 85,
        "stress": 32,
        "intonation": 100
      },
      "prosody": 78,
      "emotion": 76,
      "tone": 83,
      "rear_tone": "fall",
      "speed": 225,
      "duration_s": 1.92
    },
    "initialScore": 83.5,
    "finalScore": 83.5,
    "nasalsScore": 98,
    "nasals": 98,
    "accuracy": 100,
    "reading_skill": 78,
    "emotion": 76
  },
  "report": {
    "dimensionSuggestions": {
      "integrity": [],
      "accuracy": [],
      "fluency": [],
      "reading_skill": [
        "重音变化不够明显,关键词应当适度强调(音高提升 / 时长延长 / 加强气流)。",
        "先标出停连位置、句子重音和语调走向,再按标记朗读并回听节奏是否清楚。"
      ],
      "emotion": [
        "第三声(上声)调值偏低。练习时走 214 曲线,先降再升。推荐练习『你好/美好/小狗』等词。",
        "先判断语句的情绪基调,选定符合语义的表达方式朗读;录音回听情感是否与内容一致。"
      ]
    },
    "dimensionScores": {
      "accuracy": 100,
      "fluency": 96,
      "integrity": 100,
      "reading_skill": 78,
      "affect": 76,
      "speechRate": 85,
      "readSpeedRaw": 225
    },
    "dimensionEvidence": {
      "accuracy": [
        {
          "word": "很",
          "type": "pitchLow",
          "detail": "声调 1 分(低于 60)"
        }
      ],
      "fluency": [],
      "integrity": [],
      "affect": [],
      "speechRate": []
    },
    "rubricVersion": "v20260707b",
    "scores": {
      "compositeScore": 88.9
    },
    "dimensions": {
      "accuracy": "声调:整句调型判定 100 分;其中“很”(字级调型 1 分)的调型与标准读音有偏差,需对照标准音重点纠正,其余字词调型整体稳定。",
      "reading_skill": "停连、重音、语调和节奏基本可控,细节仍可加强。",
      "emotion": "情感表达基本到位,语气起伏与文本内容大体匹配,变化幅度还可以更明显。"
    }
  },
  "standardAudio": {},
  "asrText": {},
  "warnings": []
}
```

## 下一步

- [实时评测](https://open.shengzhiai.com/sdk/v2/guides/streaming/):边录边传的会话,状态机,心跳与断线重连
- [错误处理](https://open.shengzhiai.com/sdk/v2/guides/errors/):错误类别,异常类型与可重试判定
- [鉴权](https://open.shengzhiai.com/sdk/v2/authentication/):签名与 token 两种方式,密钥存放位置
- [上线检查清单](https://open.shengzhiai.com/sdk/v2/guides/production/):从沙箱切到生产之前逐项核对