Tous les produits
Search
Centre de documentation

Alibaba Cloud Model Studio:Référence de l'API de clonage vocal

Dernière mise à jour :Oct 11, 2026

Clonez une voix à partir de 10 à 20 secondes d'audio sans entraînement. Cette rubrique détaille les paramètres et l'utilisation de l'API de clonage vocal. Pour invoquer le modèle, consultez Qwen-Omni-Realtime ou Non-real-time (Qwen-Omni) .

ImportantCette rubrique s'applique uniquement à l'API de clonage vocal Qwen-Omni et Qwen-Omni-Realtime. Si vous utilisez un modèle de synthèse vocale, reportez-vous à la rubrique Synthèse vocale.

ImportantAlibaba Cloud Model Studio a publié des domaines spécifiques aux espaces de travail pour les régions Chine (Pékin) et Singapour. Ces nouveaux domaines dédiés offrent des performances supérieures et une stabilité accrue pour les requêtes d'inférence. Nous vous recommandons de migrer vers ces nouveaux domaines :

  • Chine (Pékin) : passez de https://dashscope.aliyuncs.com à https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com
  • Singapour : passez de https://dashscope-intl.aliyuncs.com à https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com

{WorkspaceId} correspond à votre ID d'espace de travail, disponible sur la page Workspace Details dans la console Alibaba Cloud Model Studio. Le domaine existant reste pleinement fonctionnel.

Exigences audio

Un fichier audio d'entrée de haute qualité garantit de meilleurs résultats de clonage.

Élément

Exigence

Formats pris en charge

WAV (16 bits), MP3, M4A

Durée

10 à 20 secondes recommandées. Maximum : 60 secondes.

Taille du fichier

< 10 Mo

Taux d'échantillonnage

>= 24 kHz

Canaux

Mono

Contenu

L'audio doit contenir au moins 3 secondes de parole continue et claire, sans bruit de fond. Le reste peut inclure de brèves pauses (<= 2 secondes). Évitez toute musique de fond, bruit parasite ou autre voix sur l'ensemble de l'enregistrement. Utilisez un audio parlé normal comme entrée. Ne téléchargez pas de chansons ni d'enregistrements chantés.

Langues

Chinois (zh), Anglais (en), Allemand (de), Italien (it), Portugais (pt), Espagnol (es), Japonais (ja), Coréen (ko), Français (fr), Russe (ru), Thaï (th), Indonésien (id), Arabe (ar), Tchèque (cs), Danois (da), Néerlandais (nl), Finnois (fi), Hébreu (he), Hindi (hi), Islandais (is), Malais (ms), Norvégien (no), Persan (fa), Polonais (pl), Suédois (sv), Tagalog (tl), Turc (tr), Ourdou (ur), Vietnamien (vi)

Dialectes chinois : Dongbei, Shannxi, Sichuan, Henan, Changsha, Tianjin, Hangzhou, Liaoning, Shenyang, Anshan

Prise en main rapide

image

1. Flux de travail

Le clonage vocal suit le principe « créer d'abord, utiliser ensuite » :

  1. Créer une voix

    Appelez l'API Créer une voix et chargez un extrait audio. Le système analyse l'audio et crée une voix clonée personnalisée. Vous devez spécifiertarget_modelà cette étape pour déclarer quel modèle omni pilotera la voix.

    Si vous possédez déjà une voix créée (appelez l'API Lister les voix pour vérifier), ignorez cette étape et passez à la suivante.

  2. Utiliser la voix dans une conversation

    Appelez l'API Omni (temps réel ou non temps réel) et transmettez la voix obtenue à l'étape précédente. Le modèle omni spécifié à cette étape doit correspondre autarget_modelde l'étape précédente.

2. Configuration du modèle et prérequis

Sélectionnez les modèles et remplissez les prérequis avant de commencer.

Configuration du modèle

Le clonage vocal nécessite deux modèles :

  • Modèle de clonage vocal : qwen-voice-enrollment

  • Modèle omni pilotant la voix :

    • qwen3.8-omni-flash-realtime
    • qwen3.8-omni-flash-realtime
    • qwen3.5-omni-plus-realtime
    • qwen3.5-omni-flash-realtime
    • qwen3.5-omni-plus
    • qwen3.5-omni-flash

Prérequis

  1. Obtenir une clé API : Obtenir une clé API. Pour des raisons de sécurité, configurez la clé API comme variable d'environnement.
  2. Installer le SDK : Assurez-vous d'avoir installé la dernière version du SDK DashScope.
  3. Préparer l'audio pour le clonage : L'audio doit respecter les Exigences audio.

3. Exemple de bout en bout

Cet exemple clone une voix et l'utilise dans une conversation.

Principe clé : Le target_model spécifié lors du clonage doit correspondre au modèle utilisé dans l'appel ultérieur à l'API Omni. Sinon, la synthèse échoue. Remplacez le fichier d'exemple voice.mp3 par votre propre fichier audio.

Realtime

Applicable aux modèles de la série Qwen3.5-Omni-Realtime. Pour plus d'informations, consultez Qwen-Omni-Realtime.

# Requirements: dashscope >= 1.23.9, pyaudio
import os
import requests
import base64
import pathlib
import time
import pyaudio
from dashscope.audio.qwen_omni import MultiModality, OmniRealtimeCallback, OmniRealtimeConversation
import dashscope
# China (Beijing) region. Replace {WorkspaceId} with your Bailian workspace ID. URLs vary by region.
dashscope.base_http_api_url = "https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1"

# ======= Configuration =======
DEFAULT_TARGET_MODEL = "qwen3.5-omni-plus-realtime"  # Must be the same model for cloning and conversation
DEFAULT_PREFERRED_NAME = "guanyu"
DEFAULT_AUDIO_MIME_TYPE = "audio/mpeg"
VOICE_FILE_PATH = "voice.mp3"  # Path to the local audio file for voice cloning

def create_voice(file_path: str,
                 target_model: str = DEFAULT_TARGET_MODEL,
                 preferred_name: str = DEFAULT_PREFERRED_NAME,
                 audio_mime_type: str = DEFAULT_AUDIO_MIME_TYPE) -> str:
    """
    Create a custom voice and return the voice parameter.
    """
    # API keys differ between the Singapore and Beijing regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
    # If you haven't set an environment variable, replace the following line with: api_key = "sk-xxx"
    api_key = os.getenv("DASHSCOPE_API_KEY")

    file_path_obj = pathlib.Path(file_path)
    if not file_path_obj.exists():
        raise FileNotFoundError(f"Audio file not found: {file_path}")

    base64_str = base64.b64encode(file_path_obj.read_bytes()).decode()
    data_uri = f"data:{audio_mime_type};base64,{base64_str}"

    # The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    url = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization"
    payload = {
        "model": "qwen-voice-enrollment",
        "input": {
            "action": "create",
            "target_model": target_model,
            "preferred_name": preferred_name,
            "audio": {"data": data_uri}
        }
    }
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }

    resp = requests.post(url, json=payload, headers=headers)
    if resp.status_code != 200:
        raise RuntimeError(f"Failed to create voice: {resp.status_code}, {resp.text}")

    try:
        return resp.json()["output"]["voice"]
    except (KeyError, ValueError) as e:
        raise RuntimeError(f"Failed to parse voice response: {e}")

