前面几篇我们分别用 OpenAI 和千帆实现了图像生成、语音交互。但它们分散在不同的平台和依赖里,接入方式各异。今天,我们回到阿里云百炼平台,用 Spring AI Alibaba 这一个依赖,把图像、语音、视频三种多模态能力一次性全部拿下。

如果你在做一款“全能 AI 助手”,需要它既能根据文字生成图片、又能把文字变成语音播报、还能理解图片内容甚至生成视频,那么今天这篇文章就是为你量身打造的。我们会用一套统一的配置和代码风格,在百炼平台上完成文生图、语音合成(TTS)、语音识别(STT)和文生视频。一套 API,多模态全通。

一、痛点场景:多模态能力碎片化

先看几个典型困境:

  • 场景一:你希望用户上传一张照片,AI 能识别图中的物体,然后用语音读出结果。这需要图像理解 + 语音合成。如果用不同厂商的服务,光 API Key 就要管好几把。
  • 场景二:运营人员想自动生成宣传视频:输入一段文案,先让 AI 生成分镜图片,再把文案转成配音,最后合成视频。跨平台调用、格式对齐、异步任务管理……想想就头大。
  • 场景三:开发环境里同时引入 OpenAI、千帆、百炼等多个依赖,版本冲突、Bean 注入歧义让你苦不堪言。

解决方案:全部交给阿里云百炼平台,用 Spring AI Alibaba 的 dashscope starter 统一调度。它背后是通义千问系列模型,覆盖文本、图像、语音、视频全模态,而且通过 Spring AI 的统一抽象暴露,代码风格高度一致。

二、核心概念快览

2.1 DashScope 多模态模型全景

百炼平台将多种模态能力封装为模型,通过统一 API 调用:

能力 模型名称示例 输入 输出
文本生成 qwen-plus, qwen-max 文本 文本
图像理解 qwen-vl-max 文本 + 图片 文本
文生图 wanx-v1 (通义万相) 文本描述 图片 URL
语音合成(TTS) cosyvoice-v1, sambert-xxx 文本 音频数据
语音识别(STT) paraformer-xxx 音频文件 文本
文生视频 wanx2.0-t2i-turbo 文本描述 视频 URL(异步任务)

2.2 Spring AI Alibaba 的自动配置

引入 spring-ai-alibaba-starter-dashscope 后,框架会根据 application.yml 中的 spring.ai.dashscope 配置自动创建针对各模态的 Model Bean。比如:

  • DashScopeChatModel:处理文本对话和图像理解(多模态)
  • DashScopeImageModel:处理文生图
  • DashScopeSpeechSynthesisModel:处理语音合成
  • DashScopeAudioTranscriptionModel:处理语音识别
  • DashScopeVideoModel:处理文生视频

你不需要手动 new 这些对象,直接注入即可使用。而且它们在底层共享同一套 API Key 和网络配置,避免了散乱的认证管理。

2.3 调用方式一致性

图像、语音、视频的调用模式高度相似:

// 文生图
ImageResponse imgResp = imageModel.call(new ImagePrompt(text, options));

// 语音合成
SpeechResponse speechResp = speechModel.call(new SpeechPrompt(text, options));

// 语音识别
String transcript = transcriptionModel.call(audioResource, options);

// 视频生成(可能是异步)
VideoResponse videoResp = videoModel.call(new VideoPrompt(text, options));

虽然不同的模态具体接口略有差异,但整体思路遵循“输入对象 + 选项 → 调用 → 输出对象”的模式。

三、环境准备

3.1 获取百炼 API Key

访问 百炼控制台,开通 DashScope 服务,并创建 API Key。新用户通常有免费额度,用于学习绰绰有余。

设置环境变量:

export DASHSCOPE_API_KEY=sk-你的密钥

3.2 Maven 依赖

只需要一个 starter:

<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
    <version>1.1.2.0</version>  <!-- 请根据当前最新稳定版调整 -->
</dependency>

同时需要在 dependencyManagement 中引入 Spring AI BOM(版本 1.1.6),保证底层 API 一致。

3.3 application.yml 配置

