Compare commits

..

No commits in common. "53951aa870caa0c0fcfbcaf3d0a9e0d3ff878a6a" and "f8a758ff40afe0aca7f5c0b1bd65eab42e0aaac1" have entirely different histories.

24 changed files with 58 additions and 214 deletions

View File

@ -18,9 +18,7 @@ namespace Learn.VideoAnalysis.Expand
Console.WriteLine($"{DateTime.Now}=>初始化 Coravel"); Console.WriteLine($"{DateTime.Now}=>初始化 Coravel");
service.AddScheduler(); service.AddScheduler();
#if !DEBUG
service.AddTransient<TaskFileClearJob>(); service.AddTransient<TaskFileClearJob>();
#endif
service.AddTransient<NodePackageJob>(); service.AddTransient<NodePackageJob>();
} }
public static void UseCoravelExpand(this IApplicationBuilder provider) public static void UseCoravelExpand(this IApplicationBuilder provider)

View File

@ -100,7 +100,6 @@ namespace Learn.VideoAnalysis
AppCommon.Services = app.Services; AppCommon.Services = app.Services;
app.UseMiddleware<BasicAuthMiddleware>("Swagger"); app.UseMiddleware<BasicAuthMiddleware>("Swagger");
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
//¿ªÆôredis¶ÓÁзþÎñ
_ = app.Services.GetRequiredService<RedisInit>(); _ = app.Services.GetRequiredService<RedisInit>();
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(); app.UseSwaggerUI();

View File

@ -18,8 +18,7 @@ export default {
component: () => import("@/views/welcome/runningTask.vue"), component: () => import("@/views/welcome/runningTask.vue"),
meta: { meta: {
title: "进行中任务", title: "进行中任务",
showLink: true, showLink: true
keepAlive:true,
} }
}, },
{ {
@ -37,8 +36,7 @@ export default {
component: () => import("@/views/welcome/showTask.vue"), component: () => import("@/views/welcome/showTask.vue"),
meta: { meta: {
title: "预览任务", title: "预览任务",
showLink: false, showLink: false
keepAlive:true,
} }
}, },
{ {
@ -47,8 +45,7 @@ export default {
component: () => import("@/views/welcome/errorTask.vue"), component: () => import("@/views/welcome/errorTask.vue"),
meta: { meta: {
title: "错误任务", title: "错误任务",
showLink: true, showLink: true
keepAlive:true,
} }
} }
] ]

View File

@ -139,7 +139,6 @@ function previewTask(row: any) {
meta: { meta: {
title: `任务预览` + row.id.toString().slice(-4), title: `任务预览` + row.id.toString().slice(-4),
dynamicLevel: 3, dynamicLevel: 3,
keepAlive: true,
}, },
}); });
// //

View File

