すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Model Studio:リアルタイム音声合成 - CosyVoice

最終更新日:Dec 16, 2025

音声合成 (Text-to-Speech、TTS) は、テキストを自然な音声に変換する技術です。機械学習アルゴリズムを用いて、膨大な音声サンプルから言語のプロソディ、イントネーション、発音規則を学習し、テキスト入力から人間のような自然な音声を生成します。

コア機能

  • 忠実度の高い音声をリアルタイムで生成し、中国語や英語など多言語の自然な音声に対応します。

  • 音声クローン機能を提供し、カスタムボイスを迅速に作成できます。

  • ストリーミング入出力に対応し、リアルタイムの対話シナリオで低遅延の応答を実現します。

  • 話速、ピッチ、音量、ビットレートを調整することで、音声の表現を詳細にコントロールできます。

  • 主要な音声フォーマットと互換性があり、最大 48 kHz の音声サンプリングレートに対応します。

利用可能状況

  • 対応リージョン: このサービスは中国 (北京) リージョンでのみ利用可能です。中国 (北京) リージョンの API キー を使用してください。

  • 対応モデル: cosyvoice-v3-plus、cosyvoice-v3-flash、cosyvoice-v2

  • 対応音声:CosyVoice 音声リスト」をご参照ください。

モデルの選択

シナリオ

推奨モデル

理由

ブランドボイスのカスタマイズ/パーソナライズされた音声クローンサービス

cosyvoice-v3-plus

最も強力な音声クローン機能を備え、48 kHz の高品質オーディオ出力に対応します。高品質なオーディオと音声クローンの組み合わせにより、人間らしいブランドボイスプリントの作成を支援します。

コストが高い (1万文字あたり 0.286706 米ドル)。コアシナリオでの利用を推奨します。

スマートカスタマーサービス/音声アシスタント

cosyvoice-v3-flash

最も低コストのモデルです (1万文字あたり 0.14335 米ドル)。ストリーミング対話と感情表現に対応し、高速な応答時間を実現し、コストパフォーマンスに優れています。

方言放送システム

cosyvoice-v3-flash、cosyvoice-v3-plus

東北官話や閩南語など、さまざまな方言に対応しており、ローカルコンテンツの放送に適しています。

cosyvoice-v3-plus はコストが高いです (1万文字あたり 0.286706 米ドル)

教育アプリケーション (数式読み上げを含む)

cosyvoice-v2、cosyvoice-v3-flash、cosyvoice-v3-plus

LaTeX 形式の数式を音声に変換する機能に対応しており、数学、物理、化学の授業の説明に適しています。

cosyvoice-v2 と cosyvoice-v3-plus はコストが高いです (1万文字あたり 0.286706 米ドル)。

構造化された音声アナウンス (ニュース/広報)

cosyvoice-v3-plus、cosyvoice-v3-flash、cosyvoice-v2

SSML に対応しており、話速、間、発音などを制御して、放送の専門性を高めることができます。

SSML 生成ロジックの追加開発が必要です。感情の設定には対応していません。

正確な音声とテキストのアライメント (字幕生成、講義再生、ディクテーション練習用)

cosyvoice-v3-flash、cosyvoice-v3-plus、cosyvoice-v2

タイムスタンプ出力に対応しており、合成された音声と元のテキストを同期させることができます。

タイムスタンプ機能はデフォルトで無効になっているため、明示的に有効にする必要があります。

グローバル市場向けの多言語プロダクト

cosyvoice-v3-flash、cosyvoice-v3-plus

多言語に対応しています。

Sambert はストリーミング入力に対応しておらず、cosyvoice-v3-flash よりも高価です。

詳細については、「機能比較」をご参照ください。

クイックスタート

以下のコードは、API の呼び出し方法の例です。一般的なシナリオをカバーするその他のコード例については、GitHub のリポジトリをご参照ください。

API キーを取得し、API キーを環境変数として設定する必要があります。SDK を使用して呼び出しを行う場合は、DashScope SDK をインストールする必要もあります。

CosyVoice

合成音声をファイルに保存

Python

# coding=utf-8

import dashscope
from dashscope.audio.tts_v2 import *

# 環境変数に API キーを設定していない場合は、「your-api-key」を実際の API キーに置き換えてください。
# dashscope.api_key = "your-api-key"

# モデル
# モデルのバージョンごとに、対応する音声バージョンが必要です:
# cosyvoice-v3-flash/cosyvoice-v3-plus:longanyang などの音声を使用します。
# cosyvoice-v2:longxiaochun_v2 などの音声を使用します。
model = "cosyvoice-v3-flash"
# 音声
voice = "longanyang"

