Skip to main content
Qwen-Audio-TTS

Qwen-Audio-TTS Java SDK

Sintesis suara dengan Qwen-Audio-TTS menggunakan DashScope Java SDK.

Titik akhir layanan

Secara default, SDK terhubung ke titik akhir Wilayah Beijing. Untuk menggunakan wilayah lain, atur Constants.baseWebsocketApiUrl sebelum menginisialisasi SDK.
  • Singapura
  • Tiongkok (Beijing)
wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inferenceGanti {WorkspaceId} dengan workspace ID Anda yang sebenarnya.
Beralih ke wilayah Singapura:
import com.alibaba.dashscope.utils.Constants;

// Atur ini sebelum inisialisasi SDK apa pun
Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference";
Alibaba Cloud Model Studio telah merilis domain khusus ruang kerja untuk wilayah Tiongkok (Beijing) dan Singapura. Domain khusus baru ini memberikan performa lebih unggul dan stabilitas lebih tinggi untuk permintaan inferensi. Kami merekomendasikan migrasi ke domain baru:
  • Tiongkok (Beijing): dari dashscope.aliyuncs.com ke {WorkspaceId}.cn-beijing.maas.aliyuncs.com
  • Singapura: dari dashscope-intl.aliyuncs.com ke {WorkspaceId}.ap-southeast-1.maas.aliyuncs.com

SpeechSynthesizer

Package: com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer

Konstruktor

public SpeechSynthesizer(SpeechSynthesisParam param, ResultCallback<SpeechSynthesisResult> callback)
Parameter:
  • param: Parameter sintesis suara, dibuat dengan SpeechSynthesisParam.builder()
  • callback: Callback untuk panggilan streaming. Berikan null untuk panggilan non-streaming.

call() - Sintesis non-streaming/unidirectional streaming

Signature metode:
public ByteBuffer call(String text)
Parameter:
ParameterTypeWajibDeskripsi
textStringYaTeks yang akan disintesis. Panjang maksimum: 20.000 karakter.
Nilai kembalian: ByteBuffer atau null. Untuk panggilan non-streaming, mengembalikan seluruh data audio. Untuk panggilan unidirectional streaming, metode ini mengembalikan null; audio dikirimkan melalui callback.

streamingCall() - Sintesis bidirectional streaming

Signature metode:
public void streamingCall(String text)
Parameter:
ParameterTipeWajibDeskripsi
textStringYaTeks yang akan disintesis. Panjang maksimum: 20.000 karakter. Anda dapat memanggil metode ini beberapa kali untuk menambahkan teks.

streamingComplete() - Mengakhiri bidirectional streaming

Signature metode:
public void streamingComplete()
Mengakhiri panggilan bidirectional streaming dan memberi tahu server bahwa seluruh teks telah dikirim.

streamingCancel() - Membatalkan bidirectional streaming

Signature metode:
public void streamingCancel()
Deskripsi: Membatalkan tugas sintesis suara bidirectional streaming saat ini. Setelah memanggil metode ini, SDK segera mengakhiri tugas tersebut. Anda dapat memulai tugas sintesis baru pada koneksi yang sama tanpa perlu menginisialisasi ulang instans SpeechSynthesizer.
Persyaratan versi: Fitur ini memerlukan Java SDK versi 2.22.26 atau lebih baru.

callAsFlowable() - Sintesis unidirectional streaming (reaktif)

Signature metode:
public Flowable<SpeechSynthesisResult> callAsFlowable(String text)
Parameter:
ParameterTypeWajibDeskripsi
textStringYaTeks yang akan disintesis.
Nilai kembalian: Stream reaktif Flowable<SpeechSynthesisResult>.

streamingCallAsFlowable() - Sintesis bidirectional streaming (reaktif)

