AI Agent智能体 - 实时语音对话客户端(OmniServerVad)

功能概述

基于《JavaUtils系列 - 实时PCM音频播放器(RealtimePcmPlayer)》实现支持语音和图像输入的实时对话系统,使用麦克风输入语音,并可选发送图像数据,接收语音回复并播放。


相关依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dashscope-sdk-java</artifactId>
    <version>2.20.9</version>
</dependency>
<dependency>
    <groupId>com.googlecode.soundlibs</groupId>
    <artifactId>mp3spi</artifactId>
    <version>1.9.5.4</version>
</dependency>
<dependency>
    <groupId>org.java-websocket</groupId>
    <artifactId>Java-WebSocket</artifactId>
    <version>1.5.3</version>
</dependency>

核心流程

1. 初始化
String imageB64 = null;
if (EnableVisionInput) {
    // 读取图片并转为 Base64
    File imageFile = new File("data/cat_480p.jpg");
    // ... 读取文件并编码为 Base64
}

2. 配置 Omni 参数
OmniRealtimeParam param = OmniRealtimeParam.builder()
        .model("qwen-omni-turbo-realtime-latest")
        .build();

3. 创建音频播放器
RealtimePcmPlayer audioPlayer = new RealtimePcmPlayer(24000);

4. 创建对话回调
OmniRealtimeConversation conversation = new OmniRealtimeConversation(param, new OmniRealtimeCallback() {
    @Override
    public void onEvent(JsonObject message) {
        String type = message.get("type").getAsString();
        switch(type) {
            case "response.audio.delta":
                String recvAudioB64 = message.get("delta").getAsString();
                audioPlayer.write(recvAudioB64); // 播放回复音频
                break;
            case "input_audio_buffer.speech_started":
                audioPlayer.cancel(); // 用户开始说话,取消当前播放
                break;
            // ... 其他事件处理
        }
    }
});

5. 连接并配置会话
conversation.connect();
OmniRealtimeConfig config = OmniRealtimeConfig.builder()
        .modalities(Arrays.asList(OmniRealtimeModality.AUDIO, OmniRealtimeModality.TEXT))
        .voice("Chelsie")
        .enableTurnDetection(true)
        .enableInputAudioTranscription(true)
        .InputAudioTranscription("gummy-realtime-v1")
        .build();
conversation.updateSession(config);

6. 录音和发送数据
TargetDataLine targetDataLine = AudioSystem.getTargetDataLine(audioFormat);
targetDataLine.open(audioFormat);
targetDataLine.start();

ByteBuffer buffer = ByteBuffer.allocate(1024);
while (System.currentTimeMillis() - start < 50000) {
    int read = targetDataLine.read(buffer.array(), 0, buffer.capacity());
    if (read > 0) {
        String audioB64 = Base64.getEncoder().encodeToString(buffer.array());
        conversation.appendAudio(audioB64); // 发送音频数据
        
        if (EnableVisionInput && System.currentTimeMillis() - last_photo_time > 500) {
            conversation.appendVideo(imageB64); // 每 500ms 发送一次图片
            last_photo_time = System.currentTimeMillis();
        }
        
        Thread.sleep(20); // 控制发送频率
    }
}

7. 结束会话
conversation.commit();
conversation.createResponse(null, null);
conversation.close(1000, "bye");
audioPlayer.waitForComplete();
audioPlayer.shutdown();

系统交互流程

  1. 初始化:加载图片、创建音频播放器、连接 Omni 服务

  2. 录音:从麦克风读取音频数据,实时发送到服务端

  3. 视觉输入:可选定时发送图片数据

  4. 接收回复

    • 文本回复:打印到控制台

    • 音频回复:通过 RealtimePcmPlayer 播放

  5. VAD 检测:检测到用户说话时打断当前播放

  6. 结束:等待所有音频播放完成后关闭资源


关键技术点

  • 多线程音频处理:解码和播放分离,避免阻塞

  • 实时音频播放:使用 SourceDataLine 实现低延迟播放

  • Base64 编解码:音频和图片数据编码传输

  • 事件驱动架构:通过回调处理服务端推送的各种事件

  • VAD 支持:检测用户语音开始,实现打断效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值