Commit 851c290c0d3240822272757cc0ef940fb2ebfb47

Authored by xiaoxin
1 parent c0de6cc5

【增加】AI:使用suno-api服务接入Suno

yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java
1 package cn.iocoder.yudao.module.ai.controller.admin.music.vo; 1 package cn.iocoder.yudao.module.ai.controller.admin.music.vo;
2 2
3 -import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; 3 +import cn.iocoder.yudao.framework.ai.core.model.suno.api.AceDataSunoApi;
4 import com.fasterxml.jackson.annotation.JsonProperty; 4 import com.fasterxml.jackson.annotation.JsonProperty;
5 import lombok.Data; 5 import lombok.Data;
6 6
@@ -66,7 +66,7 @@ public class MusicDataVO { @@ -66,7 +66,7 @@ public class MusicDataVO {
66 */ 66 */
67 private String style; 67 private String style;
68 68
69 - public static List<MusicDataVO> convertFrom(List<SunoApi.SunoResp.MusicData> musicDataList) { 69 + public static List<MusicDataVO> convertFrom(List<AceDataSunoApi.SunoResp.MusicData> musicDataList) {
70 return musicDataList.stream().map(musicData -> { 70 return musicDataList.stream().map(musicData -> {
71 MusicDataVO musicDataVO = new MusicDataVO(); 71 MusicDataVO musicDataVO = new MusicDataVO();
72 musicDataVO.setId(musicData.id()); 72 musicDataVO.setId(musicData.id());
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java
1 package cn.iocoder.yudao.module.ai.controller.admin.music.vo; 1 package cn.iocoder.yudao.module.ai.controller.admin.music.vo;
2 2
3 -import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; 3 +import cn.iocoder.yudao.framework.ai.core.model.suno.api.AceDataSunoApi;
4 import com.fasterxml.jackson.annotation.JsonProperty; 4 import com.fasterxml.jackson.annotation.JsonProperty;
5 import lombok.Data; 5 import lombok.Data;
6 6
@@ -29,7 +29,7 @@ public class SunoRespVO { @@ -29,7 +29,7 @@ public class SunoRespVO {
29 29
30 30
31 //把 SunoResp转为本vo类 31 //把 SunoResp转为本vo类
32 - public static SunoRespVO convertFrom(SunoApi.SunoResp sunoResp) { 32 + public static SunoRespVO convertFrom(AceDataSunoApi.SunoResp sunoResp) {
33 SunoRespVO sunoRespVO = new SunoRespVO(); 33 SunoRespVO sunoRespVO = new SunoRespVO();
34 sunoRespVO.setSuccess(sunoResp.success()); 34 sunoRespVO.setSuccess(sunoResp.success());
35 sunoRespVO.setTaskId(sunoResp.taskId()); 35 sunoRespVO.setTaskId(sunoResp.taskId());
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java
1 package cn.iocoder.yudao.module.ai.service.music; 1 package cn.iocoder.yudao.module.ai.service.music;
2 2
3 -import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; 3 +import cn.iocoder.yudao.framework.ai.core.model.suno.api.AceDataSunoApi;
4 import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoReqVO; 4 import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoReqVO;
5 import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoRespVO; 5 import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoRespVO;
6 import lombok.RequiredArgsConstructor; 6 import lombok.RequiredArgsConstructor;
@@ -14,11 +14,11 @@ import org.springframework.stereotype.Service; @@ -14,11 +14,11 @@ import org.springframework.stereotype.Service;
14 @RequiredArgsConstructor 14 @RequiredArgsConstructor
15 public class MusicServiceImpl implements MusicService { 15 public class MusicServiceImpl implements MusicService {
16 16
17 - private final SunoApi sunoApi; 17 + private final AceDataSunoApi aceDataSunoApi;
18 18
19 @Override 19 @Override
20 public SunoRespVO musicGen(SunoReqVO sunoReqVO) { 20 public SunoRespVO musicGen(SunoReqVO sunoReqVO) {
21 - SunoApi.SunoResp sunoResp = sunoApi.musicGen(new SunoApi.SunoReq( 21 + AceDataSunoApi.SunoResp sunoResp = aceDataSunoApi.musicGen(new AceDataSunoApi.SunoReq(
22 sunoReqVO.getPrompt(), 22 sunoReqVO.getPrompt(),
23 sunoReqVO.getLyric(), 23 sunoReqVO.getLyric(),
24 sunoReqVO.isCustom(), 24 sunoReqVO.isCustom(),
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java
@@ -4,7 +4,7 @@ import cn.hutool.core.io.IoUtil; @@ -4,7 +4,7 @@ import cn.hutool.core.io.IoUtil;
4 import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; 4 import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory;
5 import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactoryImpl; 5 import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactoryImpl;
6 import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig; 6 import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig;
7 -import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; 7 +import cn.iocoder.yudao.framework.ai.core.model.suno.api.AceDataSunoApi;
8 import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; 8 import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient;
9 import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; 9 import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal;
10 import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; 10 import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions;
@@ -150,8 +150,8 @@ public class YudaoAiAutoConfiguration { @@ -150,8 +150,8 @@ public class YudaoAiAutoConfiguration {
150 150
151 @Bean 151 @Bean
152 @ConditionalOnProperty(value = "yudao.ai.suno.enable", havingValue = "true") 152 @ConditionalOnProperty(value = "yudao.ai.suno.enable", havingValue = "true")
153 - public SunoApi sunoApi(YudaoAiProperties yudaoAiProperties) {  
154 - return new SunoApi(new SunoConfig(yudaoAiProperties.getSuno().getToken())); 153 + public AceDataSunoApi sunoApi(YudaoAiProperties yudaoAiProperties) {
  154 + return new AceDataSunoApi(new SunoConfig(yudaoAiProperties.getSuno().getToken()));
155 } 155 }
156 156
157 private static @NotNull MidjourneyConfig getMidjourneyConfig(ApplicationContext applicationContext, 157 private static @NotNull MidjourneyConfig getMidjourneyConfig(ApplicationContext applicationContext,
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/AceDataSunoApi.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.suno.api;
  2 +
  3 +import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig;
  4 +import com.fasterxml.jackson.annotation.JsonInclude;
  5 +import com.fasterxml.jackson.annotation.JsonProperty;
  6 +import lombok.extern.slf4j.Slf4j;
  7 +import org.springframework.ai.openai.api.ApiUtils;
  8 +import org.springframework.web.reactive.function.client.WebClient;
  9 +import reactor.core.publisher.Mono;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * Suno API
  15 + * <br>
  16 + * 文档地址:https://platform.acedata.cloud/documents/d016ee3f-421b-4b6e-989a-8beba8701701
  17 + *
  18 + * @Author xiaoxin
  19 + * @Date 2024/5/27
  20 + */
  21 +@Slf4j
  22 +public class AceDataSunoApi {
  23 +
  24 + public static final String DEFAULT_BASE_URL = "https://api.acedata.cloud/suno";
  25 + private final WebClient webClient;
  26 +
  27 + public AceDataSunoApi(SunoConfig config) {
  28 + this.webClient = WebClient.builder()
  29 + .baseUrl(DEFAULT_BASE_URL)
  30 + .defaultHeaders(ApiUtils.getJsonContentHeaders(config.getToken()))
  31 + .build();
  32 + }
  33 +
  34 + // TODO @芋艿:方法名,要考虑下;
  35 + public SunoResp musicGen(SunoReq sunReq) {
  36 + return this.webClient.post()
  37 + .uri("/audios")
  38 + .body(Mono.just(sunReq), SunoReq.class)
  39 + .retrieve()
  40 + .onStatus(status -> !status.is2xxSuccessful(),
  41 + response -> response.bodyToMono(String.class)
  42 + .handle((respBody, sink) -> {
  43 + log.error("【Suno】调用失败!resp: 【{}】", respBody);
  44 + sink.error(new IllegalStateException("【Suno】调用失败!"));
  45 + }))
  46 + .bodyToMono(SunoResp.class)
  47 + .block();
  48 + }
  49 +
  50 + /**
  51 + * 请求数据对象,用于生成音乐音频。
  52 + *
  53 + * @param prompt 用于生成音乐音频的提示
  54 + * @param lyric 用于生成音乐音频的歌词
  55 + * @param custom 指示音乐音频是否为定制,如果为 true,则从歌词生成,否则从提示生成
  56 + * @param title 音乐音频的标题
  57 + * @param style 音乐音频的风格
  58 + * @param callbackUrl 音乐音频生成后回调的 URL
  59 + */
  60 + @JsonInclude(value = JsonInclude.Include.NON_NULL)
  61 + public record SunoReq(
  62 + String prompt,
  63 + String lyric,
  64 + boolean custom,
  65 + String title,
  66 + String style,
  67 + String callbackUrl
  68 + ) {
  69 + public SunoReq(String prompt) {
  70 + this(prompt, null, false, null, null, null);
  71 + }
  72 +
  73 + }
  74 +
  75 + /**
  76 + * SunoAPI 响应的数据。
  77 + *
  78 + * @param success 表示请求是否成功
  79 + * @param taskId 任务 ID
  80 + * @param data 音乐数据列表
  81 + */
  82 + public record SunoResp(
  83 + boolean success,
  84 + @JsonProperty("task_id") String taskId,
  85 + List<MusicData> data
  86 + ) {
  87 + /**
  88 + * 单个音乐数据。
  89 + *
  90 + * @param id 音乐数据的 ID
  91 + * @param title 音乐音频的标题
  92 + * @param imageUrl 音乐音频的图片 URL
  93 + * @param lyric 音乐音频的歌词
  94 + * @param audioUrl 音乐音频的 URL
  95 + * @param videoUrl 音乐视频的 URL
  96 + * @param createdAt 音乐音频的创建时间
  97 + * @param model 使用的模型名称
  98 + * @param prompt 生成音乐音频的提示
  99 + * @param style 音乐音频的风格
  100 + */
  101 + public record MusicData(
  102 + String id,
  103 + String title,
  104 + @JsonProperty("image_url") String imageUrl,
  105 + String lyric,
  106 + @JsonProperty("audio_url") String audioUrl,
  107 + @JsonProperty("video_url") String videoUrl,
  108 + @JsonProperty("created_at") String createdAt,
  109 + String model,
  110 + String prompt,
  111 + String style
  112 + ) {
  113 + }
  114 + }
  115 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java
1 package cn.iocoder.yudao.framework.ai.core.model.suno.api; 1 package cn.iocoder.yudao.framework.ai.core.model.suno.api;
2 2
3 -import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig;  
4 import com.fasterxml.jackson.annotation.JsonInclude; 3 import com.fasterxml.jackson.annotation.JsonInclude;
5 import com.fasterxml.jackson.annotation.JsonProperty; 4 import com.fasterxml.jackson.annotation.JsonProperty;
6 import lombok.extern.slf4j.Slf4j; 5 import lombok.extern.slf4j.Slf4j;
7 -import org.springframework.ai.openai.api.ApiUtils; 6 +import org.springframework.core.ParameterizedTypeReference;
  7 +import org.springframework.http.HttpStatusCode;
  8 +import org.springframework.http.MediaType;
  9 +import org.springframework.web.reactive.function.client.ClientResponse;
8 import org.springframework.web.reactive.function.client.WebClient; 10 import org.springframework.web.reactive.function.client.WebClient;
9 import reactor.core.publisher.Mono; 11 import reactor.core.publisher.Mono;
10 12
11 import java.util.List; 13 import java.util.List;
  14 +import java.util.function.Function;
  15 +import java.util.function.Predicate;
12 16
13 /** 17 /**
14 * Suno API 18 * Suno API
15 * <br> 19 * <br>
16 - * 文档地址:https://platform.acedata.cloud/documents/d016ee3f-421b-4b6e-989a-8beba8701701 20 + * 文档地址:https://github.com/status2xx/suno-api/blob/main/README_CN.md
17 * 21 *
18 * @Author xiaoxin 22 * @Author xiaoxin
19 - * @Date 2024/5/27 23 + * @Date 2024/6/3
20 */ 24 */
21 @Slf4j 25 @Slf4j
22 public class SunoApi { 26 public class SunoApi {
23 27
24 - public static final String DEFAULT_BASE_URL = "https://api.acedata.cloud/suno"; 28 + public static final String DEFAULT_BASE_URL = "https://suno-9323szg26-status2xxs-projects.vercel.app";
25 private final WebClient webClient; 29 private final WebClient webClient;
26 30
27 - public SunoApi(SunoConfig config) { 31 +
  32 + private final Predicate<HttpStatusCode> STATUS_PREDICATE = status -> !status.is2xxSuccessful();
  33 + private final Function<ClientResponse, Mono<? extends Throwable>> EXCEPTION_FUNCTION = response -> response.bodyToMono(String.class)
  34 + .handle((respBody, sink) -> {
  35 + log.error("【suno-api】调用失败!resp: 【{}】", respBody);
  36 + sink.error(new IllegalStateException("【suno-api】调用失败!"));
  37 + });
  38 +
  39 +
  40 + public SunoApi() {
28 this.webClient = WebClient.builder() 41 this.webClient = WebClient.builder()
29 .baseUrl(DEFAULT_BASE_URL) 42 .baseUrl(DEFAULT_BASE_URL)
30 - .defaultHeaders(ApiUtils.getJsonContentHeaders(config.getToken())) 43 + .defaultHeaders((headers) -> headers.setContentType(MediaType.APPLICATION_JSON))
31 .build(); 44 .build();
32 } 45 }
33 46
34 - // TODO @芋艿:方法名,要考虑下;  
35 - public SunoResp musicGen(SunoReq sunReq) { 47 + public List<MusicData> generate(SunoApi.SunoReq sunReq) {
  48 + return this.webClient.post()
  49 + .uri("/api/generate")
  50 + .body(Mono.just(sunReq), SunoApi.SunoReq.class)
  51 + .retrieve()
  52 + .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION)
  53 + .bodyToMono(new ParameterizedTypeReference<List<MusicData>>() {
  54 + })
  55 + .block();
  56 + }
  57 +
  58 + public List<MusicData> doChatCompletion(String prompt) {
  59 + return this.webClient.post()
  60 + .uri("/v1/chat/completions")
  61 + .body(Mono.just(new SunoReq(prompt)), SunoApi.SunoReq.class)
  62 + .retrieve()
  63 + .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION)
  64 + .bodyToMono(new ParameterizedTypeReference<List<MusicData>>() {
  65 + })
  66 + .block();
  67 + }
  68 +
  69 + public LyricsData generateLyrics(String prompt) {
36 return this.webClient.post() 70 return this.webClient.post()
37 - .uri("/audios")  
38 - .body(Mono.just(sunReq), SunoReq.class) 71 + .uri("/api/generate_lyrics")
  72 + .body(Mono.just(new SunoReq(prompt)), SunoApi.SunoReq.class)
  73 + .retrieve()
  74 + .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION)
  75 + .bodyToMono(LyricsData.class)
  76 + .block();
  77 + }
  78 +
  79 +
  80 + public List<MusicData> selectById(String ids) {
  81 + return this.webClient.get()
  82 + .uri(uriBuilder -> uriBuilder
  83 + .path("/api/get")
  84 + .queryParam("ids", ids)
  85 + .build())
39 .retrieve() 86 .retrieve()
40 - .onStatus(status -> !status.is2xxSuccessful(),  
41 - response -> response.bodyToMono(String.class)  
42 - .handle((respBody, sink) -> {  
43 - log.error("【Suno】调用失败!resp: 【{}】", respBody);  
44 - sink.error(new IllegalStateException("【Suno】调用失败!"));  
45 - }))  
46 - .bodyToMono(SunoResp.class) 87 + .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION)
  88 + .bodyToMono(new ParameterizedTypeReference<List<MusicData>>() {
  89 + })
47 .block(); 90 .block();
48 } 91 }
49 92
  93 +
  94 + public LimitData selectLimit() {
  95 + return this.webClient.get()
  96 + .uri("/api/get_limit")
  97 + .retrieve()
  98 + .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION)
  99 + .bodyToMono(LimitData.class)
  100 + .block();
  101 + }
  102 +
  103 +
50 /** 104 /**
51 - * 请求数据对象,用于生成音乐音频。 105 + * 根据提示生成音频
52 * 106 *
53 - * @param prompt 用于生成音乐音频的提示  
54 - * @param lyric 用于生成音乐音频的歌词  
55 - * @param custom 指示音乐音频是否为定制,如果为 true,则从歌词生成,否则从提示生成  
56 - * @param title 音乐音频的标题  
57 - * @param style 音乐音频的风格  
58 - * @param callbackUrl 音乐音频生成后回调的 URL 107 + * @param prompt 用于生成音乐音频的提示
  108 + * @param tags 自定义模式才需要
  109 + * @param title 自定义模式才需要
  110 + * @param waitAudio false表示后台模式,仅返回音频任务信息,需要调用get API获取详细的音频信息。
  111 + * true表示同步模式,API最多等待100s,音频生成完毕后直接返回音频链接等信息,建议在GPT等agent中使用。
  112 + * @param makeInstrumental 指示音乐音频是否为定制,如果为 true,则从歌词生成,否则从提示生成
59 */ 113 */
60 @JsonInclude(value = JsonInclude.Include.NON_NULL) 114 @JsonInclude(value = JsonInclude.Include.NON_NULL)
61 public record SunoReq( 115 public record SunoReq(
62 String prompt, 116 String prompt,
63 - String lyric,  
64 - boolean custom, 117 + String tags,
65 String title, 118 String title,
66 - String style,  
67 - String callbackUrl 119 + @JsonProperty("wait_audio") boolean waitAudio,
  120 + @JsonProperty("make_instrumental") boolean makeInstrumental
68 ) { 121 ) {
69 public SunoReq(String prompt) { 122 public SunoReq(String prompt) {
70 - this(prompt, null, false, null, null, null); 123 + this(prompt, null, null, false, false);
71 } 124 }
72 125
  126 + public SunoReq(String prompt, String tags, String title) {
  127 + this(prompt, tags, title, false, false);
  128 + }
73 } 129 }
74 130
  131 +
75 /** 132 /**
76 - * SunoAPI 响应的数据。 133 + * SunoAPI 响应的音频数据。
77 * 134 *
78 - * @param success 表示请求是否成功  
79 - * @param taskId 任务 ID  
80 - * @param data 音乐数据列表 135 + * @param id 音乐数据的 ID
  136 + * @param title 音乐音频的标题
  137 + * @param imageUrl 音乐音频的图片 URL
  138 + * @param lyric 音乐音频的歌词
  139 + * @param audioUrl 音乐音频的 URL
  140 + * @param videoUrl 音乐视频的 URL
  141 + * @param createdAt 音乐音频的创建时间
  142 + * @param modelName
  143 + * @param status
  144 + * @param gptDescriptionPrompt
  145 + * @param prompt 生成音乐音频的提示
  146 + * @param type
  147 + * @param tags
81 */ 148 */
82 - public record SunoResp(  
83 - boolean success,  
84 - @JsonProperty("task_id") String taskId,  
85 - List<MusicData> data 149 + public record MusicData(
  150 + String id,
  151 + String title,
  152 + @JsonProperty("image_url") String imageUrl,
  153 + String lyric,
  154 + @JsonProperty("audio_url") String audioUrl,
  155 + @JsonProperty("video_url") String videoUrl,
  156 + @JsonProperty("created_at") String createdAt,
  157 + @JsonProperty("model_name") String modelName,
  158 + String status,
  159 + @JsonProperty("gpt_description_prompt") String gptDescriptionPrompt,
  160 + String prompt,
  161 + String type,
  162 + String tags
86 ) { 163 ) {
87 - /**  
88 - * 单个音乐数据。  
89 - *  
90 - * @param id 音乐数据的 ID  
91 - * @param title 音乐音频的标题  
92 - * @param imageUrl 音乐音频的图片 URL  
93 - * @param lyric 音乐音频的歌词  
94 - * @param audioUrl 音乐音频的 URL  
95 - * @param videoUrl 音乐视频的 URL  
96 - * @param createdAt 音乐音频的创建时间  
97 - * @param model 使用的模型名称  
98 - * @param prompt 生成音乐音频的提示  
99 - * @param style 音乐音频的风格  
100 - */  
101 - public record MusicData(  
102 - String id,  
103 - String title,  
104 - @JsonProperty("image_url") String imageUrl,  
105 - String lyric,  
106 - @JsonProperty("audio_url") String audioUrl,  
107 - @JsonProperty("video_url") String videoUrl,  
108 - @JsonProperty("created_at") String createdAt,  
109 - String model,  
110 - String prompt,  
111 - String style  
112 - ) {  
113 - }  
114 } 164 }
  165 +
  166 +
  167 + /**
  168 + * SunoAPI 响应的歌词数据。
  169 + *
  170 + * @param text 歌词
  171 + * @param title 标题
  172 + * @param status 状态
  173 + */
  174 + public record LyricsData(
  175 + String text,
  176 + String title,
  177 + String status
  178 + ) {
  179 + }
  180 +
  181 +
  182 + /**
  183 + * SunoAPI 响应的限额数据,目前每日免费50
  184 + */
  185 + public record LimitData(
  186 + @JsonProperty("credits_left") Long creditsLeft,
  187 + String period,
  188 + @JsonProperty("monthly_limit") Long monthlyLimit,
  189 + @JsonProperty("monthly_usage") Long monthlyUsage
  190 + ) {
  191 + }
  192 +
  193 +
115 } 194 }
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java
@@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; @@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
5 import org.junit.Before; 5 import org.junit.Before;
6 import org.junit.Test; 6 import org.junit.Test;
7 7
  8 +import java.util.List;
  9 +
8 /** 10 /**
9 * @Author xiaoxin 11 * @Author xiaoxin
10 * @Date 2024/5/27 12 * @Date 2024/5/27
@@ -20,12 +22,43 @@ public class SunoTests { @@ -20,12 +22,43 @@ public class SunoTests {
20 } 22 }
21 23
22 @Test 24 @Test
23 - public void generateMusic() {  
24 - SunoApi sunoApi = new SunoApi(sunoConfig);  
25 - SunoApi.SunoReq sunoReq = new SunoApi.SunoReq("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。"); 25 + public void selectById() {
  26 + SunoApi sunoApi = new SunoApi();
  27 + System.out.println(sunoApi.selectById("d460ddda-7c87-4f34-b751-419b08a590ca,ff90ea66-49cd-4fd2-b44c-44267dfd5551"));
  28 +
  29 + }
  30 +
  31 + @Test
  32 + public void generate() {
  33 + SunoApi sunoApi = new SunoApi();
  34 + List<SunoApi.MusicData> generate = sunoApi.generate(new SunoApi.SunoReq("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。"));
  35 + System.out.println(generate);
  36 + }
  37 +
  38 +
  39 + @Test
  40 + public void doChatCompletion() {
  41 + SunoApi sunoApi = new SunoApi();
  42 + List<SunoApi.MusicData> generate = sunoApi.doChatCompletion("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。");
  43 + System.out.println(generate);
  44 + }
  45 +
  46 +
  47 + @Test
  48 + public void generateLyrics() {
  49 + SunoApi sunoApi = new SunoApi();
  50 + SunoApi.LyricsData lyricsData = sunoApi.generateLyrics("A soothing lullaby");
  51 + System.out.println(lyricsData);
  52 + }
26 53
27 - SunoApi.SunoResp sunoResp = sunoApi.musicGen(sunoReq);  
28 - System.out.println(sunoResp); 54 +
  55 +
  56 + @Test
  57 + public void selectLimit() {
  58 + SunoApi sunoApi = new SunoApi();
  59 + SunoApi.LimitData limitData = sunoApi.selectLimit();
  60 + System.out.println(limitData);
29 } 61 }
30 62
  63 +
31 } 64 }