Signature metode:
public Flowable<SpeechSynthesisResult> streamingCallAsFlowable(Flowable<String> textStream)
Parameter:
ParameterTipeWajibDeskripsi
textStreamFlowable<String>YaStream reaktif teks.
Nilai kembalian: Stream reaktif Flowable<SpeechSynthesisResult>.

getDuplexApi().close() - Menutup koneksi WebSocket

Signature metode:
public boolean getDuplexApi().close(int code, String reason)
Parameter:
ParameterTipeWajibDeskripsi
codeintYaKode penutupan.
reasonStringYaAlasan penutupan.
Nilai kembalian: boolean. Mengembalikan true jika koneksi berhasil ditutup, false jika tidak.

getLastRequestId() - Mendapatkan ID permintaan

Signature metode:
public String getLastRequestId()
Nilai kembalian: String, ID permintaan.

getFirstPackageDelay() - Mendapatkan latensi paket pertama

Signature metode:
public long getFirstPackageDelay()
Nilai kembalian: long. Latensi paket pertama dalam milidetik, diukur dari pengiriman segmen teks pertama hingga menerima paket audio pertama.

SpeechSynthesisParam

Package: com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam Contoh:
SpeechSynthesisParam param = SpeechSynthesisParam.builder()
    .model("qwen-audio-3.0-tts-flash") // Model
    .voice("longanhuan_v3.6") // Voice
    .format(SpeechSynthesisAudioFormat.WAV_8000HZ_MONO_16BIT) // Format encoding audio dan laju sampel
    .volume(50) // Volume. Rentang nilai: [0, 100]
    .speechRate(1.0f) // Laju bicara. Rentang nilai: [0.5, 2]
    .pitchRate(1.0f) // Pitch. Rentang nilai: [0.5, 2]
    .build();

Metode builder

MetodeTipe parameterWajibDeskripsi
model(String)StringYaNama model.
voice(String)StringYaVoice yang digunakan untuk sintesis suara.
  • Voice sistem: Lihat Daftar voice Qwen-Audio-TTS
  • Suara kloning: Suara kustom yang dibuat melalui kloning suara.
  • Suara kustom: Suara kustom yang dibuat melalui desain suara.
format(SpeechSynthesisAudioFormat)enumTidakFormat encoding audio dan laju sampel.Default: SpeechSynthesisAudioFormat.MP3_22050HZ_MONO_256KBPS.Package SpeechSynthesisAudioFormat: com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisAudioFormat.
volume(int)intTidakTingkat volume.Nilai default: 50.Nilai valid: [0, 100].
speechRate(float)floatTidakLaju bicara.Nilai default: 1.0.Nilai valid: [0.5, 2.0].
pitchRate(float)floatTidakPitch.Nilai default: 1.0.Nilai valid: [0.5, 2.0].
enableWordTimestamp(boolean)booleanTidakMenentukan apakah akan mengaktifkan timestamp tingkat kata.Nilai default: false.Hanya tersedia dalam mode keluaran streaming. Suara hasil kloning didukung. Untuk suara sistem yang didukung, lihat Daftar voice Qwen-Audio-TTS.
seed(int)intTidakSeed acak untuk mengontrol variasi dalam output sintesis. Ketika versi model, teks, voice, dan parameter lainnya tidak berubah, penggunaan seed yang sama menghasilkan output identik.Nilai default: 0.Nilai valid: [0, 65535].Untuk versi SDK sebelum 2.21.7, atur seed melalui parameter tambahan.
languageHints(List<String>)List<String>Tidak
  • Parameter ini berupa array, tetapi versi saat ini hanya memproses elemen pertama. Berikan satu nilai saja.
  • Parameter ini menentukan bahasa target untuk sintesis suara. Tidak terkait dengan bahasa sampel audio yang digunakan dalam voice cloning. Untuk mengatur bahasa sumber dalam tugas kloning, lihat referensi API voice cloning.