@ -155,13 +155,9 @@ function timeupdateVideo() {
let subtitleI = subtitles.value.findIndex( let subtitleI = subtitles.value.findIndex(
(subtitle) => currentTime >= subtitle.start && currentTime <= subtitle.end (subtitle) => currentTime >= subtitle.start && currentTime <= subtitle.end
); );
// AI
let subtitleI1 = subtitles1.value.findLastIndex(
(subtitle) => currentTime >= subtitle.start
);
if (subtitleI > -1 && currentSubtitle.value !== subtitles.value[subtitleI].text) { if (subtitleI > -1 && currentSubtitle.value !== subtitles.value[subtitleI].text) {
currentSubtitle.value = subtitles.value[subtitleI].text; currentSubtitle.value = subtitles.value[subtitleI].text;
currentSubtitle1.value = subtitles1.value[subtitleI1]?.text || ""; currentSubtitle1.value = subtitles1.value[subtitleI]?.text || "";
} else if (subtitleI == -1) { } else if (subtitleI == -1) {
currentSubtitle.value = ""; currentSubtitle.value = "";
currentSubtitle1.value = ""; currentSubtitle1.value = "";

View File

@ -62,6 +62,12 @@ namespace VideoAnalysisCore.AICore.GPT
public float? max_tokens { get; set; } = 8000; public float? max_tokens { get; set; } = 8000;
public float? max_completion_tokens { get; set; } = 8000; public float? max_completion_tokens { get; set; } = 8000;
/// <summary> /// <summary>
/// 要使用的采样温度,介于 0 和 2 之间。较高的值(如 0.8)将使输出更加随机,而较低的值(如 0.2)将使其更加集中和确定。 我们通常建议更改此项或同时更改两者。top_p
/// <para> 默认为 1</para>
/// <para> <see cref="ChatRequest.top_p"/>联动</para>
/// </summary>
public float? temperature { get; set; } = 0.2f;
/// <summary>
/// 一种替代温度采样的方法,称为原子核采样, 其中模型考虑具有top_p概率的标记的结果 质量。所以 0.1 表示仅包含前 10% 概率质量的代币 被考 /// 一种替代温度采样的方法,称为原子核采样, 其中模型考虑具有top_p概率的标记的结果 质量。所以 0.1 表示仅包含前 10% 概率质量的代币 被考
/// <para>建议与<see cref="ChatRequest.temperature"/>联动</para> /// <para>建议与<see cref="ChatRequest.temperature"/>联动</para>
/// </summary> /// </summary>

View File

@ -58,6 +58,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
title = title, title = title,
max_tokens = max_tokens, max_tokens = max_tokens,
stream = true, stream = true,
temperature = 0.2f,
messages = messageArr messages = messageArr
}; };

View File

@ -57,6 +57,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
model = model ?? ChatGPTType.Deepseek_Chat, model = model ?? ChatGPTType.Deepseek_Chat,
max_tokens = model == ChatGPTType.Deepseek_Reasoner ? 32000 : max_tokens, max_tokens = model == ChatGPTType.Deepseek_Reasoner ? 32000 : max_tokens,
stream = true, stream = true,
temperature = 0.2f,
messages = messageArr messages = messageArr
}; };
return await base.ChatAsync<T>(chatReq); return await base.ChatAsync<T>(chatReq);

View File

@ -1,4 +1,4 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -34,10 +34,9 @@ namespace VideoAnalysisCore.AICore.GPT.Dto
} }
public class VideoKnowPointDto public class VideoKnowPointDto
{ {
public float KnowPointWeight { get; set; }
public string KnowPoint { get; set; } public string KnowPoint { get; set; }
public string KnowPointId { get; set; } public string KnowPointId { get; set; }
public float KnowSourceTime { get; set; }
public float KnowPointWeight { get; set; }
public string KnowSource { get; set; } public string KnowSource { get; set; }
} }
public class VideoKnowRes public class VideoKnowRes
@ -66,6 +65,10 @@ namespace VideoAnalysisCore.AICore.GPT.Dto
/// </summary> /// </summary>
public virtual string? KnowPoint { get; set; } public virtual string? KnowPoint { get; set; }
/// <summary> /// <summary>
/// 知识点权重
/// </summary>
public virtual float? KnowPointWeight { get; set; }
/// <summary>
/// 知识点ID /// 知识点ID
/// </summary> /// </summary>
public virtual string? KnowPointId { get; set; } public virtual string? KnowPointId { get; set; }

View File