# SpeechSynthesizer をインスタンス化し、コンストラクターでモデルや音声などのリクエストパラメーターを渡します。
synthesizer = SpeechSynthesizer(model=model, voice=voice)
# 合成するテキストを送信して、バイナリ音声を取得します。
audio = synthesizer.call("今日の天気はどうですか?")
# 初めてテキストを送信する際には WebSocket 接続を確立する必要があるため、初回パケット遅延には接続確立時間が含まれます。
print('[Metric] Request ID: {}, First-packet latency: {} ms'.format(
    synthesizer.get_last_request_id(),
    synthesizer.get_first_package_delay()))

# 音声をローカルファイルに保存します。
with open('output.mp3', 'wb') as f:
    f.write(audio)

Java

import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;

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

public class Main {
    // モデル
    // モデルのバージョンごとに、対応する音声バージョンが必要です:
    // cosyvoice-v3-flash/cosyvoice-v3-plus:longanyang などの音声を使用します。
    // cosyvoice-v2:longxiaochun_v2 などの音声を使用します。
    private static String model = "cosyvoice-v3-flash";
    // 音声
    private static String voice = "longanyang";

    public static void streamAudioDataToSpeaker() {
        // リクエストパラメーター
        SpeechSynthesisParam param =
                SpeechSynthesisParam.builder()
                        // 環境変数に API キーを設定していない場合は、次の行のコメントを解除し、「your-api-key」を実際の API キーに置き換えてください。
                        // .apiKey("your-api-key")
                        .model(model) // モデル
                        .voice(voice) // 音声
                        .build();

        // 同期モード:コールバックを無効にします (2番目のパラメーターは null)。
        SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);
        ByteBuffer audio = null;
        try {
            // 音声が返されるまでブロックします。
            audio = synthesizer.call("今日の天気はどうですか?");
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            // タスクが終了したら WebSocket 接続を閉じます。
            synthesizer.getDuplexApi().close(1000, "bye");
        }
        if (audio != null) {
            // 音声データをローカルファイル「output.mp3」に保存します。
            File file = new File("output.mp3");
            // 初めてテキストを送信する際には WebSocket 接続を確立する必要があるため、初回パケット遅延には接続確立時間が含まれます。
            System.out.println(
                    "[Metric] Request ID: "
                            + synthesizer.getLastRequestId()
                            + " First-packet latency (ms): "
                            + synthesizer.getFirstPackageDelay());
            try (FileOutputStream fos = new FileOutputStream(file)) {
                fos.write(audio.array());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) {
        streamAudioDataToSpeaker();
        System.exit(0);
    }
}

LLM が生成したテキストをリアルタイムで音声に変換し、スピーカーで再生

以下のコードは、Qwen 大規模言語モデル (qwen-turbo) からのリアルタイムテキスト出力をオンプレミスデバイスで再生する方法を示しています。

Python

Python の例を実行する前に、pip を使用してサードパーティの音声再生ライブラリをインストールする必要があります。

# coding=utf-8
# pyaudio のインストール手順:
# APPLE Mac OS X
#   brew install portaudio
#   pip install pyaudio
# Debian/Ubuntu
#   sudo apt-get install python-pyaudio python3-pyaudio
#   または
#   pip install pyaudio
# CentOS
#   sudo yum install -y portaudio portaudio-devel && pip install pyaudio
# Microsoft Windows
#   python -m pip install pyaudio

import pyaudio
import dashscope
from dashscope.audio.tts_v2 import *


from http import HTTPStatus
from dashscope import Generation

# 環境変数に API キーを設定していない場合は、次の行のコメントを解除し、「apiKey」を実際の API キーに置き換えてください。
# dashscope.api_key = "apiKey"

# モデルのバージョンごとに、対応する音声バージョンが必要です:
# cosyvoice-v3-flash/cosyvoice-v3-plus:longanyang などの音声を使用します。
# cosyvoice-v2:longxiaochun_v2 などの音声を使用します。
model = "cosyvoice-v3-flash"
voice = "longanyang"


class Callback(ResultCallback):
    _player = None
    _stream = None

    def on_open(self):
        print("websocket is open.")
        self._player = pyaudio.PyAudio()
        self._stream = self._player.open(
            format=pyaudio.paInt16, channels=1, rate=22050, output=True
        )

    def on_complete(self):
        print("speech synthesis task complete successfully.")

    def on_error(self, message: str):
        print(f"speech synthesis task failed, {message}")

    def on_close(self):
        print("websocket is closed.")
        # プレーヤーを停止
        self._stream.stop_stream()
        self._stream.close()
        self._player.terminate()

    def on_event(self, message):
        print(f"recv speech synthsis message {message}")