Menentukan bahasa target untuk sintesis suara guna meningkatkan kualitas output.Ketika pelafalan angka, ekspansi singkatan, pembacaan simbol, atau sintesis bahasa minoritas tidak sesuai harapan, gunakan parameter ini. Contohnya:
  • Pelafalan angka tidak sesuai: "hello, this is 110" dibaca sebagai "hello, this is one zero" alih-alih pelafalan Mandarin yang diharapkan
  • Pelafalan simbol tidak akurat: "@" dibaca sebagai ekuivalen Mandarin alih-alih "at"
  • Kualitas sintesis bahasa minoritas buruk dengan hasil tidak alami
  • zh: Tionghoa
  • en: Inggris
  • fr: Prancis
  • de: Jerman
  • ja: Jepang
  • ko: Korea
  • ru: Rusia
  • pt: Portugis
  • th: Thai
  • id: Bahasa Indonesia
  • vi: Bahasa Vietnam
  • es: Spanyol
  • it: Italia
  • ms: Bahasa Melayu
  • fil: Filipino
  • ar: Arab
instruction(String)StringTidakMengontrol karakteristik sintesis seperti dialek, emosi, atau gaya bicara.Untuk detail penggunaan, lihat Kontrol instruksi.
hotFix(ParamHotFix)ParamHotFixTidakMengonfigurasi koreksi pelafalan dan penggantian teks yang diterapkan sebelum sintesis.Parameter:
  • pronunciation: Pelafalan kustom. Menentukan anotasi pinyin untuk kata-kata guna memperbaiki pelafalan default yang tidak akurat.
  • replace: Penggantian teks. Mengganti kata-kata tertentu dengan teks target sebelum sintesis. Teks yang diganti digunakan sebagai input sintesis sebenarnya.
Contoh:
List<ParamHotFix.PronunciationItem> pronunciationItems = new ArrayList<>();
pronunciationItems.add(new ParamHotFix.PronunciationItem("weather", "tian1 qi4"));

List<ParamHotFix.ReplaceItem> replaceItems = new ArrayList<>();
replaceItems.add(new ParamHotFix.ReplaceItem("today", "gold day"));

ParamHotFix paramHotFix = new ParamHotFix();
paramHotFix.setPronunciation(pronunciationItems);
paramHotFix.setReplace(replaceItems);

SpeechSynthesisParam param = SpeechSynthesisParam.builder()
                        .model("qwen-audio-3.0-tts-flash") // Model
                        .voice("longanhuan_v3.6") // Voice
                        .hotFix(paramHotFix)
                        .build();
parameter(String key, Object value)String, ObjectTidakMengatur Parameter tambahan.
parameters(Map<String, Object>)MapTidakMengatur Parameter tambahan.

Parameter tambahan

Diatur melalui parameter() atau parameters(). Contoh:
SpeechSynthesisParam param = SpeechSynthesisParam.builder()
  .model("qwen-audio-3.0-tts-flash")
  .voice("longanhuan_v3.6")
  .parameter("bit_rate", 32)
  .build();
ParameterTipeWajibDeskripsi
bit_rateintegerTidakLaju bit audio dalam kbps. Ketika format audio adalah mp3 atau opus, gunakan bit_rate untuk menyesuaikan laju bit.Nilai default: 32.Nilai valid: [6, 510].
enable_aigc_tagbooleanTidakMenentukan apakah akan menyematkan watermark AIGC dalam audio yang dihasilkan. Ketika diatur ke true, watermark disematkan dalam file audio dengan format yang didukung (wav/mp3/opus).Nilai default: false.
aigc_propagatorStringTidakMengatur bidang ContentPropagator dalam watermark AIGC, mengidentifikasi propagator konten. Hanya berlaku ketika enable_aigc_tag bernilai true.Nilai default: UID Alibaba Cloud.
aigc_propagate_idStringTidakMengatur bidang PropagateID dalam watermark AIGC, mengidentifikasi secara unik aksi propagasi tertentu. Hanya berlaku ketika enable_aigc_tag bernilai true.Nilai default: ID permintaan dari permintaan sintesis suara saat ini.

