Skip to main content
即時音視頻翻譯(Qwen-Livetranslate-Realtime)

即時音視頻翻譯(Qwen-LiveTranslate)Java SDK-API參考

本文檔介紹如何使用 DashScope Java SDK 調用即時音視頻翻譯(Qwen-LiveTranslate)模型。

前提條件

  1. 安裝SDK,確保DashScope SDK版本不低於2.22.5。
  2. 擷取API Key
  3. 瞭解即時語音/音視頻翻譯-千問
阿里雲百鍊為華北2(北京)、新加坡地區推出了業務空間專屬網域名稱,能夠為推理請求提供卓越的效能和更高的穩定性,建議遷移至新網域名稱:
  • 華北2(北京)地區:從 wss://dashscope.aliyuncs.com 遷移至 wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com
  • 新加坡地區:從 wss://dashscope-intl.aliyuncs.com 遷移至 wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com
其中 {WorkspaceId} 為您的業務空間 ID,可在阿里雲百鍊控制台的業務空間詳情頁面查看。現有網域名稱仍可正常使用。

請求參數

關鍵介面

OmniRealtimeConversation類

OmniRealtimeConversation通過import com.alibaba.dashscope.audio.omni.OmniRealtimeConversation;方法引入。
方法簽名服務端響應事件(通過回調下發)說明
public OmniRealtimeConversation(OmniRealtimeParam param, OmniRealtimeCallback callback)
構造方法。
public void connect() throws NoApiKeyException, InterruptedException
服務端事件
會話已建立
服務端事件
會話配置已更新
和服務端建立串連。
public void updateSession(OmniRealtimeConfig config)
服務端事件
會話配置已更新
用於更新會話配置,建議在串連建立後首先調用該方法進行設定。若未調用該方法,系統將使用預設配置。只需關注OmniRealtimeConfig中涉及的參數。
public void appendAudio(String audioBase64)
將Base64編碼後的音頻資料片段追加到雲端輸入音頻緩衝區。服務端會自動檢測語音起止並觸發翻譯。
public void commit()
input_audio_buffer.committed
輸入音頻緩衝區已提交
Manual 模式下,提交之前通過appendAudio方法追加到雲端緩衝區的音頻,服務端收到後自動開始產生翻譯響應。VAD 模式下無需調用此方法,服務端會自動認可。
public void clearAppendedAudio()
input_audio_buffer.cleared
輸入音頻緩衝區已清空
清空當前雲端緩衝區中尚未提交的音頻資料。
public void endSession() throws InterruptedException
session.finished
服務端完成語音翻譯,結束會話
通知服務端結束會話,服務端收到會話結束通知後將完成最後的語音翻譯。
public void close(int code, String reason)
終止任務,並關閉串連。
public String getSessionId()
擷取當前任務的session_id。
public String getResponseId()
擷取最近一次response的response_id。
public long getFirstTextDelay()
擷取最近一次響應的首個文本延遲(毫秒)。
public long getFirstAudioDelay()
擷取最近一次響應的首個音頻延遲(毫秒)。

回調介面(OmniRealtimeCallback)

服務端會通過回調的方式,將服務端響應事件和資料返回給用戶端。 繼承此類並實現相應方法以處理服務端事件。 通過import com.alibaba.dashscope.audio.omni.OmniRealtimeCallback;引入。
方法簽名參數說明
public void onOpen()
WebSocket串連成功建立時觸發。
public abstract void onEvent(JsonObject message)
message:服務端事件收到服務端事件時觸發。
public abstract void onClose(int code, String reason)
code:狀態代碼reason:WebSocket串連關閉時的日誌資訊WebSocket串連關閉時觸發。

完整樣本

以下樣本展示如何從麥克風即時錄音並進行翻譯。
import com.alibaba.dashscope.audio.omni.*;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.google.gson.JsonObject;

import javax.sound.sampled.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 即時音視頻翻譯模型麥克風樣本
 */
public class Main {
    private static final int INPUT_CHUNK_SIZE = 3200;   // 100ms 的 16kHz 16bit 單聲道音頻
    private static final int OUTPUT_CHUNK_SIZE = 4800;  // 100ms 的 24kHz 16bit 單聲道音頻
    private static final AtomicBoolean running = new AtomicBoolean(true);
    private static SourceDataLine speaker;  // 擴音器

