Todos los productos
Search
Centro de documentos

Alibaba Cloud Model Studio:Referencia de la API de clonación de voz

Última actualización: Oct 12, 2026

Clone una voz a partir de 10-20 segundos de audio sin entrenamiento. Este documento cubre los parámetros y el uso de la API de clonación de voz. Para la invocación de modelos, consulte Qwen-Omni-Realtime o No en tiempo real (Qwen-Omni) .

ImportanteEste documento se aplica únicamente a la API de clonación de voz de Qwen-Omni y Qwen-Omni-Realtime. Si utiliza un modelo de texto a voz, consulte Síntesis de voz.

ImportanteAlibaba Cloud Model Studio ha lanzado dominios específicos de espacio de trabajo para las regiones de China (Beijing) y Singapur. Los nuevos dominios dedicados ofrecen un rendimiento superior y una mayor estabilidad para las solicitudes de inferencia. Recomendamos migrar a los nuevos dominios:

  • China (Pekín): de https://dashscope.aliyuncs.com a https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com
  • Singapur: de https://dashscope-intl.aliyuncs.com a https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com

{WorkspaceId} es su ID de espacio de trabajo, que se encuentra en la página Workspace Details de la consola de Alibaba Cloud Model Studio. El dominio existente permanece totalmente funcional.

Requisitos de audio

Un audio de entrada de alta calidad produce mejores resultados de clonación.

Elemento

Requisito

Formatos admitidos

WAV (16 bits), MP3, M4A

Duración

Se recomiendan de 10 a 20 segundos. Máximo: 60 segundos.

Tamaño del archivo

< 10 MB

Tasa de muestreo

>= 24 kHz

Canales

Mono

Contenido

El audio debe contener al menos 3 segundos de habla continua y clara sin sonidos de fondo. La parte restante puede incluir breves pausas (<=2 segundos). Evite música de fondo, ruido u otras voces en todo el audio. Utilice audio hablado normal como entrada. No suba canciones ni audio de canto.

Idiomas

Chino (zh), inglés (en), alemán (de), italiano (it), portugués (pt), español (es), japonés (ja), coreano (ko), francés (fr), ruso (ru), tailandés (th), indonesio (id), árabe (ar), checo (cs), danés (da), neerlandés (nl), finés (fi), hebreo (he), hindi (hi), islandés (is), malayo (ms), noruego (no), persa (fa), polaco (pl), sueco (sv), tagalo (tl), turco (tr), urdu (ur), vietnamita (vi)

Dialectos chinos: Dongbei, Shannxi, Sichuan, Henan, Changsha, Tianjin, Hangzhou, Liaoning, Shenyang, Anshan

Inicio rápido

imagen

1. Flujo de trabajo

La clonación de voz sigue un flujo de trabajo de "crear primero, usar después":

  1. Crear una voz

    Llame a la API Crear una voz y suba un clip de audio. El sistema analiza el audio y crea una voz clonada personalizada. Debe especificartarget_modelen este paso para declarar qué modelo omni impulsará la voz.

    Si ya tiene una voz creada (llame a la API List voices para verificarlo), omita este paso y continúe con el siguiente.

  2. Usar la voz en una conversación

    Llame a la API Omni (en tiempo real o no en tiempo real) y pase la voz obtenida en el paso anterior. El modelo omni especificado en este paso debe coincidir con eltarget_modeldel paso anterior.

2. Configuración del modelo y requisitos previos

Seleccione los modelos y complete los requisitos previos antes de comenzar.

Configuración del modelo

La clonación de voz requiere dos modelos:

  • Modelo de clonación de voz: qwen-voice-enrollment

  • Modelo Omni que controla la voz:

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

Requisitos previos

  1. Obtener una clave de API: Obtenga una clave de API. Por seguridad, configure la clave de API como una variable de entorno.
  2. Instalar el SDK: Asegúrese de haber instalado la última versión del SDK de DashScope.
  3. Preparar el audio para la clonación: El audio debe cumplir con los Requisitos de audio.

3. Ejemplo de extremo a extremo

Este ejemplo clona una voz y la utiliza en una conversación.

Principio clave: El target_model especificado durante la clonación debe coincidir con el modelo en la llamada posterior a la API Omni. De lo contrario, la síntesis fallará. Reemplace el archivo de ejemplo voice.mp3 con su propio audio.

Tiempo real

Aplicable a los modelos de la serie Qwen3.5-Omni-Realtime. Para más información, consulte Qwen-Omni-Realtime.