    def on_data(self, data: bytes) -> None:
        print("audio result length:", len(data))
        self._stream.write(data)


def synthesizer_with_llm():
    callback = Callback()
    synthesizer = SpeechSynthesizer(
        model=model,
        voice=voice,
        format=AudioFormat.PCM_22050HZ_MONO_16BIT,
        callback=callback,
    )

    messages = [{"role": "user", "content": "自己紹介をしてください。"}]
    responses = Generation.call(
        model="qwen-turbo",
        messages=messages,
        result_format="message",  # 結果のフォーマットを 'message' に設定
        stream=True,  # ストリーム出力を有効化
        incremental_output=True,  # インクリメンタル出力を有効化
    )
    for response in responses:
        if response.status_code == HTTPStatus.OK:
            print(response.output.choices[0]["message"]["content"], end="")
            synthesizer.streaming_call(response.output.choices[0]["message"]["content"])
        else:
            print(
                "Request id: %s, Status code: %s, error code: %s, error message: %s"
                % (
                    response.request_id,
                    response.status_code,
                    response.code,
                    response.message,
                )
            )
    synthesizer.streaming_complete()
    print('Request ID: ', synthesizer.get_last_request_id())


if __name__ == "__main__":
    synthesizer_with_llm()

Java

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.audio.tts.SpeechSynthesisResult;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisAudioFormat;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import io.reactivex.Flowable;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.sound.sampled.*;

public class Main {
    // モデルのバージョンごとに、対応する音声バージョンが必要です:
    // cosyvoice-v3-flash/cosyvoice-v3-plus:longanyang などの音声を使用します。
    // cosyvoice-v2:longxiaochun_v2 などの音声を使用します。
    private static String model = "cosyvoice-v3-flash";
    private static String voice = "longanyang";
    public static void process() throws NoApiKeyException, InputRequiredException {
        // 再生スレッド
        class PlaybackRunnable implements Runnable {
            // オーディオフォーマットを設定します。デバイス、
            // 合成音声のパラメーター、プラットフォームに基づいて設定してください。ここでは、
            // 22050 Hz 16 ビットモノラルに設定されています。モデルのサンプルレートとデバイスの
            // 互換性に基づいて、他の
            // サンプルレートとフォーマットを選択することを推奨します。
            private AudioFormat af = new AudioFormat(22050, 16, 1, true, false);
            private DataLine.Info info = new DataLine.Info(SourceDataLine.class, af);
            private SourceDataLine targetSource = null;
            private AtomicBoolean runFlag = new AtomicBoolean(true);
            private ConcurrentLinkedQueue<ByteBuffer> queue =
                    new ConcurrentLinkedQueue<>();

            // プレーヤーを準備します。
            public void prepare() throws LineUnavailableException {
                targetSource = (SourceDataLine) AudioSystem.getLine(info);
                targetSource.open(af, 4096);
                targetSource.start();
            }

            public void put(ByteBuffer buffer) {
                queue.add(buffer);
            }

            // 再生を停止します。
            public void stop() {
                runFlag.set(false);
            }

            @Override
            public void run() {
                if (targetSource == null) {
                    return;
                }

                while (runFlag.get()) {
                    if (queue.isEmpty()) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                        }
                        continue;
                    }

                    ByteBuffer buffer = queue.poll();
                    if (buffer == null) {
                        continue;
                    }

                    byte[] data = buffer.array();
                    targetSource.write(data, 0, data.length);
                }

                // 残りのキャッシュされた音声をすべて再生します。
                if (!queue.isEmpty()) {
                    ByteBuffer buffer = null;
                    while ((buffer = queue.poll()) != null) {
                        byte[] data = buffer.array();
                        targetSource.write(data, 0, data.length);
                    }
                }
                // プレーヤーを解放します。
                targetSource.drain();
                targetSource.stop();
                targetSource.close();
            }
        }

        // ResultCallback<SpeechSynthesisResult> を継承するサブクラスを作成して
        // コールバックインターフェイスを実装します。
        class ReactCallback extends ResultCallback<SpeechSynthesisResult> {
            private PlaybackRunnable playbackRunnable = null;

            public ReactCallback(PlaybackRunnable playbackRunnable) {
                this.playbackRunnable = playbackRunnable;
            }

            // サービスがストリーミング合成結果を返したときのコールバック。
            @Override
            public void onEvent(SpeechSynthesisResult result) {
                // getAudioFrame を使用してストリーミング結果のバイナリデータを取得します。
                if (result.getAudioFrame() != null) {
                    // データをプレーヤーにストリーミングします。
                    playbackRunnable.put(result.getAudioFrame());
                }
            }