class SimpleCallback(OmniRealtimeCallback):
    def __init__(self, pya):
        self.pya = pya
        self.out = None
    def on_open(self):
        self.out = self.pya.open(
            format=pyaudio.paInt16,
            channels=1,
            rate=24000,
            output=True
        )
    def on_event(self, response):
        if response['type'] == 'response.audio.delta':
            self.out.write(base64.b64decode(response['delta']))
        elif response['type'] == 'conversation.item.input_audio_transcription.completed':
            print(f"[User] {response['transcript']}")
        elif response['type'] == 'response.audio_transcript.done':
            print(f"[LLM] {response['transcript']}")

if __name__ == '__main__':
    # If you haven't set an environment variable, replace the following line with: dashscope.api_key = "sk-xxx"
    dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
    # The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    url = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtime"

    # Step 1: Clone a voice
    voice = create_voice(VOICE_FILE_PATH)
    print(f"Voice cloning complete. Voice: {voice}")

    # Step 2: Start a real-time conversation with the cloned voice
    pya = pyaudio.PyAudio()
    callback = SimpleCallback(pya)
    conv = OmniRealtimeConversation(model=DEFAULT_TARGET_MODEL, callback=callback, url=url)
    conv.connect()
    conv.update_session(
        output_modalities=[MultiModality.AUDIO, MultiModality.TEXT],
        voice=voice  # Use the cloned voice
    )
    mic = pya.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True)
    print("Conversation started. Speak into your microphone (Ctrl+C to exit)...")
    try:
        while True:
            audio_data = mic.read(3200, exception_on_overflow=False)
            conv.append_audio(base64.b64encode(audio_data).decode())
            time.sleep(0.01)
    except KeyboardInterrupt:
        conv.close()
        mic.close()
        callback.out.close()
        pya.terminate()
        print("\nConversation ended")
import com.alibaba.dashscope.audio.omni.*;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.Constants;
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import javax.sound.sampled.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

public class Main {
        // China (Beijing) region. Replace {WorkspaceId} with your Bailian workspace ID. URLs vary by region.
        Constants.baseHttpApiUrl = "https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1";
    // ===== Constants =====
    // Use the same model for voice cloning and real-time conversation
    private static final String TARGET_MODEL = "qwen3.5-omni-plus-realtime";
    private static final String PREFERRED_NAME = "guanyu";
    // Relative path to the local audio file for voice cloning
    private static final String AUDIO_FILE = "voice.mp3";
    private static final String AUDIO_MIME_TYPE = "audio/mpeg";

    // Generate a data URI
    public static String toDataUrl(String filePath) throws IOException {
        byte[] bytes = Files.readAllBytes(Paths.get(filePath));
        String encoded = Base64.getEncoder().encodeToString(bytes);
        return "data:" + AUDIO_MIME_TYPE + ";base64," + encoded;
    }

    // Call the API to create a voice
    public static String createVoice() throws Exception {
        // The API keys for the Singapore and Beijing regions are different. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
        // If you haven't configured the environment variable, replace the following line with: String apiKey = "sk-xxx"
        String apiKey = System.getenv("DASHSCOPE_API_KEY");

        String jsonPayload =
                "{"
                        + "\"model\": \"qwen-voice-enrollment\","
                        + "\"input\": {"
                        +     "\"action\": \"create\","
                        +     "\"target_model\": \"" + TARGET_MODEL + "\","
                        +     "\"preferred_name\": \"" + PREFERRED_NAME + "\","
                        +     "\"audio\": {"
                        +         "\"data\": \"" + toDataUrl(AUDIO_FILE) + "\""
                        +     "}"
                        + "}"
                        + "}";

        // The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
        String url = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization";
        HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("Authorization", "Bearer " + apiKey);
        con.setRequestProperty("Content-Type", "application/json");
        con.setDoOutput(true);

        try (OutputStream os = con.getOutputStream()) {
            os.write(jsonPayload.getBytes(StandardCharsets.UTF_8));
        }

        int status = con.getResponseCode();
        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(status >= 200 && status < 300 ? con.getInputStream() : con.getErrorStream(),
                        StandardCharsets.UTF_8))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                response.append(line);
            }
            if (status == 200) {
                JsonObject jsonObj = new Gson().fromJson(response.toString(), JsonObject.class);
                return jsonObj.getAsJsonObject("output").get("voice").getAsString();
            }
            throw new IOException("Failed to create voice: " + status + " - " + response);
        }
    }

    // Simple audio player
    static class SimpleAudioPlayer {
        private final SourceDataLine line;
        private final Queue<byte[]> audioQueue = new ConcurrentLinkedQueue<>();
        private final Thread playerThread;
        private final AtomicBoolean shouldStop = new AtomicBoolean(false);

        public SimpleAudioPlayer() throws LineUnavailableException {
            AudioFormat format = new AudioFormat(24000, 16, 1, true, false);
            line = AudioSystem.getSourceDataLine(format);
            line.open(format);
            line.start();
            playerThread = new Thread(() -> {
                while (!shouldStop.get()) {
                    byte[] audio = audioQueue.poll();
                    if (audio != null) {
                        line.write(audio, 0, audio.length);
                    } else {
                        try { Thread.sleep(10); } catch (InterruptedException ignored) {}
                    }
                }
            }, "AudioPlayer");
            playerThread.start();
        }

        public void play(String base64Audio) {
            audioQueue.add(Base64.getDecoder().decode(base64Audio));
        }

        public void close() {
            shouldStop.set(true);
            try { playerThread.join(1000); } catch (InterruptedException ignored) {}
            line.drain();
            line.close();
        }
    }

    public static void main(String[] args) {
        try {
            // 1. Voice cloning: create a custom voice
            String voice = createVoice();
            System.out.println("Voice cloning complete. Voice: " + voice);

            // 2. Use the cloned voice in a real-time conversation
            SimpleAudioPlayer player = new SimpleAudioPlayer();
            AtomicBoolean shouldStop = new AtomicBoolean(false);

            OmniRealtimeParam param = OmniRealtimeParam.builder()
                    .model(TARGET_MODEL)
                    // The API keys for the Singapore and Beijing regions are different. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
                    // If you haven't configured the environment variable, replace the following line with: .apikey("sk-xxx")
                    .apikey(System.getenv("DASHSCOPE_API_KEY"))
                    // The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
                    .url("wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtime")
                    .build();

            OmniRealtimeConversation conversation = new OmniRealtimeConversation(param, new OmniRealtimeCallback() {
                @Override public void onOpen() { System.out.println("Connection established"); }
                @Override public void onClose(int code, String reason) {
                    System.out.println("Connection closed (" + code + "): " + reason);
                    shouldStop.set(true);
                }
                @Override public void onEvent(JsonObject event) {
                    String type = event.get("type").getAsString();
                    if ("response.audio.delta".equals(type)) {
                        player.play(event.get("delta").getAsString());
                    } else if ("conversation.item.input_audio_transcription.completed".equals(type)) {
                        System.out.println("[User] " + event.get("transcript").getAsString());
                    } else if ("response.audio_transcript.done".equals(type)) {
                        System.out.println("[LLM] " + event.get("transcript").getAsString());
                    }
                }
            });

            conversation.connect();
            conversation.updateSession(OmniRealtimeConfig.builder()
                    .modalities(Arrays.asList(OmniRealtimeModality.AUDIO, OmniRealtimeModality.TEXT))
                    .voice(voice)  // Use the cloned custom voice
                    .enableTurnDetection(true)
                    .enableInputAudioTranscription(true)
                    .build()
            );

            System.out.println("Conversation started. Speak into the microphone (Ctrl+C to exit)...");
            AudioFormat format = new AudioFormat(16000, 16, 1, true, false);
            TargetDataLine mic = AudioSystem.getTargetDataLine(format);
            mic.open(format);
            mic.start();

            ByteBuffer buffer = ByteBuffer.allocate(3200);
            while (!shouldStop.get()) {
                int bytesRead = mic.read(buffer.array(), 0, buffer.capacity());
                if (bytesRead > 0) {
                    conversation.appendAudio(Base64.getEncoder().encodeToString(buffer.array()));
                }
                Thread.sleep(20);
            }

            conversation.close(1000, "Normal exit");
            player.close();
            mic.close();
            System.out.println("\nConversation ended");
        } catch (NoApiKeyException e) {
            System.err.println("API KEY not found. Set the DASHSCOPE_API_KEY environment variable.");
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.exit(0);
    }
}

