Spring-ai-alibaba音频

发布时间:2026/8/4 7:29:57
Spring-ai-alibaba音频 文章目录Spring AI Alibaba 语音模型实战TTS STT版本一、依赖引入二、yml 配置三、代码案例TTS文字 → 音频四、代码案例STT音频 → 文字1. 公网 URL 同步 call()录音文件识别2. 本地上传用 stream()Spring AI Alibaba 语音模型实战TTS STT用 Spring AI Alibaba 接入百炼文字转语音TTS与语音转文字STT。版本Spring Boot3.4.5spring-ai-alibaba-starter-dashscope1.1.2.1修复call()只返回部分音频的问题Java17Spring-ai更新速度快,请以官方为准可参考网址:Spring-ai官网Spring-ai阿里巴巴阿里百炼模型广场开发者指南(API/SDK)一、依赖引入dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdcom.alibaba.cloud.ai/groupIdartifactIdspring-ai-alibaba-starter-dashscope/artifactId!-- 1.1.2.1TTS call() 能拿完整音频 --version1.1.2.1/version/dependencydependencygroupIdcom.alibaba/groupIdartifactIddashscope-sdk-java/artifactIdversion2.22.18/version/dependency二、yml 配置spring:application:name:spring-audio-demoai:dashscope:api-key:${DASHSCOPE_API_KEY}audio:synthesis:options:# 默认音色配置接口里也可按需覆盖 model / voicemodel:cosyvoice-v1voice:longhua说明CosyVoice 的model 与 voice 必须成套。例如代码里用cosyvoice-v3-flash时音色要用longdaiyu_v3这类 v3 音色否则可能 418。三、代码案例TTS文字 → 音频RestControllerRequestMapping(/ai/tts)publicclassTTSAudioController{/** 相对运行目录的 audio/IDE 从父工程启动时可能落在 spring-ai-second/audio */privatestaticfinalPathAUDIO_DIRPaths.get(audio);privatestaticfinalStringDEFAULT_TEXT哟,我来的不巧了,早知她来,我就不来了.;/** 注入 DashScope 语音合成模型Bean 名dashScopeSpeechSynthesisModel */privatefinalTextToSpeechModeltextToSpeechModel;publicTTSAudioController(Qualifier(dashScopeSpeechSynthesisModel)TextToSpeechModeltextToSpeechModel){this.textToSpeechModeltextToSpeechModel;}/** * GET /ai/tts/speak?text你好 * 流程拼 Options → Prompt → call() → 落盘 → 返回 mp3 字节 */GetMapping(value/speak,producesaudio/mpeg)publicbyte[]speak(RequestParam(defaultValueDEFAULT_TEXT)Stringtext){// 1合成参数模型、音色、格式、采样率等DashScopeAudioSpeechOptionsoptionsDashScopeAudioSpeechOptions.builder().model(cosyvoice-v3-flash)// 合成模型.voice(longdaiyu_v3)// 必须与模型版本匹配.responseFormat(DashScopeAudioSpeechApi.ResponseFormat.MP3).sampleRate(22050)// 采样率.volume(50)// 音量 0~100.speed(1.0)// 语速.build();// 2文本 参数 → PromptTextToSpeechPromptpromptnewTextToSpeechPrompt(text,options);// 3同步合成拿到音频字节TextToSpeechResponseresponsetextToSpeechModel.call(prompt);byte[]audioresponse.getResult().getOutput();// 4先存本地再读回学习「生成 → 落盘 → 再读」Stringfilenametts-UUID.randomUUID().mp3;saveToFolder(audio,filename);returnreadFromFolder(filename);}privatevoidsaveToFolder(byte[]data,Stringfilename){try{Files.createDirectories(AUDIO_DIR);Files.write(AUDIO_DIR.resolve(filename),data);}catch(IOExceptione){e.printStackTrace();}}privatebyte[]readFromFolder(Stringfilename){try{returnFiles.readAllBytes(AUDIO_DIR.resolve(filename));}catch(IOExceptione){e.printStackTrace();returnnewbyte[0];}}}浏览器直接访问/ai/tts/speak即可播放返回的 MP3。四、代码案例STT音频 → 文字1. 公网 URL 同步call()录音文件识别RestControllerRequestMapping(/ai/stt)publicclassController{/** * call() 走「录音文件识别」云端自己下载音频所以必须是公网 URL。 * 本地文件 / MultipartFile 对云端不可见要用 stream()见下方 upload。 */privatestaticfinalStringDEMO_AUDIO_URLhttps://dashscope.oss-cn-beijing.aliyuncs.com/samples/audio/paraformer/hello_world_female2.wav;privatefinalDashScopeAudioTranscriptionModeltranscriptionModel;publicController(DashScopeAudioTranscriptionModeltranscriptionModel){this.transcriptionModeltranscriptionModel;}/** * GET /ai/stt/basic * 流程Options → UrlResource → Prompt → call() → 文本 */GetMapping(value/basic,producestext/html;charsetUTF-8)publicStringbasic(RequestParam(defaultValueDEMO_AUDIO_URL)Stringurl)throwsMalformedURLException{DashScopeAudioTranscriptionOptionsoptionsDashScopeAudioTranscriptionOptions.builder()// 录音文件识别模型非实时.model(DashScopeModel.AudioModel.PARAFORMER_V2.getValue()).languageHints(List.of(zh,en)).build();// 告诉框架音频在这个网络地址UrlResourceaudioResourcenewUrlResource(url);AudioTranscriptionPromptpromptnewAudioTranscriptionPrompt(audioResource,options);// 同步调用提交任务并等待内部会轮询日志里出现 pending 属正常AudioTranscriptionResponseresponsetranscriptionModel.call(prompt);Stringtextresponse.getResult().getOutput();return识别结果: text;}}2. 本地上传用stream()上传文件时云端拿不到你本机路径应走实时流/** * POST /ai/stt/upload form-data 字段名 file * sampleRate 必须与文件真实采样率一致本项目 TTS 的 mp3 常用 22050 */PostMapping(value/upload,producestext/html;charsetUTF-8)publicStringupload(RequestParam(file)MultipartFilefile,RequestParam(defaultValue22050)IntegersampleRate)throwsIOException{DashScopeAudioTranscriptionOptionsoptionsDashScopeAudioTranscriptionOptions.builder().model(DashScopeModel.AudioModel.PARAFORMER_REALTIME_V2.getValue()).sampleRate(sampleRate).format(DashScopeAudioTranscriptionApi.AudioFormat.MP3)// 按实际后缀选择.languageHints(List.of(zh,en)).build();ResourceaudioResourcenewByteArrayResource(file.getBytes()){OverridepublicStringgetFilename(){returnfile.getOriginalFilename();}};AudioTranscriptionPromptpromptnewAudioTranscriptionPrompt(audioResource,options);// 实时流每帧常是「整句修订版」取最后一帧即可不要把所有帧 join 起来StringtexttranscriptionModel.stream(prompt).map(r-r.getResult()null?:r.getResult().getOutput()).filter(t-t!null!t.isBlank()).last().block();return识别结果: text;}