# Requirements: dashscope >= 1.26.5, 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.8-omni-flash-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/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",
        "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"
    }

    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.8-omni-flash-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/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\","
                        + "\"parameters\": {\"voice_clone_mode\": \"normal\"},"
                        + "\"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/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);
    }
}

No en tiempo real

Aplicable a los modelos de la serie Qwen3.5-Omni. Para más información, consulte No en tiempo real (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/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/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/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();
        }
    }
}

Referencia de API

Utilice la misma cuenta en todas las API.

Crear una voz

Suba el audio para clonar y cree una voz personalizada.

  • URL

    Norte de China 2 (Beijing):

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

Singapur:

POST https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization
  • Encabezados de solicitud

    Parámetro

    Tipo

    Obligatorio

    Descripción

    Authorization

    string

    Compatible

    Token de autenticación en el formato Bearer <your_api_key>. Reemplace <your_api_key> con su clave API real.

    Content-Type

    string

    Compatible

    Tipo de medio del cuerpo de la solicitud. Establézcalo en application/json.

  • Cuerpo de la solicitud El cuerpo de la solicitud incluye todos los parámetros. Omita los campos opcionales según sea necesario. Tenga en cuenta la distinción entre:

    Importantemodel: El modelo de clonación de voz. Establézcalo en qwen-voice-enrollment.

    target_model: El modelo omni que impulsa la voz. Esto debe coincidir con el modelo utilizado en la llamada posterior a la API multimodal en tiempo real. De lo contrario, la síntesis fallará.

{
    "model": "qwen-voice-enrollment",
    "input": {
        "action": "create",
        "target_model": "qwen3.8-omni-flash-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
    }
}