@ -31,7 +31,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
/// <summary> /// <summary>
/// 视频分析工作流1 /// 视频分析工作流1
/// </summary> /// </summary>
public class GTP_Analysis_1 : IBserGPTWorkflow public class GTP_Analysis_1 : IBserGPTWorkflow
{ {
private readonly GeminiGPTClient geminiClient; private readonly GeminiGPTClient geminiClient;
private readonly DeepSeekGPTClient deepSeekClient; private readonly DeepSeekGPTClient deepSeekClient;
@ -187,7 +187,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
$"字幕列表 {rCaptionArr}。" + $"字幕列表 {rCaptionArr}。" +
$"输出格式 json字符串 对象格式{fileNameResFormat}"; $"输出格式 json字符串 对象格式{fileNameResFormat}";
var task = taskInfo.Id.ToString(); var task = taskInfo.Id.ToString();
var fileNameInfoRes = await geminiClient.ChatAsync<FileNameInfo> var fileNameInfoRes = await chatGPTClient.ChatAsync<FileNameInfo>
(task, fileNamePostMessages, "授课章节"); (task, fileNamePostMessages, "授课章节");
taskInfo.Sections = fileNameInfoRes.; taskInfo.Sections = fileNameInfoRes.;
await videoTaskDB.AsUpdateable() await videoTaskDB.AsUpdateable()
@ -309,7 +309,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
await Parallel.ForAsync(0, totalCount, await Parallel.ForAsync(0, totalCount,
new ParallelOptions() new ParallelOptions()
#if DEBUG #if DEBUG
{ MaxDegreeOfParallelism = 4 }, { MaxDegreeOfParallelism = 1 },
#else #else
{ MaxDegreeOfParallelism = 9 }, { MaxDegreeOfParallelism = 9 },
#endif #endif
@ -326,23 +326,25 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
var postMessages = var postMessages =
$$""" $$"""
# Role # Role
{{subject}},{{sections}}STTJSON {{subject}}{{sections}}STTJSON
# Input & Output Protocol # Input & Output Protocol
JSON `[{"t": number, "r": string}]` JSON `[{"t": number, "r": string}]`
`t` (Time): * `t` (Time):
`r` (Result): * `r` (Result):
Processing Rules () # Processing Rules ()
1. () 1. ()
N N N N
i `t` i `t` i `t` i `t`
使 使
2.
`r` `""` 2. ()
LaTeX / LaTeX ( `$\\frac{a}{b}$`)JSON (`\\\\`)
3. ()
3.
`r` `""`
LaTeX / LaTeX ( `$\\frac{a}{b}$`)JSON (`\\\\`)
# Task Data # Task Data
( {{cStrArr.Count()}} ): ( {{cStrArr.Count()}} ):
{{nowCaptionStr}} {{nowCaptionStr}}
@ -434,13 +436,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
} }
return null; return null;
} }
/// <summary>
/// 作业内容检查
/// </summary>
/// <param name="taskInfo"></param>
/// <param name="captions"></param>
/// <param name="sections"></param>
/// <returns></returns>
private async Task<VideoKnowRes?> DetectHomeworkAssignment(VideoTask taskInfo, TotalCaptionsDto captions, string sections) private async Task<VideoKnowRes?> DetectHomeworkAssignment(VideoTask taskInfo, TotalCaptionsDto captions, string sections)
{ {
if (captions is null || string.IsNullOrWhiteSpace(captions.Captions)) if (captions is null || string.IsNullOrWhiteSpace(captions.Captions))
@ -725,8 +721,6 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
throw new Exception("未能找到对应知识点=>" + sections); throw new Exception("未能找到对应知识点=>" + sections);
List<KnowledgeInfo>? knowledgeInfos = new List<KnowledgeInfo>(); List<KnowledgeInfo>? knowledgeInfos = new List<KnowledgeInfo>();
var kInfo = await knowledgeInfoDB.GetByIdAsync(know.Parent_Id); var kInfo = await knowledgeInfoDB.GetByIdAsync(know.Parent_Id);
if (know.Parent_Id == 0)
kInfo = know;
try try
{ {
knowledgeInfos = await knowledgeInfoDB.AsQueryable() knowledgeInfos = await knowledgeInfoDB.AsQueryable()
@ -802,10 +796,6 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
Stage = s.First().Stage, Stage = s.First().Stage,
Theme = s.First().Theme, Theme = s.First().Theme,
VideoTaskId = taskInfo.Id, VideoTaskId = taskInfo.Id,
CourseLevel = taskInfo.CourseLevel,
TextBookVersionId = taskInfo.TextBookVersionId,
GradeSemester= taskInfo.GradeSemester,
GradeId = taskInfo.GradeId,
}).ToList(); }).ToList();
//尝试追加 作业布置分段 //尝试追加 作业布置分段
if (homework != null && (!questionRes.Any(s => s.Stage == StageEnum..ToString()))) if (homework != null && (!questionRes.Any(s => s.Stage == StageEnum..ToString())))
@ -856,8 +846,6 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
if (know is null) if (know is null)
throw new Exception("未能找到对应知识点=>" + sections); throw new Exception("未能找到对应知识点=>" + sections);
var kInfo = await knowledgeInfoDB.GetByIdAsync(know.Parent_Id); var kInfo = await knowledgeInfoDB.GetByIdAsync(know.Parent_Id);
if (know.Parent_Id == 0)
kInfo = know;
var knowledgeInfos = await knowledgeInfoDB.AsQueryable() var knowledgeInfos = await knowledgeInfoDB.AsQueryable()
.ToChildListAsync(s => s.Parent_Id, kInfo.Parent_Id == 0 ? kInfo.Id : kInfo.Parent_Id); .ToChildListAsync(s => s.Parent_Id, kInfo.Parent_Id == 0 ? kInfo.Id : kInfo.Parent_Id);
//开始分析复习课 试题 //开始分析复习课 试题

