From 8da82889d181f9ee17fb8745b5a14457e5c6dc18 Mon Sep 17 00:00:00 2001 From: jianzhichu <279225040@.com> Date: Wed, 14 Jan 2026 17:13:15 +0800 Subject: [PATCH] =?UTF-8?q?=E9=BB=98=E8=AE=A4=E9=9F=B3=E9=A2=91=E6=94=B9?= =?UTF-8?q?=E6=88=90=E9=9A=8F=E6=9C=BA=E4=BB=8Emp3=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Controllers/ConfigController.cs | 192 ++++++++++++++--------------- service/DouyinMergeVideoService.cs | 45 +++++-- 2 files changed, 128 insertions(+), 109 deletions(-) diff --git a/Controllers/ConfigController.cs b/Controllers/ConfigController.cs index e04a002..114b92e 100644 --- a/Controllers/ConfigController.cs +++ b/Controllers/ConfigController.cs @@ -28,16 +28,16 @@ namespace dy.net.Controllers private readonly DouyinFollowService douyinFollowService; private readonly DouyinCookieService douyinCookieService; - // 定义允许上传的音频扩展名(小写) - private readonly string[] _allowedAudioExtensions = { ".mp3", ".wav" }; + //// 定义允许上传的音频扩展名(小写) + //private readonly string[] _allowedAudioExtensions = { ".mp3", ".wav" }; - // 定义允许的音频 MIME 类型(增强验证) - private readonly string[] _allowedAudioMimeTypes = { - "audio/mpeg", "audio/wav" - }; + //// 定义允许的音频 MIME 类型(增强验证) + //private readonly string[] _allowedAudioMimeTypes = { + // "audio/mpeg", "audio/wav" + //}; // 最大文件大小:20MB(可根据需求调整) - private const long _maxFileSize = 20 * 1024 * 1024; + //private const long _maxFileSize = 20 * 1024 * 1024; public ConfigController(DouyinCookieService dyCookieService, DouyinCommonService commonService, DouyinQuartzJobService quartzJobService, DouyinFollowService douyinFollowService, DouyinCookieService douyinCookieService) @@ -388,106 +388,106 @@ namespace dy.net.Controllers } - /// - /// 上传音频文件接口 - /// - /// 要上传的音频文件 - /// 上传结果 - [HttpPost("UploadAudio")] - public IActionResult UploadAudio(IFormFile file) - { - // 1. 验证文件是否为空 - if (file == null || file.Length == 0) - { - return BadRequest(new { success = false, message = "请选择要上传的音频文件" }); - } + ///// + ///// 上传音频文件接口 + ///// + ///// 要上传的音频文件 + ///// 上传结果 + //[HttpPost("UploadAudio")] + //public IActionResult UploadAudio(IFormFile file) + //{ + // // 1. 验证文件是否为空 + // if (file == null || file.Length == 0) + // { + // return BadRequest(new { success = false, message = "请选择要上传的音频文件" }); + // } - try - { - // 2. 验证文件大小 - if (file.Length > _maxFileSize) - { - return BadRequest(new { success = false, message = $"文件大小超过限制(最大允许 {_maxFileSize / 1024 / 1024}MB)" }); - } + // try + // { + // // 2. 验证文件大小 + // if (file.Length > _maxFileSize) + // { + // return BadRequest(new { success = false, message = $"文件大小超过限制(最大允许 {_maxFileSize / 1024 / 1024}MB)" }); + // } - // 3. 获取文件扩展名并验证 - var fileExtension = Path.GetExtension(file.FileName).ToLower(); - if (!_allowedAudioExtensions.Contains(fileExtension)) - { - return BadRequest(new - { - success = false, - message = $"不支持的音频格式,仅允许:{string.Join(", ", _allowedAudioExtensions)}" - }); - } + // // 3. 获取文件扩展名并验证 + // var fileExtension = Path.GetExtension(file.FileName).ToLower(); + // if (!_allowedAudioExtensions.Contains(fileExtension)) + // { + // return BadRequest(new + // { + // success = false, + // message = $"不支持的音频格式,仅允许:{string.Join(", ", _allowedAudioExtensions)}" + // }); + // } - // 4. 验证 MIME 类型(可选但推荐,防止扩展名伪造) - var contentType = file.ContentType.ToLower(); - if (!_allowedAudioMimeTypes.Contains(contentType)) - { - return BadRequest(new - { - success = false, - message = "文件类型验证失败,请上传合法的音频文件" - }); - } + // // 4. 验证 MIME 类型(可选但推荐,防止扩展名伪造) + // var contentType = file.ContentType.ToLower(); + // if (!_allowedAudioMimeTypes.Contains(contentType)) + // { + // return BadRequest(new + // { + // success = false, + // message = "文件类型验证失败,请上传合法的音频文件" + // }); + // } - //先删除 - var uploadMp3 = Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "mp3")) - .Where(filePath => Path.GetFileNameWithoutExtension(filePath) != "silent_10") - .FirstOrDefault(); - if (!string.IsNullOrWhiteSpace(uploadMp3) && System.IO.File.Exists(uploadMp3)) - { - System.IO.File.Delete(uploadMp3); - } + // //先删除 + // var uploadMp3 = Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "mp3")) + // .Where(filePath => Path.GetFileNameWithoutExtension(filePath) != "silent_10") + // .FirstOrDefault(); + // if (!string.IsNullOrWhiteSpace(uploadMp3) && System.IO.File.Exists(uploadMp3)) + // { + // System.IO.File.Delete(uploadMp3); + // } - // 5. 生成唯一文件名(避免重复) - var uniqueFileName = $"dysync_default{fileExtension}"; + // // 5. 生成唯一文件名(避免重复) + // var uniqueFileName = $"dysync_default{fileExtension}"; - // 6. 定义文件保存路径(建议配置在 appsettings.json 中,这里简化处理) - var uploadPath = Path.Combine(AppContext.BaseDirectory, "mp3"); + // // 6. 定义文件保存路径(建议配置在 appsettings.json 中,这里简化处理) + // var uploadPath = Path.Combine(AppContext.BaseDirectory, "mp3"); - // 确保目录存在 - if (!Directory.Exists(uploadPath)) - { - Directory.CreateDirectory(uploadPath); - } + // // 确保目录存在 + // if (!Directory.Exists(uploadPath)) + // { + // Directory.CreateDirectory(uploadPath); + // } - // 7. 保存文件 - var filePath = Path.Combine(uploadPath, uniqueFileName); + // // 7. 保存文件 + // var filePath = Path.Combine(uploadPath, uniqueFileName); - if (System.IO.File.Exists(filePath)) - { - System.IO.File.Delete(filePath); - } - using (var stream = new FileStream(filePath, FileMode.Create)) - { - file.CopyTo(stream); - } + // if (System.IO.File.Exists(filePath)) + // { + // System.IO.File.Delete(filePath); + // } + // using (var stream = new FileStream(filePath, FileMode.Create)) + // { + // file.CopyTo(stream); + // } - // 8. 返回成功结果(可根据需求返回文件路径/URL 等) - return ApiResult.Success(new { fileName = uniqueFileName, filePath }); - } - catch (Exception ex) - { - // 捕获异常并返回错误信息 - return ApiResult.Fail(ex.Message); - } - } - [AllowAnonymous] - [HttpGet("defaudio")] - public async Task GetDefaultAudioUrl() - { - var uploadMp3 = Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "mp3")) - .Where(filePath => Path.GetFileNameWithoutExtension(filePath) != "silent_10") - .FirstOrDefault(); - if (!string.IsNullOrWhiteSpace(uploadMp3) && System.IO.File.Exists(uploadMp3)) - { - return File(System.IO.File.ReadAllBytes(uploadMp3), "application/octet-stream", Path.GetFileName(uploadMp3)); - } - return ApiResult.Fail("未上传音频"); - } + // // 8. 返回成功结果(可根据需求返回文件路径/URL 等) + // return ApiResult.Success(new { fileName = uniqueFileName, filePath }); + // } + // catch (Exception ex) + // { + // // 捕获异常并返回错误信息 + // return ApiResult.Fail(ex.Message); + // } + //} + //[AllowAnonymous] + //[HttpGet("defaudio")] + //public async Task GetDefaultAudioUrl() + //{ + // var uploadMp3 = Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "mp3")) + // .Where(filePath => Path.GetFileNameWithoutExtension(filePath) != "silent_10") + // .FirstOrDefault(); + // if (!string.IsNullOrWhiteSpace(uploadMp3) && System.IO.File.Exists(uploadMp3)) + // { + // return File(System.IO.File.ReadAllBytes(uploadMp3), "application/octet-stream", Path.GetFileName(uploadMp3)); + // } + // return ApiResult.Fail("未上传音频"); + //} } } diff --git a/service/DouyinMergeVideoService.cs b/service/DouyinMergeVideoService.cs index 290727d..77619bd 100644 --- a/service/DouyinMergeVideoService.cs +++ b/service/DouyinMergeVideoService.cs @@ -2,6 +2,8 @@ using dy.net.dto; using dy.net.utils; using Serilog; +using System.Collections.Generic; +using System.Security.Cryptography; namespace dy.net.service { @@ -44,34 +46,51 @@ namespace dy.net.service int width = 1080, int height = 1920) { - string mp3FilePath = GetDefaultAudio(); + string mergMusicPath = GetRandomMergeMusic(); if (!string.IsNullOrWhiteSpace(audioPath)) { var (SuccessPaths, _) = await DownloadMediaAsync(new List { audioPath }, Path.GetDirectoryName(savePath), "audio_", "mp3", ck); if (SuccessPaths != null && SuccessPaths.Length > 0) { - mp3FilePath = SuccessPaths[0]; + mergMusicPath = SuccessPaths[0]; } } var ffmpeg = new FFmpegHelper(); - return await ffmpeg.MergeMultipleVideosAsync(videoFilePaths, mp3FilePath, savePath, width, height); + return await ffmpeg.MergeMultipleVideosAsync(videoFilePaths, mergMusicPath, savePath, width, height); } - private static string GetDefaultAudio() + private static string GetRandomMergeMusic() { - string mp3FilePath = Path.Combine(AppContext.BaseDirectory, "mp3", "silent_10.mp3"); - var uploadMp3 = Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "mp3")) - .Where(filePath => Path.GetFileNameWithoutExtension(filePath) != "silent_10") - .FirstOrDefault(); - if (!string.IsNullOrWhiteSpace(uploadMp3) && File.Exists(uploadMp3)) + var allowedExtensions = new HashSet { ".mp3", ".wav" }; + string mergMusic = Path.Combine(AppContext.BaseDirectory, "mp3", "silent_10.mp3");//默认音频 + var customMusics = Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "mp3")) + .Where(filePath => + allowedExtensions.Contains(Path.GetExtension(filePath).ToLowerInvariant()) && + Path.GetFileNameWithoutExtension(filePath) != "silent_10") + .ToList(); + + if (customMusics != null && customMusics.Any()) { - mp3FilePath = uploadMp3; + if (customMusics.Count() == 1) + return customMusics.FirstOrDefault(); + + // 使用加密级别的随机数生成器(RNGCryptoServiceProvider)获取高随机性的索引 + using (var rng = RandomNumberGenerator.Create()) + { + byte[] randomNumber = new byte[4]; + rng.GetBytes(randomNumber); + + // 将随机字节转换为非负整数,并取模得到有效索引 + int randomIndex = Math.Abs(BitConverter.ToInt32(randomNumber, 0)) % customMusics.Count(); + + return customMusics.ToList()[randomIndex]; + } } - return mp3FilePath; + return mergMusic; } @@ -171,8 +190,8 @@ namespace dy.net.service if (rawAudios.Length == 0) { - var mp3Path = GetDefaultAudio(); - rawAudios = new string[] { mp3Path }; + var musicPath = GetRandomMergeMusic(); + rawAudios = new string[] { musicPath }; Log.Debug("版权原因无法下载音频,使用默认无声音频文件"); }