ImportanteEl parámetro voice_clone_mode en parameters es obligatorio al utilizar modelos de la serie qwen3.8-omni. Si se omite, el sistema recurre al modo de instrucción del sistema talker de qwen3.5-omni por compatibilidad con versiones anteriores.

  • Parámetros de solicitud
    ParámetroTipoPredeterminadoObligatorioDescripción

    model

    string

    Compatible

    El modelo de clonación de voz. Establézcalo en qwen-voice-enrollment.

    action

    string

    Compatible

    El tipo de acción. Establézcalo en create.

    target_model

    string

    Compatible

    El modelo omni que controla la voz:

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

    Esto debe coincidir con el modelo omni utilizado en la llamada posterior a la API. De lo contrario, la síntesis fallará.

    preferred_name

    string

    Compatible

    Un nombre legible para humanos para la voz. Caracteres permitidos: dígitos, letras, guiones bajos. Máximo: 16 caracteres.

    Esta palabra clave aparece en el nombre final de la voz. Por ejemplo, si la palabra clave es "guanyu", el nombre de voz resultante es "qwen-omni-vc-guanyu-voice-20250812105009984-838b".

    audio.data

    string

    Compatible

    El audio para la clonación (siga la Guía de grabación al grabar y asegúrese de que el audio cumpla con los Requisitos de audio).

    Envíe los datos de audio de una de las siguientes maneras:

    1. URL de datos

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

      • <mediatype>: El tipo MIME

        • WAV: audio/wav
        • MP3: audio/mpeg
        • M4A: audio/mp4
      • <data>: La cadena codificada en Base64 del audio

        La codificación Base64 aumenta el tamaño del archivo. Mantenga el resultado codificado por debajo de 10 MB.

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

        Ver código de ejemplo

        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 de audio (recomendamos subir su audio a OSS)

      • El tamaño del archivo no debe exceder los 10 MB.
      • La URL debe ser accesible públicamente sin autenticación.

    text

    string

    No compatible

    La transcripción que coincide con el audio en audio.data.

    Cuando se proporciona, el servidor valida el audio con respecto al texto. Si la discrepancia es demasiado grande, se devuelve un Audio.PreprocessError.

    language

    string

    No compatible

    El idioma del audio en audio.data.

    Valores admitidos: zh (chino), en (inglés), de (alemán), it (italiano), pt (portugués), es (español), ja (japonés), ko (coreano), fr (francés), ru (ruso), th (tailandés), id (indonesio), ar (árabe), cs (checo), da (danés), nl (neerlandés), fi (finés), he (hebreo), hi (hindi), is (islandés), ms (malayo), no (noruego), fa (persa), pl (polaco), sv (sueco), tl (tagalo), tr (turco), ur (urdu), vi (vietnamita).

    Dialectos chinos: Dongbei, Shannxi, Sichuan, Henan, Changsha, Tianjin, Hangzhou, Liaoning, Shenyang, Anshan.

    Establezca esto en el idioma real del audio utilizado para la clonación.

    voice_clone_mode

    string

    Condicionalmente requerido

    Modo de clonación de voz. Requerido al utilizar modelos de la serie qwen3.8-omni. Si se omite, se recurre al modo de instrucción del sistema talker de qwen3.5-omni por compatibilidad con versiones anteriores.

    Valores válidos:

    • normal: Modo estándar
    • dialect: Modo de dialecto
    • crosslingual: Modo multilingüe

    Este parámetro debe colocarse en parameters.

    skip_audio_process

    boolean

    false

    No compatible

    Indica si se debe omitir el preprocesamiento de audio. Valor predeterminado: false. Este parámetro debe colocarse en parameters.

  • Parámetros de respuesta

    Ver ejemplo de respuesta

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

    Parámetros de respuesta clave:

    Parámetro

    Tipo

    Descripción

    voice

    string

    El nombre de la voz. Utilice este valor directamente como el parámetro voice en la API multimodal en tiempo real.

    target_model

    string

    El modelo omni que controla la voz:

    • qwen3.8-omni-flash-realtime

    • qwen3.5-omni-plus-realtime

    • qwen3.5-omni-flash-realtime

    Esto debe coincidir con el modelo utilizado en la llamada posterior a la API multimodal en tiempo real. De lo contrario, la síntesis fallará.

    request_id

    string

    ID de solicitud.

    count

    integer

    El número de operaciones de "crear voz" facturadas para esta solicitud. El costo es $ cantidad × 0.01.

    Al crear una voz, count siempre es 1.

  • Código de ejemplo

    Importantemodel: El modelo de clonación de voz. Establézcalo en qwen-voice-enrollment.

    target_model: El modelo omni que impulsa la voz. Esto debe coincidir con el modelo utilizado en la llamada posterior a la API multimodal en tiempo real. De lo contrario, la síntesis fallará.

    curl

    Si no ha configurado la clave de API como variable de entorno, debe reemplazar $DASHSCOPE_API_KEY en el ejemplo con su clave de API real.

    # ======= 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/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 Singapore and Beijing. Get an API key: https://www.alibabacloud.com/help/model-studio/get-api-key
    # If the environment variable is not set, replace the following line with: api_key = "sk-xxx"
    api_key = os.getenv("DASHSCOPE_API_KEY")
    # Singapore region. Replace {WorkspaceId} with your Bailian 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"
    }
    
    # Send the POST request
    resp = requests.post(url, json=payload, headers=headers)
    
    if resp.status_code == 200:
        data = resp.json()
        voice = data["output"]["voice"]
        print(f"Created voice: {voice}")
    else:
        print("Request failed:", resp.status_code, resp.text)
    

    java

    import com.google.gson.Gson;
    import com.google.gson.JsonObject;
    
    import java.io.*;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.nio.file.*;
    import java.util.Base64;
    
    public class Main {
        private static final String TARGET_MODEL = "qwen3.8-omni-flash-realtime";
        private static final String PREFERRED_NAME = "guanyu";
        private static final String AUDIO_FILE = "input.mp3";
        private static final String AUDIO_MIME_TYPE = "audio/mpeg";
    
        public static String toDataUrl(String filePath) throws Exception {
            byte[] bytes = Files.readAllBytes(Paths.get(filePath));
            String encoded = Base64.getEncoder().encodeToString(bytes);
            return "data:" + AUDIO_MIME_TYPE + ";base64," + encoded;
        }
    
        public static void main(String[] args) {
            // API keys differ between Singapore and Beijing. Get an API key: https://www.alibabacloud.com/help/model-studio/get-api-key
            // If the environment variable is not set, replace the following line with: String apiKey = "sk-xxx"
            String apiKey = System.getenv("DASHSCOPE_API_KEY");
            // Singapore region. Replace {WorkspaceId} with your Bailian workspace ID. URLs vary by region.
            String apiUrl = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization";
    
            try {
                // Build the JSON request body
                String jsonPayload =
                        "{"
                                + "\"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\": \"" + toDataUrl(AUDIO_FILE) + "\""
                                +     "}"
                                + "}"
                                + "}";
    
                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 the request body
                try (OutputStream os = con.getOutputStream()) {
                    os.write(jsonPayload.getBytes("UTF-8"));
                }
    
                int status = con.getResponseCode();
                InputStream is = (status >= 200 && status < 300)
                        ? con.getInputStream()
                        : con.getErrorStream();
    
                StringBuilder response = new StringBuilder();
                try (BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"))) {
                    String line;
                    while ((line = br.readLine()) != null) {
                        response.append(line);
                    }
                }
    
                System.out.println("HTTP status: " + status);
                System.out.println("Response: " + response.toString());
    
                if (status == 200) {
                    // Parse JSON
                    Gson gson = new Gson();
                    JsonObject jsonObj = gson.fromJson(response.toString(), JsonObject.class);
                    String voice = jsonObj.getAsJsonObject("output").get("voice").getAsString();
                    System.out.println("Created voice: " + voice);
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

Listar voces

Consulte sus voces creadas con paginación.

  • URL

    Norte de China 2 (Beijing):

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

Singapur:

POST https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization
  • Encabezados de solicitud

    Parámetro

    Tipo

    Obligatorio

    Descripción

    Authorization

    string

    Compatible

    Token de autenticación en el formato Bearer <your_api_key>. Reemplace <your_api_key> con su clave API real.

    Content-Type

    string

    Compatible

    Tipo de medio del cuerpo de la solicitud. Establézcalo en application/json.

  • Parámetros de solicitud

    Parámetro

    Tipo

    Predeterminado

    Obligatorio

    Descripción

    model

    string

    -

    Compatible

    El modelo de clonación de voz. Establézcalo en qwen-voice-enrollment.

    action

    string

    -

    Compatible

    El tipo de acción. Establézcalo en list.

    page_index

    integer

    0

    No compatible

    Índice de número de página. Valores válidos: de 0 a 1,000,000.

    page_size

    integer

    10

    No compatible

    Número de elementos por página. Valores válidos: de 0 a 1,000,000.

  • Parámetros de respuesta

    Ver ejemplo de respuesta

    {
        "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"
    }
    

    Parámetros de respuesta clave:

    Parámetro

    Tipo

    Descripción

    voice

    string

    El nombre de la voz. Utilice este valor directamente en el parámetro voice de la API multimodal en tiempo real.

    gmt_create

    string

    La hora en que se creó la voz.

    target_model

    string

    El modelo omni que controla la voz:

    • qwen3.8-omni-flash-realtime

    • qwen3.5-omni-plus-realtime

    • qwen3.5-omni-flash-realtime

    • qwen3.5-omni-plus

    • qwen3.5-omni-flash

    Esto debe coincidir con el modelo omni utilizado en la llamada posterior a la API. De lo contrario, la síntesis fallará.

    request_id

    string

    ID de solicitud.

    count

    integer

    Esta solicitud se cobra según el número real de operaciones de 'Crear voz'. El costo de esta solicitud es $ cantidad × 0.01 .

    Listar voces es gratuito. count siempre es 0.

  • Código de ejemplo

    Importantemodel: El modelo de clonación de voz. El valor está fijado como qwen-voice-enrollment. No modifique este valor.

    cURL

    Si no ha configurado la clave de API como variable de entorno, debe reemplazar $DASHSCOPE_API_KEY en el ejemplo con su clave de API real.

    # ======= 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/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/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/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();
            }
        }
    }
    

Eliminar una voz

Elimine una voz específica y libere la cuota correspondiente.

  • URL

    Norte de China 2 (Beijing):

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

Singapur:

POST https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/audio/tts/customization
  • Encabezados de solicitud

    Parámetro

    Tipo

    Obligatorio

    Descripción

    Authorization

    string

    Compatible

    Token de autenticación en el formato Bearer <your_api_key>. Reemplace <your_api_key> con su clave API real.

    Content-Type

    string

    Compatible

    Tipo de medio del cuerpo de la solicitud. Establézcalo en application/json.

  • Cuerpo de la solicitud

    Omita los campos opcionales según sea necesario.

    Importantemodel: El modelo de clonación de voz. El valor está fijado como qwen-voice-enrollment. No modifique este valor.

{
    "model": "qwen-voice-enrollment",
    "input": {
        "action": "delete",
        "voice": "yourVoice"
    }
}
  • Parámetros de solicitud

    Parámetro

    Tipo

    Predeterminado

    Obligatorio

    Descripción

    model

    string

    -

    Compatible

    El modelo de clonación de voz. Establézcalo en qwen-voice-enrollment.

    action

    string

    -

    Compatible

    El tipo de acción. Establézcalo en delete.

    voice

    string

    -

    Compatible

    La voz que se va a eliminar.

  • Parámetros de respuesta

    Ver ejemplo de respuesta

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

    Parámetros de respuesta clave:

    Parámetro

    Tipo

    Descripción

    request_id

    string

    ID de solicitud.

    count

    integer

    Esta solicitud se cobra según el número real de operaciones de 'Crear voz'. El costo de esta solicitud es $ cantidad × 0.01 .

    Eliminar una voz es gratuito. count siempre es 0.

  • Código de ejemplo

    Importantemodel: El modelo de clonación de voz. El valor está fijado como qwen-voice-enrollment. No modifique este valor.

    cURL

    Si no ha configurado la clave de API como variable de entorno, debe reemplazar $DASHSCOPE_API_KEY en el ejemplo con su clave de API real.

    # ======= 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/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/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/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();
            }
        }
    }
    