Non-realtime

Applicable aux modèles de la série Qwen3.5-Omni. Pour plus d'informations, consultez Non-real-time (Qwen-Omni).

# Requirements: dashscope >= 1.23.9, soundfile, numpy
import os
import requests
import base64
import pathlib
import numpy as np
import soundfile as sf
import dashscope
# China (Beijing) region. Replace {WorkspaceId} with your Bailian workspace ID. URLs vary by region.
dashscope.base_http_api_url = "https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1"

# ======= Configuration =======
DEFAULT_TARGET_MODEL = "qwen3.5-omni-plus"  # Voice cloning and non-realtime calls must use the same model
DEFAULT_PREFERRED_NAME = "guanyu"
DEFAULT_AUDIO_MIME_TYPE = "audio/mpeg"
VOICE_FILE_PATH = "voice.mp3"  # Path to the local audio file for voice cloning

def create_voice(file_path: str,
                 target_model: str = DEFAULT_TARGET_MODEL,
                 preferred_name: str = DEFAULT_PREFERRED_NAME,
                 audio_mime_type: str = DEFAULT_AUDIO_MIME_TYPE) -> str:
    """
    Create a custom voice and return the voice parameter.
    """
    # API keys differ between Singapore and Beijing regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
    # If the environment variable is not configured, replace the following line with: api_key = "sk-xxx"
    api_key = os.getenv("DASHSCOPE_API_KEY")

    file_path_obj = pathlib.Path(file_path)
    if not file_path_obj.exists():
        raise FileNotFoundError(f"Audio file not found: {file_path}")

    base64_str = base64.b64encode(file_path_obj.read_bytes()).decode()
    data_uri = f"data:{audio_mime_type};base64,{base64_str}"

    # The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    url = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization"
    payload = {
        "model": "qwen-voice-enrollment",
        "input": {
            "action": "create",
            "target_model": target_model,
            "preferred_name": preferred_name,
            "audio": {"data": data_uri}
        }
    }
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }

    resp = requests.post(url, json=payload, headers=headers)
    if resp.status_code != 200:
        raise RuntimeError(f"Failed to create voice: {resp.status_code}, {resp.text}")

    try:
        return resp.json()["output"]["voice"]
    except (KeyError, ValueError) as e:
        raise RuntimeError(f"Failed to parse voice response: {e}")