View File

@ -56,6 +56,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
model = model, model = model,
max_tokens = max_tokens, max_tokens = max_tokens,
stream = true, stream = true,
temperature = 0.2f,
messages = messageArr, messages = messageArr,
max_completion_tokens= 12288, max_completion_tokens= 12288,
}; };

View File

@ -11,7 +11,6 @@ using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using UserCenter.Model.Enum;
using VideoAnalysisCore.Common; using VideoAnalysisCore.Common;
using VideoAnalysisCore.Model; using VideoAnalysisCore.Model;
using VideoAnalysisCore.Model.Enum; using VideoAnalysisCore.Model.Enum;
@ -50,7 +49,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
/// </summary> /// </summary>
/// <param name="numThreads">默认6线程</param> /// <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> /// <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 void Init(SubjectEnum? subject = null, int numThreads = 10, bool useGPU = false, bool useHotwords = false) public void Init(int numThreads = 6, bool useGPU = false, bool useHotwords = false)
{ {
Console.WriteLine("初始化 FunASRNano"); Console.WriteLine("初始化 FunASRNano");
OfflineRecognizerConfig config = new OfflineRecognizerConfig(); OfflineRecognizerConfig config = new OfflineRecognizerConfig();
@ -64,23 +63,17 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
//将非结构化数据(文本、图像、音频等)转换为低维稠密向量 //将非结构化数据(文本、图像、音频等)转换为低维稠密向量
config.ModelConfig.FunAsrNano.EncoderAdaptor = Path.Combine(topFolder, "encoder_adaptor.int8.onnx"); config.ModelConfig.FunAsrNano.EncoderAdaptor = Path.Combine(topFolder, "encoder_adaptor.int8.onnx");
//接入的大语言模型 //接入的大语言模型
//config.ModelConfig.FunAsrNano.LLM = Path.Combine(topFolder ,"llm.fp16.onnx"); config.ModelConfig.FunAsrNano.LLM = Path.Combine(topFolder, "llm.fp16.onnx");
config.ModelConfig.FunAsrNano.LLM = Path.Combine(topFolder, "int8-2025-12-30", "llm.int8.onnx");
//插入预训练模型如Transformer的小型可训练模块 (如语音识别、情感分析) //插入预训练模型如Transformer的小型可训练模块 (如语音识别、情感分析)
config.ModelConfig.FunAsrNano.Embedding = Path.Combine(topFolder, "embedding.int8.onnx"); config.ModelConfig.FunAsrNano.Embedding = Path.Combine(topFolder, "embedding.int8.onnx");
//分词器 //分词器
config.ModelConfig.FunAsrNano.Tokenizer = Path.Combine(topFolder, "Qwen3-0.6B"); config.ModelConfig.FunAsrNano.Tokenizer = Path.Combine(topFolder, "Qwen3-0.6B");
//提示词 //提示词
config.ModelConfig.FunAsrNano.SystemPrompt = "You are a professional video audio transcription assistant."; config.ModelConfig.FunAsrNano.SystemPrompt = "You are a professional video audio transcription assistant.";
//加上学科为空的处理 config.ModelConfig.FunAsrNano.UserPrompt = "这是一堂中国的课堂视频音频,请你帮我分析出它讲述的内容!";
if (subject != null)
config.ModelConfig.FunAsrNano.UserPrompt = $"这是一堂中国{subject}的课堂视频音频,请你帮我分析出它讲述的内容!";
else
config.ModelConfig.FunAsrNano.UserPrompt = "这是一堂中国课堂的视频音频,请你帮我分析出它讲述的内容!";
config.ModelConfig.FunAsrNano.MaxNewTokens = 512; config.ModelConfig.FunAsrNano.MaxNewTokens = 512;
config.ModelConfig.FunAsrNano.Temperature = 1E-06f; config.ModelConfig.FunAsrNano.Temperature = 1E-06f;
config.ModelConfig.FunAsrNano.TopP = 0.7f; config.ModelConfig.FunAsrNano.TopP = 0.8f;
//种子
config.ModelConfig.FunAsrNano.Seed = 42; config.ModelConfig.FunAsrNano.Seed = 42;
//模型类型 //模型类型
@ -88,10 +81,10 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
config.ModelConfig.NumThreads = numThreads; config.ModelConfig.NumThreads = numThreads;
config.ModelConfig.Provider = "cpu"; config.ModelConfig.Provider = "cpu";
//需要使用GPU //需要使用GPU
if (useGPU) if (!useGPU)
config.ModelConfig.Provider = "cuda"; config.ModelConfig.Provider = "cuda";
#if DEBUG #if DEBUG
//config.ModelConfig.Debug = 1; config.ModelConfig.Debug = 1;
#endif #endif
OR = new OfflineRecognizer(config); OR = new OfflineRecognizer(config);
} }
@ -113,17 +106,15 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
/// </summary> /// </summary>
/// <param name="task"></param> /// <param name="task"></param>
/// <returns></returns> /// <returns></returns>
public Task RunTask(string task) public Task RunTask(string task)
{ {
var taskInfo = serviceProvider.GetRequiredService<Repository<VideoTask>>().GetById(task);
if(taskInfo is null)
throw new Exception("task 未找到");
var filePath = Path.Combine(task.LocalPath(), "task.wav"); var filePath = Path.Combine(task.LocalPath(), "task.wav");
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
throw new Exception("task 音频路径未找到"); throw new Exception("task 音频路径未找到");
if (OR is null) Init(taskInfo.Subject); if (OR is null) Init();
serviceProvider.GetRequiredService<SherpaVad>() serviceProvider.GetRequiredService<SherpaVad>()
.TaskHandle(new WaveReader(filePath), task, SoundHandle, SherpaVadVersion.ten_vad_324); .TaskHandle(new WaveReader(filePath), null, SoundHandle, SherpaVadVersion.ten_vad_324);
return Task.CompletedTask; return Task.CompletedTask;
} }
/// <summary> /// <summary>

