!7 【增加】AI:我的音乐

Merge pull request !7 from 小新/master-jdk21-ai
This commit is contained in:
芋道源码 2024-06-29 00:00:59 +00:00 committed by Gitee
commit 2e9915b77b
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
11 changed files with 219 additions and 59 deletions

View File

@ -15,8 +15,8 @@ import java.util.Arrays;
@Getter @Getter
public enum AiMusicGenerateModeEnum implements IntArrayValuable { public enum AiMusicGenerateModeEnum implements IntArrayValuable {
LYRIC(1, "歌词模式"), DESCRIPTION(1, "描述模式"),
DESCRIPTION(2, "描述模式"); LYRIC(2, "歌词模式");
/** /**
* 模式 * 模式

View File

@ -1,12 +1,10 @@
package cn.iocoder.yudao.module.ai.controller.admin.music; package cn.iocoder.yudao.module.ai.controller.admin.music;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiMusicPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.music.vo.*;
import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiMusicRespVO;
import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiMusicUpdatePublicStatusReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiSunoGenerateReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO; import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO;
import cn.iocoder.yudao.module.ai.service.music.AiMusicService; import cn.iocoder.yudao.module.ai.service.music.AiMusicService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -30,13 +28,39 @@ public class AiMusicController {
@Resource @Resource
private AiMusicService musicService; private AiMusicService musicService;
// TODO @xin一个接口获得我的音乐分页参考 获得我的聊天角色分页 来写用于我自己生成的列表和音乐广场 @GetMapping("/my-page")
@Operation(summary = "获得【我的】音乐分页")
public CommonResult<PageResult<AiMusicRespVO>> getMusicMyPage(@Valid AiMusicPageReqVO pageReqVO) {
PageResult<AiMusicDO> pageResult = musicService.getMusicMyPage(pageReqVO, getLoginUserId());
return success(BeanUtils.toBean(pageResult, AiMusicRespVO.class));
}
// TODO @xin一个接口删除我的音乐 @Operation(summary = "删除【我的】音乐记录")
@DeleteMapping("/delete-my")
@Parameter(name = "id", required = true, description = "音乐编号", example = "1024")
public CommonResult<Boolean> deleteMusicMy(@RequestParam("id") Long id) {
musicService.deleteMusicMy(id, getLoginUserId());
return success(true);
}
// TODO @xin一个接口获得我的音乐 @GetMapping("/get-my")
@Operation(summary = "获取【我的】音乐")
@Parameter(name = "id", required = true, description = "音乐编号", example = "1024")
public CommonResult<AiMusicRespVO> getMusicMy(@RequestParam("id") Long id) {
AiMusicDO music = musicService.getMusic(id);
if (music == null || ObjUtil.notEqual(getLoginUserId(), music.getUserId())) {
return success(null);
}
return success(BeanUtils.toBean(music, AiMusicRespVO.class));
}
// TODO @xin一个接口修改我的音乐目前只支持修改标题 @PostMapping("/updateTitle-my")
@Operation(summary = "修改【我的】音乐 目前只支持修改标题")
@Parameter(name = "title", required = true, description = "音乐名称", example = "夜空中最亮的星")
public CommonResult<Boolean> updateMusicTitle(AiMusicUpdateTitleReqVO updateReqVO) {
musicService.updateMusicTitle(updateReqVO);
return success(true);
}
@PostMapping("/generate") @PostMapping("/generate")
@Operation(summary = "音乐生成") @Operation(summary = "音乐生成")
@ -44,7 +68,7 @@ public class AiMusicController {
return success(musicService.generateMusic(getLoginUserId(), reqVO)); return success(musicService.generateMusic(getLoginUserId(), reqVO));
} }
// ================ 绘图管理 ================ // ================ 音乐管理 ================
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得音乐分页") @Operation(summary = "获得音乐分页")

View File

@ -61,6 +61,9 @@ public class AiMusicRespVO {
@Schema(description = "错误信息") @Schema(description = "错误信息")
private String errorMessage; private String errorMessage;
@Schema(description = "音乐时长")
private Double duration;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime; private LocalDateTime createTime;

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.ai.controller.admin.music.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - AI 音乐修改名称 Request VO")
@Data
public class AiMusicUpdateTitleReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583")
private Long id;
@Schema(description = "音乐名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "夜空中最亮的星")
@NotNull(message = "音乐名称不能为空")
private String title;
}

View File

@ -17,24 +17,38 @@ public class AiSunoGenerateReqVO {
private String platform; // 参见 AiPlatformEnum 枚举 private String platform; // 参见 AiPlatformEnum 枚举
/** /**
* 1. 描述模式描述词 + 是否纯音乐 + 模型 TODO @xin目前貌似描述词没弄对看着不是 prompt 字段也可能我弄错了可以微信再沟通下哈 * 1. 描述模式描述词 + 是否纯音乐 + 模型
* 2. 歌词模式歌词 + 音乐风格 + 标题 + 模型 TODO @xin目前这块少传递了标题 * 2. 歌词模式歌词 + 音乐风格 + 标题 + 模型
*/ */
@Schema(description = "生成模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @Schema(description = "生成模式 1.描述模式 2. 歌词模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "生成模式不能为空") @NotNull(message = "生成模式不能为空")
private Integer generateMode; // 参见 AiMusicGenerateModeEnum 枚举 private Integer generateMode; // 参见 AiMusicGenerateModeEnum 枚举
@Schema(description = "用于生成音乐音频的提示", requiredMode = Schema.RequiredMode.REQUIRED, @Schema(description = "歌词模式用:用于生成音乐音频的歌词提示", requiredMode = Schema.RequiredMode.NOT_REQUIRED,
example = "创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。") example = """
[Verse]
阳光下奔跑 多么欢快
假期就要来 心都飞起来
朋友在一旁 笑声又灿烂
无忧无虑的 每一天甜蜜
[Chorus]
马上放假了 快来庆祝
一起去旅行 快去冒险
日子太短暂 别再等待
马上放假了 梦想起飞
""")
private String prompt; private String prompt;
@Schema(description = "描述模式用:用于生成音乐音频的描述", requiredMode = Schema.RequiredMode.NOT_REQUIRED,
example = "创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。")
private String gptDescriptionPrompt;
@Schema(description = "是否纯音乐", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "true") @Schema(description = "是否纯音乐", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "true")
private Boolean makeInstrumental; private Boolean makeInstrumental;
// TODO @xin看了下这个字段发现最终还是 model 合适点因为它其实是模型 @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "chirp-v3.5")
@Schema(description = "模型版本", requiredMode = Schema.RequiredMode.REQUIRED, example = "chirp-v3.5")
@NotEmpty(message = "模型不能为空") @NotEmpty(message = "模型不能为空")
private String modelVersion; // 参见 AiModelEnum 枚举 private String model; // 参见 AiModelEnum 枚举
@Schema(description = "音乐风格", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "[\"pop\",\"jazz\",\"punk\"]") @Schema(description = "音乐风格", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "[\"pop\",\"jazz\",\"punk\"]")
private List<String> tags; private List<String> tags;

View File

@ -30,7 +30,7 @@ public class AiMusicDO extends BaseDO {
/** /**
* 用户编号 * 用户编号
* * <p>
* 关联 AdminUserDO userId 字段 * 关联 AdminUserDO userId 字段
*/ */
private Long userId; private Long userId;
@ -67,7 +67,7 @@ public class AiMusicDO extends BaseDO {
/** /**
* 生成模式 * 生成模式
* * <p>
* 枚举 {@link AiMusicGenerateModeEnum} * 枚举 {@link AiMusicGenerateModeEnum}
*/ */
private Integer generateMode; private Integer generateMode;
@ -113,4 +113,10 @@ public class AiMusicDO extends BaseDO {
*/ */
private String errorMessage; private String errorMessage;
/**
* 音乐时长
*/
private Double duration;
} }

View File

@ -32,4 +32,13 @@ public interface AiMusicMapper extends BaseMapperX<AiMusicDO> {
.orderByDesc(AiMusicDO::getId)); .orderByDesc(AiMusicDO::getId));
} }
default PageResult<AiMusicDO> selectPageByMy(AiMusicPageReqVO reqVO, Long userId) {
return selectPage(reqVO, new LambdaQueryWrapperX<AiMusicDO>()
// 情况一公开
.eq(Boolean.TRUE.equals(reqVO.getPublicStatus()), AiMusicDO::getPublicStatus, reqVO.getPublicStatus())
// 情况二私有
.eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiMusicDO::getUserId, userId)
.orderByAsc(AiMusicDO::getId));
}
} }