if __name__ == '__main__':
    # The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    dashscope.base_http_api_url = 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1'

    # 1. Voice cloning: create a custom voice
    voice = create_voice(VOICE_FILE_PATH)
    print(f"Voice cloning complete. Voice: {voice}")

    # 2. Non-realtime conversation with the cloned voice
    messages = [{"role": "user", "content": [{"text": "Hello, please introduce yourself"}]}]

    response = dashscope.MultiModalConversation.call(
        # If the environment variable is not configured, replace with: api_key="sk-xxx"
        api_key=os.getenv("DASHSCOPE_API_KEY"),
        model=DEFAULT_TARGET_MODEL,
        messages=messages,
        modalities=["text", "audio"],
        audio={"voice": voice, "format": "wav"},  # Use the cloned voice
        stream=True
    )

    print("Model response:")
    audio_base64_string = ""
    for r in response:
        try:
            content = r.output.choices[0].message.content
            for item in content:
                if isinstance(item, dict):
                    if "audio" in item:
                        audio_base64_string += item["audio"].get("data", "")
                    elif "text" in item:
                        print(item["text"], end="")
        except Exception:
            pass

    if audio_base64_string:
        wav_bytes = base64.b64decode(audio_base64_string)
        audio_np = np.frombuffer(wav_bytes, dtype=np.int16)
        sf.write("audio_cloned.wav", audio_np, samplerate=24000)
        print("\nAudio saved to: audio_cloned.wav")
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Main {
    // ===== Constants =====
    // Voice cloning and non-realtime calls must use the same model
    private static final String TARGET_MODEL = "qwen3.5-omni-plus";
    private static final String PREFERRED_NAME = "guanyu";
    // Path to the local audio file for voice cloning
    private static final String AUDIO_FILE = "voice.mp3";
    private static final String AUDIO_MIME_TYPE = "audio/mpeg";

    // Write PCM data as a standard WAV file
    public static void writeWav(String path, byte[] pcmData, int sampleRate) throws IOException {
        int channels = 1, bitsPerSample = 16;
        int byteRate = sampleRate * channels * bitsPerSample / 8;
        int blockAlign = channels * bitsPerSample / 8;
        ByteBuffer header = ByteBuffer.allocate(44).order(ByteOrder.LITTLE_ENDIAN);
        header.put("RIFF".getBytes()); header.putInt(36 + pcmData.length);
        header.put("WAVE".getBytes()); header.put("fmt ".getBytes());
        header.putInt(16); header.putShort((short) 1); header.putShort((short) channels);
        header.putInt(sampleRate); header.putInt(byteRate);
        header.putShort((short) blockAlign); header.putShort((short) bitsPerSample);
        header.put("data".getBytes()); header.putInt(pcmData.length);
        try (FileOutputStream fos = new FileOutputStream(path)) {
            fos.write(header.array());
            fos.write(pcmData);
        }
    }

    // Generate a data URI from a file
    public static String toDataUrl(String filePath) throws IOException {
        byte[] bytes = Files.readAllBytes(Paths.get(filePath));
        String encoded = Base64.getEncoder().encodeToString(bytes);
        return "data:" + AUDIO_MIME_TYPE + ";base64," + encoded;
    }

    // Call the API to create a voice
    public static String createVoice() throws Exception {
        // API keys differ between Singapore and Beijing regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
        // If the environment variable is not configured, replace the following line with: String apiKey = "sk-xxx"
        String apiKey = System.getenv("DASHSCOPE_API_KEY");

        String jsonPayload =
                "{"
                        + "\"model\": \"qwen-voice-enrollment\","
                        + "\"input\": {"
                        +     "\"action\": \"create\","
                        +     "\"target_model\": \"" + TARGET_MODEL + "\","
                        +     "\"preferred_name\": \"" + PREFERRED_NAME + "\","
                        +     "\"audio\": {"
                        +         "\"data\": \"" + toDataUrl(AUDIO_FILE) + "\""
                        +     "}"
                        + "}"
                        + "}";

        // The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
        String url = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization";
        HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("Authorization", "Bearer " + apiKey);
        con.setRequestProperty("Content-Type", "application/json");
        con.setDoOutput(true);

        try (OutputStream os = con.getOutputStream()) {
            os.write(jsonPayload.getBytes(StandardCharsets.UTF_8));
        }

        int status = con.getResponseCode();
        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(status >= 200 && status < 300 ? con.getInputStream() : con.getErrorStream(),
                        StandardCharsets.UTF_8))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                response.append(line);
            }
            if (status == 200) {
                JsonObject jsonObj = new Gson().fromJson(response.toString(), JsonObject.class);
                return jsonObj.getAsJsonObject("output").get("voice").getAsString();
            }
            throw new IOException("Failed to create voice: " + status + " - " + response);
        }
    }

    public static void main(String[] args) {
        try {
            // API keys differ between Singapore and Beijing regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
            // If the environment variable is not configured, replace the following line with: String apiKey = "sk-xxx"
            String apiKey = System.getenv("DASHSCOPE_API_KEY");

            // 1. Voice cloning: create a custom voice
            String voice = createVoice();
            System.out.println("Voice cloning complete. Voice: " + voice);

            // 2. Non-realtime conversation with the cloned voice (OpenAI-compatible API)
            String requestBody = "{"
                    + "\"model\": \"" + TARGET_MODEL + "\","
                    + "\"messages\": [{\"role\": \"user\", \"content\": \"Hello, please introduce yourself\"}],"
                    + "\"modalities\": [\"text\", \"audio\"],"
                    + "\"audio\": {\"voice\": \"" + voice + "\", \"format\": \"wav\"},"
                    + "\"stream\": true,"
                    + "\"stream_options\": {\"include_usage\": true}"
                    + "}";

            // The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
            String url = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1/chat/completions";
            HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
            con.setRequestMethod("POST");
            con.setRequestProperty("Authorization", "Bearer " + apiKey);
            con.setRequestProperty("Content-Type", "application/json");
            con.setDoOutput(true);

            try (OutputStream os = con.getOutputStream()) {
                os.write(requestBody.getBytes(StandardCharsets.UTF_8));
            }

            // 3. Parse streaming SSE response
            StringBuilder audioBase64 = new StringBuilder();
            System.out.println("Model response:");

            try (BufferedReader br = new BufferedReader(
                    new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8))) {
                String line;
                while ((line = br.readLine()) != null) {
                    if (!line.startsWith("data: ") || line.equals("data: [DONE]")) continue;
                    String json = line.substring(6);
                    JsonObject chunk = new Gson().fromJson(json, JsonObject.class);
                    if (!chunk.has("choices") || chunk.getAsJsonArray("choices").size() == 0) continue;

                    JsonObject delta = chunk.getAsJsonArray("choices").get(0)
                            .getAsJsonObject().getAsJsonObject("delta");
                    if (delta.has("content") && !delta.get("content").isJsonNull()) {
                        System.out.print(delta.get("content").getAsString());
                    }
                    if (delta.has("audio") && !delta.get("audio").isJsonNull()) {
                        JsonObject audio = delta.getAsJsonObject("audio");
                        if (audio.has("data")) {
                            audioBase64.append(audio.get("data").getAsString());
                        }
                    }
                }
            }

            // 4. Save audio file (API returns raw PCM data, WAV header required)
            if (audioBase64.length() > 0) {
                byte[] pcmBytes = Base64.getDecoder().decode(audioBase64.toString());
                writeWav("audio_cloned.wav", pcmBytes, 24000);
                System.out.println("\nAudio saved to: audio_cloned.wav");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Référence de l'API

Utilisez le même compte pour toutes les API.

Créer une voix

Chargez un fichier audio pour le clonage et créez une voix personnalisée.

  • URL

    Chine du Nord 2 (Pékin) :

    POST https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1/services/audio/tts/customization
    

    Singapour :

    POST https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization
    
  • En-têtes de requête

    Parameter

    Type

    Required

    Description

    Authorization

    string

    Supported

    Jeton d'authentification au format Bearer <your_api_key>. Remplacez <your_api_key> par votre véritable clé API.

    Content-Type

    string

    Supported

    Type MIME du corps de la requête. Définissez-le sur application/json.

  • Corps de la requête Le corps de la requête contient tous les paramètres. Omettez les champs facultatifs selon vos besoins. Notez la distinction entre :

    Importantmodel : Modèle de clonage vocal. Définissez-le sur qwen-voice-enrollment.

    target_model : Modèle omni pilotant la voix. Il doit correspondre au modèle utilisé dans l'appel ultérieur à l'API multimodale temps réel. Sinon, la synthèse échoue.

    {
        "model": "qwen-voice-enrollment",
        "input": {
            "action": "create",
            "target_model": "qwen3.5-omni-plus-realtime",
            "preferred_name": "guanyu",
            "audio": {
                "data": "https://xxx.wav"
            },
            "text": "Optional. The transcript of the audio in audio.data.",
            "language": "Optional. The language of the audio in audio.data, such as zh."
        },
        "parameters": {
            "voice_clone_mode": "normal",
            "skip_audio_process": false
        }
    }
    
  • Paramètres de la requête
    ParameterTypeDefaultRequiredDescription

    model

    string

    Supported

    Modèle de clonage vocal. Définissez-le sur qwen-voice-enrollment.

    action

    string

    Supported

    Type d'action. Définissez-le sur create.

    target_model

    string

    Supported

    Modèle omni pilotant la voix :

    • qwen3.8-omni-flash-realtime
    • qwen3.5-omni-plus-realtime
    • qwen3.5-omni-flash-realtime
    • qwen3.5-omni-plus
    • qwen3.5-omni-flash

    Il doit correspondre au modèle omni utilisé dans l'appel API ultérieur. Sinon, la synthèse échoue.

    preferred_name

    string

    Supported

    Nom lisible par l'homme pour la voix. Caractères autorisés : chiffres, lettres, traits de soulignement. Maximum : 16 caractères.

    Ce mot-clé apparaît dans le nom final de la voix. Par exemple, si le mot-clé est « guanyu », le nom de voix résultant sera « qwen-omni-vc-guanyu-voice-20250812105009984-838b ».

    audio.data

    string

    Supported

    Audio à cloner (suivez le Guide d'enregistrement lors de la prise de son, et assurez-vous que l'audio respecte les Exigences audio).

    Soumettez les données audio de l'une des manières suivantes :

    1. Data URL

      Format : data:<mediatype>;base64,<data>

      • <mediatype> : Type MIME

        • WAV : audio/wav
        • MP3 : audio/mpeg
        • M4A : audio/mp4
      • <data> : Chaîne encodée en Base64 de l'audio

        L'encodage Base64 augmente la taille du fichier. Maintenez le résultat encodé sous 10 Mo.

      • Exemple : data:audio/wav;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjI5LjEwMAAAAAAAAAAAAAAA//PAxABQ/BXRbMPe4IQAhl9

        Voir l'exemple de code

        import base64, pathlib
        
        # input.mp3 is the local audio file for voice cloning. Replace with your own file path. Make sure the file meets the audio requirements.
        file_path = pathlib.Path("input.mp3")
        base64_str = base64.b64encode(file_path.read_bytes()).decode()
        data_uri = f"data:audio/mpeg;base64,{base64_str}"
        
        import java.nio.file.*;
            import java.util.Base64;
        
            public class Main {
                /**
                 * filePath is the local audio file for voice cloning. Replace with your own file path. Make sure the file meets the audio requirements.
                 */
                public static String toDataUrl(String filePath) throws Exception {
                    byte[] bytes = Files.readAllBytes(Paths.get(filePath));
                    String encoded = Base64.getEncoder().encodeToString(bytes);
                    return "data:audio/mpeg;base64," + encoded;
                }
        
                // Usage example
                public static void main(String[] args) throws Exception {
                    System.out.println(toDataUrl("input.mp3"));
                }
            }
        
    2. URL audio (nous recommandons de charger votre audio sur OSS)

      • La taille du fichier ne doit pas dépasser 10 Mo.
      • L'URL doit être accessible publiquement sans authentification.

    text

    string

    Unsupported

    Transcription correspondant à l'audio dans audio.data.

    Lorsqu'elle est fournie, le serveur valide l'audio par rapport au texte. Si l'écart est trop important, une erreur Audio.PreprocessError est renvoyée.

    language

    string

    Unsupported

    Langue de l'audio dans audio.data.

    Valeurs prises en charge : zh (Chinois), en (Anglais), de (Allemand), it (Italien), pt (Portugais), es (Espagnol), ja (Japonais), ko (Coréen), fr (Français), ru (Russe), th (Thaï), id (Indonésien), ar (Arabe), cs (Tchèque), da (Danois), nl (Néerlandais), fi (Finnois), he (Hébreu), hi (Hindi), is (Islandais), ms (Malais), no (Norvégien), fa (Persan), pl (Polonais), sv (Suédois), tl (Tagalog), tr (Turc), ur (Ourdou), vi (Vietnamien).

    Dialectes chinois : Dongbei, Shannxi, Sichuan, Henan, Changsha, Tianjin, Hangzhou, Liaoning, Shenyang, Anshan.

    Définissez cette valeur sur la langue réelle de l'audio utilisé pour le clonage.

  • Paramètres de réponse

    Voir l'exemple de réponse

    {
        "output": {
            "voice": "yourVoice",
            "target_model": "qwen3.5-omni-plus-realtime"
        },
        "usage": {
            "count": 1
        },
        "request_id": "yourRequestId"
    }
    

    Paramètres de réponse clés :

    ParameterTypeDescription

    voice

    string

    Nom de la voix. Utilisez directement cette valeur comme paramètre voice dans l'API multimodale temps réel.

    target_model

    string

    Modèle omni pilotant la voix :

    • qwen3.5-omni-plus-realtime
    • qwen3.5-omni-flash-realtime

    Il doit correspondre au modèle utilisé dans l'appel ultérieur à l'API multimodale temps réel. Sinon, la synthèse échoue.

    request_id

    string

    ID de la requête.

    count

    integer

    Nombre d'opérations « créer une voix » facturées pour cette requête. Le coût est de $ count \times 0.01.

    Lors de la création d'une voix, count est toujours égal à 1.

  • Exemple de code

    Importantmodel : Modèle de clonage vocal. Définissez-le sur qwen-voice-enrollment.

    target_model : Modèle omni pilotant la voix. Il doit correspondre au modèle utilisé dans l'appel ultérieur à l'API multimodale temps réel. Sinon, la synthèse échoue.

    curl

    Si vous n'avez pas défini la clé API comme variable d'environnement, remplacez $DASHSCOPE_API_KEY dans l'exemple par votre véritable clé API.

    # ======= Important =======
    # The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    # API keys differ between regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
    # === Remove these comments before running ===
    
    curl --location --request POST 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization' \
    --header "Authorization: Bearer $DASHSCOPE_API_KEY" \
    --header 'Content-Type: application/json' \
    --data '{
        "model": "qwen-voice-enrollment",
        "parameters": {"voice_clone_mode": "normal"},
        "input": {
            "action": "create",
            "target_model": "qwen3.8-omni-flash-realtime",
            "preferred_name": "guanyu",
            "audio": {"data": "https://xxx.wav"}
        }
    }'
    

    python

    import os
    import requests
    import base64, pathlib
    
    target_model = "qwen3.8-omni-flash-realtime"
    preferred_name = "guanyu"
    audio_mime_type = "audio/mpeg"
    
    file_path = pathlib.Path("input.mp3")
    base64_str = base64.b64encode(file_path.read_bytes()).decode()
    data_uri = f"data:{audio_mime_type};base64,{base64_str}"
    
    # API keys differ between regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
    # If you haven't set an environment variable, replace the following line with: api_key = "sk-xxx"
    api_key = os.getenv("DASHSCOPE_API_KEY")
    # The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    url = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization"
    
    payload = {
        "model": "qwen-voice-enrollment", # Do not modify
        "parameters": {"voice_clone_mode": "normal"},
        "input": {
            "action": "create",
            "target_model": target_model,
            "preferred_name": preferred_name,
            "audio": {
                "data": data_uri
            }
        }
    }
    
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    
    # Envoyer la requête POST
    resp = requests.post(url, json=payload, headers=headers)
    
    if resp.status_code == 200:
        data = resp.json()
        voice = data["output"]["voice"]
        print(f"Voix créée : {voice}")
    else:
        print("Échec de la requête :", resp.status_code, resp.text)
    

    java

    import com.google.gson.Gson;
    import com.google.gson.JsonArray;
    import com.google.gson.JsonObject;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class Main {
        public static void main(String[] args) {
            // API keys differ between regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
            // If you haven't set an environment variable, replace the following line with: String apiKey = "sk-xxx"
            String apiKey = System.getenv("DASHSCOPE_API_KEY");
            // The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
            String apiUrl = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization";
    
            // JSON request body
            String jsonPayload =
                    "{"
                            + "\"model\": \"qwen-voice-enrollment\"," // Do not modify
                            + "\"input\": {"
                            +     "\"action\": \"list\","
                            +     "\"page_size\": 10,"
                            +     "\"page_index\": 0"
                            + "}"
                            + "}";
    
            try {
                HttpURLConnection con = (HttpURLConnection) new URL(apiUrl).openConnection();
                con.setRequestMethod("POST");
                con.setRequestProperty("Authorization", "Bearer " + apiKey);
                con.setRequestProperty("Content-Type", "application/json");
                con.setDoOutput(true);
    
                try (OutputStream os = con.getOutputStream()) {
                    os.write(jsonPayload.getBytes("UTF-8"));
                }
    
                int status = con.getResponseCode();
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        status >= 200 && status < 300 ? con.getInputStream() : con.getErrorStream(), "UTF-8"));
    
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) {
                    response.append(line);
                }
                br.close();
    
                System.out.println("HTTP status: " + status);
                System.out.println("Response JSON: " + response.toString());
    
                if (status == 200) {
                    Gson gson = new Gson();
                    JsonObject jsonObj = gson.fromJson(response.toString(), JsonObject.class);
                    JsonArray voiceList = jsonObj.getAsJsonObject("output").getAsJsonArray("voice_list");
    
                    System.out.println("\n Voice list:");
                    for (int i = 0; i < voiceList.size(); i++) {
                        JsonObject voiceItem = voiceList.get(i).getAsJsonObject();
                        String voice = voiceItem.get("voice").getAsString();
                        String gmtCreate = voiceItem.get("gmt_create").getAsString();
                        String targetModel = voiceItem.get("target_model").getAsString();
    
                        System.out.printf("- Voice: %s  Created: %s  Model: %s\n",
                                voice, gmtCreate, targetModel);
                    }
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

Lister les voix

Interrogez vos voix créées avec pagination.

  • URL

    Chine du Nord 2 (Pékin) :

    POST https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1/services/audio/tts/customization
    

    Singapour :

    POST https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization
    
  • En-têtes de requête

    Parameter

    Type

    Required

    Description

    Authorization

    string

    Supported

    Jeton d'authentification au format Bearer <your_api_key>. Remplacez <your_api_key> par votre véritable clé API.

    Content-Type

    string

    Supported

    Type MIME du corps de la requête. Définissez-le sur application/json.

  • Paramètres de la requête

    Parameter

    Type

    Default

    Required

    Description

    model

    string

    -

    Supported

    Modèle de clonage vocal. Définissez-le sur qwen-voice-enrollment.

    action

    string

    -

    Supported

    Type d'action. Définissez-le sur list.

    page_index

    integer

    0

    Unsupported

    Index de numéro de page. Valeurs valides : 0 à 1 000 000.

    page_size

    integer

    10

    Unsupported

    Nombre d'éléments par page. Valeurs valides : 0 à 1 000 000.

  • Paramètres de réponse

    Voir l'exemple de réponse

    {
        "output": {
            "voice_list": [
                {
                    "voice": "yourVoice1",
                    "gmt_create": "2025-08-11 17:59:32",
                    "target_model": "qwen3.5-omni-plus-realtime"
                },
                {
                    "voice": "yourVoice2",
                    "gmt_create": "2025-08-11 17:38:10",
                    "target_model": "qwen3.5-omni-plus-realtime"
                }
            ]
        },
        "usage": {
            "count": 0
        },
        "request_id": "yourRequestId"
    }
    

    Paramètres de réponse clés :

    ParameterTypeDescription

    voice

    string

    Nom de la voix. Utilisez directement cette valeur dans le paramètre voice de l'API multimodale temps réel.

    gmt_create

    string

    Heure de création de la voix.

    target_model

    string

    Modèle omni pilotant la voix :

    • qwen3.8-omni-flash-realtime
    • qwen3.5-omni-plus-realtime
    • qwen3.5-omni-flash-realtime
    • qwen3.5-omni-plus
    • qwen3.5-omni-flash

    Il doit correspondre au modèle omni utilisé dans l'appel API ultérieur. Sinon, la synthèse échoue.

    request_id

    string

    ID de la requête.

    count

    integer

    Cette requête est facturée en fonction du nombre réel d'opérations « Créer une voix ». Le coût de cette requête est de $ count \times 0.01 .

    Le listage des voix est gratuit. count est toujours égal à 0.

  • Exemple de code

    Importantmodel : Modèle de clonage vocal. La valeur est fixée à qwen-voice-enrollment. Ne modifiez pas cette valeur.

    cURL

    Si vous n'avez pas défini la clé API comme variable d'environnement, remplacez $DASHSCOPE_API_KEY dans l'exemple par votre véritable clé API.

    # ======= Important =======
    # The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    # API keys differ between regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
    # === Remove these comments before running ===
    
    curl --location --request POST 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization' \
    --header "Authorization: Bearer $DASHSCOPE_API_KEY" \
    --header 'Content-Type: application/json' \
    --data '{
        "model": "qwen-voice-enrollment",
        "input": {
            "action": "list",
            "page_size": 10,
            "page_index": 0
        }
    }'
    

    Python

    import os
    import requests
    
    # API keys differ between regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
    # If you haven't set an environment variable, replace the following line with: api_key = "sk-xxx"
    api_key = os.getenv("DASHSCOPE_API_KEY")
    # The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    url = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization"
    
    payload = {
        "model": "qwen-voice-enrollment", # Do not modify
        "input": {
            "action": "list",
            "page_size": 10,
            "page_index": 0
        }
    }
    
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    
    response = requests.post(url, json=payload, headers=headers)
    
    print("HTTP status:", response.status_code)
    
    if response.status_code == 200:
        data = response.json()
        voice_list = data["output"]["voice_list"]
    
        print("Voice list:")
        for item in voice_list:
            print(f"- Voice: {item['voice']}  Created: {item['gmt_create']}  Model: {item['target_model']}")
    else:
        print("Request failed:", response.text)
    

    Java

    import com.google.gson.Gson;
    import com.google.gson.JsonArray;
    import com.google.gson.JsonObject;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class Main {
        public static void main(String[] args) {
            // API keys differ between regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
            // If you haven't set an environment variable, replace the following line with: String apiKey = "sk-xxx"
            String apiKey = System.getenv("DASHSCOPE_API_KEY");
            // The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
            String apiUrl = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization";
    
            // JSON request body
            String jsonPayload =
                    "{"
                            + "\"model\": \"qwen-voice-enrollment\"," // Do not modify
                            + "\"input\": {"
                            +     "\"action\": \"list\","
                            +     "\"page_size\": 10,"
                            +     "\"page_index\": 0"
                            + "}"
                            + "}";
    
            try {
                HttpURLConnection con = (HttpURLConnection) new URL(apiUrl).openConnection();
                con.setRequestMethod("POST");
                con.setRequestProperty("Authorization", "Bearer " + apiKey);
                con.setRequestProperty("Content-Type", "application/json");
                con.setDoOutput(true);
    
                try (OutputStream os = con.getOutputStream()) {
                    os.write(jsonPayload.getBytes("UTF-8"));
                }
    
                int status = con.getResponseCode();
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        status >= 200 && status < 300 ? con.getInputStream() : con.getErrorStream(), "UTF-8"));
    
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) {
                    response.append(line);
                }
                br.close();
    
                System.out.println("HTTP status: " + status);
                System.out.println("Response JSON: " + response.toString());
    
                if (status == 200) {
                    Gson gson = new Gson();
                    JsonObject jsonObj = gson.fromJson(response.toString(), JsonObject.class);
                    JsonArray voiceList = jsonObj.getAsJsonObject("output").getAsJsonArray("voice_list");
    
                    System.out.println("\n Voice list:");
                    for (int i = 0; i < voiceList.size(); i++) {
                        JsonObject voiceItem = voiceList.get(i).getAsJsonObject();
                        String voice = voiceItem.get("voice").getAsString();
                        String gmtCreate = voiceItem.get("gmt_create").getAsString();
                        String targetModel = voiceItem.get("target_model").getAsString();
    
                        System.out.printf("- Voice: %s  Created: %s  Model: %s\n",
                                voice, gmtCreate, targetModel);
                    }
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

Supprimer une voix

Supprimez une voix spécifique et libérez le quota correspondant.

  • URL

    Chine du Nord 2 (Pékin) :

    POST https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1/services/audio/tts/customization
    

    Singapour :

    POST https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization
    
  • En-têtes de requête

    Parameter

    Type

    Required

    Description

    Authorization

    string

    Supported

    Jeton d'authentification au format Bearer <your_api_key>. Remplacez <your_api_key> par votre véritable clé API.

    Content-Type

    string

    Supported

    Type MIME du corps de la requête. Définissez-le sur application/json.

  • Corps de la requête

    Omettez les champs facultatifs selon vos besoins.

    Importantmodel : Modèle de clonage vocal. La valeur est fixée à qwen-voice-enrollment. Ne modifiez pas cette valeur.

    {
        "model": "qwen-voice-enrollment",
        "input": {
            "action": "delete",
            "voice": "yourVoice"
        }
    }
    
  • Paramètres de la requête

    Parameter

    Type

    Default

    Required

    Description

    model

    string

    -

    Supported

    Modèle de clonage vocal. Définissez-le sur qwen-voice-enrollment.

    action

    string

    -

    Supported

    Type d'action. Définissez-le sur delete.

    voice

    string

    -

    Supported

    Voix à supprimer.

  • Paramètres de réponse

    Voir l'exemple de réponse

    {
        "usage": {
            "count": 0
        },
        "request_id": "yourRequestId"
    }
    

    Paramètres de réponse clés :

    Parameter

    Type

    Description

    request_id

    string

    ID de la requête.

    count

    integer

    Cette requête est facturée en fonction du nombre réel d'opérations « Créer une voix ». Le coût de cette requête est de $ count \times 0.01 .

    La suppression d'une voix est gratuite. count est toujours égal à 0.

  • Exemple de code

    Importantmodel : Modèle de clonage vocal. La valeur est fixée à qwen-voice-enrollment. Ne modifiez pas cette valeur.

    cURL

    Si vous n'avez pas défini la clé API comme variable d'environnement, remplacez $DASHSCOPE_API_KEY dans l'exemple par votre véritable clé API.

    # ======= Important =======
    # The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    # API keys differ between regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
    # === Remove these comments before running ===
    
    curl --location --request POST 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization' \
    --header "Authorization: Bearer $DASHSCOPE_API_KEY" \
    --header 'Content-Type: application/json' \
    --data '{
        "model": "qwen-voice-enrollment",
        "input": {
            "action": "delete",
            "voice": "yourVoice"
        }
    }'
    

    Python

    import os
    import requests
    
    # API keys differ between regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
    # If you haven't set an environment variable, replace the following line with: api_key = "sk-xxx"
    api_key = os.getenv("DASHSCOPE_API_KEY")
    # The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    url = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization"
    
    voice_to_delete = "yourVoice"  # Replace with the actual voice name
    
    payload = {
        "model": "qwen-voice-enrollment", # Do not modify
        "input": {
            "action": "delete",
            "voice": voice_to_delete
        }
    }
    
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    
    response = requests.post(url, json=payload, headers=headers)
    
    print("HTTP status:", response.status_code)
    
    if response.status_code == 200:
        data = response.json()
        request_id = data["request_id"]
    
        print(f"Deleted successfully")
        print(f"Request ID: {request_id}")
    else:
        print("Request failed:", response.text)
    

    Java

    import com.google.gson.Gson;
    import com.google.gson.JsonObject;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class Main {
        public static void main(String[] args) {
            // API keys differ between regions. Get an API key: https://www.alibabacloud.com/help/en/model-studio/get-api-key
            // If you haven't set an environment variable, replace the following line with: String apiKey = "sk-xxx"
            String apiKey = System.getenv("DASHSCOPE_API_KEY");
            // The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
            String apiUrl = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization";
            String voiceToDelete = "yourVoice"; // Replace with the actual voice name
    
            // Build JSON request body
            String jsonPayload =
                    "{"
                            + "\"model\": \"qwen-voice-enrollment\"," // Do not modify
                            + "\"input\": {"
                            +     "\"action\": \"delete\","
                            +     "\"voice\": \"" + voiceToDelete + "\""
                            + "}"
                            + "}";
    
            try {
                // Create POST connection
                HttpURLConnection con = (HttpURLConnection) new URL(apiUrl).openConnection();
                con.setRequestMethod("POST");
                con.setRequestProperty("Authorization", "Bearer " + apiKey);
                con.setRequestProperty("Content-Type", "application/json");
                con.setDoOutput(true);
    
                // Send request body
                try (OutputStream os = con.getOutputStream()) {
                    os.write(jsonPayload.getBytes("UTF-8"));
                }
    
                int status = con.getResponseCode();
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        status >= 200 && status < 300 ? con.getInputStream() : con.getErrorStream(), "UTF-8"));
    
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) {
                    response.append(line);
                }
                br.close();
    
                System.out.println("HTTP status: " + status);
                System.out.println("Response JSON: " + response.toString());
    
                if (status == 200) {
                    Gson gson = new Gson();
                    JsonObject jsonObj = gson.fromJson(response.toString(), JsonObject.class);
                    String requestId = jsonObj.get("request_id").getAsString();
    
                    System.out.println("Deleted successfully");
                    System.out.println("Request ID: " + requestId);
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

Utilisation dans une conversation

Pour utiliser une voix clonée dans une conversation, consultez la section Prise en main rapide.

Quota de voix et nettoyage automatique

Limite totale : 1 000 voix par compte.

Aucun endpoint dédié au comptage n'existe. Appelez l'API Lister les voix pour compter vos voix.

Nettoyage automatique : Les voix inutilisées pendant un an sont automatiquement supprimées.

Facturation

Le clonage vocal et l'invocation du modèle sont facturés séparément :

  • Clonage vocal : facturé à 0,01 $/voix. Les créations échouées ne sont pas facturées.

    RemarqueQuota gratuit (uniquement pour la région Pékin du site Chine et la région Singapour du site International) :

    • 1 000 créations de voix gratuites dans les 90 jours suivant l'activation de Model Studio.
    • Les créations échouées ne consomment pas le quota gratuit.
    • La suppression d'une voix ne restaure pas le quota gratuit.
    • Une fois le quota gratuit épuisé ou la période de 90 jours expirée, la création de voix est facturée à 0,01 $/voix.
  • Conversation avec une voix clonée : Facturée selon l'utilisation des tokens pour l'invocation du modèle. Pour plus de détails, consultez Tarification de l'inférence de modèle.

Droits d'auteur et conformité légale

Vous êtes responsable de la propriété et de l'utilisation légale de la voix que vous fournissez. Lisez l'Accord de service.

Guide d'enregistrement

Matériel d'enregistrement

Utilisez un microphone à réduction de bruit, ou enregistrez avec un téléphone à courte distance dans un environnement calme.

Environnement d'enregistrement

Emplacement

  • Enregistrez dans un petit espace clos de 10 mètres carrés ou moins.
  • Choisissez une pièce dotée de matériaux absorbants tels que de la mousse acoustique, des tapis ou des rideaux.
  • Évitez les grands halls ouverts, les salles de conférence ou les classes où la réverbération est importante.

Contrôle du bruit

  • Bruit extérieur : Fermez les portes et les fenêtres pour bloquer le trafic, les travaux et autres sons externes.
  • Bruit intérieur : Éteignez les climatiseurs, les ventilateurs et les ballasts de lampes fluorescentes.
  • Enregistrez le son ambiant avec votre téléphone et écoutez-le à volume élevé pour identifier les sources de bruit cachées.

Contrôle de la réverbération

  • La réverbération rend l'audio étouffé et réduit la clarté.
  • Réduisez les réflexions sur les surfaces lisses : fermez les rideaux, ouvrez les portes de placard et couvrez les bureaux et étagères avec des vêtements ou des couvertures.
  • Utilisez des objets irréguliers tels que des bibliothèques et des meubles rembourrés pour créer des réflexions diffuses.

Préparation du script

  • Adaptez le script au cas d'utilisation cible. Par exemple, utilisez un style de dialogue de service client pour un scénario de service client.
  • Assurez-vous que le script ne contient pas de contenu sensible ou illégal (tel que du matériel politique, pornographique ou violent), car cela entraîne l'échec du clonage.
  • Évitez les phrases courtes (comme « bonjour » ou « oui »). Utilisez des phrases complètes.
  • Maintenez une cohérence sémantique et évitez les pauses fréquentes lors de la lecture. Au moins 3 secondes consécutives sans interruption sont recommandées.
  • Vous pouvez transmettre l'émotion cible (comme amical ou sérieux), mais évitez un ton trop dramatique ou théâtral. Gardez un ton naturel.

Étapes recommandées

En prenant une chambre typique comme exemple :

  1. Fermez les portes et les fenêtres pour bloquer le bruit extérieur.
  2. Éteignez les climatiseurs, les ventilateurs et autres appareils électroménagers.
  3. Fermez les rideaux pour réduire les réflexions sur le verre.
  4. Couvrez la surface du bureau avec des vêtements ou une couverture pour réduire les réflexions du bureau.
  5. Familiarisez-vous avec le script, définissez le ton du personnage et livrez-le naturellement.
  6. Maintenez une distance d'environ 10 cm par rapport à l'appareil d'enregistrement pour éviter la distorsion des plosives ou un signal faible.

Messages d'erreur

Si vous rencontrez des erreurs, consultez la rubrique Codes d'erreur pour le dépannage.