spring:
  ai:
    dashscope:
      api-key: ${DASHSCOPE_API_KEY}
      # 图像生成默认选项
      image:
        options:
          model: wanx-v1
          size: 1024x1024
          n: 1
      # 语音合成默认选项
      speech:
        synthesis:
          options:
            model: cosyvoice-v1
            voice: longxiaochun    # 音色,可在百炼控制台试听
            format: mp3
      # 语音识别默认选项
      speech:
        transcription:
          options:
            model: paraformer-8k   # 采样率 8kHz 版本
      # 视频生成默认选项
      video:
        options:
          model: wanx2.0-t2i-turbo  # 文生视频模型

四、代码实战

4.1 创建多模态服务

新建 BailianMultiModalService.java,注入各模态模型:

package com.example.springaihelloworld.service;

import com.alibaba.cloud.ai.dashscope.audio.DashScopeSpeechSynthesisModel;
import com.alibaba.cloud.ai.dashscope.audio.DashScopeAudioTranscriptionModel;
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel;
import com.alibaba.cloud.ai.dashscope.video.DashScopeVideoModel;
import org.springframework.ai.image.ImagePrompt;
import org.springframework.ai.image.ImageResponse;
import org.springframework.ai.audio.speech.SpeechPrompt;
import org.springframework.ai.audio.speech.SpeechResponse;
import org.springframework.ai.video.VideoPrompt;
import org.springframework.ai.video.VideoResponse;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Service
public class BailianMultiModalService {

    private final DashScopeImageModel imageModel;
    private final DashScopeSpeechSynthesisModel synthesisModel;
    private final DashScopeAudioTranscriptionModel transcriptionModel;
    private final DashScopeVideoModel videoModel;

    public BailianMultiModalService(DashScopeImageModel imageModel,
                                    DashScopeSpeechSynthesisModel synthesisModel,
                                    DashScopeAudioTranscriptionModel transcriptionModel,
                                    DashScopeVideoModel videoModel) {
        this.imageModel = imageModel;
        this.synthesisModel = synthesisModel;
        this.transcriptionModel = transcriptionModel;
        this.videoModel = videoModel;
    }

    /**
     * 文生图:输入文本描述,返回图片 URL
     */
    public String generateImage(String prompt) {
        ImageResponse response = imageModel.call(new ImagePrompt(prompt));
        return response.getResult().getOutput().getUrl();
    }

    /**
     * 语音合成(TTS):文字转语音,返回音频字节数组
     */
    public byte[] synthesizeSpeech(String text) {
        SpeechResponse response = synthesisModel.call(new SpeechPrompt(text));
        return response.getResult().getOutput(); // byte[]
    }

    /**
     * 语音识别(STT):上传音频文件,返回转写文本
     */
    public String transcribeAudio(MultipartFile audioFile) throws IOException {
        Resource audioResource = new InputStreamResource(audioFile.getInputStream());
        return transcriptionModel.call(audioResource);
    }

    /**
     * 文生视频:输入文本描述,返回视频 URL(可能是异步任务)
     * 注意:视频生成可能需要一定时间,实际返回可能为异步任务 ID
     */
    public String generateVideo(String prompt) {
        VideoResponse response = videoModel.call(new VideoPrompt(prompt));
        // 视具体 API 返回而定,这里假设 getUrl() 返回最终视频地址
        return response.getResult().getOutput().getUrl();
    }
}

注意:实际文生视频可能为异步任务,百炼会先返回任务 ID,需要通过任务 ID 查询结果。为了教学方便,此处假设同步返回视频 URL。你的生产代码可能需要实现轮询逻辑。本章结尾会给出异步处理的提示。

4.2 创建多模态 Controller

新建 BailianMultiModalController.java

package com.example.springaihelloworld.controller;

import com.example.springaihelloworld.service.BailianMultiModalService;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@RestController
public class BailianMultiModalController {

    private final BailianMultiModalService service;

    public BailianMultiModalController(BailianMultiModalService service) {
        this.service = service;
    }

    // ===== 文生图 =====
    @GetMapping("/bailian/image")
    public String createImage(@RequestParam String prompt) {
        String url = service.generateImage(prompt);
        return "图片生成成功,地址:" + url;
    }