View File

@ -90,7 +90,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
VADModelConfig.SileroVad = new SileroVadModelConfig(); VADModelConfig.SileroVad = new SileroVadModelConfig();
VADModelConfig.SileroVad.Model = path; VADModelConfig.SileroVad.Model = path;
//(阈值 / 灵敏度) 含义:判定为“语音”的置信度。取值范围通常在 0 到 1 之间。 //(阈值 / 灵敏度) 含义:判定为“语音”的置信度。取值范围通常在 0 到 1 之间。
VADModelConfig.SileroVad.Threshold = 0.25f; VADModelConfig.SileroVad.Threshold = 0.3f;
//(最小静音长度)秒。 含义:“要沉默多久,我才认为这句话说完了?” //(最小静音长度)秒。 含义:“要沉默多久,我才认为这句话说完了?”
VADModelConfig.SileroVad.MinSilenceDuration = 0.2f; VADModelConfig.SileroVad.MinSilenceDuration = 0.2f;
// (最小语音长度)秒 含义:“这段声音至少要多长,我才认为它是有效的说话?” // (最小语音长度)秒 含义:“这段声音至少要多长,我才认为它是有效的说话?”

View File

@ -255,7 +255,7 @@ namespace VideoAnalysisCore.Common
} }
} }
var sp = spList.Distinct().ToList(); var sp = spList.Distinct().ToList();
if (sp.Count > 0 && !string.IsNullOrWhiteSpace(segment.Text)) if (sp.Count > 0)
results.Add(segment, sp); results.Add(segment, sp);
} }

