阿里巴巴智能语音交互(实时语音识别)
写作时间:2025-09-18
💡 本章任务:
通过调用系统麦克风在于智能语音交互进行实时语音识别。
导入sdk:
<dependency>
<groupId>com.alibaba.nls</groupId>
<artifactId>nls-sdk-transcriber</artifactId>
<version>2.2.1</version>
</dependency>
基础概念
1. 音频编码格式
概念:决定如何压缩原始音频数据
影响:音频文件的大小和音质
SDK允许格式:PCM、OPUS、OPU、SPEEX、WAV
格式介绍:
| 格式 | 编码类型 | 核心优势 | 核心应用场景 |
| PCM | 未压缩(原始) | 音质绝对无损,基准标准 | 专业录音、CD 底层、设备测试 |
| WAV | 容器(封装 PCM) | 兼容性极强,通用素材格式 | 音频素材、短录音 |
| OPUS | 有损压缩 | 低延迟,语音 / 音乐双优化 | 实时通信、流媒体、高质量音乐 |
| SPEEX | 有损压缩(语音) | 极低码率,语音清晰度高 | 旧版 VoIP、对讲机、语音存储 |
| OPU | 误写(Ogg Opus) | 同 Opus,开源容器适配 | 同 Opus,侧重开源平台 |
public enum InputFormatEnum {
PCM("pcm", 1),
OPUS("opus", 2),
OPU("opu", 3),
SPEEX("speex", 4),
WAV("wav", 5);
String name;
int index;
public String getName() {
return this.name;
}
private InputFormatEnum(String name, int index) {
this.name = name;
this.index = index;
}
}
2. 音频采样率
概念:每秒对声音的采样次数,决定频率上限
影响:音质与文件大小。越高越保真,但占用资源越多。
SDK允许格式:8kHz、16kHz
格式介绍:
| 对比维度 | 8kHz 采样率 | 16kHz 采样率 |
| 频率响应上限 | ~4kHz(按奈奎斯特定理,8kHz/2=4kHz) | ~8kHz(16kHz/2=8kHz) |
| 覆盖的声音范围 | 仅能还原中低频(如人声基频、低沉乐器) | 覆盖中低频 + 部分中高频(如人声泛音、高频乐器泛音) |
| 音质特点 | 音质较粗糙,高频缺失明显,听感 “闷” | 音质更细腻,高频细节更丰富,听感更自然 |
| 数据量(同条件下) | 较低(采样次数少,存储 / 传输成本低) | 较高(采样次数翻倍,数据量约为 8kHz 的 2 倍) |
| 典型应用场景 | 语音通话、语音指令、低带宽语音存储 | 高清语音、语音直播、短视频配音、轻量级音乐 |
public enum SampleRateEnum {
SAMPLE_RATE_8K(8000),
SAMPLE_RATE_16K(16000);
public int value;
private SampleRateEnum(int value) {
this.value = value;
}
}
关键接口
- NlsClient:语音处理客户端,利用该客户端可以进行一句话识别、实时语音识别和语音合成的语音处理任务。该客户端为线程安全,建议全局仅创建一个实例。
- SpeechTranscriber:实时语音识别类,通过该接口设置请求参数,发送请求及声音数据。非线程安全。
- SpeechTranscriberListener:实时语音识别结果监听类,监听识别结果。非线程安全。
SDK调用注意事项:
- NlsClient使用了Netty框架,NlsClient对象的创建会消耗一定时间和资源,一经创建可以重复使用。建议调用程序将NlsClient的创建和关闭与程序本身的生命周期相结合。
- SpeechTranscriber对象不可重复使用,一个识别任务对应一个SpeechTranscriber对象。例如,N个音频文件要进行N次识别任务,创建N个SpeechTranscriber对象。
- SpeechTranscriberListener对象和SpeechTranscriber对象是一一对应的,不能在不同SpeechTranscriber对象中使用同一个SpeechTranscriberListener对象,否则不能将各识别任务区分开。
- Java SDK依赖Netty网络库,如果您的应用依赖Netty,其版本需更新至4.1.17.Final及以上。
代码编写
逻辑:先初始化实时语音识别器,再监听计算机麦克风输入,直接将麦克风输入发送到云服务识别。
- 创建识别结构监听器(数据发送到阿里云后返回的识别结果)
public class SpeechTranscriberListenerImpl extends SpeechTranscriberListener {
@Override
public void onClose(int closeCode, String reason) {
// 在连接关闭后调用。
super.onClose(closeCode, reason);
}
@Override
public void onMessage(ByteBuffer message) {
// 在二进制消息到达时调用
super.onMessage(message);
}
@Override
public void onMessage(String message) {
// 收到服务端返回的消息时调用
super.onMessage(message);
}
@Override
public void onOpen() {
// 一旦建立了与远程URL的连接,就会调用。
super.onOpen();
}
@Override
public void onTranscriberStart(SpeechTranscriberResponse speechTranscriberResponse) {
// 服务端准备好了进行识别
}
@Override
public void onSentenceBegin(SpeechTranscriberResponse speechTranscriberResponse) {
// 服务端检测到了一句话的开始
}
@Override
public void onSentenceEnd(SpeechTranscriberResponse speechTranscriberResponse) {
// 服务端检测到了一句话的结束
}
@Override
public void onTranscriptionResultChange(SpeechTranscriberResponse speechTranscriberResponse) {
// 语音识别过程中返回的结果
// 识别出中间结果.服务端识别出一个字或词时会返回此消息.仅当setEnableIntermediateResult(true)时,才会有此类消息返回
}
@Override
public void onTranscriptionComplete(SpeechTranscriberResponse speechTranscriberResponse) {
// 识别结束后返回的最终结果
}
@Override
public void onFail(SpeechTranscriberResponse speechTranscriberResponse) {
// 失败状况处理
}
}
- 创建阿里云连接类
public class VoiceRecognitioConnection {
// 日志
private static final Logger logger = LoggerFactory.getLogger(SpeechMyDemo.class);
private String appKey;
private String accessToken;
NlsClient client; // 客户端建立
// 本地音频输入格式
private static final AudioFormat AUDIO_FORMAT = new AudioFormat(
16000.0F, // 采样率
16, // 位深度
1, // 单声道
true, // 有符号
false // 小端字节序
);
public SpeechMyDemo(String appKey, String token) {
this.appKey = appKey;
this.accessToken = token;
//创建NlsClient实例,应用全局创建一个即可,默认服务地址为阿里云线上服务地址
client = new NlsClient(accessToken);
}
/**
* 实时语音识别监听器
* 上一面创建的类
* @return
*/
public SpeechTranscriberListener getTranscriberListener() {
return new SpeechTranscriberListenerImpl();
}
/**
* 实时语音识别创建连接
*/
public void process() {
// 初始化实时语音识别器
SpeechTranscriber transcriber = null;
try {
// 创建实例,建立连接
transcriber = new SpeechTranscriber(client, getTranscriberListener());
// 设置 appKey
transcriber.setAppKey(appKey);
// 输入音频编码方式。
transcriber.setFormat(InputFormatEnum.PCM);
//输入音频采样率。
transcriber.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
//是否返回中间识别结果,默认为false
transcriber.setEnableIntermediateResult(false);
//是否生成并返回标点符号。
transcriber.setEnablePunctuation(true);
//是否将返回结果规整化,比如将一百返回为100。
transcriber.setEnableITN(false);
//此方法将以上参数设置序列化为json发送给服务端,并等待服务端确认
transcriber.start();
// 待服务端确认--调用本地麦克风开始语音输入--本地音频采样
AudioFormat audioFormat = new AudioFormat(16000.0F, 16, 1, true, false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, audioFormat);
TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
targetDataLine.open(audioFormat);
targetDataLine.start();
System.out.println("You can speak now!");
int nByte = 0;
final int bufSize = 3200;
byte[] buffer = new byte[bufSize];
while ((nByte = targetDataLine.read(buffer, 0, bufSize)) > 0) {
// 直接发送麦克风数据流
transcriber.send(buffer, nByte);
}
transcriber.stop();
} catch (Exception e) {
System.err.println(e.getMessage());
} finally {
if (null != transcriber) {
transcriber.close();
}
}
}
// 结束关闭客户端
public void shutdown() {
client.shutdown();
}
public static void main(String[] args) {
// token and key
String appKey = "you_appKey";
String token = "you_token";
VoiceRecognitioConnection demo = new VoiceRecognitioConnection(appKey, token);
demo.process();
demo.shutdown();
}
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)