Commit 447526a6d9c31cce93a27da4176a345f881baf6f

Authored by xiaoxin
1 parent 3afb3089

【新增】AI:suno

yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoApi.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.suno;
  2 +
  3 +
  4 +import com.fasterxml.jackson.annotation.JsonInclude;
  5 +import com.fasterxml.jackson.annotation.JsonProperty;
  6 +import com.fasterxml.jackson.databind.ObjectMapper;
  7 +import lombok.Data;
  8 +import lombok.experimental.Accessors;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import okhttp3.*;
  11 +
  12 +import java.io.IOException;
  13 +import java.util.List;
  14 +import java.util.concurrent.TimeUnit;
  15 +
  16 +/**
  17 + * @Author xiaoxin
  18 + * @Date 2024/5/27
  19 + */
  20 +@Slf4j
  21 +public class SunoApi {
  22 +
  23 + public static final String APPLICATION_JSON = "application/json";
  24 + public static final String TOKEN_PREFIX = "Bearer ";
  25 + public static final String API_URL = "https://api.acedata.cloud/suno/audios";
  26 + public static final String TEST_TOKEN = "13f13540dd3f4ae9885f63ac9f5d0b9f";
  27 + private static final int READ_TIMEOUT = 160; // 连接超时时间(秒),音乐生成时间较长,设置为 160s,后续可做callback
  28 + private final OkHttpClient client;
  29 + private final ObjectMapper objectMapper;
  30 +
  31 + public SunoApi() {
  32 + this.client = new OkHttpClient().newBuilder().readTimeout(READ_TIMEOUT, TimeUnit.SECONDS).build();
  33 + this.objectMapper = new ObjectMapper();
  34 + }
  35 +
  36 + public SunoResponse generateMusic(SunoRequest sunoRequest) throws IOException {
  37 + Request request = new Request.Builder()
  38 + .url(API_URL)
  39 + .header("Authorization", TOKEN_PREFIX + TEST_TOKEN)
  40 + .post(RequestBody.create(MediaType.parse(APPLICATION_JSON), objectMapper.writeValueAsString(sunoRequest)))
  41 + .build();
  42 +
  43 + try (Response response = client.newCall(request).execute()) {
  44 + if (!response.isSuccessful()) {
  45 + log.error("suno调用失败! response: {}", response);
  46 + throw new IllegalStateException("suno调用失败!" + response);
  47 + }
  48 + return objectMapper.readValue(response.body().string(), SunoResponse.class);
  49 + }
  50 + }
  51 +
  52 +
  53 + /**
  54 + * 请求数据对象,用于生成音乐音频
  55 + */
  56 + @Data
  57 + @Accessors(chain = true)
  58 + @JsonInclude(value = JsonInclude.Include.NON_NULL)
  59 + public static class SunoRequest {
  60 + /**
  61 + * 用于生成音乐音频的提示
  62 + */
  63 + private String prompt;
  64 +
  65 + /**
  66 + * 用于生成音乐音频的歌词
  67 + */
  68 + private String lyric;
  69 +
  70 + /**
  71 + * 指示音乐音频是否为定制,如果为 true,则从歌词生成,否则从提示生成
  72 + */
  73 + private boolean custom;
  74 +
  75 + /**
  76 + * 音乐音频的标题
  77 + */
  78 + private String title;
  79 +
  80 + /**
  81 + * 音乐音频的风格
  82 + */
  83 + private String style;
  84 +
  85 + /**
  86 + * 音乐音频生成后回调的 URL
  87 + */
  88 + private String callbackUrl;
  89 + }
  90 +
  91 +
  92 + /**
  93 + * API 响应的数据
  94 + */
  95 + @Data
  96 + public static class SunoResponse {
  97 + /**
  98 + * 表示请求是否成功
  99 + */
  100 + private boolean success;
  101 +
  102 + /**
  103 + * 任务 ID
  104 + */
  105 + @JsonProperty("task_id")
  106 + private String taskId;
  107 +
  108 + /**
  109 + * 音乐数据列表
  110 + */
  111 + private List<MusicData> data;
  112 +
  113 + /**
  114 + * 表示单个音乐数据的类
  115 + */
  116 + @Data
  117 + static class MusicData {
  118 + /**
  119 + * 音乐数据的 ID
  120 + */
  121 + private String id;
  122 +
  123 + /**
  124 + * 音乐音频的标题
  125 + */
  126 + private String title;
  127 +
  128 + /**
  129 + * 音乐音频的图片 URL
  130 + */
  131 + @JsonProperty("image_url")
  132 + private String imageUrl;
  133 +
  134 + /**
  135 + * 音乐音频的歌词
  136 + */
  137 + private String lyric;
  138 +
  139 + /**
  140 + * 音乐音频的 URL
  141 + */
  142 + @JsonProperty("audio_url")
  143 + private String audioUrl;
  144 +
  145 + /**
  146 + * 音乐视频的 URL
  147 + */
  148 + @JsonProperty("video_url")
  149 + private String videoUrl;
  150 +
  151 + /**
  152 + * 音乐音频的创建时间
  153 + */
  154 + @JsonProperty("created_at")
  155 + private String createdAt;
  156 +
  157 + /**
  158 + * 使用的模型名称
  159 + */
  160 + private String model;
  161 +
  162 + /**
  163 + * 生成音乐音频的提示
  164 + */
  165 + private String prompt;
  166 +
  167 + /**
  168 + * 音乐音频的风格
  169 + */
  170 + private String style;
  171 + }
  172 + }
  173 +
  174 +
  175 +}
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.suno;
  2 +
  3 +import cn.iocoder.yudao.framework.ai.core.model.suno.SunoApi;
  4 +import org.junit.Test;
  5 +
  6 +import java.io.IOException;
  7 +
  8 +/**
  9 + * @Author xiaoxin
  10 + * @Date 2024/5/27
  11 + */
  12 +public class SunoTests {
  13 +
  14 +
  15 + @Test
  16 + public void generateMusic() throws IOException {
  17 + SunoApi sunoApi = new SunoApi();
  18 + SunoApi.SunoRequest sunoRequest = new SunoApi
  19 + .SunoRequest()
  20 + .setPrompt("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。");
  21 + SunoApi.SunoResponse sunoResponse = sunoApi.generateMusic(sunoRequest);
  22 + System.out.println(sunoResponse);
  23 + }
  24 +}
... ...