    public static void main(String[] args) throws InterruptedException {
        String apiKey = System.getenv("DASHSCOPE_API_KEY");
        if (apiKey == null || apiKey.isEmpty()) {
            System.err.println("請設定環境變數 DASHSCOPE_API_KEY");
            System.exit(1);
        }

        // 建立串連參數
        OmniRealtimeParam param = OmniRealtimeParam.builder()
                .model("qwen3.5-livetranslate-flash-realtime")
                .url("wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtime")
                .apikey(apiKey)
                .build();

        // 建立回調處理
        OmniRealtimeCallback callback = new OmniRealtimeCallback() {
            @Override
            public void onOpen() {
                System.out.println("[串連已建立]");
            }

            @Override
            public void onEvent(JsonObject message) {
                String type = message.get("type").getAsString();
                switch (type) {
                    case "input_audio_buffer.speech_started":
                        System.out.println("====== 檢測到語音輸入 ======");
                        break;
                    case "input_audio_buffer.speech_stopped":
                        System.out.println("====== 語音輸入結束 ======");
                        break;
                    case "conversation.item.input_audio_transcription.completed":
                        String originalText = message.get("transcript").getAsString();
                        System.out.println("[原文] " + originalText);
                        break;
                    case "response.audio_transcript.done":
                        String translatedText = message.get("transcript").getAsString();
                        System.out.println("[翻譯結果] " + translatedText);
                        break;
                    case "response.audio.delta":
                        // 解碼並播放翻譯後的音頻
                        String audioB64 = message.get("delta").getAsString();
                        byte[] audioBytes = Base64.getDecoder().decode(audioB64);
                        if (speaker != null) {
                            speaker.write(audioBytes, 0, audioBytes.length);
                        }
                        break;
                    case "error":
                        JsonObject error = message.get("error").getAsJsonObject();
                        System.err.println("[錯誤] " + error.get("message").getAsString());
                        break;
                }
            }

            @Override
            public void onClose(int code, String reason) {
                System.out.println("[串連已關閉] code: " + code + ", reason: " + reason);
            }
        };

        // 建立會話
        OmniRealtimeConversation conversation = new OmniRealtimeConversation(param, callback);

        try {
            // 初始化擴音器(用於播放翻譯後的語音)
            AudioFormat speakerFormat = new AudioFormat(24000, 16, 1, true, false);
            DataLine.Info speakerInfo = new DataLine.Info(SourceDataLine.class, speakerFormat);
            speaker = (SourceDataLine) AudioSystem.getLine(speakerInfo);
            speaker.open(speakerFormat, OUTPUT_CHUNK_SIZE * 4);
            speaker.start();

            // 初始化麥克風(用於採集語音輸入)
            AudioFormat micFormat = new AudioFormat(16000, 16, 1, true, false);
            DataLine.Info micInfo = new DataLine.Info(TargetDataLine.class, micFormat);
            if (!AudioSystem.isLineSupported(micInfo)) {
                System.err.println("麥克風不可用");
                System.exit(1);
            }
            TargetDataLine microphone = (TargetDataLine) AudioSystem.getLine(micInfo);
            microphone.open(micFormat);
            microphone.start();

            // 串連服務端
            conversation.connect();

            // 配置翻譯參數
            Map<String, Object> phrases = new HashMap<>();
            phrases.put("人工智慧", "Artificial Intelligence");
            phrases.put("機器學習", "Machine Learning");

            OmniRealtimeConfig config = OmniRealtimeConfig.builder()
                    .modalities(Arrays.asList(OmniRealtimeModality.AUDIO, OmniRealtimeModality.TEXT))
                    .voice("Tina")
                    .inputAudioFormat(OmniRealtimeAudioFormat.PCM_16000HZ_MONO_16BIT)
                    .outputAudioFormat(OmniRealtimeAudioFormat.PCM_24000HZ_MONO_16BIT)
                    .InputAudioTranscription("qwen3-asr-flash-realtime")
                    .translationConfig(OmniRealtimeTranslationParam.builder()
                            .language("en")
                            .corpus(OmniRealtimeTranslationParam.Corpus.builder()
                                    .phrases(phrases)
                                    .build())
                            .build())
                    .build();

            conversation.updateSession(config);

            // 註冊退出訊號處理
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                System.out.println("\n[正在退出...]");
                running.set(false);
                microphone.stop();
                microphone.close();
                speaker.stop();
                speaker.close();
                try {
                    conversation.endSession();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                conversation.close(1000, "使用者停止");
            }));

            System.out.println("[開始即時翻譯] 請對著麥克風說話,按 Ctrl+C 退出");

            // 持續採集麥克風音頻並發送
            byte[] buffer = new byte[INPUT_CHUNK_SIZE];
            while (running.get()) {
                int bytesRead = microphone.read(buffer, 0, buffer.length);
                if (bytesRead > 0) {
                    conversation.appendAudio(Base64.getEncoder().encodeToString(buffer));
                }
            }

        } catch (NoApiKeyException e) {
            System.err.println("API Key 錯誤: " + e.getMessage());
        } catch (Exception e) {
            System.err.println("發生異常: " + e.getMessage());
            e.printStackTrace();
        }
    }
}