Uso en conversación

Para usar una voz clonada en una conversación, consulte la Guía de inicio rápido.

Cuota de voces y limpieza automática

Límite total: 1,000 voces por cuenta.

No existe un endpoint dedicado para contar. Llame a la API List voices para contar sus voces.

Limpieza automática: Las voces no utilizadas durante un año se eliminan automáticamente.

Facturación

La clonación de voz y la invocación del modelo se facturan por separado:

  • Clonación de voz: se factura a $0.01/voz. Las creaciones fallidas no se facturan.

    NotaCuota gratuita (solo región de Pekín del sitio de China y región de Singapur del sitio internacional):

    • 1,000 creaciones de voz gratuitas dentro de los 90 días posteriores a la activación de Model Studio.
    • Las creaciones fallidas no consumen la cuota gratuita.
    • Eliminar una voz no restaura la cuota gratuita.
    • Una vez agotada la cuota gratuita o vencido el periodo de 90 días, la creación de voces se factura a $0.01/voz.
  • Conversación con una voz clonada: Se factura por uso de tokens para la invocación del modelo. Para más detalles, consulte Precios de inferencia de modelos.

Usted es responsable de la propiedad y el uso legal de la voz que proporciona. Lea el Acuerdo de servicio.

Guía de grabación

Equipo de grabación

