更新记录

1.0.2(2026-10-10)

文档更新

1.0.1(2026-10-10)

iOS问题修复

1.0.0(2026-01-22)

  • 首个版本发布
  • 支持 Android、iOS、鸿蒙三端
  • 实现腾讯云口语评测核心功能
    • 实时录音评测
    • 音量实时监测
    • VAD 静音检测
    • 完整的评测结果回调
  • 提供统一的三端 API 接口
  • 支持中英文评测
  • 支持单词/句子/段落/自由说四种评测模式
查看更多

平台兼容性

uni-app(4.72)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android Android插件版本 iOS iOS插件版本 鸿蒙
× × × × - - 4.4 1.0.2 12 1.0.2 ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

腾讯云口语评测 UTS 插件 (hl-qcloud-uts)

UTS环境兼容性

uni-app uni-app x
√ √

插件简介

本插件封装了腾讯云口语评测 SDK(QCloudSOE),支持 Android、iOS、鸿蒙三端,提供以下功能:

  • 实时评测模式:边录音边评测
  • 文件评测模式:使用本地 PCM 音频文件进行评测
  • 支持中文/英文评测
  • 支持单词/句子/段落/自由说多种评测模式
  • 支持静音检测(VAD)
  • 支持音量实时回调
  • 完整的评测结果回调
  • 统一的三端接口

平台支持

Android iOS 鸿蒙
√ (minSdk 21) √ (iOS 12.0+) √ (API 12+)

使用准备

1. 获取腾讯云密钥

在使用前,需要在 腾讯云控制台 获取:

  • AppID
  • SecretID
  • SecretKey

2. 开通口语评测服务

在腾讯云控制台开通口语评测服务。

使用说明

导入插件

import {
    enableDebugLog,
    onLogCallback,
    createSoeController,
    stopOralEvaluation,
    cancelOralEvaluation,
    release
} from '@/uni_modules/hl-qcloud-uts'

基本使用示例(三端通用)

// 1. 开启调试日志(可选)
enableDebugLog()

// 2. 配置日志回调(可选)
onLogCallback((level, tag, message) => {
    console.log(`[${level}] ${tag}: ${message}`)
})

// 3. 配置评测参数
const config = {
    appId: 1393187574, // 腾讯云 AppID
    secretId: 'your-secret-id',
    secretKey: 'your-secret-key',
    token: '', // 可选,临时token

    // API 参数
    apiParams: {
        serverEngineType: '16k_en', // '16k_zh'中文 / '16k_en'英文
        evalMode: 1, // 0-单词 1-句子 2-段落 3-自由说
        refText: 'Hello', // 评测文本
        scoreCoeff: 1.0, // 评价苛刻指数 [1.0-4.0]
        sentenceInfoEnabled: 1, // 0-不输出 1-输出断句中间结果
        textMode: 0 // 可选,0-普通文本 1-音素结构文本
    },

    // VAD(静音检测)配置
    enableVAD: true, // 是否开启静音检测
    vadInterval: 3000, // 静音检测时长(ms)
    vadDBThreshold: 20, // 静音检测音量阈值(0-120)
    stopOnVadDetected: true, // 检测到静音是否停止

    // 其他配置
    connectTimeout: 3000 // WebSocket 连接超时(ms)
}

// 4. 创建控制器
const controller = createSoeController(config)

// 5. 设置回调
controller.onMessage((message) => {
    console.log('评测消息:', message)
})

controller.onFinish((result) => {
    console.log('评测完成:', result)
    console.log('建议评分:', result.suggestedScore)
    console.log('准确度:', result.pronAccuracy)
    console.log('流利度:', result.pronFluency)
    console.log('完整度:', result.pronCompletion)
})

controller.onError((error) => {
    console.error('评测错误:', error.response)
})

controller.onVad((hasVoice) => {
    if (!hasVoice) {
        console.log('检测到静音')
        // 可以自动停止评测
        controller.stop()
    }
})

controller.onVolumeDb((volume) => {
    console.log('当前音量:', volume)
})

controller.onStartRecord(() => {
    console.log('开始录音')
})

controller.onStopRecord(() => {
    console.log('停止录音')
})

// 6. 开始评测
controller.start()

// 7. 停止评测(向服务器发送结束信息,等待服务器返回最终结果)
// controller.stop()

// 8. 取消评测(立即停止评测)
// controller.cancel()

// 9. 释放资源(页面销毁时调用)
// controller.dispose()

全局方法

// 停止当前评测(全局)
stopOralEvaluation()

// 取消当前评测(全局)
cancelOralEvaluation()

// 释放所有资源(全局)
release()

文件评测模式

// 使用本地音频文件进行评测(需要三端原生实现支持)
const fileConfig = {
    ...config,
    useCustomAudioSource: true, // 使用自定义音频源
    recordAudioData: base64AudioData // Base64 编码的 PCM 数据
}

const controller = createSoeController(fileConfig)
controller.start()

完整示例(带界面交互)

