diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Music/MusicBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Music/MusicBLL.cs
index 9c0a76d..d8a21e4 100644
--- a/src/0-core/HuanMeng.MiaoYu.Code/Music/MusicBLL.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Code/Music/MusicBLL.cs
@@ -7,13 +7,19 @@ using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Net.Http.Headers;
+using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json;
+using HuanMeng.MiaoYu.Code.Chat.Contract;
+using Org.BouncyCastle.Utilities;
namespace HuanMeng.MiaoYu.Code.Music
{
///
- /// ai音乐逻辑类
+ /// ai音乐逻辑类
///
public class MusicBLL : MiaoYuBase
{
@@ -78,5 +84,105 @@ namespace HuanMeng.MiaoYu.Code.Music
musicUserGenresDtos = musicUserGenresDtos.OrderBy(it => it.GenreType).ThenBy(it => it.OrderId).ToList();
return new BaseResponse>(ResonseCode.Success, "", musicUserGenresDtos);
}
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task> CreateMusic(MusicCreateRequest musicCreateRequest)
+ {
+ if (_UserId == 0)
+ {
+ throw new Exception("请先登录");
+ }
+ UserInfoBLL userInfoBLL = new UserInfoBLL(Dao, _UserId);
+ if (!userInfoBLL.IsCheckingSufficient(UserCurrencyType.生成音乐点数, 10))
+ {
+ throw new Exception("音乐点数不足");
+ }
+ Dictionary keyValuePairs = new Dictionary();
+ keyValuePairs.Add("gpt_description_prompt", $"歌曲风格:{musicCreateRequest.GenreName}");
+ keyValuePairs.Add("make_instrumental", false);
+ keyValuePairs.Add("mv", "chirp-v3-5");
+ keyValuePairs.Add("prompt", musicCreateRequest.Prompt);
+ var requestBody = JsonConvert.SerializeObject(keyValuePairs);
+ var httpClient = HttpClientFactory.CreateClient();
+ httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ httpClient.DefaultRequestHeaders.Add("authorization", "Bearer hk-ylg6c31000042000fef54b80aec96b39e83b36f6e551440b");
+ var content = new StringContent(requestBody, Encoding.UTF8, "application/json");
+ var url = "https://api.openai-hk.com/sunoapi/generate/description-mode";
+ var response = await httpClient.PostAsync(url, content);
+ if (response == null || !response.IsSuccessStatusCode)
+ {
+ throw new Exception("创建音乐失败");
+ }
+ var responseContent = await response.Content.ReadAsStringAsync();
+ if (string.IsNullOrEmpty(responseContent))
+ {
+ throw new Exception("创建音乐失败!");
+ }
+ var obj = JsonConvert.DeserializeObject(responseContent);
+ var id = obj?["id"]?.ToString() ?? "";
+
+ var musicId1 = obj?.SelectToken("clips[0].id")?.ToString();
+ var musicId2 = obj?.SelectToken("clips[1].id")?.ToString();
+ M_SongInfo m_SongInfo = new M_SongInfo()
+ {
+ CompleteAt = DateTime.Now,
+ CreateAt = DateTime.Now,
+ GetUrl = url,
+ RequestInfo = requestBody,
+ ResonseInfo = responseContent,
+ Status = "已完成",
+ UpdateAt = DateTime.Now,
+ };
+ Dao.daoDbMiaoYu.context.Add(m_SongInfo);
+ Dao.daoDbMiaoYu.context.SaveChanges();
+ if (string.IsNullOrEmpty(musicId1) && string.IsNullOrEmpty(musicId2))
+ {
+ throw new Exception("创建音乐失败!!!");
+ }
+ if (!string.IsNullOrEmpty(musicId1))
+ {
+ var song1 = GetSong(musicCreateRequest.GenreName, musicCreateRequest.Name, musicId1, m_SongInfo.Id);
+ Dao.daoDbMiaoYu.context.Add(song1);
+ }
+ if (!string.IsNullOrEmpty(musicId2))
+ {
+ var song2 = GetSong(musicCreateRequest.GenreName, musicCreateRequest.Name, musicId2, m_SongInfo.Id);
+ Dao.daoDbMiaoYu.context.Add(song2);
+ }
+ //扣除货币
+ userInfoBLL[UserCurrencyType.生成音乐点数].ConsumeMoneyNoWork(-10, Dao);
+ return new BaseResponse(ResonseCode.Success, "音乐正在生成", true) { };
+ }
+
+ private M_Songs GetSong(string genreName, string name, string? musicId1, int songInfoId)
+ {
+ M_Songs m_Songs = new M_Songs()
+ {
+ AuthorId = _UserId,
+ CoverImage = "https://cos.shhuanmeng.com/yinyue/fengmian.png",
+ CreationTimestamp = DateTime.Now,
+ DownloadCount = 0,
+ LikeCount = 0,
+ PlayCount = 0,
+ Duration = TimeOnly.MinValue,
+ Genre = genreName,
+ GenreId = 0,
+ ImageLargeUrl = "https://cos.shhuanmeng.com/yinyue/fengmian.png",
+ IsPublic = false,
+ Lyrics = "",
+ MusicAddress = "",
+ SongInfoId = songInfoId,
+ SpecialId = musicId1,
+ State = 1,
+ Title = name
+
+ };
+ return m_Songs;
+ }
}
}
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Music/MusicService.cs b/src/0-core/HuanMeng.MiaoYu.Code/Music/MusicService.cs
new file mode 100644
index 0000000..dde8c8a
--- /dev/null
+++ b/src/0-core/HuanMeng.MiaoYu.Code/Music/MusicService.cs
@@ -0,0 +1,114 @@
+using HuanMeng.DotNetCore.MultiTenant.Contract;
+using HuanMeng.DotNetCore.Processors;
+using HuanMeng.MiaoYu.Code.AppExtend;
+
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+
+using StackExchange.Redis;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http.Headers;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace HuanMeng.MiaoYu.Code.Music
+{
+ ///
+ ///
+ ///
+ public class MusicService(IServiceProvider serviceProvider) : IHostedService, IDisposable
+ {
+ MusicProcessor? musicProcessor = null;
+ public Task StartAsync(CancellationToken cancellationToken)
+ {
+ musicProcessor = new MusicProcessor(serviceProvider);
+ musicProcessor.Run();
+ return Task.CompletedTask;
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ if (musicProcessor != null)
+ {
+ musicProcessor.Stop();
+ musicProcessor.Dispose();
+ }
+ return Task.CompletedTask;
+ }
+
+ public void Dispose()
+ {
+ musicProcessor?.Dispose();
+ }
+ }
+
+ public class MusicProcessor(IServiceProvider serviceProvider) : ThreadProcessor
+ {
+ protected override async void Proc_Do()
+ {
+ while (true)
+ {
+
+ foreach (var item in AppConfigurationExtend.AppConfigs.Values)
+ {
+
+ var service = serviceProvider.CreateScope();
+ var temantInfo = serviceProvider.GetRequiredService();
+ item.ToITenantInfo(temantInfo);
+ DAO dao = new DAO(serviceProvider);
+ var list = dao.daoDbMiaoYu.context.M_Songs.Where(it => it.State == 1).ToList();
+ if (list.Count > 0)
+ {
+ var httpFactory = serviceProvider.GetRequiredService();
+ foreach (var songs in list)
+ {
+ var httpClient = httpFactory.CreateClient();
+ httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ httpClient.DefaultRequestHeaders.Add("authorization", "Bearer hk-ylg6c31000042000fef54b80aec96b39e83b36f6e551440b");
+ var url = $"https://api.openai-hk.com/suno/feed/{songs.SpecialId}";
+ var response = await httpClient.GetAsync(url);
+ if (response == null || !response.IsSuccessStatusCode)
+ {
+ //throw new Exception("创建音乐失败");
+ continue;
+ }
+ var responseContent = await response.Content.ReadAsStringAsync();
+ if (string.IsNullOrEmpty(responseContent))
+ {
+ continue;
+ }
+ var obj = JsonConvert.DeserializeObject(responseContent);
+ //status
+ var status = obj?.SelectToken("[0].status")?.ToString();
+ if (status == "complete")
+ {
+ //obj.SelectToken("[0].video_url")?.ToString();
+
+ songs.MusicAddress = obj?.SelectToken("[0].audio_url")?.ToString() ?? "";
+ songs.CoverImage = obj?.SelectToken("[0].image_url")?.ToString() ?? "";
+ songs.ImageLargeUrl = obj?.SelectToken("[0].image_large_url")?.ToString() ?? "";
+ songs.Lyrics = obj?.SelectToken("[0].metadata.prompt")?.ToString() ?? "";
+ var duration = obj?.SelectToken("[0].metadata.duration")?.ToString() ?? "";
+ if (!string.IsNullOrEmpty(duration))
+ {
+ if (int.TryParse(duration, out var d))
+ {
+ songs.Duration = new TimeOnly(0, 0, d);
+ }
+ }
+ dao.daoDbMiaoYu.context.SaveChanges();
+ }
+ }
+ }
+ }
+ Thread.Sleep(1000 * 5);
+
+ }
+ }
+ }
+}
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs
index 99259bd..fbe0e70 100644
--- a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs
@@ -116,7 +116,7 @@ namespace HuanMeng.MiaoYu.Code.Users
public async Task> GetUserInfo()
{
var user = await Dao.daoDbMiaoYu.context.T_User.FirstOrDefaultAsync(it => it.Id == _UserId);
- var userData = await Dao.daoDbMiaoYu.context.T_User_Data.FirstOrDefaultAsync(it => it.Id == _UserId);
+ var userData = await Dao.daoDbMiaoYu.context.T_User_Data.FirstOrDefaultAsync(it => it.UserId == _UserId);
//获取用户余额
UserInfoBLL userInfoBLL = new UserInfoBLL(Dao, _UserId);
var Currency = userInfoBLL[UserCurrencyType.语珠]?.CurrencyMoney;
@@ -134,7 +134,7 @@ namespace HuanMeng.MiaoYu.Code.Users
NickName = user.NickName,
UserId = user.Id,
Currency = (int)Currency,
- UserIconUrl = string.IsNullOrEmpty(userData.UserIconUrl) ? "https://cos.shhuanmeng.com/default.png" : userData.UserIconUrl,
+ UserIconUrl = string.IsNullOrEmpty(userData?.UserIconUrl) ? "https://cos.shhuanmeng.com/default.png" : userData?.UserIconUrl,
RemainingChatCount = (int)RemainingChatCount,//这里先写1,我不会decimal转int
HasTalked = hasTalked,
Photographs = 0,
diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/M_SongInfo.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/M_SongInfo.cs
new file mode 100644
index 0000000..61f3618
--- /dev/null
+++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/M_SongInfo.cs
@@ -0,0 +1,48 @@
+using System;
+
+namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu;
+
+///
+/// 音乐任务表
+///
+public partial class M_SongInfo: MultiTenantEntity
+{
+ public virtual int Id { get; set; }
+
+ public override Guid TenantId { get; set; }
+
+ ///
+ /// 请求数据
+ ///
+ public virtual string? RequestInfo { get; set; }
+
+ ///
+ /// 返回数据
+ ///
+ public virtual string? ResonseInfo { get; set; }
+
+ ///
+ /// 请求地址
+ ///
+ public virtual string? GetUrl { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public virtual DateTime CreateAt { get; set; }
+
+ ///
+ /// 任务完成时间
+ ///
+ public virtual DateTime? CompleteAt { get; set; }
+
+ ///
+ /// 任务状态
+ ///
+ public virtual string Status { get; set; } = null!;
+
+ ///
+ /// 修改时间
+ ///
+ public virtual DateTime UpdateAt { get; set; }
+}
diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/M_Songs.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/M_Songs.cs
index a5ea316..2a1d5eb 100644
--- a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/M_Songs.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/M_Songs.cs
@@ -3,7 +3,7 @@
namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu;
///
-/// 存储所有生成的歌曲的信息。
+/// 存储所有生成的歌曲的信息
///
public partial class M_Songs: MultiTenantEntity
{
@@ -78,4 +78,24 @@ public partial class M_Songs: MultiTenantEntity
/// 音乐风格Id
///
public virtual int? GenreId { get; set; }
+
+ ///
+ /// 封面缩略图
+ ///
+ public virtual string? ImageLargeUrl { get; set; }
+
+ ///
+ /// 所属任务Id
+ ///
+ public virtual int SongInfoId { get; set; }
+
+ ///
+ /// 音乐状态,0生成功,1生成中
+ ///
+ public virtual int State { get; set; }
+
+ ///
+ /// 特殊Id
+ ///
+ public virtual string SpecialId { get; set; } = null!;
}
diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs
index 3184476..1584bfd 100644
--- a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs
@@ -74,7 +74,12 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext
public virtual DbSet M_SongComments { get; set; }
///
- /// 存储所有生成的歌曲的信息。
+ /// 音乐任务表
+ ///
+ public virtual DbSet M_SongInfo { get; set; }
+
+ ///
+ /// 存储所有生成的歌曲的信息
///
public virtual DbSet M_Songs { get; set; }
@@ -379,11 +384,39 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext
}
});
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("PK__M_SongIn__3214EC070CFDD5C9");
+
+ entity.ToTable(tb => tb.HasComment("音乐任务表"));
+
+ entity.Property(e => e.CompleteAt)
+ .HasComment("任务完成时间")
+ .HasColumnType("datetime");
+ entity.Property(e => e.CreateAt)
+ .HasComment("创建时间")
+ .HasColumnType("datetime");
+ entity.Property(e => e.GetUrl).HasComment("请求地址");
+ entity.Property(e => e.RequestInfo).HasComment("请求数据");
+ entity.Property(e => e.ResonseInfo).HasComment("返回数据");
+ entity.Property(e => e.Status)
+ .HasMaxLength(100)
+ .HasComment("任务状态");
+ entity.Property(e => e.UpdateAt)
+ .HasComment("修改时间")
+ .HasColumnType("datetime");
+ //添加全局筛选器
+ if (this.TenantInfo != null)
+ {
+ entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId);
+ }
+ });
+
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id).HasName("PK__Songs__3214EC0728D42B46");
- entity.ToTable(tb => tb.HasComment("存储所有生成的歌曲的信息。"));
+ entity.ToTable(tb => tb.HasComment("存储所有生成的歌曲的信息"));
entity.Property(e => e.Id).HasComment("歌曲唯一标识");
entity.Property(e => e.AuthorId).HasComment("歌曲作者ID");
@@ -395,14 +428,18 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext
entity.Property(e => e.DownloadCount).HasComment("下载次数");
entity.Property(e => e.Duration).HasComment("歌曲时长");
entity.Property(e => e.Genre)
- .HasMaxLength(50)
+ .HasMaxLength(200)
.HasComment("音乐风格");
entity.Property(e => e.GenreId).HasComment("音乐风格Id");
+ entity.Property(e => e.ImageLargeUrl).HasComment("封面缩略图");
entity.Property(e => e.IsPublic).HasComment("歌曲是否公开展示");
entity.Property(e => e.LikeCount).HasComment("点赞次数");
entity.Property(e => e.Lyrics).HasComment("歌词内容");
entity.Property(e => e.MusicAddress).HasComment("音乐下载地址");
entity.Property(e => e.PlayCount).HasComment("播放次数");
+ entity.Property(e => e.SongInfoId).HasComment("所属任务Id");
+ entity.Property(e => e.SpecialId).HasComment("特殊Id");
+ entity.Property(e => e.State).HasComment("音乐状态,0生成功,1生成中");
entity.Property(e => e.Title)
.HasMaxLength(200)
.HasComment("歌曲名称");
diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Music/MusicCreateRequest.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Music/MusicCreateRequest.cs
new file mode 100644
index 0000000..61a64d9
--- /dev/null
+++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Music/MusicCreateRequest.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HuanMeng.MiaoYu.Model.Dto.Music
+{
+ ///
+ /// 创建音乐
+ ///
+ public class MusicCreateRequest
+ {
+
+ ///
+ /// 音乐风格
+ ///
+ public string GenreName { get; set; }
+
+ ///
+ /// 音乐描述
+ ///
+ public string Prompt { get; set; }
+
+ ///
+ /// 歌曲名称
+ ///
+ public string Name { get; set; }
+ }
+}
diff --git a/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/User/UserCurrencyType.cs b/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/User/UserCurrencyType.cs
index ade3b93..2070f9c 100644
--- a/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/User/UserCurrencyType.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/User/UserCurrencyType.cs
@@ -29,6 +29,10 @@ namespace HuanMeng.MiaoYu.Model.EnumModel.User
///
记忆卡 = 3,
+ ///
+ /// 生成音乐次数
+ ///
+ 生成音乐点数 = 4,
///
/// 初级记忆卡
///
diff --git a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/MusicController.cs b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/MusicController.cs
index 80ab856..228408d 100644
--- a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/MusicController.cs
+++ b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/MusicController.cs
@@ -24,7 +24,7 @@ namespace HuanMeng.MiaoYu.WebApi.Controllers
///
///
[HttpGet]
- public async Task>> GetMusicGenresList()
+ public async Task>> GetMusicGenresList()
{
MusicBLL musicBLL = new MusicBLL(ServiceProvider);
return await musicBLL.GetMusicGenresList();
@@ -51,5 +51,16 @@ namespace HuanMeng.MiaoYu.WebApi.Controllers
MusicBLL musicBLL = new MusicBLL(ServiceProvider);
return await musicBLL.GetUserMusicGenresList();
}
+
+ ///
+ /// 创作音乐
+ ///
+ ///
+ [HttpPost]
+ public async Task> CreateMusic([FromBody] MusicCreateRequest musicCreateRequest)
+ {
+ MusicBLL musicBLL = new MusicBLL(ServiceProvider);
+ return await musicBLL.CreateMusic(musicCreateRequest); ;
+ }
}
}
diff --git a/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs b/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs
index bc513b9..5bb55c5 100644
--- a/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs
+++ b/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs
@@ -1,8 +1,7 @@
-using AgileConfig.Client;
-
using HuanMeng.DotNetCore.CustomExtension;
using HuanMeng.DotNetCore.MiddlewareExtend;
using HuanMeng.DotNetCore.Utility.AssemblyHelper;
+using HuanMeng.MiaoYu.Code.AppExtend;
using HuanMeng.MiaoYu.Code.Base;
using HuanMeng.MiaoYu.Code.JwtUtil;
using HuanMeng.MiaoYu.Code.MultiTenantUtil;
@@ -13,9 +12,8 @@ using HuanMeng.MiaoYu.Code.TencentUtile;
using HuanMeng.MiaoYu.Code.Users.UserAccount.VerificationCodeManager;
using HuanMeng.MiaoYu.Model.Dto;
using HuanMeng.MiaoYu.WebApi.Base;
-using HuanMeng.MiaoYu.Code.AppExtend;
+
using Microsoft.AspNetCore.Authentication.JwtBearer;
-using Microsoft.Extensions.Configuration;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json.Serialization;