Utilice un micrófono con cancelación de ruido o grabe con un teléfono a corta distancia en un entorno silencioso.

Entorno de grabación

Ubicación

  • Grabe en un espacio cerrado pequeño de 10 metros cuadrados o menos.
  • Elija una habitación con materiales absorbentes de sonido, como espuma acústica, alfombras o cortinas.
  • Evite grandes salones abiertos, salas de conferencias o aulas donde la reverberación sea alta.

Control de ruido

  • Ruido exterior: Cierre puertas y ventanas para bloquear el tráfico, la construcción y otros sonidos externos.
  • Ruido interior: Apague los acondicionadores de aire, ventiladores y balastos de luces fluorescentes.
  • Grabe el sonido ambiental con su teléfono y reprodúzcalo a alto volumen para identificar fuentes de ruido ocultas.

Control de reverberación

  • La reverberación hace que el audio suene amortiguado y reduce la claridad.
  • Reduzca las reflexiones de superficies lisas: cierre cortinas, abra las puertas de los armarios y cubra escritorios y estantes con ropa o mantas.
  • Utilice objetos irregulares, como estanterías y muebles tapizados, para crear reflexiones difusas.

Preparación del guion

  • Adapte el guion al caso de uso objetivo. Por ejemplo, utilice un estilo de diálogo de servicio al cliente para un escenario de servicio al cliente.
  • Asegúrese de que el guion no contenga contenido sensible o ilegal (como material político, pornográfico o violento), ya que esto provoca el fallo de la clonación.
  • Evite frases cortas (como "hola" o "sí"). Utilice oraciones completas.
  • Mantenga la coherencia semántica y evite pausas frecuentes al leer. Se recomiendan al menos 3 segundos consecutivos sin interrupción.
  • Puede transmitir la emoción objetivo (como amabilidad o seriedad), pero evite una entonación excesivamente dramática o teatral. Mantenga un tono natural.

Pasos recomendados

Tomando como ejemplo un dormitorio típico:

  1. Cierre puertas y ventanas para bloquear el ruido externo.
  2. Apague acondicionadores de aire, ventiladores y otros electrodomésticos.
  3. Cierre las cortinas para reducir los reflejos en el vidrio.
  4. Cubra la superficie del escritorio con ropa o una manta para reducir las reflexiones del escritorio.
  5. Familiarícese con el guion, establezca el tono del personaje y hable con naturalidad.
  6. Mantenga una distancia de aproximadamente 10 cm del dispositivo de grabación para evitar distorsión por sonidos plosivos o señal débil.

Mensajes de error

Si encuentra errores, consulte Códigos de error para solucionar problemas.