优化 各个模块的注入方式

修复 初始化时 之前未执行完的任务 导致的死循环
This commit is contained in:
小肥羊 2025-09-29 17:32:08 +08:00
parent 94cde3af70
commit 0edf143f8a
18 changed files with 350 additions and 239 deletions

View File

@ -2,7 +2,9 @@
using Learn.VideoAnalysis.API.Expand;
using Mapster;
using Microsoft.OpenApi.Models;
using VideoAnalysisCore.AICore.FFMPGE;
using VideoAnalysisCore.AICore.GPT.DeepSeek;
using VideoAnalysisCore.AICore.SherpaOnnx;
using VideoAnalysisCore.Common;
using VideoAnalysisCore.Common.Expand;
@ -37,8 +39,12 @@ namespace Learn.VideoAnalysis.API
builder.Services.AddHttpClient();
builder.Services.AddSqlSugarExpand();
builder.Services.AddRedisExpand();
builder.Services.AddCoravel();
builder.Services.AddCorsExpand();
builder.Services.AddDownloadFileExpand();
builder.Services.AddFFMPGEExpand();
builder.Services.AddSenseVoiceExpand();
builder.Services.AddHttpContextAccessor();
builder.Services.AddControllersWithViews(options =>
{

View File

@ -23,6 +23,8 @@ namespace Learn.VideoAnalysis.Components.Pages
[Inject] private ConfirmService ComfirmService { get; set; } = default!;
[Inject] private Repository<VideoTask> taskDB { get; set; } = default!;
[Inject] private NavigationManager NavigationManager { get; set; } = default!;
[Inject] private RedisManager redisManager { get; set; } = default!;
[Inject] private INotificationService _notice { get; set; } = default!;
@ -54,7 +56,7 @@ namespace Learn.VideoAnalysis.Components.Pages
async void ReStartClick(VideoTaskDto query)
{
selectDefaultValue =
(await RedisExpand.Redis.HMGetAsync<int>(RedisExpandKey.Task(query.Id), "LastEnum")).FirstOrDefault();
(await redisManager.Redis.HMGetAsync<int>(RedisExpandKey.Task(query.Id), "LastEnum")).FirstOrDefault();
selectEnum = selectDefaultValue;
reStartTask = query;
modalShow = true;
@ -69,9 +71,9 @@ namespace Learn.VideoAnalysis.Components.Pages
/// <param name="query"></param>
async void ReStart()
{
await RedisExpand.ClearTaskError(reStartTask.Id);
await redisManager.ClearTaskError(reStartTask.Id);
_=Task.Run(() =>
RedisExpand.InsertChannel((RedisChannelEnum)selectEnum, reStartTask.Id)
redisManager.InsertChannel((RedisChannelEnum)selectEnum, reStartTask.Id)
);
modalShow = false;
}
@ -125,7 +127,7 @@ namespace Learn.VideoAnalysis.Components.Pages
var item = rowData.Data;
if (item is null)
return;
var data = RedisExpand.Redis.HMGet<string>(RedisExpandKey.Task(item.Id),
var data = redisManager.Redis.HMGet<string>(RedisExpandKey.Task(item.Id),
"Progress", "LastEnum", "StartTime", "ErrorMessage");
item.Progress = data[0];
item.LastEnum = data[1] == null ?default:data[1].ToEnum<RedisChannelEnum>() ?? default;

View File

@ -32,6 +32,7 @@ namespace Learn.VideoAnalysis.Components.Pages
[Inject] private Repository<VideoQuestion> videoQuestionDB { get; set; } = default!;
[Inject] private Repository<VideoQuestionKonw> videoQuestionKonwDB { get; set; } = default!;
[Inject] private Repository<VideoKonwPoint> videoKonwPointDB { get; set; } = default!;
[Inject] private RedisManager redisManager { get; set; } = default!;
[Inject] private IJSRuntime JSRuntime { get; set; } = default!;
private VideoTask nowTask { get; set; } = default!;
@ -76,7 +77,7 @@ namespace Learn.VideoAnalysis.Components.Pages
return;
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(nowTask.Captions);
var captionsArr1 = JsonSerializer.Deserialize<SenseVoiceRes[]>(nowTask.CaptionsAI??"[]") ;
RedisExpand.Redis.HMGet<SenseVoiceRes[]>(RedisExpandKey.Task(taskId), "Captions").FirstOrDefault();
redisManager.Redis.HMGet<SenseVoiceRes[]>(RedisExpandKey.Task(taskId), "Captions").FirstOrDefault();
var konwArr = await videoKonwPointDB.AsQueryable()
.Where(s => s.VideoTaskId == nowTask.Id)

View File

@ -68,13 +68,17 @@ namespace Learn.VideoAnalysis
builder.Configuration.AddAppConfig(args);
builder.Services.AddSqlSugarExpand();
builder.Services.AddRedisExpand();
builder.Services.AddSimpleTexOcrClient();
builder.Services.AddDownloadFileExpand();
builder.Services.AddFFMPGEExpand();
builder.Services.AddAlibabaCloudVod();
builder.Services.AddAliyunOSS();
builder.Services.AddRedisExpand();
builder.Services.AddSpeakerAI();
builder.Services.AddSenseVoiceExpand();
//builder.Services.AddSpeakerAI();
builder.Services.AddCoravel();
//SenseVoice.Init();
//Òì³£¹ýÂËÆ÷
builder.Services.AddControllersWithViews(options =>
@ -110,6 +114,7 @@ namespace Learn.VideoAnalysis
//builder.Services.AddSingleton<IBserGPT, Chat_GPT>();
builder.Services.AddSingleton<IBserGPT, DeepSeek_GPT>();
builder.Services.AddTaskSubscribe();
var app = builder.Build();
@ -119,6 +124,7 @@ namespace Learn.VideoAnalysis
// Configure the HTTP request pipeline.
_ = app.Services.GetRequiredService<RedisInit>();
app.UseSwagger();
app.UseSwaggerUI();
app.UseExceptionHandler("/Error");

View File

@ -14,9 +14,22 @@ using SixLabors.ImageSharp.Processing;
using System.Text.Json;
using System;
using Microsoft.VisualBasic.FileIO;
using Microsoft.Extensions.DependencyInjection;
namespace VideoAnalysisCore.AICore.FFMPGE
{
public static class FFMPGEExpand
{
/// <summary>
/// 添加跨域拓展
/// </summary>
/// <param name="services"></param>
public static void AddFFMPGEExpand(this IServiceCollection services)
{
services.AddSingleton<FFMPGEHandle>();
}
}
/// <summary>
/// Ffmpeg处理程序
/// </summary>
@ -28,21 +41,27 @@ namespace VideoAnalysisCore.AICore.FFMPGE
public static string FFmpegPath = RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
? $"/usr/bin/ffmpeg"
: Path.Combine(AppCommon.AIModelFile, "ffmpeg.exe");
private Repository<VideoTask> videoTaskDB { get; set; }
private RedisManager redisManager { get; set; }
public FFMPGEHandle(RedisManager redisManager, Repository<VideoTask> videoTaskDB)
{
this.redisManager = redisManager;
this.videoTaskDB = videoTaskDB;
}
/// <summary>
/// 识别视频关键帧
/// </summary>
/// <param name="task">任务id</param>
/// <returns></returns>
public static async Task VideoKeyFrames(string task)
public async Task VideoKeyFrames(string task)
{
var taskID = long.Parse(task);
//间隔秒
var intervalSec = 5;
var threshold = 8.15;
var ssimThreshold = 0.9;
var taskInfo = await DbScoped.Sugar
.Queryable<VideoTask>()
var taskInfo = await videoTaskDB.AsQueryable()
.Where(s => s.Id == long.Parse(task)).FirstAsync();
if (string.IsNullOrEmpty(taskInfo.PPTVideoCode) || string.IsNullOrEmpty(taskInfo.PPTVideoUrl)) return;
//视频切帧
@ -55,11 +74,11 @@ namespace VideoAnalysisCore.AICore.FFMPGE
}
var ffmpeg = new Engine(FFmpegPath);
var cToken = new CancellationToken();
RedisExpand.SetTaskProgress(task, "Frame=>10%");
redisManager.SetTaskProgress(task, "Frame=>10%");
foreach (string jpgFile in Directory.GetFiles(localPath, "*.jpg"))
FileSystem.DeleteFile(jpgFile, UIOption.OnlyErrorDialogs, RecycleOption.DeletePermanently);
RedisExpand.SetTaskProgress(task, "Frame=>20%");
redisManager.SetTaskProgress(task, "Frame=>20%");
await ffmpeg.ExecuteAsync($"-i {filePath} -vf \"fps=1/{intervalSec},scale=960:540\" {localPath}/{ExpandFunction.FrameName}%03d.jpg", cToken);
@ -67,7 +86,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE
var frameFiles = Directory.GetFiles(localPath, "*.jpg")
.OrderBy(f => f)
.ToList();
RedisExpand.SetTaskProgress(task, "Frame=>80%");
redisManager.SetTaskProgress(task, "Frame=>80%");
Image<Rgb24> prevFrame = null;
var keyFrames = new List<int>(10) { 5};
foreach (var frameFile in frameFiles)
@ -103,8 +122,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE
}
//写入数据库
var keyFramStr = keyFrames.Where(s => s != -1).ToJson();
await DbScoped.Sugar
.Updateable<VideoTask>()
await videoTaskDB.AsUpdateable()
.SetColumns(it => it.PPTKeyFrame == keyFramStr)
.Where(it => it.Id == taskID)
.ExecuteCommandAsync();
@ -117,7 +135,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE
/// <param name="img1"></param>
/// <param name="img2"></param>
/// <returns></returns>
static double CalculateFrameDifference(Image<Rgb24> img1, Image<Rgb24> img2)
double CalculateFrameDifference(Image<Rgb24> img1, Image<Rgb24> img2)
{
// 统一调整为64x64
var resized1 = img1.Clone(x => x.Grayscale());
@ -136,7 +154,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE
return diff / (double)(resized1.Width * resized1.Height);
}
static double GetTimestampFromFileName(string filePath)
double GetTimestampFromFileName(string filePath)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
return double.Parse(fileName.Split('_')[1]);
@ -146,7 +164,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
public static async Task RunAsync(string task)
public async Task RunAsync(string task)
{
await VideoKeyFrames(task);
await Audio2WAV16KAsync(task);
@ -156,10 +174,9 @@ namespace VideoAnalysisCore.AICore.FFMPGE
/// </summary>
/// <param name="task">任务id</param>
/// <returns></returns>
public static async Task Audio2WAV16KAsync(string task)
public async Task Audio2WAV16KAsync(string task)
{
var filePath = await DbScoped.Sugar
.Queryable<VideoTask>()
var filePath = await videoTaskDB.AsQueryable()
.Where(s => s.Id == long.Parse(task))
.Select(s=>s.LocalMediaPath).FirstAsync();
if (string.IsNullOrEmpty(filePath))

View File

@ -23,17 +23,19 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
private readonly Repository<CourseGradingCriteria> criteriaDB;
private readonly Repository<VideoTask> videoTaskDB;
private readonly Repository<KnowledgeInfo> knowledgeInfoDB;
private readonly RedisManager redisManager;
/// <summary>
/// 初始化
/// </summary>
/// <param name="moonshotClient"></param>
/// <param name="logger"></param>
public Chat_GPT(ChatGPTClient moonshotClient, Repository<CourseGradingCriteria> criteria, Repository<VideoTask> videoTaskDB, Repository<KnowledgeInfo> knowledgeInfoDB)
public Chat_GPT(ChatGPTClient moonshotClient, Repository<CourseGradingCriteria> criteria, Repository<VideoTask> videoTaskDB, Repository<KnowledgeInfo> knowledgeInfoDB, RedisManager redisManager)
{
this.chatClient = moonshotClient;
criteriaDB = criteria;
this.videoTaskDB = videoTaskDB;
this.knowledgeInfoDB = knowledgeInfoDB;
this.redisManager = redisManager;
}
private static List<VideoKnowRes> MergeRes(VideoKnowRes[] timeBases)
@ -162,7 +164,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
item.EndTime = (int)(questionRes[i + 1]?.StartTime ?? 0) - 1;
}
await RedisExpand.Redis
await redisManager.Redis
.HMSetAsync(RedisExpandKey.Task(task), "VideoKnows", questionRes);
//var postMessages1 =
@ -181,7 +183,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
////questionRes1 = MergeRes(questionRes1).ToArray();
var gptRes = new TaskRes(captions);
await RedisExpand.Redis
await redisManager.Redis
.HMSetAsync(RedisExpandKey.Task(task), "ChatAnalysis", gptRes);
return gptRes;
}
@ -203,13 +205,13 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
};
var time = DateTime.Now.ToString("MMddHHmmss");
RedisExpand.SetTaskGPTCached(task, time,chatRep);
redisManager.SetTaskGPTCached(task, time,chatRep);
var chatResp = await chatClient.Chat(chatRep);
var chatResContent = chatResp?.res;
if (string.IsNullOrEmpty(chatResContent))
throw new Exception("GPT返回message无效结果");
if (chatResp != null)
RedisExpand.SetTaskGPTCached(task, time, new object[] { chatResp.Value.res, chatResp.Value.u });
redisManager.SetTaskGPTCached(task, time, new object[] { chatResp.Value.res, chatResp.Value.u });
chatResContent = chatResContent?.Replace("字幕内容", "课堂情况");
chatResContent = chatResContent?.Replace("\n", "");
@ -307,13 +309,13 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
};
var time = DateTime.Now.ToString("MMddHHmmss");
RedisExpand.SetTaskGPTCached(task, time, chatRep);
redisManager.SetTaskGPTCached(task, time, chatRep);
var chatResp = await chatClient.Chat(chatRep);
var chatResContent = chatResp?.res;
if (string.IsNullOrEmpty(chatResContent))
throw new Exception("GPT返回message无效结果");
if (chatResp != null)
RedisExpand.SetTaskGPTCached(task, time, new object[] { chatResp.Value.res, chatResp.Value.u });
redisManager.SetTaskGPTCached(task, time, new object[] { chatResp.Value.res, chatResp.Value.u });
chatResContent = chatResContent?.Replace("字幕内容", "课堂情况");
chatResContent = chatResContent?.Replace("\n", "");
@ -413,7 +415,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
.ExecuteCommandAsync();
}
await RedisExpand.Redis
await redisManager.Redis
.HMSetAsync(RedisExpandKey.Task(task), "ChatAnalysis", gptRes);
return gptRes;

View File

@ -33,10 +33,13 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
//private readonly string Path = "v1/chat/completions";
private readonly IHttpClientFactory _httpClientFactory;
private readonly RedisManager redisManager;
public DeepSeekGPTClient(IHttpClientFactory httpClientFactory)
public DeepSeekGPTClient(IHttpClientFactory httpClientFactory, RedisManager redisManager)
{
_httpClientFactory = httpClientFactory;
this.redisManager = redisManager;
}
@ -192,7 +195,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
messageBuilder1.Append(strReasoning);
var steamCount = messageBuilder.Length + messageBuilder1.Length;
if (++threshold%30==0)
RedisExpand.SetTaskProgress(chatReq.taskId, "steam=>"+ steamCount);
redisManager.SetTaskProgress(chatReq.taskId, "steam=>"+ steamCount);
}
catch (Exception e)
{

View File

@ -14,7 +14,6 @@ using VideoAnalysisCore.Model.Enum;
using Mapster;
using System.Linq;
using System.Security.Cryptography;
using static System.Collections.Specialized.BitVector32;
using FFmpeg.NET.Services;
using Aliyun.OSS;
using Yitter.IdGenerator;
@ -31,6 +30,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{
private readonly DeepSeekGPTClient chatClient;
private readonly Repository<CourseGradingCriteria> criteriaDB;
private readonly RedisManager redisManager;
private readonly Repository<VideoTask> videoTaskDB;
private readonly Repository<VideoKonwPoint> videoKonwPointDB;
private readonly Repository<VideoQuestion> videoQuestionDB;
@ -43,7 +43,9 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
/// </summary>
/// <param name="moonshotClient"></param>
/// <param name="logger"></param>
public DeepSeek_GPT(DeepSeekGPTClient moonshotClient, Repository<CourseGradingCriteria> criteria, Repository<VideoTask> videoTaskDB, Repository<KnowledgeInfo> knowledgeInfoDB, Repository<VideoKonwPoint> videoKonwPointDB, SimpLetexClient simpLetexClient, Repository<VideoQuestion> videoQuestionDB, OssClient ossClient, Repository<VideoQuestionKonw> videoQuestionKonwDB)
public DeepSeek_GPT(DeepSeekGPTClient moonshotClient, Repository<CourseGradingCriteria> criteria, Repository<VideoTask> videoTaskDB,
Repository<KnowledgeInfo> knowledgeInfoDB, Repository<VideoKonwPoint> videoKonwPointDB, SimpLetexClient simpLetexClient,
Repository<VideoQuestion> videoQuestionDB, OssClient ossClient, Repository<VideoQuestionKonw> videoQuestionKonwDB, RedisManager redisManager)
{
chatClient = moonshotClient;
criteriaDB = criteria;
@ -54,6 +56,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
this.videoQuestionDB = videoQuestionDB;
this.ossClient = ossClient;
this.videoQuestionKonwDB = videoQuestionKonwDB;
this.redisManager = redisManager;
}
/// <summary>
/// 获取内容对应的章节
@ -151,7 +154,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
.SetColumns(it => it.Sections == fileNameInfoRes.)
.Where(it => it.Id == taskInfo.Id)
.ExecuteCommandAsync();
await RedisExpand.Redis
await redisManager.Redis
.HMSetAsync(RedisExpandKey.Task(task), "学科章节", fileNameInfoRes.);
return fileNameInfoRes?.;
@ -354,7 +357,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{
var time = title + DateTime.Now.ToString("MMddHHmmss");
var redisCached = new object[2] { chatRep, null };
RedisExpand.SetTaskGPTCached(task, time, chatRep);
redisManager.SetTaskGPTCached(task, time, chatRep);
var chatResp = await chatClient.Chat(chatRep);
var chatResContent = chatResp?.res;
if (string.IsNullOrEmpty(chatResContent))
@ -362,7 +365,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
if (chatResp != null)
{
redisCached[1] = new object[] { chatResp.Value.res, chatResp.Value.u, chatResp.Value.reasoning };
RedisExpand.SetTaskGPTCached(task, time, redisCached);
redisManager.SetTaskGPTCached(task, time, redisCached);
}
chatResContent = chatResContent?.ExtractJsonStrings()?.FirstOrDefault();
chatResContent = chatResContent?.Replace("\n", "");
@ -604,7 +607,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{
throw new Exception("重试次数过多!");
}
await RedisExpand.Redis
await redisManager.Redis
.HMSetAsync(RedisExpandKey.Task(task), "VideoKnows", questionRes);
return null;

View File

@ -1,4 +1,5 @@
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using SherpaOnnx;
using SqlSugar.IOC;
using System;
@ -17,18 +18,40 @@ using static System.Runtime.InteropServices.JavaScript.JSType;
namespace VideoAnalysisCore.AICore.SherpaOnnx
{
public static class SenseVoice
public static class SenseVoiceExpand
{
/// <summary>
/// 添加 SenseVoice 语音转文字
/// </summary>
/// <param name="services"></param>
public static void AddSenseVoiceExpand(this IServiceCollection services)
{
services.AddSingleton<SenseVoice>();
}
}
public class SenseVoice
{
const string TransducerStr = "sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20";
static OfflineRecognizer OR = default!;
//static VoiceActivityDetector VAD = default!;
static VadModelConfig VADModelConfig = default!;
public Repository<VideoTask> videoTaskDB { get; set; }
private readonly RedisManager redisManager;
public SenseVoice(Repository<VideoTask> videoTaskDB, RedisManager redisManager)
{
this.videoTaskDB = videoTaskDB;
this.redisManager = redisManager;
}
/// <summary>
/// 初始化 SenseVoice
/// </summary>
/// <param name="numThreads">默认6线程</param>
/// <param name="useGPU">是否使用gpu 报错请看安装CUDA环境<see cref="https://k2-fsa.github.io/sherpa/onnx/pretrained_models/whisper/large-v3.html#run-with-gpu-float32"/></param>
public static void Init(int numThreads = 6, bool useGPU = false, bool useHotwords = false)
public void Init(int numThreads = 6, bool useGPU = false, bool useHotwords = false)
{
Console.WriteLine("初始化 SenseVoice");
OfflineRecognizerConfig config = new OfflineRecognizerConfig();
@ -102,24 +125,19 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static async Task<List<SenseVoiceRes>> RunTask(Stream s)
public async Task<List<SenseVoiceRes>> RunTask(Stream s)
{
if (s is null)
throw new Exception("音频路径 is null");
return await TaskHandle(new WaveReader(s));
return await TaskHandle(new WaveReader(s), null);
}
/// <summary>
/// 获取语音字幕
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
public static async Task RunTask(string task)
public async Task RunTask(string task)
{
var filePath = Path.Combine(task.LocalPath(), "task.wav");
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
@ -134,7 +152,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
/// <param name="task">任务id [默认Null]</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static async Task<List<SenseVoiceRes>> TaskHandle(WaveReader reader, string? task = null)
public async Task<List<SenseVoiceRes>> TaskHandle(WaveReader reader, string? task )
{
if (OR is null)
Init();
@ -162,25 +180,30 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
{
//获取最新的发言片段
while (!VAD.IsEmpty())
await VAD.ReadNext(res, totalSecond, task);
{
var p = await ReadNext(VAD,res, totalSecond);
if (p != null) redisManager.SetTaskProgress(task, p + "%");
}
}
}
VAD.Flush();
while (!VAD.IsEmpty())
await VAD.ReadNext(res, totalSecond, task);
{
var p = await ReadNext(VAD, res, totalSecond);
if(p!= null) redisManager.SetTaskProgress(task, p + "%");
}
//如果携带任务ID
if (!string.IsNullOrEmpty(task))
{
Console.WriteLine(DateTime.Now + "=> SenseVoice 字幕数量" + res.Count);
var captionsStr = res.ToJson();
await DbScoped.Sugar
.Updateable<VideoTask>()
await videoTaskDB.AsUpdateable()
.SetColumns(it => it.Captions == captionsStr)
.Where(it => it.Id == long.Parse(task))
.ExecuteCommandAsync();
await RedisExpand.Redis.HMSetAsync(RedisExpandKey.Task(task), "Captions", res);
await redisManager.Redis.HMSetAsync(RedisExpandKey.Task(task), "Captions", res);
//分析完成视频字幕后继续接收任务
RedisExpand.NewTask();
redisManager.NewTask();
}
return res;
}
@ -190,9 +213,9 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
/// <param name="VAD"></param>
/// <param name="res">字幕处理后写入数组</param>
/// <param name="totalSecond">总时长</param>
/// <param name="task">所属任务id</param>
/// <param name="progressCallback">任务回调</param>
/// <returns></returns>
public static async Task ReadNext(this VoiceActivityDetector VAD, List<SenseVoiceRes> res, float totalSecond, string? task = null)
public async Task<double?> ReadNext(VoiceActivityDetector VAD, List<SenseVoiceRes> res, float totalSecond)
{
var segment = VAD.Front();
var sampleRate = VADModelConfig.SampleRate;
@ -202,13 +225,14 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
using var stream = OR.CreateStream();
stream.AcceptWaveform(sampleRate, segment.Samples);
OR.Decode(stream);
double? resP =null;
if (!string.IsNullOrEmpty(stream.Result.Text))
{
var text = stream.Result.Text.Trim();
if (text.Length == 1 && text == "。")// 检查字符是否只有一个句号
{
VAD.Pop();
return;
return resP;
}
res.Add(new()
{
@ -216,10 +240,10 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
Start = (float)Math.Round(startTime, 2, MidpointRounding.AwayFromZero),
End = (float)Math.Round(startTime + duration, 2, MidpointRounding.AwayFromZero),
});
if (!string.IsNullOrEmpty(task))
RedisExpand.SetTaskProgress(task, Math.Round((double)(startTime + duration) / (totalSecond) * 100,2)+"%");
resP = Math.Round((double)(startTime + duration) / (totalSecond) * 100, 2);
}
VAD.Pop();
return resP;
}
}
}

View File

@ -10,6 +10,7 @@ using System.Text.Json;
using VideoAnalysisCore.Model.Enum;
using Microsoft.Extensions.DependencyInjection;
using UserCenter.Model.Enum;
using VideoAnalysisCore.Model.Dto;
namespace VideoAnalysisCore.AICore.SherpaOnnx
{
@ -73,17 +74,16 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
if(i%20 !=0)
return 1;
var progress = (float)numProcessedChunks / numTotalChunks * 100;
RedisExpand.SetTaskProgress(task, progress);
//RedisExpand.SetTaskProgress(task, progress);
return 1;
}, nint.Zero);
var res = segments.Select(s => new OfflineSpeakerRes(s));
await RedisExpand.Redis.HSetAsync(RedisExpandKey.Task(task), "Speaker", res);
//await RedisExpand.Redis.HSetAsync(RedisExpandKey.Task(task), "Speaker", res);
var speakerStr = res.ToJson();
await DbScoped.Sugar
.Updateable<VideoTask>()
.SetColumns(it => it.Speaker == speakerStr)
.Where(it => it.Id == long.Parse(task))
.ExecuteCommandAsync();
//await videoTaskDB.Updateable()
// .SetColumns(it => it.Speaker == speakerStr)
// .Where(it => it.Id == long.Parse(task))
// .ExecuteCommandAsync();
}
}

View File

@ -45,7 +45,7 @@ namespace VideoAnalysisCore.AICore.Whisper
{
res.Add(new WhisperResDto(segment));
}
RedisExpand.Redis.HMSet(RedisExpandKey.Task(task), "Captions", res);
//RedisExpand.Redis.HMSet(RedisExpandKey.Task(task), "Captions", res);
}
/// <summary>
/// 检测语言的方法

View File

@ -93,14 +93,16 @@ namespace VideoAnalysisCore.Common
private readonly Repository<VideoTask> videoTaskDB;
private readonly Repository<NodePackageInfo> packageInfoTaskDB;
private readonly Client vodClient;
private readonly RedisManager redisManager;
readonly string taskVideoName = "task.mp4";
readonly string taskPPTVideoName = "ppt.mp4";
public DownloadFile(Repository<VideoTask> videoTaskDB, Client vodClient, Repository<NodePackageInfo> nackageInfoTaskDB)
public DownloadFile(Repository<VideoTask> videoTaskDB, Client vodClient, Repository<NodePackageInfo> nackageInfoTaskDB, RedisManager redisManager)
{
this.videoTaskDB = videoTaskDB;
this.vodClient = vodClient;
this.packageInfoTaskDB = nackageInfoTaskDB;
this.redisManager = redisManager;
}
// 根据 Content-Type 映射文件后缀
@ -187,7 +189,7 @@ namespace VideoAnalysisCore.Common
if (!string.IsNullOrEmpty(taskInfo.PPTVideoUrl))
{
await Download(taskInfo.PPTVideoUrl, localPath, taskPPTVideoName,
(s, e) => RedisExpand.SetTaskProgress(task, "PPT->" + Math.Round(e.ProgressPercentage, 1)
(s, e) => redisManager.SetTaskProgress(task, "PPT->" + Math.Round(e.ProgressPercentage, 1)
));
//try
//{
@ -217,7 +219,7 @@ namespace VideoAnalysisCore.Common
{
//下载原视频
await Download(fileUrl, localPath, taskVideoName,
(s, e) => RedisExpand.SetTaskProgress(task, Math.Round(e.ProgressPercentage,1)
(s, e) => redisManager.SetTaskProgress(task, Math.Round(e.ProgressPercentage,1)
));
}
catch

View File

@ -44,7 +44,7 @@ namespace VideoAnalysisCore.Common.Expand
DbType = s.SqlType,
IsAutoCloseConnection = true
}));
services.AddScoped(typeof(Repository<>));
services.AddTransient(typeof(Repository<>));
//注入SqlSugar 主库
services.AddSqlSugar(dbList);

View File

@ -1,6 +1,7 @@
using FreeRedis;
using FreeRedis.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using NetTaste;
using Newtonsoft.Json.Schema;
using SqlSugar.IOC;
@ -22,7 +23,6 @@ using VideoAnalysisCore.AICore.Whisper;
using VideoAnalysisCore.Model;
using VideoAnalysisCore.Model.Dto;
using VideoAnalysisCore.Model.Enum;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace VideoAnalysisCore.Common
{
@ -31,6 +31,7 @@ namespace VideoAnalysisCore.Common
/// </summary>
public static class RedisExpandKey
{
/// <summary>
/// 基础key
/// </summary>
@ -72,45 +73,112 @@ namespace VideoAnalysisCore.Common
public static string Task(object taskId) => BaseKey + "Task:" + taskId;
public static string IDTask => BaseKey + "Services:" + AppCommon.Config.ID;
public static string TaskGPT(object taskId) => Task(taskId) + ":GPTCached";
/// <summary>
/// 初始化 redis
/// <para>需要在初始化配置文件时候调用</para>
/// </summary>
public static void AddTaskSubscribe(this IServiceCollection service)
{
Console.WriteLine($"{DateTime.Now}=>初始化 Redis任务队列");
service.AddSingleton<RedisInit>();
}
public static void AddRedisExpand(this IServiceCollection service)
{
Console.WriteLine($"{DateTime.Now}=>初始化 Redis");
var redis = new RedisClient(AppCommon.Config.Redis.ConnectionString);
redis.Serialize = obj => JsonSerializer.Serialize(obj);
redis.Deserialize = (json, type) => JsonSerializer.Deserialize(json, type);
service.AddSingleton(redis);
service.AddSingleton<RedisManager>();
}
}
public class RedisInit
{
public FFMPGEHandle FFMPGE { get; set; }
public SenseVoice senseVoice { get; set; }
public RedisManager redisManager { get; set; }
public RedisInit(FFMPGEHandle fFMPGE, SenseVoice senseVoice, RedisManager redisManager)
{
FFMPGE = fFMPGE;
this.senseVoice = senseVoice;
this.redisManager = redisManager;
Init();
redisManager.InitChannel();
}
public void Init()
{
var SubscribeList = RedisManager.SubscribeList;
SubscribeList.Add(RedisChannelEnum., (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<DownloadFile>() is null)
throw new Exception("DownloadFile 未注入");
else
return scope.ServiceProvider.GetService<DownloadFile>()?.RunTask(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum., FFMPGE.RunAsync);
SubscribeList.Add(RedisChannelEnum., senseVoice.RunTask);
//SubscribeList.Add(RedisChannelEnum.解析说话人,Speaker.Run);
SubscribeList.Add(RedisChannelEnum.AI课程类型,
(task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetVideoType(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum.AI模型分析, (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetKnow(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum.AI分析试题, (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetVideoQuestion(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum., redisManager.TaskEnd);
}
}
/// <summary>
/// redis拓展
/// </summary>
public static class RedisExpand
public class RedisManager
{
/// <summary>
/// redis 连接
/// </summary>
public static RedisClient Redis = new RedisClient(AppCommon.Config.Redis.ConnectionString);
public static bool StopTask { get; set; } = false;
public static Dictionary<RedisChannelEnum, Func<string,Task>> SubscribeList = new Dictionary<RedisChannelEnum, Func<string, Task>>();
/// <summary>
/// 队列池
/// </summary>
static SubscribeListObject? Subscribe;
public RedisClient Redis { get; set; }
public Repository<VideoTask> videoTaskDB { get; set; }
/// <summary>
/// 初始化 redis
/// <para>需要在初始化配置文件时候调用</para>
/// </summary>
public static void AddRedisExpand(this IServiceCollection service)
public RedisManager(RedisClient redis, Repository<VideoTask> videoTaskDB)
{
Console.WriteLine($"{DateTime.Now}=>初始化 Redis");
Redis.Serialize = obj => JsonSerializer.Serialize(obj);
Redis.Deserialize = (json, type) => JsonSerializer.Deserialize(json, type);
Task.Run(() =>
{
Thread.Sleep(1000 * 10);
InitChannel();
});
Redis = redis;
this.videoTaskDB = videoTaskDB;
}
/// <summary>
/// 缓存GPT任务缓存
/// </summary>
/// <param name="taskId"></param>
public static void SetTaskGPTCached(object taskId,string time, object? data)
public void SetTaskGPTCached(object taskId,string time, object? data)
{
Redis.Set(RedisExpandKey.TaskGPT(taskId) + ":" + time, data, 3600 * 24);
}
@ -118,7 +186,7 @@ namespace VideoAnalysisCore.Common
/// 加入到消费队列
/// </summary>
/// <param name="taskIds"></param>
public static void JoinQueue(params long[] taskIds)
public void JoinQueue(params long[] taskIds)
{ //事务
if (taskIds is null || taskIds.Length == 0)
return;
@ -133,7 +201,7 @@ namespace VideoAnalysisCore.Common
/// 获取任务进度
/// </summary>
/// <param name="taskId"></param>
public static float GetTaskProgress(object taskId)
public float GetTaskProgress(object taskId)
{
return Redis.HMGet<float>(RedisExpandKey.Task(taskId), "Progress")[0];
}
@ -142,7 +210,7 @@ namespace VideoAnalysisCore.Common
/// </summary>
/// <param name="p">进度百分比</param>
/// <param name="taskId"></param>
public static void SetTaskProgress(object taskId, object p)
public void SetTaskProgress(object taskId, object p)
{
Redis.HMSet(RedisExpandKey.Task(taskId), "Progress", p.ToString());
@ -152,7 +220,7 @@ namespace VideoAnalysisCore.Common
/// </summary>
/// <param name="enum">枚举</param>
/// <param name="taskId">任务id</param>
public static async Task InsertChannel(RedisChannelEnum @enum, object taskId)
public async Task InsertChannel(RedisChannelEnum @enum, object taskId)
{
if (taskId is null) throw new Exception("taskId为空");
if (Redis is null) throw new Exception("redis未初始化");
@ -188,7 +256,7 @@ namespace VideoAnalysisCore.Common
}
}
public static async Task TaskEnd(string task)
public async Task TaskEnd(string task)
{
var tId = long.Parse(task);
//var gptRes = (await Redis
@ -197,8 +265,8 @@ namespace VideoAnalysisCore.Common
// throw new Exception("未能读取到GPT处理结果");
//删除任务执行状态
await Redis.LRemAsync(RedisExpandKey.IDTask,1,task);
var taskData = await DbScoped.Sugar.Queryable<VideoTask>()
.FirstAsync(s => s.Id == tId);
var taskData = await videoTaskDB
.GetFirstAsync(s => s.Id == tId);
if (taskData.Captions == "[]")
taskData.Captions = (await Redis.HMGetAsync(RedisExpandKey.Task(task), "Captions")).First();
//if (taskData.Speaker == "[]")
@ -211,7 +279,7 @@ namespace VideoAnalysisCore.Common
taskData.ErrorMessage = string.Empty;
taskData.LastEnum = RedisChannelEnum.;
taskData.EndTime = DateTime.Now;
await DbScoped.Sugar.Updateable(taskData)
await videoTaskDB.AsUpdateable(taskData)
.UpdateColumns(it => new
{
//it.ChatAnalysis,
@ -230,56 +298,36 @@ namespace VideoAnalysisCore.Common
/// <summary>
/// 初始化 队列 任务
/// </summary>
public static async void InitChannel()
public async void InitChannel()
{
if (Redis is null) throw new Exception("redis未初始化");
SubscribeList.Add(RedisChannelEnum., (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<DownloadFile>() is null)
throw new Exception("DownloadFile 未注入");
else
return scope.ServiceProvider.GetService<DownloadFile>()?.RunTask(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum., FFMPGEHandle.RunAsync);
SubscribeList.Add(RedisChannelEnum., SenseVoice.RunTask);
//SubscribeList.Add(RedisChannelEnum.解析说话人,Speaker.Run);
SubscribeList.Add(RedisChannelEnum.AI课程类型,
(task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetVideoType(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum.AI模型分析, (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetKnow(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum.AI分析试题, (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetVideoQuestion(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum., TaskEnd);
ReceivingTaskAsync();
//处理之前程序结束前未能执行完的情况
var oldTaskCount = Redis.LLen(RedisExpandKey.IDTask);
if (oldTaskCount > 0)
{
var oldTaskArr = Redis.LRange(RedisExpandKey.IDTask, 0, oldTaskCount);
Redis.LTrim(RedisExpandKey.IDTask, 1, 0);//删除 redis 列表
foreach (var oldTask in oldTaskArr)
{
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-------------> 接收上次未完成任务 " + oldTask);
await ClearTaskError(long.Parse(oldTask));
var lastEnum = (await Redis.HMGetAsync<RedisChannelEnum>(RedisExpandKey.Task(oldTask), "LastEnum")).FirstOrDefault();
await InsertChannel(lastEnum, oldTask);
}
}
else
{
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-------------> 接收新任务!");
ReceivingTaskAsync();
}
}
public static bool StopTask { get; set; } = false;
/// <summary>
/// 停止接收新任务
/// </summary>
public static void StopTaskAsync()
public void StopTaskAsync()
{
StopTask = true;
try
@ -297,7 +345,7 @@ namespace VideoAnalysisCore.Common
/// <summary>
/// 开始接收新任务
/// </summary>
public static void RestartTask()
public void RestartTask()
{
StopTask = false;
NewTask();
@ -306,7 +354,7 @@ namespace VideoAnalysisCore.Common
/// 重新执行新任务
/// </summary>
/// <returns></returns>
public static void NewTask()
public void NewTask()
{
// 取消 消费机的任务订阅
if (StopTask)
@ -320,7 +368,7 @@ namespace VideoAnalysisCore.Common
/// <summary>
/// 重新接收新任务
/// </summary>
public static void ReceivingTaskAsync()
public void ReceivingTaskAsync()
{
if (AppCommon.Config.TaskSetting.IS_Server)
{
@ -329,15 +377,6 @@ namespace VideoAnalysisCore.Common
}
Task.Run(async () =>
{
var oldTask = await Redis.LPopAsync(RedisExpandKey.IDTask);
if (!string.IsNullOrEmpty(oldTask))
{
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-------------> 接收重试任务 " + oldTask);
await ClearTaskError(long.Parse(oldTask));
var lastEnum = (await Redis.HMGetAsync<RedisChannelEnum>(RedisExpandKey.Task(oldTask), "LastEnum")).FirstOrDefault();
await InsertChannel(lastEnum, oldTask);
return;
}
lock (Redis)
{
if (Subscribe?.IsUnsubscribed == false)//排除重试机制后 多次接收任务导致内存泄露
@ -363,7 +402,7 @@ namespace VideoAnalysisCore.Common
/// <param name="taskID"></param>
/// <param name="ex"></param>
/// <returns></returns>
public static async Task<bool> SetTaskErrorMessage(long taskID, Exception? ex)
public async Task<bool> SetTaskErrorMessage(long taskID, Exception? ex)
{
var error = string.Empty;
if (ex != null)
@ -386,17 +425,17 @@ namespace VideoAnalysisCore.Common
/// </summary>
/// <param name="taskID"></param>
/// <returns></returns>
public static async Task<bool> ClearTaskError(long taskID) =>await SetTaskError(taskID, string.Empty);
public async Task<bool> ClearTaskError(long taskID) =>await SetTaskError(taskID, string.Empty);
/// <summary>
/// 修改任务的错误信息
/// </summary>
/// <param name="taskID"></param>
/// <param name="error"></param>
/// <returns></returns>
public static async Task<bool> SetTaskError(long taskID, string? error)
public async Task<bool> SetTaskError(long taskID, string? error)
{
Redis.HMSet(RedisExpandKey.Task(taskID), "ErrorMessage", error);
return await DbScoped.Sugar.Updateable<VideoTask>()
return await videoTaskDB.AsUpdateable()
.SetColumns(it => it.ErrorMessage == error)//SetColumns是可以叠加的 写2个就2个字段赋值
.Where(it => it.Id == taskID)
.ExecuteCommandAsync() == 1;
@ -408,7 +447,7 @@ namespace VideoAnalysisCore.Common
/// <param name="key"></param>
/// <param name="taskId"></param>
/// <param name="action"></param>
public static async Task TouchChannel(RedisChannelEnum key, string taskId, Func<string, Task> action = null)
public async Task TouchChannel(RedisChannelEnum key, string taskId, Func<string, Task> action = null)
{
if (taskId is null) return;
var tID = long.Parse(taskId);
@ -424,7 +463,7 @@ namespace VideoAnalysisCore.Common
Redis.HMSet(RedisExpandKey.Task(taskId), "Progress", 0);
lock (Redis)
{
DbScoped.SugarScope.Updateable<VideoTask>()
videoTaskDB.AsUpdateable()
.SetColumns(it => it.LastEnum == key)
.Where(it => it.Id == tID)
.ExecuteCommand();

View File

@ -24,16 +24,16 @@ namespace VideoAnalysisCore.Common
if (CID.ContainsKey(t))
{
base.Context = CID[t]!=null
? DbScoped.SugarScope.GetConnectionScope(CID[t])
: DbScoped.SugarScope;
? DbScoped.Sugar.GetConnectionScope(CID[t])
: DbScoped.Sugar;
return;
}
var c = t.GetCustomAttribute<TenantAttribute>();
if (!CID.ContainsKey(t))
CID.Add(t, c?.configId);
base.Context = c != null
? DbScoped.SugarScope.GetConnectionScope(c.configId)
: DbScoped.SugarScope;
? DbScoped.Sugar.GetConnectionScope(c.configId)
: DbScoped.Sugar;
}
}
}

View File

@ -28,15 +28,19 @@ namespace VideoAnalysisCore.Controllers
{
private readonly IMapper mp;
private readonly Repository<VideoTask> videoTaskDB;
private readonly RedisManager redisManager;
private readonly Repository<VideoKonwPoint> videoKonwDB;
private readonly Repository<CourseInfo> courseInfoDB;
public readonly SenseVoice senseVoice;
public ApiController(Repository<VideoTask> videoTaskDB,
IMapper mp, Repository<VideoKonwPoint> videoKonwDB, Repository<CourseInfo> courseInfoDB)
IMapper mp, Repository<VideoKonwPoint> videoKonwDB, Repository<CourseInfo> courseInfoDB, RedisManager redisManager, SenseVoice senseVoice)
{
this.videoTaskDB = videoTaskDB;
this.mp = mp;
this.videoKonwDB = videoKonwDB;
this.courseInfoDB = courseInfoDB;
this.redisManager = redisManager;
this.senseVoice = senseVoice;
}
private string GetClientIpAddress()
@ -82,9 +86,9 @@ namespace VideoAnalysisCore.Controllers
public IActionResult StartTask(bool task)
{
if(task)
RedisExpand.RestartTask();
redisManager.RestartTask();
else
RedisExpand.StopTaskAsync();
redisManager.StopTaskAsync();
return Ok();
}
/// <summary>
@ -100,7 +104,7 @@ namespace VideoAnalysisCore.Controllers
using HttpClient client = new HttpClient();
// 发送GET请求获取网络文件流
using var networkStream = await client.GetStreamAsync(url);
var res = await SenseVoice.RunTask(networkStream);
var res = await senseVoice.RunTask(networkStream);
return Ok(res);
}
catch (Exception ex)
@ -117,7 +121,7 @@ namespace VideoAnalysisCore.Controllers
public async Task<IActionResult> AudioRecognition(IFormFile file)
{
using var s = file.OpenReadStream();
var res = await SenseVoice.RunTask(s);
var res = await senseVoice.RunTask(s);
return Ok(res);
}
@ -204,8 +208,8 @@ namespace VideoAnalysisCore.Controllers
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.ToDictionary(s => s.Name, s => s.GetValue(task));
await videoTaskDB.InsertAsync(task);
RedisExpand.Redis.HMSet(RedisExpandKey.Task(task.Id), hashEntries);
RedisExpand.Redis.LPush(RedisExpandKey.ChannelKey, task.Id);
redisManager.Redis.HMSet(RedisExpandKey.Task(task.Id), hashEntries);
redisManager.Redis.LPush(RedisExpandKey.ChannelKey, task.Id);
return Ok(task.Id);
}

View File

@ -38,10 +38,11 @@ namespace VideoAnalysisCore.Controllers
private readonly Repository<NodePackageInfo> nodePackageInfoDB;
private readonly Repository<VideoQuestion> videoQuestionDB;
private readonly Repository<VideoQuestionKonw> videoQuestionKonwDB;
private readonly RedisManager redisManager;
public LJZK_Controller(IMapper mp, Repository<NodeSubscription> nodesubscriptionDB,
Repository<VideoTask> videoTaskDB = null, Repository<VideoKonwPoint> videoKonwPointDB = null
, Repository<NodePackageInfo> nodePackageInfoDB = null, Repository<VideoQuestion> videoQuestionDB = null, Repository<VideoQuestionKonw> videoQuestionKonwDB = null, Repository<CourseInfo> courseInfoDB = null)
, Repository<NodePackageInfo> nodePackageInfoDB = null, Repository<VideoQuestion> videoQuestionDB = null, Repository<VideoQuestionKonw> videoQuestionKonwDB = null, Repository<CourseInfo> courseInfoDB = null, RedisManager redisManager = null)
{
this.mp = mp;
this.nodesubscriptionDB = nodesubscriptionDB;
@ -51,6 +52,7 @@ namespace VideoAnalysisCore.Controllers
this.videoQuestionDB = videoQuestionDB;
this.videoQuestionKonwDB = videoQuestionKonwDB;
this.courseInfoDB = courseInfoDB;
this.redisManager = redisManager;
}
@ -125,7 +127,7 @@ namespace VideoAnalysisCore.Controllers
if (videos is null || videos.Count == 0)
return Ok();
var ids = videos.Select(s => s.Id).ToArray();
RedisExpand.JoinQueue(ids);
redisManager.JoinQueue(ids);
return Ok();
}

View File

@ -36,76 +36,76 @@ namespace VideoAnalysisCore.Job
public async Task Invoke()
{
throw new Exception("已经弃用");
Console.WriteLine($"{DateTime.Now} 执行=>文件节点订阅");
// Console.WriteLine($"{DateTime.Now} 执行=>文件节点订阅");
var videoIdArr = videotaskDB.AsQueryable().Select(v => v.TagId).Distinct().ToArray();
var tasks = await nodesubscriptionDB.GetListAsync(s => s.Enable && s.Subject ==SubjectEnum.);
foreach (var item in tasks)
{
var fileNodeId = item.NodeId;
var data = attachmentsDB.Context.Ado
.SqlQuery<Attachments>($"""
SELECT top {TopLength}
*
FROM
Attachments
WHERE
Id IN (
SELECT
AttachmentsId
FROM
Material
WHERE
id IN (
SELECT
MaterialId
FROM
FileContentMaterial
WHERE
FileContentId IN ( SELECT id FROM FileContent WHERE BagId IN ( SELECT Id FROM FileDirectory WHERE Id={fileNodeId} AND types = 1 AND DeleteState = 0 ) )
AND DeleteState = 0
AND ( MaterialName NOT LIKE '%PPT%' OR MaterialName NOT LIKE '%ppt%' )
)
)
AND Type = ''
AND (
NAME NOT LIKE '%PPT%'
OR NAME NOT LIKE '%ppt%'
) and id>{item.LastId}
""");
if (data is null || data.Count == 0)
continue;
Console.WriteLine($"{DateTime.Now} 视频订阅=>Node:{item.NodeId} 数量{data.Count}");
// var videoIdArr = videotaskDB.AsQueryable().Select(v => v.TagId).Distinct().ToArray();
// var tasks = await nodesubscriptionDB.GetListAsync(s => s.Enable && s.Subject ==SubjectEnum.数学);
// foreach (var item in tasks)
// {
// var fileNodeId = item.NodeId;
// var data = attachmentsDB.Context.Ado
// .SqlQuery<Attachments>($"""
//SELECT top {TopLength}
// *
//FROM
// Attachments
//WHERE
// Id IN (
// SELECT
// AttachmentsId
// FROM
// Material
// WHERE
// id IN (
// SELECT
// MaterialId
// FROM
// FileContentMaterial
// WHERE
// FileContentId IN ( SELECT id FROM FileContent WHERE BagId IN ( SELECT Id FROM FileDirectory WHERE Id={fileNodeId} AND types = 1 AND DeleteState = 0 ) )
// AND DeleteState = 0
// AND ( MaterialName NOT LIKE '%PPT%' OR MaterialName NOT LIKE '%ppt%' )
// )
// )
// AND Type = '录播视频'
// AND (
// NAME NOT LIKE '%PPT%'
// OR NAME NOT LIKE '%ppt%'
// ) and id>{item.LastId}
//""");
// if (data is null || data.Count == 0)
// continue;
// Console.WriteLine($"{DateTime.Now} 视频订阅=>Node:{item.NodeId} 数量{data.Count}");
var videos = new List<VideoTask>(data.Count);
foreach (var s in data)
{
if (videoIdArr.Contains(s.VideoCode))
continue;
//videos.Add(new VideoTask()
//{
// Id = YitIdHelper.NextId(),
// ComeFrom = "127.0.0.1",
// ApiToken = "",
// //Type = item.TaskType,
// Subject = item.Subject,
// Tag = item.NodeId.ToString(),
// TagId = s.VideoCode,
// MediaUrl = string.Empty,
//});
}
var maxId = data.Max(s => s.Id);
//入库 更新最后扫描记录
await nodesubscriptionDB.AsUpdateable()
.SetColumns(it => it.LastId == maxId)
.Where(it => it.Id == item.Id)
.ExecuteCommandAsync();
await videotaskDB.InsertRangeAsync(videos);
var ids = videos.Select(s => s.Id).ToArray();
RedisExpand.JoinQueue(ids);
// var videos = new List<VideoTask>(data.Count);
// foreach (var s in data)
// {
// if (videoIdArr.Contains(s.VideoCode))
// continue;
// //videos.Add(new VideoTask()
// //{
// // Id = YitIdHelper.NextId(),
// // ComeFrom = "127.0.0.1",
// // ApiToken = "",
// // //Type = item.TaskType,
// // Subject = item.Subject,
// // Tag = item.NodeId.ToString(),
// // TagId = s.VideoCode,
// // MediaUrl = string.Empty,
// //});
// }
// var maxId = data.Max(s => s.Id);
// //入库 更新最后扫描记录
// await nodesubscriptionDB.AsUpdateable()
// .SetColumns(it => it.LastId == maxId)
// .Where(it => it.Id == item.Id)
// .ExecuteCommandAsync();
// await videotaskDB.InsertRangeAsync(videos);
// var ids = videos.Select(s => s.Id).ToArray();
// RedisExpand.JoinQueue(ids);
}
// }
}
}
}