<template>
    <view class="content">
        <view class="section">
            <text class="title">腾讯云口语评测</text>
        </view>

        <view class="section">
            <input v-model="refText" placeholder="请输入评测文本" class="input" />
        </view>

        <view class="section">
            <button @tap="startEvaluation" :disabled="isEvaluating">开始评测</button>
            <button @tap="stopEvaluation" :disabled="!isEvaluating">停止评测</button>
        </view>

        <view class="section">
            <text>音量: {{ volume }}</text>
            <progress :percent="volumePercent" stroke-width="8" />
        </view>

        <view class="section">
            <text class="result-title">评测结果:</text>
            <text class="result-text">{{ resultText }}</text>
        </view>
    </view>
</template>

<script>
import { enableDebugLog, onLogCallback, createSoeController } from '@/uni_modules/hl-qcloud-uts'

export default {
    data() {
        return {
            refText: 'Hello',
            isEvaluating: false,
            volume: 0,
            resultText: '暂无结果',
            controller: null
        }
    },
    computed: {
        volumePercent() {
            return Math.round(this.volume / 120 * 100)
        }
    },
    onLoad() {
        // 开启调试日志
        enableDebugLog()

        // 设置日志回调
        onLogCallback((level, tag, message) => {
            console.log(`[${level}] ${tag}: ${message}`)
        })
    },
    methods: {
        startEvaluation() {
            this.isEvaluating = true
            this.resultText = '评测中...'

            const config = {
                appId: 1393187574,
                secretId: 'your-secret-id',
                secretKey: 'your-secret-key',
                apiParams: {
                    serverEngineType: '16k_en',
                    evalMode: 1,
                    refText: this.refText,
                    scoreCoeff: 1.0,
                    sentenceInfoEnabled: 1
                },
                enableVAD: true,
                vadInterval: 3000,
                vadDBThreshold: 20,
                stopOnVadDetected: true
            }

            this.controller = createSoeController(config)

            this.controller.onFinish((result) => {
                this.isEvaluating = false
                this.resultText = `建议评分: ${result.suggestedScore}\n` +
                                 `准确度: ${result.pronAccuracy}\n` +
                                 `流利度: ${result.pronFluency}\n` +
                                 `完整度: ${result.pronCompletion}`
            })

            this.controller.onError((error) => {
                this.isEvaluating = false
                this.resultText = `评测出错: ${error.response}`
            })

            this.controller.onVad((hasVoice) => {
                if (!hasVoice) {
                    this.controller.stop()
                }
            })

            this.controller.onVolumeDb((volume) => {
                this.volume = volume
            })

            this.controller.start()
        },
        stopEvaluation() {
            this.controller?.stop()
        }
    },
    onUnload() {
        this.controller?.dispose()
    }
}
</script>

<style>
.content {
    padding: 20px;
}
.section {
    margin-bottom: 20px;
}
.title {
    font-size: 18px;
    font-weight: bold;
}
.input {
    border: 1px solid #ccc;
    padding: 10px;
    border-radius: 4px;
}
.result-title {
    font-weight: bold;
    margin-bottom: 10px;
}
.result-text {
    white-space: pre-line;
}
</style>

API 参数说明

SoeConfig 配置项

参数 类型 必填 说明
appId number 是 腾讯云 AppID
secretId string 是 SecretID
secretKey string 是 SecretKey
token string 否 临时 Token
apiParams SoeApiParams 是 API 参数
enableVAD boolean 否 是否开启静音检测,默认true
vadInterval number 否 静音检测时间间隔(ms),默认3000
vadDBThreshold number 否 静音检测阈值(0-120),默认20
stopOnVadDetected boolean 否 检测到静音是否停止,默认true
useCustomAudioSource boolean 否 Android 选择插件自定义录音源;iOS 实时模式始终使用插件的 RecordDataSource
callbackAudioData boolean 否 是否回调 SDK 实际读取的 PCM,默认 false;iOS 无需额外设置 useCustomAudioSource
saveAudioFile boolean 否 仅 iOS 实时录音:是否保存本次评测的 PCM 临时文件,默认 false
recordAudioData string 否 录音评测模式的音频数据(Base64)
connectTimeout number 否 网络超时(ms),默认3000

SoeApiParams API 参数

参数 类型 必填 说明
serverEngineType string 是 引擎类型: "16k_zh"(中文) / "16k_en"(英文)
evalMode number 是 评测模式: 0-单词 1-句子 2-段落 3-自由说
refText string 是 被评估语音对应的文本
scoreCoeff number 是 评价苛刻指数 [1.0-4.0]
sentenceInfoEnabled number 是 断句中间结果: 0-不输出 1-输出
textMode number 否 文本模式: 0-普通文本 1-音素结构文本
keyword string 否 关键词

ISoeController 控制器接口