View File

@ -110,14 +110,12 @@ namespace VideoAnalysisCore.Common
public FFMPGEHandle FFMPGE { get; set; } public FFMPGEHandle FFMPGE { get; set; }
public SenseVoice senseVoice { get; set; } public SenseVoice senseVoice { get; set; }
public FunASRNano funASRNano { get; set; }
public RedisManager redisManager { get; set; } public RedisManager redisManager { get; set; }
public RedisInit(FFMPGEHandle fFMPGE, SenseVoice senseVoice, RedisManager redisManager, FunASRNano funASRNano) public RedisInit(FFMPGEHandle fFMPGE, SenseVoice senseVoice, RedisManager redisManager)
{ {
FFMPGE = fFMPGE; FFMPGE = fFMPGE;
this.senseVoice = senseVoice; this.senseVoice = senseVoice;
this.funASRNano = funASRNano;
this.redisManager = redisManager; this.redisManager = redisManager;
Init(); Init();
redisManager.InitChannel(); redisManager.InitChannel();
@ -140,7 +138,6 @@ namespace VideoAnalysisCore.Common
}); });
SubscribeList.Add(RedisChannelEnum., FFMPGE.RunAsync); SubscribeList.Add(RedisChannelEnum., FFMPGE.RunAsync);
SubscribeList.Add(RedisChannelEnum., senseVoice.RunTask); SubscribeList.Add(RedisChannelEnum., senseVoice.RunTask);
//SubscribeList.Add(RedisChannelEnum.解析字幕, funASRNano.RunTask);
//SubscribeList.Add(RedisChannelEnum.解析说话人,Speaker.Run); //SubscribeList.Add(RedisChannelEnum.解析说话人,Speaker.Run);
SubscribeList.Add(RedisChannelEnum.AI课程类型, async (task) => SubscribeList.Add(RedisChannelEnum.AI课程类型, async (task) =>
{ {
@ -433,20 +430,15 @@ namespace VideoAnalysisCore.Common
var oldTaskCount = Redis.LLen(RedisExpandKey.IDTask); var oldTaskCount = Redis.LLen(RedisExpandKey.IDTask);
//重试任务并发过多可能会导致程序崩溃 //重试任务并发过多可能会导致程序崩溃
// 未能重新分析的中断任务 则单独开一个网页来处理 // 未能重新分析的中断任务 则单独开一个网页来处理
if (oldTaskCount > 0) if (oldTaskCount > 0 )
{ {
//获取所有未完成的任务 var oldTaskArr = Redis.LRange(RedisExpandKey.IDTask, 0, oldTaskCount);
var oldTaskArr = Redis.LRange(RedisExpandKey.IDTask, 0, -1); //不自动清理未完成任务 等待执行完毕/失败后自动清理
Console.WriteLine($"{DateTime.Now:HH:mm:ss}-------------> 发现 {oldTaskArr.Length} 个未完成任务,准备恢复..."); //Redis.LTrim(RedisExpandKey.IDTask, 1, 0);//删除 redis 列表
//最多执行5个上次中断/或者未完成的任务
//使用信号量限制并发数(5),防止崩溃 foreach (var oldTask in oldTaskArr.Take(5))
using var semaphore = new System.Threading.SemaphoreSlim(5);
var retryTaskArr = new List<Task>();
foreach (var oldTask in oldTaskArr)
{ {
await semaphore.WaitAsync(); _ = Task.Run(async () =>
var res = Task.Run(async () =>
{ {
try try
{ {
@ -458,21 +450,10 @@ namespace VideoAnalysisCore.Common
catch (Exception ex) catch (Exception ex)
{ {
await SetTaskErrorMessage(long.Parse(oldTask), ex); await SetTaskErrorMessage(long.Parse(oldTask), ex);
Console.WriteLine($"恢复任务 {oldTask} 失败: {ex.Message}"); throw;
}
finally
{
semaphore.Release();
} }
}); });
retryTaskArr.Add(res);
} }
//等待所有 重试任务完成后接收新任务
await Task.WhenAll(retryTaskArr);
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-------------> 所有未完成任务处理完毕!");
ReceivingTaskAsync();
} }
else else
{ {

View File

@ -128,23 +128,11 @@ namespace VideoAnalysisCore.Controllers.Dto
/// 用户中心的云校id /// 用户中心的云校id
/// </summary> /// </summary>
public long? UserCenterCloudSchoolId { get; set; } public long? UserCenterCloudSchoolId { get; set; }
/// <summary>
/// 教材层次
/// </summary>
public CourselevelTypeEnum? CourseLevel { get; set; }
/// <summary>
/// 年级
/// </summary>
public GradeEnum? GradeId { get; set; }
/// <summary> /// <summary>
/// 教育阶段 /// 教育阶段
/// </summary> /// </summary>
public EducationStageEnum StageId { get; set; } public EducationStageEnum StageId { get; set; }
/// <summary>
/// 年级册(上册/下册)
/// </summary>
public GradeSemesterEnum? GradeSemester { get; set; }
} }
/// <summary> /// <summary>
/// 视频处理 请求 /// 视频处理 请求

View File

@ -115,10 +115,6 @@ namespace VideoAnalysisCore.Controllers
CloudSchoolId =s.UserCenterCloudSchoolId, CloudSchoolId =s.UserCenterCloudSchoolId,
Area = s.Area, Area = s.Area,
HostIP = s.HostIP, HostIP = s.HostIP,
StageId = s.StageId,
GradeId = s.GradeId,
GradeSemester = s.GradeSemester,
TextBookVersionId = s.TextBookVersionId,
}; };
nodePackages.Add(np); nodePackages.Add(np);
if (videoIdArr.Contains(s.VideoCode)) continue; if (videoIdArr.Contains(s.VideoCode)) continue;
@ -138,10 +134,6 @@ namespace VideoAnalysisCore.Controllers
PPTVideoUrl = pptUrl, PPTVideoUrl = pptUrl,
VideoType = s.CourseType, VideoType = s.CourseType,
CloudSchoolId = s.UserCenterCloudSchoolId, CloudSchoolId = s.UserCenterCloudSchoolId,
TextBookVersionId = s.TextBookVersionId,
GradeSemester =s .GradeSemester,
CourseLevel =s.CourseLevel,
GradeId = s.GradeId,
}); });
} }
await nodePackageInfoDB.InsertRangeAsync(nodePackages); await nodePackageInfoDB.InsertRangeAsync(nodePackages);