ResultCallback

Package: com.alibaba.dashscope.common.ResultCallback

onEvent() - Menerima audio data

Signature metode:
public void onEvent(SpeechSynthesisResult result)
Parameter:
ParameterTipeWajibDeskripsi
resultSpeechSynthesisResultYaDipicu ketika event sintesis diterima. Berisi frame audio, informasi timestamp, dan informasi output (tipe event, teks asli, dll.).

onComplete() - Sintesis selesai

Signature metode:
public void onComplete()
Dipicu ketika sintesis suara selesai.

onError() - Penanganan error

Signature metode:
public void onError(Exception e)
Parameter:
ParameterTipeWajibDeskripsi
eExceptionYaDipicu ketika terjadi error. Berisi informasi exception.

SpeechSynthesisResult

Package: com.alibaba.dashscope.audio.tts.SpeechSynthesisResult

getAudioFrame() - Mendapatkan frame data audio

Signature metode:
public ByteBuffer getAudioFrame()
Nilai kembalian: ByteBuffer, frame data audio.

getTimestamp() - Mendapatkan informasi timestamp

Signature metode:
public Sentence getTimestamp()
Nilai kembalian: Sentence, informasi timestamp.

getOutput() - Mendapatkan informasi output

Signature metode:
public JsonObject getOutput()
Nilai kembalian: com.google.gson.JsonObject, informasi output dari event sintesis, berisi tipe event dan konten teks. Memerlukan versi SDK >= 2.22.0.

Informasi timestamp tingkat kalimat (Sentence)

Sentence membungkus informasi timestamp tingkat kalimat.

getBeginTime() - Mendapatkan waktu mulai kalimat

Signature metode:
public int getBeginTime()
Nilai kembalian: Waktu mulai kalimat dalam milidetik.

getEndTime() - Mendapatkan waktu akhir kalimat

Signature metode:
public int getEndTime()
Nilai kembalian: Waktu akhir kalimat dalam milidetik.

getWords() - Mendapatkan timestamp tingkat kata

Signature metode:
public List<Word> getWords()
Nilai kembalian: List objek Word yang berisi informasi timestamp tingkat kata. Bisa jadi kosong.

Informasi timestamp tingkat kata (Word)

Word membungkus informasi timestamp tingkat kata.

getBeginTime() - Mendapatkan waktu mulai kata

Signature metode:
public int getBeginTime()
Nilai kembalian: Waktu mulai kata dalam milidetik.

getEndTime() - Mendapatkan waktu akhir kata

Signature metode:
public int getEndTime()
Nilai kembalian: Waktu akhir kata dalam milidetik.

getText() - Mendapatkan teks

Signature metode:
public String getText()
Nilai kembalian: String, konten teks.

getPhonemes() - Mendapatkan timestamp tingkat fonem

Signature metode:
public List<Phoneme> getPhonemes()
Nilai kembalian: List objek Phoneme yang berisi informasi timestamp tingkat fonem. Bisa jadi kosong.

Informasi timestamp tingkat fonem (Phoneme)

Phoneme membungkus informasi timestamp tingkat fonem.

getBeginTime() - Mendapatkan waktu mulai fonem

Signature metode:
public int getBeginTime()
Nilai kembalian: Waktu mulai fonem dalam milidetik.

getEndTime() - Mendapatkan waktu akhir fonem

Signature metode:
public int getEndTime()
Nilai kembalian: Waktu akhir fonem dalam milidetik.

getText() - Mendapatkan teks

Signature metode:
public String getText()
Nilai kembalian: String, konten teks.

getTone() - Mendapatkan nada