View File

@ -1,9 +1,7 @@
package cn.iocoder.yudao.module.ai.service.music; package cn.iocoder.yudao.module.ai.service.music;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiMusicPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.music.vo.*;
import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiMusicUpdatePublicStatusReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiSunoGenerateReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO; import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO;
import jakarta.validation.Valid; import jakarta.validation.Valid;
@ -20,7 +18,7 @@ public interface AiMusicService {
* 音乐生成 * 音乐生成
* *
* @param userId 用户编号 * @param userId 用户编号
* @param reqVO 请求参数 * @param reqVO 请求参数
* @return 生成的音乐ID * @return 生成的音乐ID
*/ */
List<Long> generateMusic(Long userId, AiSunoGenerateReqVO reqVO); List<Long> generateMusic(Long userId, AiSunoGenerateReqVO reqVO);
@ -39,6 +37,13 @@ public interface AiMusicService {
*/ */
void updateMusicPublicStatus(@Valid AiMusicUpdatePublicStatusReqVO updateReqVO); void updateMusicPublicStatus(@Valid AiMusicUpdatePublicStatusReqVO updateReqVO);
/**
* 更新音乐名称
*
* @param updateReqVO 更新信息
*/
void updateMusicTitle(@Valid AiMusicUpdateTitleReqVO updateReqVO);
/** /**
* 删除AI 音乐 * 删除AI 音乐
* *
@ -46,6 +51,22 @@ public interface AiMusicService {
*/ */
void deleteMusic(Long id); void deleteMusic(Long id);
/**
* 删除我的音乐记录
*
* @param id 音乐编号
* @param userId 用户编号
*/
void deleteMusicMy(Long id, Long userId);
/**
* 获得AI 音乐
*
* @param id 音乐编号
* @return 音乐内容
*/
AiMusicDO getMusic(Long id);
/** /**
* 获得音乐分页 * 获得音乐分页
* *
@ -54,4 +75,12 @@ public interface AiMusicService {
*/ */
PageResult<AiMusicDO> getMusicPage(AiMusicPageReqVO pageReqVO); PageResult<AiMusicDO> getMusicPage(AiMusicPageReqVO pageReqVO);
/**
* 获得我的音乐分页
*
* @param pageReqVO 分页查询
* @param userId 用户编号
* @return 音乐分页
*/
PageResult<AiMusicDO> getMusicMyPage(AiMusicPageReqVO pageReqVO, Long userId);
} }