View File

@ -153,8 +153,8 @@ namespace VideoAnalysisCore.Controllers
public IActionResult AudioRecognition(IFormFile file) public IActionResult AudioRecognition(IFormFile file)
{ {
using var s = file.OpenReadStream(); using var s = file.OpenReadStream();
var res = senseVoice.RunTask(s); senseVoice.RunTask(s);
return Ok(res); return Ok();
} }
/// <summary> /// <summary>
/// 语音识别 /// 语音识别
@ -266,7 +266,7 @@ namespace VideoAnalysisCore.Controllers
TagId = req.TagId, TagId = req.TagId,
PPTVideoCode = req.PPTVideoCode, PPTVideoCode = req.PPTVideoCode,
PPTVideoUrl = req.PPTVideoUrl, PPTVideoUrl = req.PPTVideoUrl,
VideoType = req.VideoType, VideoType = req.VideoType
}; };
//入库 //入库
await baseService.InsertAsync(task); await baseService.InsertAsync(task);

View File

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VideoAnalysisCore.Model.Enum
{
/// <summary>
/// 课程层次
/// </summary>
public enum CourselevelTypeEnum
{
= 1,
= 2,
= 3
}
}

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VideoAnalysisCore.Model.Enum
{
/// <summary>
/// 年级层次
/// </summary>
public enum GradeSemesterEnum
{
= 1,
= 2
}
}

