Files
sionrui/docs/cosyvoice-generate.md
2025-11-19 21:57:16 +08:00

13 KiB
Raw Blame History

阿里云CosyVoice Java SDK 调用模板(参数+示例)

一、前提条件

  1. 开通CosyVoice服务获取API Key建议配置到环境变量避免硬编码
  2. 安装最新版DashScope SDK支持2.20.3+版本SSML功能需此版本及以上
  3. 模型与音色需匹配如v2模型对应v2音色v3模型对应v3音色

二、核心参数汇总

参数名 类型 是否必填 默认值 取值范围/说明
model String - cosyvoice-v1/v2/v3/v3-plusv3系列需申请邀测
voice String - 对应模型的音色如v2longxiaochun_v2v3longhuohuo_v3详见文档音色列表
format enum 因音色而异默认MP3 22050Hz 支持WAV/MP3/PCM/OGG_OPUS如PCM_22050HZ_MONO_16BIT、MP3_24000HZ_MONO_256KBPS
volume int 50 0~100音量大小
speechRate float 1.0 0.5~2.0语速1.0为默认约4字/秒)
pitchRate float 1.0 0.5~2.0(语调)
bit_rate int 32 6~510kbps仅opus格式支持v1模型不支持
seed int 0 0~65535随机数种子仅v3/v3-plus支持
style int 0 ≥0整数风格调整仅v3/v3-plus支持
languageHints List - 仅v3/v3-plus支持单次配置1个语种"zh"/"en"
instruction String - 仅v3/v3-plus支持格式"你说话的情感是<情感值>"(如"Happy"/"Angry"

三、四种核心调用方式模板

1. 同步调用(阻塞式,适合短文本)

import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;

public class SyncCallTemplate {
    // 配置参数(根据需求修改)
    private static final String MODEL = "cosyvoice-v3"; // 模型
    private static final String VOICE = "longhuohuo_v3"; // 音色
    private static final String TEXT = "今天天气真好,适合出门散步!"; // ≤2000字符
    private static final String OUTPUT_FILE = "output.mp3"; // 输出文件

    public static void main(String[] args) {
        // 1. 构建请求参数
        SpeechSynthesisParam param = SpeechSynthesisParam.builder()
                // .apiKey("your-api-key") // 未配置环境变量时打开
                .model(MODEL)
                .voice(VOICE)
                .volume(60) // 可选:调整音量
                .speechRate(1.1f) // 可选:调整语速
                .build();

        // 2. 初始化合成器同步调用传null
        SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);
        ByteBuffer audioData = null;

        try {
            // 3. 阻塞调用,获取完整音频
            audioData = synthesizer.call(TEXT);
            // 4. 保存音频到本地
            if (audioData != null) {
                try (FileOutputStream fos = new FileOutputStream(new File(OUTPUT_FILE))) {
                    fos.write(audioData.array());
                }
                System.out.println("合成成功!输出文件:" + OUTPUT_FILE);
                System.out.println("RequestId" + synthesizer.getLastRequestId());
                System.out.println("首包延迟:" + synthesizer.getFirstPackageDelay() + "ms");
            }
        } catch (Exception e) {
            System.err.println("合成失败:" + e.getMessage());
        } finally {
            // 5. 关闭WebSocket连接
            synthesizer.getDuplexApi().close(1000, "任务结束");
        }
    }
}

2. 异步调用(非阻塞,短文本实时接收)

import com.alibaba.dashscope.audio.tts.SpeechSynthesisResult;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.common.ResultCallback;
import java.util.concurrent.CountDownLatch;

public class AsyncCallTemplate {
    private static final String MODEL = "cosyvoice-v2";
    private static final String VOICE = "longxiaochun_v2";
    private static final String TEXT = "欢迎使用阿里云CosyVoice语音合成服务"; // ≤2000字符

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);

        // 1. 配置回调(实时接收音频)
        ResultCallback<SpeechSynthesisResult> callback = new ResultCallback<SpeechSynthesisResult>() {
            @Override
            public void onEvent(SpeechSynthesisResult result) {
                // 接收音频分片(可实时播放或写入文件)
                if (result.getAudioFrame() != null) {
                    System.out.println("收到音频分片,大小:" + result.getAudioFrame().capacity() + "字节");
                    // 此处可添加音频处理逻辑(如流式播放、追加写入文件)
                }
                // 查看计费字符数(最终以最后一次为准)
                if (result.getUsage() != null) {
                    System.out.println("当前计费字符数:" + result.getUsage().getCharacters());
                }
            }

            @Override
            public void onComplete() {
                System.out.println("合成完成!");
                latch.countDown();
            }

            @Override
            public void onError(Exception e) {
                System.err.println("合成失败:" + e.getMessage());
                latch.countDown();
            }
        };

        // 2. 构建参数并初始化合成器
        SpeechSynthesisParam param = SpeechSynthesisParam.builder()
                // .apiKey("your-api-key")
                .model(MODEL)
                .voice(VOICE)
                .format(SpeechSynthesisAudioFormat.MP3_16000HZ_MONO_128KBPS) // 可选配置格式
                .build();
        SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, callback);

        try {
            // 3. 非阻塞调用
            synthesizer.call(TEXT);
            latch.await(); // 等待合成完成
            System.out.println("RequestId" + synthesizer.getLastRequestId());
        } catch (Exception e) {
            System.err.println("调用异常:" + e.getMessage());
        } finally {
            synthesizer.getDuplexApi().close(1000, "任务结束");
        }
    }
}