方法 参数 说明
start() - 开始评测
stop() - 停止评测(等待服务器返回结果)
cancel() - 取消评测(立即停止)
dispose() - 释放资源
isEvaluating() - 是否正在评测
onMessage(callback) (message: string) => void 评测消息回调
onFinish(callback) (result: SoeEvaluationResult) => void 评测完成回调
onError(callback) (error: SoeErrorResult) => void 评测错误回调
onVad(callback) (hasVoice: boolean) => void 静音检测回调
onVolumeDb(callback) (volume: number) => void 音量回调
onStartRecord(callback) () => void 开始录音回调
onStopRecord(callback) () => void 停止录音回调
onAudioData(callback) (data: string, length: number) => void data 为 Base64 PCM;Android/iOS 的 length 为 Int16 采样点数,字节数为 length × 2

iOS 实时 PCM 与录音文件

callbackAudioData: true 会逐块回传 SDK 实际用于评测的 PCM,格式为 16000 Hz、单声道、16 位小端。应先注册 onAudioData,再调用 start();录音数据在录音期间产生,无需等待评分后额外延迟。

saveAudioFile: true 会让 iOS SDK 将相同数据保存为独立的 .pcm 临时文件。这个开关与 callbackAudioData 独立。iOS 专用函数 getRecordedAudioFilePath() 在 SDK 正常完成且文件存在后返回绝对路径,未启用、尚未完成、取消、出错或释放后返回空字符串。

import { createSoeController } from '@/uni_modules/hl-qcloud-uts'
// #ifdef APP-IOS
import { getRecordedAudioFilePath } from '@/uni_modules/hl-qcloud-uts'
// #endif

const controller = createSoeController({
    ...config,
    callbackAudioData: true,
    // #ifdef APP-IOS
    saveAudioFile: true
    // #endif
})

controller.onAudioData((base64, sampleCount) => {
    const pcm = uni.base64ToArrayBuffer(base64)
    console.log('PCM 字节数:', pcm.byteLength, '采样点数:', sampleCount)
})

controller.onStopRecord(() => {
    // #ifdef APP-IOS
    const path = getRecordedAudioFilePath()
    if (path) {
        plus.io.resolveLocalFileSystemURL(`file://${path}`, (entry) => {
            entry.file((file) => {
                const reader = new plus.io.FileReader()
                reader.onload = (event) => {
                    const dataUrl = event.target.result
                    const base64 = dataUrl.substring(dataUrl.indexOf(',') + 1)
                    const pcm = uni.base64ToArrayBuffer(base64)
                    console.log('录音文件字节数:', pcm.byteLength)
                }
                reader.onerror = () => console.error('读取录音文件失败')
                reader.readAsDataURL(file)
            }, (error) => console.error(error.message))
        }, (error) => console.error(error.message))
    }
    // #endif
})

controller.start()

iOS 的评分结果回调与 SDK 完成通知独立,文件路径应在 onStopRecord 中获取,不用评分后等待固定秒数。路径属于临时目录;如需长期保留,请在释放控制器前取得路径,并将文件复制到业务存储目录。原始 PCM 没有 WAV 文件头,不能只修改后缀充当 WAV。

该能力需要包含修复源码的 iOS 自定义基座或重新打包的 App,单独更新页面/WGT 不会替换已编译的 Swift。实现依据:腾讯云 iOS SDK 的 audioFile 和数据源说明、HTML5+ 文件读取接口。

SoeEvaluationResult 评测结果

字段 类型 说明
sessionId string 会话 ID
requestId string 请求 ID
status string 评测状态
pronAccuracy number 发音准确度 (0-100)
pronFluency number 发音流利度 (0-1)
pronCompletion number 发音完整度 (0-1)
suggestedScore number 建议评分 (0-100)
words SoeWord[] | null 单词评测结果
sentenceInfoSet SoeSentenceInfo[] | null 句子信息
rawResponse string 原始响应数据

错误码

错误码 说明
-1 未知错误
-100 AudioRecord初始化失败
-101 AudioRecord启动失败
-102 重复启动口语评测
-103 录音线程启动失败
-104 数据源为空
-105 口语评测请求为空
-106 Websocket网络异常
-107 取消评测

注意事项

  1. 权限要求:

    • Android:需要录音权限(RECORD_AUDIO)和网络权限(INTERNET),插件会自动申请
    • iOS:需要在 Info.plist 中配置 NSMicrophoneUsageDescription
    • 鸿蒙:需要麦克风权限(ohos.permission.MICROPHONE),插件会自动请求
  2. 音频格式:评测音频必须为 16kHz 采样率的 PCM 格式。

  3. 安全提示:建议在生产环境中使用临时 Token 而非直接使用 SecretKey,避免密钥泄露。

  4. 资源释放:页面销毁时请调用 controller.dispose() 或 release() 释放资源。

  5. 调试日志:开发阶段建议调用 enableDebugLog() 开启日志,便于排查问题。

  6. 三端一致性:本插件提供了统一的三端接口,代码可以在 Android、iOS、鸿蒙三端通用。

  7. 静音检测:开启 VAD 后,检测到静音会触发 onVad 回调,如果 stopOnVadDetected 为 true,将自动停止评测。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

需要录音权限(RECORD_AUDIO)和网络权限(INTERNET)

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件会使用麦克风采集音频数据进行语音评测

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。