mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-31 17:40:05 +08:00
【代码优化】AI:音乐生成产物上传至内部文件服务
This commit is contained in:
parent
128c38ca02
commit
bdd7d0c1fd
@ -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, "歌词模式");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模式
|
* 模式
|
||||||
|
@ -20,21 +20,20 @@ public class AiSunoGenerateReqVO {
|
|||||||
* 1. 描述模式:描述词 + 是否纯音乐 + 模型 TODO @xin:目前貌似描述词没弄对?看着不是 prompt 字段(也可能我弄错了)。可以微信再沟通下哈
|
* 1. 描述模式:描述词 + 是否纯音乐 + 模型 TODO @xin:目前貌似描述词没弄对?看着不是 prompt 字段(也可能我弄错了)。可以微信再沟通下哈
|
||||||
* 2. 歌词模式:歌词 + 音乐风格 + 标题 + 模型 TODO @xin:目前这块少传递了标题;
|
* 2. 歌词模式:歌词 + 音乐风格 + 标题 + 模型 TODO @xin:目前这块少传递了标题;
|
||||||
*/
|
*/
|
||||||
@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 = "用于生成音乐音频的提示 1.描述模式:音乐/歌词说明 2.歌词模式:歌词", requiredMode = Schema.RequiredMode.REQUIRED,
|
||||||
example = "创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。")
|
example = "创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。")
|
||||||
private String prompt;
|
private String prompt;
|
||||||
|
|
||||||
@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;
|
||||||
|
@ -3,6 +3,7 @@ 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.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.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.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;
|
||||||
@ -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.getPrompt(), 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) {
|
||||||
// 校验存在
|
// 校验存在
|
||||||
@ -134,4 +122,33 @@ public class AiMusicServiceImpl implements AiMusicService {
|
|||||||
return musicMapper.selectPage(pageReqVO);
|
return musicMapper.selectPage(pageReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建 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()))
|
||||||
|
.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user