3. 流式调用(分段传文本,适合长文本)

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.ResultCallback;

public class StreamingCallTemplate {
    // 分段文本每段≤2000字符累计≤20万字符
    private static final String[] TEXT_SEGMENTS = {
        "流式语音合成适合长文本场景,",
        "可以分段发送文本,",
        "服务端实时返回音频,",
        "减少等待时间。"
    };
    private static final String MODEL = "cosyvoice-v3";
    private static final String VOICE = "longchuanshu_v3";

    public static void main(String[] args) {
        // 1. 配置回调
        ResultCallback<SpeechSynthesisResult> callback = new ResultCallback<SpeechSynthesisResult>() {
            @Override
            public void onEvent(SpeechSynthesisResult result) {
                if (result.getAudioFrame() != null) {
                    System.out.println("收到流式音频分片");
                    // 处理音频(如实时播放、写入缓冲文件)
                }
            }

            @Override
            public void onComplete() {
                System.out.println("流式合成全部完成!");
            }

            @Override
            public void onError(Exception e) {
                System.err.println("流式合成失败:" + e.getMessage());
            }
        };

        // 2. 构建参数
        SpeechSynthesisParam param = SpeechSynthesisParam.builder()
                // .apiKey("your-api-key")
                .model(MODEL)
                .voice(VOICE)
                .format(SpeechSynthesisAudioFormat.PCM_22050HZ_MONO_16BIT)
                .speechRate(0.9f)
                .build();
        SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, callback);

        try {
            // 3. 分段发送文本间隔≤23秒
            for (String segment : TEXT_SEGMENTS) {
                synthesizer.streamingCall(segment);
                Thread.sleep(500); // 模拟文本输入间隔
            }
            // 4. 必须调用:结束流式合成(触发剩余文本合成)
            synthesizer.streamingComplete();
            System.out.println("RequestId" + synthesizer.getLastRequestId());
        } catch (Exception e) {
            System.err.println("调用异常:" + e.getMessage());
        } finally {
            synthesizer.getDuplexApi().close(1000, "任务结束");
        }
    }
}

4. Flowable调用响应式编程支持流式输入输出

import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.exception.NoApiKeyException;
import io.reactivex.Flowable;
import io.reactivex.BackpressureStrategy;

public class FlowableCallTemplate {
    private static final String MODEL = "cosyvoice-v2";
    private static final String VOICE = "longyingtian_v2";
    private static final String[] TEXT_ARRAY = {"响应式编程模式,", "支持流式输入输出,", "适合高并发场景。"};

    public static void main(String[] args) throws NoApiKeyException {
        // 1. 模拟流式文本输入
        Flowable<String> textStream = Flowable.create(emitter -> {
            new Thread(() -> {
                for (String text : TEXT_ARRAY) {
                    emitter.onNext(text);
                    try {
                        Thread.sleep(800);
                    } catch (InterruptedException e) {
                        emitter.onError(e);
                    }
                }
                emitter.onComplete();
            }).start();
        }, BackpressureStrategy.BUFFER);

        // 2. 构建参数
        SpeechSynthesisParam param = SpeechSynthesisParam.builder()
                // .apiKey("your-api-key")
                .model(MODEL)
                .voice(VOICE)
                .volume(70)
                .build();
        SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);

        try {
            // 3. 流式调用并处理结果
            synthesizer.streamingCallAsFlowable(textStream)
                    .blockingForEach(result -> {
                        if (result.getAudioFrame() != null) {
                            System.out.println("Flowable收到音频大小" + result.getAudioFrame().capacity() + "字节");
                            // 处理音频逻辑
                        }
                    });
            System.out.println("Flowable合成完成RequestId" + synthesizer.getLastRequestId());
        } finally {
            synthesizer.getDuplexApi().close(1000, "任务结束");
        }
    }
}

四、核心注意事项

  1. 文本长度限制非流式单次≤2000字符流式累计≤20万字符含SSML标签
  2. 字符计算规则:汉字=2字符英文/数字/标点/空格=1字符。
  3. 流式调用必须调用streamingComplete(),否则结尾文本无法合成。
  4. 每次调用call()前需重新初始化SpeechSynthesizer实例。
  5. 音频格式需与播放器兼容如MP3/OPUS支持流式播放推荐使用ffmpeg、AudioFormat等工具