View File

@ -2,16 +2,17 @@ package cn.iocoder.yudao.module.ai.service.music;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrPool; import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiMusicPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.music.vo.*;
import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiMusicUpdatePublicStatusReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiSunoGenerateReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO; import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO;
import cn.iocoder.yudao.module.ai.dal.mysql.music.AiMusicMapper; import cn.iocoder.yudao.module.ai.dal.mysql.music.AiMusicMapper;
import cn.iocoder.yudao.module.ai.enums.music.AiMusicGenerateModeEnum; import cn.iocoder.yudao.module.ai.enums.music.AiMusicGenerateModeEnum;
import cn.iocoder.yudao.module.ai.enums.music.AiMusicStatusEnum; import cn.iocoder.yudao.module.ai.enums.music.AiMusicStatusEnum;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -21,6 +22,7 @@ import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.IMAGE_NOT_EXISTS;
import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.MUSIC_NOT_EXISTS; import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.MUSIC_NOT_EXISTS;
/** /**
@ -38,6 +40,9 @@ public class AiMusicServiceImpl implements AiMusicService {
@Resource @Resource
private AiMusicMapper musicMapper; private AiMusicMapper musicMapper;
@Resource
private FileApi fileApi;
@Override @Override
public List<Long> generateMusic(Long userId, AiSunoGenerateReqVO reqVO) { public List<Long> generateMusic(Long userId, AiSunoGenerateReqVO reqVO) {
// 1. 调用 Suno 生成音乐 // 1. 调用 Suno 生成音乐
@ -45,12 +50,12 @@ public class AiMusicServiceImpl implements AiMusicService {
if (Objects.equals(AiMusicGenerateModeEnum.LYRIC.getMode(), reqVO.getGenerateMode())) { if (Objects.equals(AiMusicGenerateModeEnum.LYRIC.getMode(), reqVO.getGenerateMode())) {
// 1.1 歌词模式 // 1.1 歌词模式
SunoApi.MusicGenerateRequest generateRequest = new SunoApi.MusicGenerateRequest( SunoApi.MusicGenerateRequest generateRequest = new SunoApi.MusicGenerateRequest(
reqVO.getPrompt(), reqVO.getModelVersion(), CollUtil.join(reqVO.getTags(), StrPool.COMMA), reqVO.getTitle()); reqVO.getPrompt(), reqVO.getModel(), CollUtil.join(reqVO.getTags(), StrPool.COMMA), reqVO.getTitle());
musicDataList = sunoApi.customGenerate(generateRequest); musicDataList = sunoApi.customGenerate(generateRequest);
} else if (Objects.equals(AiMusicGenerateModeEnum.DESCRIPTION.getMode(), reqVO.getGenerateMode())) { } else if (Objects.equals(AiMusicGenerateModeEnum.DESCRIPTION.getMode(), reqVO.getGenerateMode())) {
// 1.2 描述模式 // 1.2 描述模式
SunoApi.MusicGenerateRequest generateRequest = new SunoApi.MusicGenerateRequest( SunoApi.MusicGenerateRequest generateRequest = new SunoApi.MusicGenerateRequest(
reqVO.getPrompt(), reqVO.getModelVersion(), reqVO.getMakeInstrumental()); reqVO.getGptDescriptionPrompt(), reqVO.getModel(), reqVO.getMakeInstrumental());
musicDataList = sunoApi.generate(generateRequest); musicDataList = sunoApi.generate(generateRequest);
} else { } else {
throw new IllegalArgumentException(StrUtil.format("未知生成模式({})", reqVO)); throw new IllegalArgumentException(StrUtil.format("未知生成模式({})", reqVO));
@ -90,23 +95,6 @@ public class AiMusicServiceImpl implements AiMusicService {
return streamingTask.size(); return streamingTask.size();
} }
/**
* 构建 AiMusicDO 集合
*
* @param musicList suno 音乐任务列表
* @return AiMusicDO 集合
*/
private static List<AiMusicDO> buildMusicDOList(List<SunoApi.MusicData> musicList) {
// TODO @xin成功的情况下需要下载到自己的文件服务器参考图片的处理
return convertList(musicList, musicData -> new AiMusicDO()
.setTaskId(musicData.id()).setModel(musicData.modelName())
.setPrompt(musicData.prompt()).setGptDescriptionPrompt(musicData.gptDescriptionPrompt())
.setAudioUrl(musicData.audioUrl()).setVideoUrl(musicData.videoUrl()).setImageUrl(musicData.imageUrl())
.setTitle(musicData.title()).setLyric(musicData.lyric()).setTags(StrUtil.split(musicData.tags(), StrPool.COMMA))
.setStatus(Objects.equals("complete", musicData.status()) ?
AiMusicStatusEnum.SUCCESS.getStatus() : AiMusicStatusEnum.IN_PROGRESS.getStatus()));
}
@Override @Override
public void updateMusicPublicStatus(AiMusicUpdatePublicStatusReqVO updateReqVO) { public void updateMusicPublicStatus(AiMusicUpdatePublicStatusReqVO updateReqVO) {
// 校验存在 // 校验存在
@ -115,6 +103,14 @@ public class AiMusicServiceImpl implements AiMusicService {
musicMapper.updateById(new AiMusicDO().setId(updateReqVO.getId()).setPublicStatus(updateReqVO.getPublicStatus())); musicMapper.updateById(new AiMusicDO().setId(updateReqVO.getId()).setPublicStatus(updateReqVO.getPublicStatus()));
} }
@Override
public void updateMusicTitle(AiMusicUpdateTitleReqVO updateReqVO) {
// 校验存在
validateMusicExists(updateReqVO.getId());
// 更新
musicMapper.updateById(new AiMusicDO().setId(updateReqVO.getId()).setTitle(updateReqVO.getTitle()));
}
@Override @Override
public void deleteMusic(Long id) { public void deleteMusic(Long id) {
// 校验存在 // 校验存在
@ -123,10 +119,20 @@ public class AiMusicServiceImpl implements AiMusicService {
musicMapper.deleteById(id); musicMapper.deleteById(id);
} }
private void validateMusicExists(Long id) { @Override
if (musicMapper.selectById(id) == null) { public void deleteMusicMy(Long id, Long userId) {
throw exception(MUSIC_NOT_EXISTS); // 1. 校验是否存在
AiMusicDO music = validateMusicExists(id);
if (ObjUtil.notEqual(music.getUserId(), userId)) {
throw exception(IMAGE_NOT_EXISTS);
} }
// 2. 删除记录
musicMapper.deleteById(id);
}
@Override
public AiMusicDO getMusic(Long id) {
return musicMapper.selectById(id);
} }
@Override @Override
@ -134,4 +140,53 @@ public class AiMusicServiceImpl implements AiMusicService {
return musicMapper.selectPage(pageReqVO); return musicMapper.selectPage(pageReqVO);
} }
@Override
public PageResult<AiMusicDO> getMusicMyPage(AiMusicPageReqVO pageReqVO, Long userId) {
return musicMapper.selectPageByMy(pageReqVO, userId);
}
/**
* 构建 AiMusicDO 集合
*
* @param musicList suno 音乐任务列表
* @return AiMusicDO 集合
*/
private List<AiMusicDO> buildMusicDOList(List<SunoApi.MusicData> musicList) {
return convertList(musicList, musicData -> new AiMusicDO()
.setTaskId(musicData.id()).setModel(musicData.modelName())
.setPrompt(musicData.prompt()).setGptDescriptionPrompt(musicData.gptDescriptionPrompt())
.setAudioUrl(createFile(musicData.audioUrl())).setVideoUrl(createFile(musicData.videoUrl())).setImageUrl(createFile(musicData.imageUrl())).setDuration(musicData.duration())
.setTitle(musicData.title()).setLyric(musicData.lyric()).setTags(StrUtil.split(musicData.tags(), StrPool.COMMA))
.setStatus(Objects.equals("complete", musicData.status()) ?
AiMusicStatusEnum.SUCCESS.getStatus() : AiMusicStatusEnum.IN_PROGRESS.getStatus()));
}
/**
* 将生成的音频文件上传到文件服务器
*
* @param url 音频文件地址
* @return 内部文件地址
*/
private String createFile(String url) {
if (StrUtil.isBlank(url)) {
return null;
}
byte[] bytes = HttpUtil.downloadBytes(url);
return fileApi.createFile(bytes);
}
/**
* 校验音乐是否存在
*
* @param id 音乐编号
* @return 音乐信息
*/
private AiMusicDO validateMusicExists(Long id) {
AiMusicDO music = musicMapper.selectById(id);
if (music == null) {
throw exception(MUSIC_NOT_EXISTS);
}
return music;
}
} }