View File

@ -83,25 +83,6 @@ namespace VideoAnalysisCore.Model
/// </summary> /// </summary>
public string Area { get; set; } public string Area { get; set; }
/// <summary> /// <summary>
/// 年级
/// </summary>
[SugarColumn(IsNullable = true)]
public GradeEnum? GradeId { get; set; }
/// <summary>
/// 教育阶段
/// </summary>
[SugarColumn(IsNullable = true)]
public EducationStageEnum StageId { get; set; }
/// <summary>
/// 年级册(上册/下册)
/// </summary>
[SugarColumn(IsNullable = true)]
public GradeSemesterEnum? GradeSemester { get; set; }
/// <summary>
/// 学科网的教材版本Id
/// </summary>
public long TextBookVersionId { get; set; }
/// <summary>
/// 请求区域 /// 请求区域
/// <para>回调添加到Headers</para> /// <para>回调添加到Headers</para>
/// </summary> /// </summary>

View File

@ -145,26 +145,5 @@ namespace VideoAnalysisCore.Model
[SugarColumn(IsNullable = true)] [SugarColumn(IsNullable = true)]
public long? CloudSchoolId { get; set; } public long? CloudSchoolId { get; set; }
/// <summary>
/// 教材层次
/// </summary>
[SugarColumn(IsNullable = true)]
public CourselevelTypeEnum? CourseLevel { get; set; }
/// <summary>
/// 年级
/// </summary>
[SugarColumn(IsNullable = true)]
public GradeEnum? GradeId { get; set; }
/// <summary>
/// 年级册(上册/下册)
/// </summary>
[SugarColumn(IsNullable = true)]
public GradeSemesterEnum? GradeSemester { get; set; }
/// <summary>
/// 学科网的教材版本Id
/// </summary>
public long TextBookVersionId { get; set; }
} }
} }

View File

@ -57,7 +57,6 @@ namespace VideoAnalysisCore.Model
/// <summary> /// <summary>
/// 知识点来源 视频秒,来源原因 /// 知识点来源 视频秒,来源原因
/// </summary> /// </summary>
[SugarColumn(Length = 500, IsNullable = true)]
public string Content { get; set; } public string Content { get; set; }
/// <summary> /// <summary>
/// 课程阶段 /// 课程阶段
@ -76,26 +75,5 @@ namespace VideoAnalysisCore.Model
/// </summary> /// </summary>
[SugarColumn(IsNullable = true)] [SugarColumn(IsNullable = true)]
public virtual string? TextbookSource { get; set; } public virtual string? TextbookSource { get; set; }
/// <summary>
/// 教材层次
/// </summary>
[SugarColumn(IsNullable = true)]
public CourselevelTypeEnum? CourseLevel { get; set; }
/// <summary>
/// 年级
/// </summary>
[SugarColumn(IsNullable = true)]
public GradeEnum? GradeId { get; set; }
/// <summary>
/// 年级册(上册/下册)
/// </summary>
[SugarColumn(IsNullable = true)]
public GradeSemesterEnum? GradeSemester { get; set; }
/// <summary>
/// 学科网的教材版本Id
/// </summary>
public long TextBookVersionId { get; set; }
} }
} }

View File

@ -71,7 +71,7 @@
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyModel" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="org.k2fsa.sherpa.onnx" Version="1.12.22" /> <PackageReference Include="org.k2fsa.sherpa.onnx" Version="1.12.21" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
<PackageReference Include="SqlSugar.IOC" Version="2.0.0" /> <PackageReference Include="SqlSugar.IOC" Version="2.0.0" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.205" /> <PackageReference Include="SqlSugarCore" Version="5.1.4.205" />