Signature metode:
public int getTone()
Nilai kembalian: Nilai nada.
  • Dalam bahasa Inggris, 0, 1, dan 2 masing-masing merepresentasikan unstressed, primary stress, dan secondary stress.
  • Dalam pinyin Mandarin, 1, 2, 3, 4, dan 5 masing-masing merepresentasikan nada pertama, kedua, ketiga, keempat, dan netral.

Informasi output (output)

getOutput() mengembalikan JsonObject yang membungkus informasi output event sintesis. Ambil informasi ini dalam callback onEvent atau stream Flowable. Informasi ini berisi bidang-bidang berikut:
BidangTipeDeskripsi
typeStringTipe event. Nilai yang mungkin: sentence-begin (awal kalimat; mengembalikan teks yang akan disintesis), sentence-synthesis (sedang berlangsung sintesis audio; mengembalikan chunk data audio), sentence-end (akhir kalimat; mengembalikan konten teks dan timestamp tingkat kata).
original_textStringTeks asli kalimat saat ini. Dikembalikan dalam event sentence-begin dan sentence-end.
sentenceJsonObjectInformasi kalimat, berisi indeks kalimat (index) dan timestamp tingkat kata (words). Event sentence-end mencakup informasi timestamp tingkat kata lengkap.

Kode contoh

SDK mendukung mode sintesis berikut:
  • Non-streaming: Panggilan blocking yang mengirimkan seluruh teks sekaligus dan langsung mengembalikan audio lengkap. Paling cocok untuk sintesis suara teks pendek.
  • Unidirectional streaming: Panggilan non-blocking yang mengirimkan seluruh teks sekaligus dan mengirimkan data audio (mungkin dalam beberapa bagian) melalui fungsi callback. Paling cocok untuk skenario teks pendek yang memerlukan latensi rendah.
  • Bidirectional streaming: Panggilan non-blocking yang mengirimkan teks dalam beberapa segmen dan mengirimkan audio yang disintesis secara inkremental melalui fungsi callback secara real time. Paling cocok untuk skenario teks panjang yang memerlukan latensi rendah.
  • Panggilan non-streaming
  • Panggilan unidirectional streaming
  • Panggilan bidirectional streaming