    // ===== 语音合成 =====
    @GetMapping("/bailian/tts")
    public ResponseEntity<byte[]> textToSpeech(@RequestParam String text) {
        byte[] audio = service.synthesizeSpeech(text);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("audio/mpeg"));
        headers.setContentDisposition(ContentDisposition.inline().filename("speech.mp3").build());
        headers.setContentLength(audio.length);
        return ResponseEntity.ok().headers(headers).body(audio);
    }

    // ===== 语音识别 =====
    @PostMapping("/bailian/asr")
    public String speechToText(@RequestParam("file") MultipartFile file) throws IOException {
        return service.transcribeAudio(file);
    }

    // ===== 文生视频 =====
    @GetMapping("/bailian/video")
    public String createVideo(@RequestParam String prompt) {
        String videoUrl = service.generateVideo(prompt);
        return "视频生成成功,地址:" + videoUrl;
    }
}

4.3 前端测试页面(可选)

可以在 src/main/resources/static 下创建一个 bailian-demo.html,集成图片展示、音频播放、文件上传和视频播放。这里就不展开了,你可以参照前几篇文章自己实现。

五、运行与演示

5.1 启动应用

确保 DASHSCOPE_API_KEY 环境变量已配置,启动 Spring Boot。

5.2 测试文生图

http://localhost:8080/bailian/image?prompt=一只戴着圣诞帽的金毛犬在雪地里奔跑

返回图片 URL,在浏览器打开即可看到生成的金毛犬图片。

5.3 测试语音合成

http://localhost:8080/bailian/tts?text=你好,欢迎使用百炼多模态平台

浏览器会直接播放 MP3 音频,听到自然的人声播报。

5.4 测试语音识别

准备一个中文音频文件(如录制“今天天气真好”),用 curl 调用:

curl -X POST -F "file=@test.m4a" http://localhost:8080/bailian/asr

返回转写结果:“今天天气真好”。

5.5 测试文生视频

http://localhost:8080/bailian/video?prompt=一只小猫在草地上追逐蝴蝶

返回视频地址。如果是异步任务,可能会返回一个类似 task_id 的标识,需要再调用查询接口。实际开发中应实现任务提交和轮询机制。

六、常见问题与避坑提示

问题一:文生视频是异步的,接口返回的不是最终视频

百炼的文生视频模型通常采用异步任务方式。调用后立即返回一个任务 ID,你需要通过任务 ID 轮询结果。Spring AI Alibaba 的 DashScopeVideoModel 可能封装了同步等待或返回 VideoResponse 时已包含结果,这取决于使用的版本。在实际生产代码中,建议参考百炼官方文档实现异步处理逻辑。

问题二:语音合成模型名称变化

百炼平台不断更新模型库,cosyvoice-v1 可能会被新版替代。如果调用时提示模型不存在,请到百炼控制台查看最新的模型列表并更新 application.yml

问题三:图像生成和语音合成有频率限制

免费额度下,每分钟调用次数有限。如果频繁调用返回 429 错误,请降低请求频率或升级账户。

问题四:依赖冲突

如果项目中同时引入了 spring-ai-starter-model-openaispring-ai-alibaba-starter-dashscope,由于它们都提供了 ChatModel 等接口的实现,可能导致 Bean 注入歧义。建议在学习本篇文章时创建独立项目,或者在注入时使用 @Qualifier 指定具体 Bean 名称。

问题五:音频文件格式

语音识别支持多种格式:mp3, wav, m4a, flac 等。但采样率需要注意,如果你用的是 paraformer-8k,音频采样率应为 8kHz。更通用的 paraformer-16k 对应 16kHz 采样率,请根据实际录音设备调整。

七、小结与下一步预告

本篇回顾

  • 使用 Spring AI Alibaba DashScope starter,一个依赖搞定图像、语音、视频四种多模态能力。
  • 学习了 DashScopeImageModelDashScopeSpeechSynthesisModelDashScopeAudioTranscriptionModelDashScopeVideoModel 的基本用法。
  • 在同一个项目中,用统一的配置和调用风格完成了文生图、TTS、STT、文生视频的实战。

下一步预告

多模态能力已经齐备,但我们的 AI 应用还缺少一种“超能力”——调用外部工具。下一篇,我们将进入 Tool Calling 的世界,让 AI 学会调用你的业务方法(比如查询数据库、发送邮件、调用第三方 API),真正从“参谋”变成“执行者”。

下一篇《Tool Calling:让 AI 动手调用你的业务方法》见。


本系列博客基于 Spring AI 1.1.6 和 Spring AI Alibaba 1.1.2.0 版本编写。百炼平台模型列表和服务状态可能会更新,请以阿里云官方文档为准。实际生产环境中,请处理好异步任务、费用控制和异常重试。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