From bdd7d0c1fdc0ad20ad48bcc11455808f2a3bc55b Mon Sep 17 00:00:00 2001 From: xiaoxin <718949661@qq.com> Date: Fri, 28 Jun 2024 10:45:59 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E3=80=91AI=EF=BC=9A=E9=9F=B3=E4=B9=90=E7=94=9F=E6=88=90?= =?UTF-8?q?=E4=BA=A7=E7=89=A9=E4=B8=8A=E4=BC=A0=E8=87=B3=E5=86=85=E9=83=A8?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/music/AiMusicGenerateModeEnum.java | 4 +- .../admin/music/vo/AiSunoGenerateReqVO.java | 9 ++- .../ai/service/music/AiMusicServiceImpl.java | 55 ++++++++++++------- 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicGenerateModeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicGenerateModeEnum.java index 425e2bb8c..ad4b81b36 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicGenerateModeEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicGenerateModeEnum.java @@ -15,8 +15,8 @@ import java.util.Arrays; @Getter public enum AiMusicGenerateModeEnum implements IntArrayValuable { - LYRIC(1, "歌词模式"), - DESCRIPTION(2, "描述模式"); + DESCRIPTION(1, "描述模式"), + LYRIC(2, "歌词模式"); /** * 模式 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiSunoGenerateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiSunoGenerateReqVO.java index 4f0859134..d087d41e5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiSunoGenerateReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiSunoGenerateReqVO.java @@ -20,21 +20,20 @@ public class AiSunoGenerateReqVO { * 1. 描述模式:描述词 + 是否纯音乐 + 模型 TODO @xin:目前貌似描述词没弄对?看着不是 prompt 字段(也可能我弄错了)。可以微信再沟通下哈 * 2. 歌词模式:歌词 + 音乐风格 + 标题 + 模型 TODO @xin:目前这块少传递了标题; */ - @Schema(description = "生成模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @Schema(description = "生成模式 1.描述模式 2. 歌词模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @NotNull(message = "生成模式不能为空") private Integer generateMode; // 参见 AiMusicGenerateModeEnum 枚举 - @Schema(description = "用于生成音乐音频的提示", requiredMode = Schema.RequiredMode.REQUIRED, + @Schema(description = "用于生成音乐音频的提示 1.描述模式:音乐/歌词说明 2.歌词模式:歌词", requiredMode = Schema.RequiredMode.REQUIRED, example = "创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。") private String prompt; @Schema(description = "是否纯音乐", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "true") 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 = "模型不能为空") - private String modelVersion; // 参见 AiModelEnum 枚举 + private String model; // 参见 AiModelEnum 枚举 @Schema(description = "音乐风格", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "[\"pop\",\"jazz\",\"punk\"]") private List tags; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/AiMusicServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/AiMusicServiceImpl.java index 99323b73f..f352c8829 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/AiMusicServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/AiMusicServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.service.music; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.text.StrPool; 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.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.music.vo.AiMusicPageReqVO; @@ -12,6 +13,7 @@ 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.enums.music.AiMusicGenerateModeEnum; import cn.iocoder.yudao.module.ai.enums.music.AiMusicStatusEnum; +import cn.iocoder.yudao.module.infra.api.file.FileApi; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -38,6 +40,9 @@ public class AiMusicServiceImpl implements AiMusicService { @Resource private AiMusicMapper musicMapper; + @Resource + private FileApi fileApi; + @Override public List generateMusic(Long userId, AiSunoGenerateReqVO reqVO) { // 1. 调用 Suno 生成音乐 @@ -45,12 +50,12 @@ public class AiMusicServiceImpl implements AiMusicService { if (Objects.equals(AiMusicGenerateModeEnum.LYRIC.getMode(), reqVO.getGenerateMode())) { // 1.1 歌词模式 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); } else if (Objects.equals(AiMusicGenerateModeEnum.DESCRIPTION.getMode(), reqVO.getGenerateMode())) { // 1.2 描述模式 SunoApi.MusicGenerateRequest generateRequest = new SunoApi.MusicGenerateRequest( - reqVO.getPrompt(), reqVO.getModelVersion(), reqVO.getMakeInstrumental()); + reqVO.getPrompt(), reqVO.getModel(), reqVO.getMakeInstrumental()); musicDataList = sunoApi.generate(generateRequest); } else { throw new IllegalArgumentException(StrUtil.format("未知生成模式({})", reqVO)); @@ -90,23 +95,6 @@ public class AiMusicServiceImpl implements AiMusicService { return streamingTask.size(); } - /** - * 构建 AiMusicDO 集合 - * - * @param musicList suno 音乐任务列表 - * @return AiMusicDO 集合 - */ - private static List buildMusicDOList(List 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 public void updateMusicPublicStatus(AiMusicUpdatePublicStatusReqVO updateReqVO) { // 校验存在 @@ -134,4 +122,33 @@ public class AiMusicServiceImpl implements AiMusicService { return musicMapper.selectPage(pageReqVO); } + /** + * 构建 AiMusicDO 集合 + * + * @param musicList suno 音乐任务列表 + * @return AiMusicDO 集合 + */ + private List buildMusicDOList(List 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())) + .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); + } }