            // サービスが合成を完了したときのコールバック。
            @Override
            public void onComplete() {
                // 再生スレッドに終了を通知します。
                playbackRunnable.stop();
            }

            // エラーが発生したときのコールバック。
            @Override
            public void onError(Exception e) {
                // 再生スレッドに終了を通知します。
                System.out.println(e);
                playbackRunnable.stop();
            }
        }

        PlaybackRunnable playbackRunnable = new PlaybackRunnable();
        try {
            playbackRunnable.prepare();
        } catch (LineUnavailableException e) {
            throw new RuntimeException(e);
        }
        Thread playbackThread = new Thread(playbackRunnable);
        // 再生スレッドを開始します。
        playbackThread.start();
        /*******  生成 AI モデルを呼び出してストリーミングテキストを取得 *******/
        // LLM 呼び出しの準備をします。
        Generation gen = new Generation();
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content("自己紹介をしてください。")
                .build();
        GenerationParam genParam =
                GenerationParam.builder()
                        // 環境変数に API キーを設定していない場合は、次の行のコメントを解除し、「apiKey」を実際の API キーに置き換えてください。
                        // .apiKey("apikey")
                        .model("qwen-turbo")
                        .messages(Arrays.asList(userMsg))
                        .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                        .topP(0.8)
                        .incrementalOutput(true)
                        .build();
        // 音声合成タスクを準備します。
        SpeechSynthesisParam param =
                SpeechSynthesisParam.builder()
                        // 環境変数に API キーを設定していない場合は、次の行のコメントを解除し、「apiKey」を実際の API キーに置き換えてください。
                        // .apiKey("apikey")
                        .model(model)
                        .voice(voice)
                        .format(SpeechSynthesisAudioFormat
                                .PCM_22050HZ_MONO_16BIT)
                        .build();
        SpeechSynthesizer synthesizer =
                new SpeechSynthesizer(param, new ReactCallback(playbackRunnable));
        Flowable<GenerationResult> result = gen.streamCall(genParam);
        result.blockingForEach(message -> {
            String text =
                    message.getOutput().getChoices().get(0).getMessage().getContent().trim();
            if (text != null && !text.isEmpty()) {
                System.out.println("LLM output: " + text);
                synthesizer.streamingCall(text);
            }
        });
        synthesizer.streamingComplete();
        System.out.print("Request ID: " + synthesizer.getLastRequestId());
        try {
            // 再生スレッドがすべての音声の再生を終えるのを待ちます。
            playbackThread.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws NoApiKeyException, InputRequiredException {
        process();
        System.exit(0);
    }
}

API リファレンス

機能比較

機能

cosyvoice-v3-plus

cosyvoice-v3-flash

cosyvoice-v2

対応言語

音声によって異なります:中国語 (標準語、広東語、東北、甘粛、貴州、河南、湖北、江西、閩南、寧夏、山西、陝西、山東、上海、四川、天津、雲南)、英語、フランス語、ドイツ語、日本語、韓国語、ロシア語

音声によって異なります:中国語、英語 (イギリス、アメリカ)、韓国語、日本語

オーディオフォーマット

pcm、wav、mp3、opus

音声サンプリングレート

8 kHz、16 kHz、22.05 kHz、24 kHz、44.1 kHz、48 kHz

音声クローン

対応。「CosyVoice 音声クローン API」をご参照ください。

SSML

対応。「SSML マークアップ言語の概要をご参照ください。この機能は、クローンされた音声と、音声リストで対応とマークされたシステム音声に適用されます。

LaTeX

対応。「LaTeX 数式を音声に変換」をご参照ください。

音量調整

対応

話速調整

対応

ピッチ調整

対応

ビットレート調整

対応。opus フォーマットでのみ利用可能です。

タイムスタンプ

対応デフォルトでは無効ですが、有効にできます。この機能は、クローンされた音声と、音声リストで対応とマークされたシステム音声に適用されます。

命令制御 (Instruct)

対応。この機能は、クローンされた音声と、音声リストで対応とマークされたシステム音声に適用されます。

非対応

ストリーミング入力

対応

ストリーミング出力

対応

レート制限 (RPS)

3

接続タイプ

Java/Python SDK、WebSocket API

価格

1万文字あたり 0.286706 米ドル

1万文字あたり 0.14335 米ドル

1万文字あたり 0.286706 米ドル

よくある質問

Q:音声合成で誤った発音があった場合はどうすればよいですか?多音字の発音を制御するにはどうすればよいですか?

  • 多音字を同音異義語に置き換えることで、発音を迅速に修正できます。

  • 音声合成マークアップ言語 (SSML) を使用して発音を制御します。