Panjang teks per permintaan tidak boleh melebihi 20.000 karakter.
Inisialisasi ulang instans SpeechSynthesizer sebelum setiap pemanggilan metode call.
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.utils.Constants;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public class Main {
    // Model
    private static String model = "qwen-audio-3.0-tts-flash";
    // Voice
    private static String voice = "longanhuan_v3.6";

    public static void streamAudioDataToSpeaker() {
        // Parameter permintaan
        SpeechSynthesisParam param =
                SpeechSynthesisParam.builder()
                        // Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
                        // Jika variabel lingkungan belum dikonfigurasi, ganti baris berikut dengan Kunci API Studio Model Anda: .apiKey("sk-xxx")
                        .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                        .model(model) // Model
                        .voice(voice) // Voice
                        .build();

        // Mode sinkron: nonaktifkan callback (parameter kedua adalah null)
        SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);
        ByteBuffer audio = null;
        try {
            // Blokir hingga audio dikembalikan
            audio = synthesizer.call("What's the weather like today?");
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            // Tutup koneksi WebSocket setelah tugas selesai
            synthesizer.getDuplexApi().close(1000, "bye");
        }
        if (audio != null) {
            // Simpan data audio ke file lokal "output.mp3"
            File file = new File("output.mp3");
            // Transmisi teks pertama memerlukan pembentukan koneksi WebSocket, sehingga latensi paket pertama mencakup waktu pembentukan koneksi
            System.out.println(
                    "[Metric] requestId: "
                            + synthesizer.getLastRequestId()
                            + ", first packet latency (ms): "
                            + synthesizer.getFirstPackageDelay());
            try (FileOutputStream fos = new FileOutputStream(file)) {
                fos.write(audio.array());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) {
        // Konfigurasi berikut untuk wilayah Singapura. Ganti "{WorkspaceId}" dengan workspace ID Anda yang sebenarnya. Konfigurasi berbeda untuk setiap wilayah.
        Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference";
        streamAudioDataToSpeaker();
        System.exit(0);
    }
}

Panggilan berbasis Flowable

Flowable adalah tipe RxJava yang merepresentasikan stream reaktif yang mendukung backpressure. Untuk informasi lebih lanjut, lihat dokumentasi RxJava Flowable. Sebelum menggunakan Flowable, pastikan library RxJava telah diintegrasikan dan Anda memahami dasar-dasar pemrograman reaktif. Panjang teks per pemanggilan individu tidak boleh melebihi 20.000 karakter, dan panjang teks kumulatif dari semua pemanggilan tidak boleh melebihi 200.000 karakter.
  • Panggilan unidirectional streaming
  • Panggilan bidirectional streaming
Contoh berikut menunjukkan cara menggunakan antarmuka blockingForEach objek Flowable untuk mengambil setiap objek SpeechSynthesisResult yang distream secara blocking.
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.Constants;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

class TimeUtils {
    private static final DateTimeFormatter formatter =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

    public static String getTimestamp() {
        return LocalDateTime.now().format(formatter);
    }
}

public class Main {
    private static String model = "qwen-audio-3.0-tts-flash"; // Model
    private static String voice = "longanhuan_v3.6"; // Voice

    public static void streamAudioDataToSpeaker() throws NoApiKeyException {
        // Parameter permintaan
        SpeechSynthesisParam param =
                SpeechSynthesisParam.builder()
                        // Kunci API untuk wilayah Singapura dan Beijing berbeda. Dapatkan Kunci API: https://www.alibabacloud.com/help/en/model-studio/get-api-key
                        // Jika variabel lingkungan belum dikonfigurasi, ganti baris berikut dengan Kunci API Studio Model Anda: .apiKey("sk-xxx")
                        .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                        .model(model) // Model
                        .voice(voice) // Voice
                        .build();
        SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);
        synthesizer.callAsFlowable("What's the weather like today?").blockingForEach(result -> {
            if (result.getAudioFrame() != null) {
                // Implementasikan logika untuk memproses data audio di sini
                System.out.println(TimeUtils.getTimestamp() + " Audio received");
            }
            // Dapatkan informasi output, termasuk tipe event dan teks asli
            if (result.getOutput() != null && result.getOutput().has("type")) {
                System.out.println("Event type: " + result.getOutput().get("type").getAsString()
                        + ", Original text: " + (result.getOutput().has("original_text") ? result.getOutput().get("original_text").getAsString() : ""));
            }
        });
        // Tutup koneksi WebSocket setelah tugas selesai
        synthesizer.getDuplexApi().close(1000, "bye");
        // Transmisi teks pertama memerlukan pembentukan koneksi WebSocket, sehingga latensi paket pertama mencakup waktu pembentukan koneksi
        System.out.println(
                "[Metric] requestId: "
                        + synthesizer.getLastRequestId()
                        + ", first packet latency (ms): "
                        + synthesizer.getFirstPackageDelay());
    }

    public static void main(String[] args) throws NoApiKeyException {
        // Konfigurasi berikut untuk wilayah Singapura. Ganti "{WorkspaceId}" dengan workspace ID Anda yang sebenarnya. Konfigurasi berbeda untuk setiap wilayah.
        Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference";
        streamAudioDataToSpeaker();
        System.exit(0);
    }
}

Panggilan konkurensi tinggi

DashScope Java SDK menggunakan pooling koneksi OkHttp3 untuk mengurangi overhead pembentukan koneksi berulang. Untuk informasi lebih lanjut, lihat Praktik terbaik konkurensi tinggi.
Pembuatan Gambar
  • FAQ
Video Generation
Model Dunia
Audio
  • Pembuatan audio
Realtime API
Penyematan Teks
TokenPlan
Model production