From a0e00c8b5d3ee0dda1f6a1ccdee37db719172393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=82=A5=E7=BE=8A?= <1048382248@qq.com> Date: Sun, 14 Sep 2025 15:17:06 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=90=8E=E7=9A=84=E6=96=B0=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AICore/FFMPGE/FFMPGEHandle.cs | 14 ++-- .../AICore/GPT/DeepSeek/DeepSeek_GPT.cs | 2 +- .../AICore/SherpaOnnx/SenseVoice.cs | 2 +- .../AICore/SherpaOnnx/Speaker.cs | 2 +- VideoAnalysisCore/Common/AppCommon.cs | 27 ++++++- VideoAnalysisCore/Common/DownloadFile.cs | 81 ++++++++++++------- .../Controllers/LJZK_Controller.cs | 2 + VideoAnalysisCore/Job/TaskFileClearJob.cs | 16 +--- VideoAnalysisCore/Model/VideoTask.cs | 5 ++ 9 files changed, 95 insertions(+), 56 deletions(-) diff --git a/VideoAnalysisCore/AICore/FFMPGE/FFMPGEHandle.cs b/VideoAnalysisCore/AICore/FFMPGE/FFMPGEHandle.cs index aa220fe..a69ba46 100644 --- a/VideoAnalysisCore/AICore/FFMPGE/FFMPGEHandle.cs +++ b/VideoAnalysisCore/AICore/FFMPGE/FFMPGEHandle.cs @@ -41,16 +41,18 @@ namespace VideoAnalysisCore.AICore.FFMPGE var intervalSec = 5; var threshold = 8.15; var ssimThreshold = 0.9; - var PPTVideoCode = await DbScoped.Sugar + var taskInfo = await DbScoped.Sugar .Queryable() - .Where(s => s.Id == long.Parse(task)) - .Select(s => s.PPTVideoCode).FirstAsync(); - if (string.IsNullOrEmpty(PPTVideoCode)) return; + .Where(s => s.Id == long.Parse(task)).FirstAsync(); + if (string.IsNullOrEmpty(taskInfo.PPTVideoCode) || string.IsNullOrEmpty(taskInfo.PPTVideoUrl)) return; //视频切帧 var localPath = task.LocalPath(); var filePath = Path.Combine(localPath, "ppt.mp4"); if (!File.Exists(filePath)) - throw new Exception("存在PPTCOde但未能找到对应资源文件"); + { + Console.WriteLine("存在PPT Code但未能找到对应资源文件"); + return; + } var ffmpeg = new Engine(FFmpegPath); var cToken = new CancellationToken(); RedisExpand.SetTaskProgress(task, "Frame=>10%"); @@ -65,7 +67,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE var frameFiles = Directory.GetFiles(localPath, "*.jpg") .OrderBy(f => f) .ToList(); - RedisExpand.SetTaskProgress(task, "Frame=>50%"); + RedisExpand.SetTaskProgress(task, "Frame=>80%"); Image prevFrame = null; var keyFrames = new List(10) { 5}; foreach (var frameFile in frameFiles) diff --git a/VideoAnalysisCore/AICore/GPT/DeepSeek/DeepSeek_GPT.cs b/VideoAnalysisCore/AICore/GPT/DeepSeek/DeepSeek_GPT.cs index c1e0dbf..d739843 100644 --- a/VideoAnalysisCore/AICore/GPT/DeepSeek/DeepSeek_GPT.cs +++ b/VideoAnalysisCore/AICore/GPT/DeepSeek/DeepSeek_GPT.cs @@ -257,7 +257,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek { try { - var keyFrameArr = string.IsNullOrEmpty(taskInfo?.PPTVideoCode) + var keyFrameArr = string.IsNullOrEmpty(taskInfo?.PPTVideoCode) || string.IsNullOrEmpty(taskInfo?.PPTKeyFrame) ? string.Empty : $"授课PPT发生了变化的时间是{taskInfo.PPTKeyFrame},所以在这些时间段附近应该发生了授课内容得变化,授课阶段结果尽量参考这些时间节点(PPT与字幕有一定的延时)。"; var resFormat = """[{"StartTime":开始秒(number),"EndTime":结束秒(number),"Stage":阶段(string),"Theme":主题(string),"Content":内容总结(string)}]"""; diff --git a/VideoAnalysisCore/AICore/SherpaOnnx/SenseVoice.cs b/VideoAnalysisCore/AICore/SherpaOnnx/SenseVoice.cs index ffda138..b18f3de 100644 --- a/VideoAnalysisCore/AICore/SherpaOnnx/SenseVoice.cs +++ b/VideoAnalysisCore/AICore/SherpaOnnx/SenseVoice.cs @@ -121,7 +121,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx /// public static async Task RunTask(string task) { - var filePath = Path.Combine(task.LocalPath(), task + ".wav"); + var filePath = Path.Combine(task.LocalPath(), "task.wav"); if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) throw new Exception("task 音频路径未找到"); await TaskHandle(new WaveReader(filePath), task); diff --git a/VideoAnalysisCore/AICore/SherpaOnnx/Speaker.cs b/VideoAnalysisCore/AICore/SherpaOnnx/Speaker.cs index 81b0b1c..d8ecb3e 100644 --- a/VideoAnalysisCore/AICore/SherpaOnnx/Speaker.cs +++ b/VideoAnalysisCore/AICore/SherpaOnnx/Speaker.cs @@ -55,7 +55,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx /// public static async Task Run(string task) { - var filePath = Path.Combine(task.LocalPath(), task + ".wav"); + var filePath = Path.Combine(task.LocalPath(), "task.wav"); if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) throw new Exception("task 音频路径未找到"); diff --git a/VideoAnalysisCore/Common/AppCommon.cs b/VideoAnalysisCore/Common/AppCommon.cs index 1859849..a48e510 100644 --- a/VideoAnalysisCore/Common/AppCommon.cs +++ b/VideoAnalysisCore/Common/AppCommon.cs @@ -84,7 +84,7 @@ namespace VideoAnalysisCore.Common /// public static class ExpandFunction { - + static Dictionary FormulaData; static string FormulaDataKey; /// @@ -92,6 +92,31 @@ namespace VideoAnalysisCore.Common /// public static string FrameName = "frame_"; + /// + /// 删除 AI分析任务的缓存文件 + /// + /// + /// + public static bool DeleteTaskFile(long? taskId) + { + if(taskId is null || taskId == 0) return false; + var path = taskId.ToString().LocalPath(); + if (!string.IsNullOrEmpty(path) && Directory.Exists(path)) + { + try + { + Directory.Delete(path, true); + Console.WriteLine($"已删除缓存文件: {taskId}"); + } + catch (Exception ex) + { + Console.WriteLine($"删除缓存文件 {taskId} 时出错: {ex.Message}"); + } + } + else return false; + return true; + } + /// /// 对象转化为JSON字符串 /// diff --git a/VideoAnalysisCore/Common/DownloadFile.cs b/VideoAnalysisCore/Common/DownloadFile.cs index 834d3a2..f1e4f71 100644 --- a/VideoAnalysisCore/Common/DownloadFile.cs +++ b/VideoAnalysisCore/Common/DownloadFile.cs @@ -13,6 +13,7 @@ using VideoAnalysisCore.Model; using VideoAnalysisCore.Model.Enum; using AlibabaCloud.SDK.Vod20170321; using UserCenter.Model.Enum; +using System.Security.Policy; namespace VideoAnalysisCore.Common { @@ -90,12 +91,16 @@ namespace VideoAnalysisCore.Common public static DownloadConfiguration Opt { get; set; } = default!; public static int DownloadSpeed { get; set; } = default!; private readonly Repository videoTaskDB; + private readonly Repository packageInfoTaskDB; private readonly Client vodClient; + readonly string taskVideoName = "task.mp4"; + readonly string taskPPTVideoName = "ppt.mp4"; - public DownloadFile(Repository videoTaskDB, Client vodClient) + public DownloadFile(Repository videoTaskDB, Client vodClient, Repository nackageInfoTaskDB) { this.videoTaskDB = videoTaskDB; this.vodClient = vodClient; + this.packageInfoTaskDB = nackageInfoTaskDB; } // 根据 Content-Type 映射文件后缀 @@ -157,7 +162,7 @@ namespace VideoAnalysisCore.Common if (!Directory.Exists(AppCommon.TaskCachedFile)) Directory.CreateDirectory(AppCommon.TaskCachedFile); var localPath = task.LocalPath(); - var outputPath = Path.Combine(localPath, task + fileExtension); + var outputPath = Path.Combine(localPath, taskVideoName); if (!Directory.Exists(localPath)) Directory.CreateDirectory(localPath); await videoTaskDB @@ -166,38 +171,52 @@ namespace VideoAnalysisCore.Common .Where(it => it.Id == long.Parse(task)) .ExecuteCommandAsync(); //下载PPT视频 - if (!string.IsNullOrEmpty(taskInfo.PPTVideoCode)) + if (string.IsNullOrEmpty(taskInfo.PPTVideoUrl)&& + !string.IsNullOrEmpty(taskInfo.PPTVideoCode)) { - try - { - var url = string.Empty; - if (taskInfo.PPTVideoCode.Contains("http")) - url = taskInfo.PPTVideoCode; - else - { - var videoInfo = await vodClient.GetPlayInfoAsync(new AlibabaCloud.SDK.Vod20170321.Models.GetPlayInfoRequest() - { - VideoId = taskInfo.PPTVideoCode, - Formats = "mp4", - OutputType = "cdn", - AuthTimeout = 3600 * 24 * 12, - }); - if (videoInfo is null || videoInfo.StatusCode != 200 && !videoInfo.Body.PlayInfoList.PlayInfo.Any()) - throw new Exception($"{DateTime.Now} 视频订阅=>获取阿里云视频信息失败 VideoCode {taskInfo.TagId} StatusCode {videoInfo?.StatusCode}"); - url = videoInfo.Body.PlayInfoList.PlayInfo.First().PlayURL; - } - await Download(url, localPath, "ppt.mp4", - (s, e) => RedisExpand.SetTaskProgress(task, "PPT->" + Math.Round(e.ProgressPercentage, 1) - )); - } - catch - { - throw; - } + taskInfo.PPTVideoUrl = await packageInfoTaskDB.AsQueryable() + .Where(s => s.VideoCode == taskInfo.PPTVideoCode) + .Select(s => s.VideoUrl) + .FirstAsync(); + if (!string.IsNullOrEmpty(taskInfo.PPTVideoUrl)) + await videoTaskDB.AsUpdateable(taskInfo) + .UpdateColumns(it => new { it.PPTVideoUrl }) + .ExecuteCommandAsync(); + + } + if (!string.IsNullOrEmpty(taskInfo.PPTVideoUrl)) + { + await Download(taskInfo.PPTVideoUrl, localPath, taskPPTVideoName, + (s, e) => RedisExpand.SetTaskProgress(task, "PPT->" + Math.Round(e.ProgressPercentage, 1) + )); + //try + //{ + // var url = string.Empty; + // if (taskInfo.PPTVideoCode.Contains("http")) + // url = taskInfo.PPTVideoCode; + // else + // { + // var videoInfo = await vodClient.GetPlayInfoAsync(new AlibabaCloud.SDK.Vod20170321.Models.GetPlayInfoRequest() + // { + // VideoId = taskInfo.PPTVideoCode, + // Formats = "mp4", + // OutputType = "cdn", + // AuthTimeout = 3600 * 24 * 12, + // }); + // if (videoInfo is null || videoInfo.StatusCode != 200 && !videoInfo.Body.PlayInfoList.PlayInfo.Any()) + // throw new Exception($"{DateTime.Now} 视频订阅=>获取阿里云视频信息失败 VideoCode {taskInfo.TagId} StatusCode {videoInfo?.StatusCode}"); + // url = videoInfo.Body.PlayInfoList.PlayInfo.First().PlayURL; + // } + //} + //catch + //{ + // throw; + //} } try - {//下载原视频 - await Download(fileUrl, localPath, task + fileExtension, + { + //下载原视频 + await Download(fileUrl, localPath, taskVideoName, (s, e) => RedisExpand.SetTaskProgress(task, Math.Round(e.ProgressPercentage,1) )); } diff --git a/VideoAnalysisCore/Controllers/LJZK_Controller.cs b/VideoAnalysisCore/Controllers/LJZK_Controller.cs index e90f665..d04712e 100644 --- a/VideoAnalysisCore/Controllers/LJZK_Controller.cs +++ b/VideoAnalysisCore/Controllers/LJZK_Controller.cs @@ -104,6 +104,7 @@ namespace VideoAnalysisCore.Controllers nodePackages.Add(np); if (videoIdArr.Contains(s.VideoCode)) continue; var pptCode = sPPT != null ? sPPT.VideoCode : string.Empty; + var pptUrl = sPPT != null ? sPPT.VideoUrl : string.Empty; videos.Add(new VideoTask() { Id = YitIdHelper.NextId(), @@ -115,6 +116,7 @@ namespace VideoAnalysisCore.Controllers TagId = s.VideoCode, MediaUrl = s.VideoUrl, PPTVideoCode = pptCode, + PPTVideoUrl = pptUrl, VideoType = s.CourseType }); } diff --git a/VideoAnalysisCore/Job/TaskFileClearJob.cs b/VideoAnalysisCore/Job/TaskFileClearJob.cs index da056eb..f871f14 100644 --- a/VideoAnalysisCore/Job/TaskFileClearJob.cs +++ b/VideoAnalysisCore/Job/TaskFileClearJob.cs @@ -51,21 +51,7 @@ namespace VideoAnalysisCore.Job // 遍历查询结果,删除缓存文件 foreach (var task in completedTasks) - { - var path = task.Id.ToString().LocalPath(); - if (!string.IsNullOrEmpty(path) && Directory.Exists(path)) - { - try - { - Directory.Delete(path, true); - Console.WriteLine($"已删除缓存文件: {task.LocalMediaPath}"); - } - catch (Exception ex) - { - Console.WriteLine($"删除缓存文件 {task.Id} 时出错: {ex.Message}"); - } - } - } + ExpandFunction.DeleteTaskFile(task?.Id); } catch (Exception ex) { diff --git a/VideoAnalysisCore/Model/VideoTask.cs b/VideoAnalysisCore/Model/VideoTask.cs index 4e56cfb..224d9e6 100644 --- a/VideoAnalysisCore/Model/VideoTask.cs +++ b/VideoAnalysisCore/Model/VideoTask.cs @@ -79,6 +79,11 @@ namespace VideoAnalysisCore.Model [SugarColumn(Length = 255, ColumnDataType = "varchar", IsNullable = true)] public string? PPTVideoCode { get; set; } /// + /// 授课视频对应PPT视频ID + /// + [SugarColumn(Length = 255, ColumnDataType = "varchar", IsNullable = true)] + public string? PPTVideoUrl { get; set; } + /// /// 授课视频对应PPT视频关键帧 /// [SugarColumn(ColumnDataType = "longtext",IsNullable = true)]