写作时间:2025-09-18

💡 本章任务:
通过调用系统麦克风在于智能语音交互进行实时语音识别。

  1. 接口说明文档
  2. API接口说明
  3. 智能语音交互示例
  4. 通过SDK获取Token

导入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;
    }
}

关键接口

  1. NlsClient:语音处理客户端,利用该客户端可以进行一句话识别、实时语音识别和语音合成的语音处理任务。该客户端为线程安全,建议全局仅创建一个实例。
  2. SpeechTranscriber:实时语音识别类,通过该接口设置请求参数,发送请求及声音数据。非线程安全。
  3. SpeechTranscriberListener:实时语音识别结果监听类,监听识别结果。非线程安全。

SDK调用注意事项:

  • NlsClient使用了Netty框架,NlsClient对象的创建会消耗一定时间和资源,一经创建可以重复使用。建议调用程序将NlsClient的创建和关闭与程序本身的生命周期相结合。
  • SpeechTranscriber对象不可重复使用,一个识别任务对应一个SpeechTranscriber对象。例如,N个音频文件要进行N次识别任务,创建N个SpeechTranscriber对象。
  • SpeechTranscriberListener对象和SpeechTranscriber对象是一一对应的,不能在不同SpeechTranscriber对象中使用同一个SpeechTranscriberListener对象,否则不能将各识别任务区分开。
  • Java SDK依赖Netty网络库,如果您的应用依赖Netty,其版本需更新至4.1.17.Final及以上。

代码编写

逻辑:先初始化实时语音识别器,再监听计算机麦克风输入,直接将麦克风输入发送到云服务识别。

  1. 创建识别结构监听器(数据发送到阿里云后返回的识别结果)
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) {
        // 失败状况处理
    }
}

  1. 创建阿里云连接类
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();
    }

}

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