View File

@ -117,7 +117,7 @@ public class SunoApi {
* @param prompt 用于生成音乐音频的提示 * @param prompt 用于生成音乐音频的提示
* @param tags 音乐风格 * @param tags 音乐风格
* @param title 音乐名称 * @param title 音乐名称
* @param mv 模型 * @param model 模型
* @param waitAudio false 表示后台模式仅返回音频任务信息需要调用 get API 获取详细的音频信息 * @param waitAudio false 表示后台模式仅返回音频任务信息需要调用 get API 获取详细的音频信息
* true 表示同步模式API 最多等待 100s音频生成完毕后直接返回音频链接等信息建议在 GPT agent 中使用 * true 表示同步模式API 最多等待 100s音频生成完毕后直接返回音频链接等信息建议在 GPT agent 中使用
* @param makeInstrumental 指示音乐音频是否为定制如果为 true则从歌词生成否则从提示生成 * @param makeInstrumental 指示音乐音频是否为定制如果为 true则从歌词生成否则从提示生成
@ -127,7 +127,7 @@ public class SunoApi {
String prompt, String prompt,
String tags, String tags,
String title, String title,
String mv, String model,
@JsonProperty("wait_audio") boolean waitAudio, @JsonProperty("wait_audio") boolean waitAudio,
@JsonProperty("make_instrumental") boolean makeInstrumental @JsonProperty("make_instrumental") boolean makeInstrumental
) { ) {
@ -136,12 +136,12 @@ public class SunoApi {
this(prompt, null, null, null, false, false); this(prompt, null, null, null, false, false);
} }
public MusicGenerateRequest(String prompt, String mv, boolean makeInstrumental) { public MusicGenerateRequest(String prompt, String model, boolean makeInstrumental) {
this(prompt, null, null, mv, false, makeInstrumental); this(prompt, null, null, model, false, makeInstrumental);
} }
public MusicGenerateRequest(String prompt, String mv, String tags, String title) { public MusicGenerateRequest(String prompt, String model, String tags, String title) {
this(prompt, tags, title, mv, false, false); this(prompt, tags, title, model, false, false);
} }
} }
@ -162,6 +162,7 @@ public class SunoApi {
* @param prompt 生成音乐音频的提示 * @param prompt 生成音乐音频的提示
* @param type 操作类型 * @param type 操作类型
* @param tags 音乐类型标签 * @param tags 音乐类型标签
* @param duration 音乐时长
*/ */
public record MusicData( public record MusicData(
String id, String id,
@ -176,7 +177,8 @@ public class SunoApi {
@JsonProperty("gpt_description_prompt") String gptDescriptionPrompt, @JsonProperty("gpt_description_prompt") String gptDescriptionPrompt,
String prompt, String prompt,
String type, String type,
String tags String tags,
Double duration
) { ) {
} }

View File

@ -201,8 +201,8 @@ yudao.ai:
notify-url: http://java.nat300.top/admin-api/ai/image/midjourney/notify notify-url: http://java.nat300.top/admin-api/ai/image/midjourney/notify
suno: suno:
enable: true enable: true
# base-url: https://suno-om0w1cy6e-status2xxs-projects.vercel.app base-url: https://suno-55ishh05u-status2xxs-projects.vercel.app
base-url: http://127.0.0.1:3001 # base-url: http://127.0.0.1:3001
--- #################### 芋道相关配置 #################### --- #################### 芋道相关配置 ####################