Compare commits
3 Commits
b161d83aac
...
de3bd90822
| Author | SHA1 | Date |
|---|---|---|
|
|
de3bd90822 | |
|
|
00e0664940 | |
|
|
270395e939 |
|
|
@ -42,8 +42,7 @@
|
||||||
"ApiKey": "sk-8BvvhESZIkgUbiaaJhglPxFa4o2X9H3xEv9lXELrWWwGxHWY"
|
"ApiKey": "sk-8BvvhESZIkgUbiaaJhglPxFa4o2X9H3xEv9lXELrWWwGxHWY"
|
||||||
},
|
},
|
||||||
"ChatGpt": {
|
"ChatGpt": {
|
||||||
"Host": "https://api.g4f.icu/",
|
"Host": "https://api.oaibest.com/",
|
||||||
//"Host": "https://api.oaibest.com/",
|
|
||||||
"ApiKey": "sk-D15tBln31N7dI9Fi7lds7OySFv5tOEK7DMNsG5rY2E6DCr4s"
|
"ApiKey": "sk-D15tBln31N7dI9Fi7lds7OySFv5tOEK7DMNsG5rY2E6DCr4s"
|
||||||
},
|
},
|
||||||
"DeepSeek": {
|
"DeepSeek": {
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.18" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.18" />
|
||||||
<PackageReference Include="Mapster.DependencyInjection" Version="1.0.2-pre01" />
|
<PackageReference Include="Mapster.DependencyInjection" Version="1.0.2-pre01" />
|
||||||
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.13.0" />
|
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.13.0" />
|
||||||
<PackageReference Include="AlibabaCloud.SDK.Vod20170321" Version="3.6.1" />
|
<PackageReference Include="AlibabaCloud.SDK.Vod20170321" Version="3.11.1" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
//public const string Gemini_3_Chat_thinking = "gemini-3-pro-preview-thinking";
|
//public const string Gemini_3_Chat_thinking = "gemini-3-pro-preview-thinking";
|
||||||
public const string Gemini_3_Chat = "gemini-3.1-pro-preview";
|
public const string Gemini_3_Chat = "gemini-3.1-pro-preview";
|
||||||
//public const string Gemini_3_Chat_flash = "gemini-3-flash-preview";
|
//public const string Gemini_3_Chat_flash = "gemini-3-flash-preview";
|
||||||
public const string Gemini_31_Chat_flash = "gemini-3.1-flash-preview";
|
//已失效
|
||||||
|
//public const string Gemini_31_Chat_flash = "gemini-3.1-flash-lite-preview";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ using Dm.util;
|
||||||
using static System.Net.Mime.MediaTypeNames;
|
using static System.Net.Mime.MediaTypeNames;
|
||||||
using VideoAnalysisCore.AICore.GPT.DeepSeek;
|
using VideoAnalysisCore.AICore.GPT.DeepSeek;
|
||||||
using VideoAnalysisCore.AICore.GPT.Gemini;
|
using VideoAnalysisCore.AICore.GPT.Gemini;
|
||||||
|
using static System.Collections.Specialized.BitVector32;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.AICore.GPT
|
namespace VideoAnalysisCore.AICore.GPT
|
||||||
{
|
{
|
||||||
|
|
@ -115,10 +116,10 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
await _workflowManager.AddTaskLog(taskInfo.Id, "==>2.开始分析视频内容知识点");
|
await _workflowManager.AddTaskLog(taskInfo.Id, "==>2.开始分析视频内容知识点");
|
||||||
List<VideoKnowRes> konwRes;
|
List<VideoKnowRes> konwRes;
|
||||||
var knowOK = false;
|
var knowOK = false;
|
||||||
var chatClentArr = new GPTClient[] { chatGPTClient, geminiClient, bset_deepSeekClient };
|
//var chatClentArr = new GPTClient[] { chatGPTClient, geminiClient, bset_deepSeekClient };
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
konwRes = await chatClentArr[i].ChatAsync<List<VideoKnowRes>>(taskInfo.Id.ToString(), knowMessages, "知识点");
|
konwRes = await chatGPTClient.ChatAsync<List<VideoKnowRes>>(taskInfo.Id.ToString(), knowMessages, "知识点");
|
||||||
// 分析结果的片段数量与预期不匹配
|
// 分析结果的片段数量与预期不匹配
|
||||||
if (questionRes.Count() != konwRes.Count()) continue;
|
if (questionRes.Count() != konwRes.Count()) continue;
|
||||||
for (int xi = 0; xi < konwRes.Count(); xi++)
|
for (int xi = 0; xi < konwRes.Count(); xi++)
|
||||||
|
|
@ -193,7 +194,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
$"字幕列表 {rCaptionArr}。" +
|
$"字幕列表 {rCaptionArr}。" +
|
||||||
$"输出格式 json字符串 对象格式{fileNameResFormat}";
|
$"输出格式 json字符串 对象格式{fileNameResFormat}";
|
||||||
var task = taskInfo.Id.ToString();
|
var task = taskInfo.Id.ToString();
|
||||||
var fileNameInfoRes = await geminiClient.ChatAsync<FileNameInfo>(task, fileNamePostMessages, "授课章节");
|
var fileNameInfoRes = await chatGPTClient.ChatAsync<FileNameInfo>(task, fileNamePostMessages, "授课章节");
|
||||||
taskInfo.Sections = fileNameInfoRes.授课章节;
|
taskInfo.Sections = fileNameInfoRes.授课章节;
|
||||||
await videoTaskDB.AsUpdateable()
|
await videoTaskDB.AsUpdateable()
|
||||||
.SetColumns(it => it.Sections == fileNameInfoRes.授课章节)
|
.SetColumns(it => it.Sections == fileNameInfoRes.授课章节)
|
||||||
|
|
@ -242,7 +243,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
输出格式:
|
输出格式:
|
||||||
输出格式为json: {checkResFormat}
|
输出格式为json: {checkResFormat}
|
||||||
""";
|
""";
|
||||||
return await chatGPTClient.ChatAsync<CheckMessageDto>(taskInfo.Id.ToString(), checkMessage, "结果检查");
|
return await chatGPTClient.ChatAsync<CheckMessageDto>(taskInfo.Id.ToString(), checkMessage, "结果检查",ChatGPTType.GPT54);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 采用改进意见
|
/// 采用改进意见
|
||||||
|
|
@ -282,11 +283,43 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
输出格式(仅 JSON):{resFormat}
|
输出格式(仅 JSON):{resFormat}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
var improved = await geminiClient.ChatAsync<List<VideoKnowRes>>(taskInfo.Id.ToString(), message, "分段优化");
|
//var improved = await geminiClient.ChatAsync<List<VideoKnowRes>>(taskInfo.Id.ToString(), message, "分段优化");
|
||||||
if (improved is null || improved.Count() != questionRes.Count())
|
//if (improved is null || improved.Count() != questionRes.Count())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return improved.OrderBy(s => s.StartTime ?? 0).ToList();
|
//return improved.OrderBy(s => s.StartTime ?? 0).ToList();
|
||||||
|
}
|
||||||
|
private async Task<(string, List<KnowledgeInfo>)> GetKnowledgeInfos(VideoTask taskInfo,long Course_Id)
|
||||||
|
{
|
||||||
|
List<KnowledgeInfo>? knowledgeInfos =null;
|
||||||
|
string? sections = null;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
sections = await GetSections(taskInfo, Course_Id);
|
||||||
|
var know = await knowledgeInfoDB.GetFirstAsync(s => s.Course_Id == Course_Id && s.Name == sections);
|
||||||
|
if (know is null)
|
||||||
|
{
|
||||||
|
await _workflowManager.AddTaskLog(taskInfo.Id, $"==>识别的知识点无效 {sections}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var kInfo = await knowledgeInfoDB.GetByIdAsync(know.Parent_Id);
|
||||||
|
if (know.Parent_Id == 0)
|
||||||
|
kInfo = know;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
knowledgeInfos = await knowledgeInfoDB.AsQueryable()
|
||||||
|
.ToChildListAsync(s => s.Parent_Id, kInfo.Parent_Id == 0 ? kInfo.Id : kInfo.Parent_Id);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
await _workflowManager.AddTaskLog(taskInfo.Id, $"==>识别的知识没有对应的子知识点 {sections } {kInfo?.Name}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(knowledgeInfos is null)
|
||||||
|
throw new Exception("多次识别后未能识别到有效课堂知识点=>" + sections);
|
||||||
|
return new(sections, knowledgeInfos);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -308,12 +341,13 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
[
|
[
|
||||||
async (m)=>await bset_deepSeekClient
|
async (m)=>await bset_deepSeekClient
|
||||||
.ChatAsync<List<SenseVoiceInput>>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.Deepseek_v32,8_000),
|
.ChatAsync<List<SenseVoiceInput>>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.Deepseek_v32,8_000),
|
||||||
async (m)=>await bset_deepSeekClient
|
//async (m)=>await bset_deepSeekClient
|
||||||
.ChatAsync<List<SenseVoiceInput>>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.Deepseek_Chat,8_000),
|
// .ChatAsync<List<SenseVoiceInput>>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.Deepseek_Chat,8_000),
|
||||||
async (m)=>await chatGPTClient
|
//async (m)=>await chatGPTClient
|
||||||
.ChatAsync<List<SenseVoiceInput>>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.GPT54_mini,16_000),
|
// .ChatAsync<List<SenseVoiceInput>>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.GPT54_mini,16_000),
|
||||||
async (m)=>await geminiClient
|
//async (m)=>await geminiClient
|
||||||
.ChatAsync<List<SenseVoiceInput>>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.Gemini_3_Chat,16_000), ];
|
// .ChatAsync<List<SenseVoiceInput>>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.Gemini_3_Chat,16_000),
|
||||||
|
];
|
||||||
await Parallel.ForAsync(0, totalCount,
|
await Parallel.ForAsync(0, totalCount,
|
||||||
new ParallelOptions()
|
new ParallelOptions()
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|
@ -731,24 +765,10 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
|
|
||||||
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.Captions);
|
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.Captions);
|
||||||
//处理视频授课章节
|
//处理视频授课章节
|
||||||
var sections = await GetSections(taskInfo, Course_Id);
|
var kr = await GetKnowledgeInfos(taskInfo, Course_Id);
|
||||||
|
var sections = kr.Item1;
|
||||||
var know = await knowledgeInfoDB.GetFirstAsync(s => s.Course_Id == Course_Id && s.Name == sections);
|
List<KnowledgeInfo>? knowledgeInfos = kr.Item2;
|
||||||
if (know is null)
|
|
||||||
throw new Exception("未能找到对应知识点=>" + sections);
|
|
||||||
List<KnowledgeInfo>? knowledgeInfos = new List<KnowledgeInfo>();
|
|
||||||
var kInfo = await knowledgeInfoDB.GetByIdAsync(know.Parent_Id);
|
|
||||||
if (know.Parent_Id == 0)
|
|
||||||
kInfo = know;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
knowledgeInfos = await knowledgeInfoDB.AsQueryable()
|
|
||||||
.ToChildListAsync(s => s.Parent_Id, kInfo.Parent_Id == 0 ? kInfo.Id : kInfo.Parent_Id);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
throw new Exception("没有对应的子知识点=>" + sections + " " + kInfo?.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
//AI优化字幕
|
//AI优化字幕
|
||||||
captionsArr = await OptimizeSubtitles(taskInfo, captionsArr, sections);
|
captionsArr = await OptimizeSubtitles(taskInfo, captionsArr, sections);
|
||||||
|
|
@ -762,7 +782,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
}
|
}
|
||||||
var maxVideoTime = captions?.TimeBase?.LastOrDefault()?.End ?? 0;
|
var maxVideoTime = captions?.TimeBase?.LastOrDefault()?.End ?? 0;
|
||||||
List<VideoKnowRes>? questionRes = null;
|
List<VideoKnowRes>? questionRes = null;
|
||||||
var tryCount = 20;
|
var tryCount = 3;
|
||||||
var last改进意见 = string.Empty;
|
var last改进意见 = string.Empty;
|
||||||
while (tryCount-- > 0)
|
while (tryCount-- > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -801,7 +821,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if (checkRes != null && checkRes.Score >= 90)
|
if (checkRes != null && checkRes.Score >= 88)
|
||||||
{
|
{
|
||||||
//写入知识点
|
//写入知识点
|
||||||
await videoKonwPointDB.DeleteAsync(s => s.VideoTaskId == taskInfo.Id);
|
await videoKonwPointDB.DeleteAsync(s => s.VideoTaskId == taskInfo.Id);
|
||||||
|
|
@ -822,6 +842,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
TextBookVersionId = taskInfo.TextBookVersionId,
|
TextBookVersionId = taskInfo.TextBookVersionId,
|
||||||
GradeSemester = taskInfo.GradeSemester,
|
GradeSemester = taskInfo.GradeSemester,
|
||||||
GradeId = taskInfo.GradeId,
|
GradeId = taskInfo.GradeId,
|
||||||
|
GradeYear = taskInfo.GradeYear,
|
||||||
}).ToList();
|
}).ToList();
|
||||||
//尝试追加 作业布置分段
|
//尝试追加 作业布置分段
|
||||||
if (homework != null && !questionRes.Any(s => s.Stage == StageEnum.作业布置.ToString()))
|
if (homework != null && !questionRes.Any(s => s.Stage == StageEnum.作业布置.ToString()))
|
||||||
|
|
@ -838,7 +859,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tryCount == 0)
|
if (tryCount < 1)
|
||||||
{
|
{
|
||||||
throw new Exception("重试次数过多!");
|
throw new Exception("重试次数过多!");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ namespace VideoAnalysisCore.AICore.GPT.Gemini
|
||||||
Message[] messageArr = [
|
Message[] messageArr = [
|
||||||
new Message(postMessages,"user"),
|
new Message(postMessages,"user"),
|
||||||
];
|
];
|
||||||
model = model ?? ChatGPTType.Gemini_31_Chat_flash;
|
model = model ?? ChatGPTType.Gemini_3_Chat;
|
||||||
messageArr = messageArr.Where(s => s != null).ToArray();
|
messageArr = messageArr.Where(s => s != null).ToArray();
|
||||||
var chatReq = new ChatRequest
|
var chatReq = new ChatRequest
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ namespace VideoAnalysisCore.Common
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Task(object taskId) => BaseKey + "Info:" + taskId;
|
public static string Task(object taskId) => BaseKey + "Info:" + taskId;
|
||||||
public static string IDTask => BaseKey + "Services:" + AppCommon.Config.ID;
|
public static string IDTask => BaseKey + "Services:" + AppCommon.Config.ID;
|
||||||
|
public static string DeviceTaskLog(string deviceId) => BaseKey + "Services:" + deviceId;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 在线设备Key集合 (已弃用,直接扫描 Heartbeat)
|
/// 在线设备Key集合 (已弃用,直接扫描 Heartbeat)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ namespace VideoAnalysisCore.Common
|
||||||
public override async Task TaskEnd(string task)
|
public override async Task TaskEnd(string task)
|
||||||
{
|
{
|
||||||
var tId = long.Parse(task);
|
var tId = long.Parse(task);
|
||||||
await base.TaskEnd(task);
|
//await base.TaskEnd(task);
|
||||||
|
|
||||||
// TidySlide 工作流结束时清理文件
|
// TidySlide 工作流结束时清理文件
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ namespace VideoAnalysisCore.Controllers.Dto
|
||||||
/// 年级
|
/// 年级
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GradeEnum? GradeId { get; set; }
|
public GradeEnum? GradeId { get; set; }
|
||||||
|
public int? Trem { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 教育阶段
|
/// 教育阶段
|
||||||
|
|
@ -346,12 +347,39 @@ namespace VideoAnalysisCore.Controllers.Dto
|
||||||
public class VideoKonwPointQueryReq
|
public class VideoKonwPointQueryReq
|
||||||
{
|
{
|
||||||
public long? CloudSchoolId { get; set; }
|
public long? CloudSchoolId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 难度 [PN TK BJ]
|
||||||
|
/// </summary>
|
||||||
public CourselevelTypeEnum? CourseLevel { get; set; }
|
public CourselevelTypeEnum? CourseLevel { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 年级
|
||||||
|
/// </summary>
|
||||||
public GradeEnum? GradeId { get; set; }
|
public GradeEnum? GradeId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 毕业届
|
||||||
|
/// </summary>
|
||||||
|
public int? GradeYear { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上下册
|
||||||
|
/// </summary>
|
||||||
public GradeSemesterEnum? GradeSemester { get; set; }
|
public GradeSemesterEnum? GradeSemester { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 教材版本
|
||||||
|
/// </summary>
|
||||||
public long? TextBookVersionId { get; set; }
|
public long? TextBookVersionId { get; set; }
|
||||||
public string[]? KnowPointIdArr { get; set; }
|
/// <summary>
|
||||||
|
/// 知识点名称
|
||||||
|
/// </summary>
|
||||||
|
public string[]? KnowPointStrArr { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 切片主题
|
||||||
|
/// </summary>
|
||||||
public string? Theme { get; set; }
|
public string? Theme { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 切片内容
|
||||||
|
/// </summary>
|
||||||
public string? Content { get; set; }
|
public string? Content { get; set; }
|
||||||
public int PageIndex { get; set; } = 0;
|
public int PageIndex { get; set; } = 0;
|
||||||
public int PageSize { get; set; } = 200;
|
public int PageSize { get; set; } = 200;
|
||||||
|
|
@ -363,6 +391,7 @@ namespace VideoAnalysisCore.Controllers.Dto
|
||||||
/// 视频vid
|
/// 视频vid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long VideoTaskId { get; set; }
|
public long VideoTaskId { get; set; }
|
||||||
|
public string PlayUrl { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 分段
|
/// 分段
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -372,10 +401,17 @@ namespace VideoAnalysisCore.Controllers.Dto
|
||||||
public class VideoTaskStageRes
|
public class VideoTaskStageRes
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 视频封面地址
|
||||||
|
/// </summary>
|
||||||
|
public string PreviewUrl { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 视频地址
|
||||||
|
/// </summary>
|
||||||
|
public string PlayUrl { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// id
|
/// id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsPrimaryKey = true)]
|
|
||||||
public long Id { get; set; } = YitIdHelper.NextId();
|
public long Id { get; set; } = YitIdHelper.NextId();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 视频任务id
|
/// 视频任务id
|
||||||
|
|
@ -386,23 +422,19 @@ namespace VideoAnalysisCore.Controllers.Dto
|
||||||
/// 自定义Id [任务视频自定义id]
|
/// 自定义Id [任务视频自定义id]
|
||||||
/// <see cref="VideoTask.TagId"/>
|
/// <see cref="VideoTask.TagId"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length = 500, IsNullable = true)]
|
|
||||||
public string? TagId { get; set; }
|
public string? TagId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开始时间
|
/// 开始时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable = true)]
|
|
||||||
public float? StartTime { get; set; }
|
public float? StartTime { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 结束时间
|
/// 结束时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable = true)]
|
|
||||||
public float? EndTime { get; set; }
|
public float? EndTime { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 持续时间
|
/// 持续时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsIgnore = true)]
|
|
||||||
public float? KeepTime => (EndTime ?? 0) - StartTime ?? 0;
|
public float? KeepTime => (EndTime ?? 0) - StartTime ?? 0;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 主题
|
/// 主题
|
||||||
|
|
@ -411,13 +443,11 @@ namespace VideoAnalysisCore.Controllers.Dto
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 课程阶段
|
/// 课程阶段
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsIgnore = true)]
|
|
||||||
public virtual StageEnum? Stage { get; set; }
|
public virtual StageEnum? Stage { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 视频所属云校ID
|
/// 视频所属云校ID
|
||||||
/// <para><see cref="UserCenter.Model.CloudSchool"/> 用户中心的云校id</para>
|
/// <para><see cref="UserCenter.Model.CloudSchool"/> 用户中心的云校id</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable = true)]
|
|
||||||
public long? CloudSchoolId { get; set; }
|
public long? CloudSchoolId { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 知识点
|
/// 知识点
|
||||||
|
|
@ -432,12 +462,12 @@ namespace VideoAnalysisCore.Controllers.Dto
|
||||||
Data = [];
|
Data = [];
|
||||||
Total = 0;
|
Total = 0;
|
||||||
}
|
}
|
||||||
public VideoTaskStageQueryRes(VideoTaskInfoRes[] data, int total = 0)
|
public VideoTaskStageQueryRes(VideoTaskStageRes[] data, int total = 0)
|
||||||
{
|
{
|
||||||
Data = data;
|
Data = data;
|
||||||
Total = total;
|
Total = total;
|
||||||
}
|
}
|
||||||
public int Total { get; set; }
|
public int Total { get; set; }
|
||||||
public VideoTaskInfoRes[] Data { get; set; }
|
public VideoTaskStageRes[] Data { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@ using VideoAnalysisCore.Model;
|
||||||
using VideoAnalysisCore.Controllers.Dto;
|
using VideoAnalysisCore.Controllers.Dto;
|
||||||
using VideoAnalysisCore.Model.Dto;
|
using VideoAnalysisCore.Model.Dto;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
using AlibabaCloud.SDK.Vod20170321;
|
||||||
using VideoAnalysisCore.Model.À¶¾¨ÖÇ¿â;
|
using VideoAnalysisCore.Model.À¶¾¨ÖÇ¿â;
|
||||||
|
using AlibabaCloud.SDK.Vod20170321.Models;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.Controllers
|
namespace VideoAnalysisCore.Controllers
|
||||||
{
|
{
|
||||||
|
|
@ -34,6 +36,7 @@ namespace VideoAnalysisCore.Controllers
|
||||||
private readonly Repository<VideoTask> videoTaskDB;
|
private readonly Repository<VideoTask> videoTaskDB;
|
||||||
private readonly Repository<CourseInfo> courseInfoDB;
|
private readonly Repository<CourseInfo> courseInfoDB;
|
||||||
private readonly Repository<VideoKonwPoint> videoKonwPointDB;
|
private readonly Repository<VideoKonwPoint> videoKonwPointDB;
|
||||||
|
private readonly Client vodClient;
|
||||||
private readonly Repository<VideoTaskStage> videoTaskStageDB;
|
private readonly Repository<VideoTaskStage> videoTaskStageDB;
|
||||||
private readonly Repository<NodePackageInfo> nodePackageInfoDB;
|
private readonly Repository<NodePackageInfo> nodePackageInfoDB;
|
||||||
private readonly Repository<VideoQuestion> videoQuestionDB;
|
private readonly Repository<VideoQuestion> videoQuestionDB;
|
||||||
|
|
@ -42,7 +45,7 @@ namespace VideoAnalysisCore.Controllers
|
||||||
|
|
||||||
public LJZK_Controller(IMapper mp, Repository<NodeSubscription> nodesubscriptionDB,
|
public LJZK_Controller(IMapper mp, Repository<NodeSubscription> nodesubscriptionDB,
|
||||||
Repository<VideoTask> videoTaskDB = null, Repository<VideoKonwPoint> videoKonwPointDB = null
|
Repository<VideoTask> videoTaskDB = null, Repository<VideoKonwPoint> videoKonwPointDB = null
|
||||||
, Repository<NodePackageInfo> nodePackageInfoDB = null, Repository<VideoQuestion> videoQuestionDB = null, Repository<VideoQuestionKonw> videoQuestionKonwDB = null, Repository<CourseInfo> courseInfoDB = null, RedisManager redisManager = null, Repository<VideoTaskStage> videoTaskStageDB = null)
|
, Repository<NodePackageInfo> nodePackageInfoDB = null, Repository<VideoQuestion> videoQuestionDB = null, Repository<VideoQuestionKonw> videoQuestionKonwDB = null, Repository<CourseInfo> courseInfoDB = null, RedisManager redisManager = null, Repository<VideoTaskStage> videoTaskStageDB = null, Client vodClient = null)
|
||||||
{
|
{
|
||||||
this.mp = mp;
|
this.mp = mp;
|
||||||
this.nodesubscriptionDB = nodesubscriptionDB;
|
this.nodesubscriptionDB = nodesubscriptionDB;
|
||||||
|
|
@ -54,6 +57,7 @@ namespace VideoAnalysisCore.Controllers
|
||||||
this.courseInfoDB = courseInfoDB;
|
this.courseInfoDB = courseInfoDB;
|
||||||
this.redisManager = redisManager;
|
this.redisManager = redisManager;
|
||||||
this.videoTaskStageDB = videoTaskStageDB;
|
this.videoTaskStageDB = videoTaskStageDB;
|
||||||
|
this.vodClient = vodClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -124,6 +128,7 @@ namespace VideoAnalysisCore.Controllers
|
||||||
HostIP = s.HostIP,
|
HostIP = s.HostIP,
|
||||||
StageId = s.StageId,
|
StageId = s.StageId,
|
||||||
GradeId = s.GradeId,
|
GradeId = s.GradeId,
|
||||||
|
GradeYear = s.Trem==0?null : s.Trem,
|
||||||
GradeSemester = s.GradeSemester,
|
GradeSemester = s.GradeSemester,
|
||||||
TextBookVersionId = s.TextBookVersionId,
|
TextBookVersionId = s.TextBookVersionId,
|
||||||
};
|
};
|
||||||
|
|
@ -149,6 +154,7 @@ namespace VideoAnalysisCore.Controllers
|
||||||
GradeSemester =s .GradeSemester,
|
GradeSemester =s .GradeSemester,
|
||||||
CourseLevel =s.CourseLevel,
|
CourseLevel =s.CourseLevel,
|
||||||
GradeId = s.GradeId,
|
GradeId = s.GradeId,
|
||||||
|
GradeYear = np.GradeYear,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await nodePackageInfoDB.InsertRangeAsync(nodePackages);
|
await nodePackageInfoDB.InsertRangeAsync(nodePackages);
|
||||||
|
|
@ -297,6 +303,7 @@ namespace VideoAnalysisCore.Controllers
|
||||||
|
|
||||||
var stageQuery = videoTaskStageDB.AsQueryable();
|
var stageQuery = videoTaskStageDB.AsQueryable();
|
||||||
stageQuery = stageQuery.WhereIF(req.CloudSchoolId.HasValue, s => s.CloudSchoolId == req.CloudSchoolId);
|
stageQuery = stageQuery.WhereIF(req.CloudSchoolId.HasValue, s => s.CloudSchoolId == req.CloudSchoolId);
|
||||||
|
stageQuery = stageQuery.WhereIF(req.GradeYear.HasValue, s => s.GradeYear == req.GradeYear);
|
||||||
stageQuery = stageQuery.WhereIF(req.CourseLevel.HasValue, s => s.CourseLevel == req.CourseLevel);
|
stageQuery = stageQuery.WhereIF(req.CourseLevel.HasValue, s => s.CourseLevel == req.CourseLevel);
|
||||||
stageQuery = stageQuery.WhereIF(req.GradeId.HasValue, s => s.GradeId == req.GradeId);
|
stageQuery = stageQuery.WhereIF(req.GradeId.HasValue, s => s.GradeId == req.GradeId);
|
||||||
stageQuery = stageQuery.WhereIF(req.GradeSemester.HasValue, s => s.GradeSemester == req.GradeSemester);
|
stageQuery = stageQuery.WhereIF(req.GradeSemester.HasValue, s => s.GradeSemester == req.GradeSemester);
|
||||||
|
|
@ -305,15 +312,15 @@ namespace VideoAnalysisCore.Controllers
|
||||||
stageQuery = stageQuery.WhereIF(!string.IsNullOrWhiteSpace(req.Content), s => s.Content.Contains(req.Content));
|
stageQuery = stageQuery.WhereIF(!string.IsNullOrWhiteSpace(req.Content), s => s.Content.Contains(req.Content));
|
||||||
|
|
||||||
var pageIndex = req.PageIndex < 0 ? 0 : req.PageIndex;
|
var pageIndex = req.PageIndex < 0 ? 0 : req.PageIndex;
|
||||||
var pageSize = req.PageSize <= 0 ? 200 : req.PageSize > 500 ? 500 : req.PageSize;
|
var pageSize = req.PageSize <= 0 ? 50 : req.PageSize > 100 ?100 : req.PageSize;
|
||||||
|
string[]? knowArr = null;
|
||||||
if (req.KnowPointIdArr is not null && req.KnowPointIdArr.Length > 0)
|
if (req.KnowPointStrArr is not null && req.KnowPointStrArr.Length > 0)
|
||||||
{
|
{
|
||||||
var knowArr = req.KnowPointIdArr.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToArray();
|
knowArr = req.KnowPointStrArr.Where(s => !string.IsNullOrWhiteSpace(s)).Select(s=>s.Trim()).Distinct().ToArray();
|
||||||
if (knowArr.Length > 0)
|
if (knowArr.Length > 0)
|
||||||
{
|
{
|
||||||
stageQuery = stageQuery.Where(s => SqlFunc.Subqueryable<VideoKonwPoint>()
|
stageQuery = stageQuery.Where(s => SqlFunc.Subqueryable<VideoKonwPoint>()
|
||||||
.Where(k => k.StageId == s.Id && k.KnowPointId != null && knowArr.Contains(k.KnowPointId))
|
.Where(k => k.StageId == s.Id && k.KnowPoint != null && knowArr.Contains(k.KnowPoint))
|
||||||
.Any());
|
.Any());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -326,12 +333,8 @@ namespace VideoAnalysisCore.Controllers
|
||||||
var taskIdArr = stagePageArr.Select(s => s.VideoTaskId).ToArray();
|
var taskIdArr = stagePageArr.Select(s => s.VideoTaskId).ToArray();
|
||||||
var kpQuery = videoKonwPointDB.AsQueryable()
|
var kpQuery = videoKonwPointDB.AsQueryable()
|
||||||
.Where(s => taskIdArr.Contains(s.VideoTaskId) && s.KnowPointId != null);
|
.Where(s => taskIdArr.Contains(s.VideoTaskId) && s.KnowPointId != null);
|
||||||
if (req.KnowPointIdArr is not null && req.KnowPointIdArr.Length > 0)
|
if (knowArr !=null && knowArr.Length > 0)
|
||||||
{
|
kpQuery = kpQuery.Where(s => knowArr.Contains(s.KnowPointId));
|
||||||
var knowArr = req.KnowPointIdArr.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToArray();
|
|
||||||
if (knowArr.Length > 0)
|
|
||||||
kpQuery = kpQuery.Where(s => knowArr.Contains(s.KnowPointId));
|
|
||||||
}
|
|
||||||
|
|
||||||
var kpArr = await kpQuery
|
var kpArr = await kpQuery
|
||||||
.Select(s => new { s.StageId, s.KnowPoint })
|
.Select(s => new { s.StageId, s.KnowPoint })
|
||||||
|
|
@ -340,6 +343,12 @@ namespace VideoAnalysisCore.Controllers
|
||||||
.GroupBy(s => s.StageId)
|
.GroupBy(s => s.StageId)
|
||||||
.ToDictionary(s => s.Key, s => s.Select(x => x.KnowPoint!).Distinct().ToArray());
|
.ToDictionary(s => s.Key, s => s.Select(x => x.KnowPoint!).Distinct().ToArray());
|
||||||
|
|
||||||
|
//var gDataKey = stagePageArr.GroupBy(s => s.VideoTaskId).Select(s => s.Key).Distinct();
|
||||||
|
//var videoInfoQRes = vodClient.GetVideoInfos(new GetVideoInfosRequest()
|
||||||
|
//{
|
||||||
|
// VideoIds = string.Join(",", gDataKey)
|
||||||
|
//});
|
||||||
|
//var videoInfoRes = videoInfoQRes.Body.VideoList.ToDictionary(s => s.VideoId, s => s.CoverURL);
|
||||||
var data = stagePageArr.Select(s => new VideoTaskStageRes()
|
var data = stagePageArr.Select(s => new VideoTaskStageRes()
|
||||||
{
|
{
|
||||||
Id = s.Id,
|
Id = s.Id,
|
||||||
|
|
@ -349,23 +358,47 @@ namespace VideoAnalysisCore.Controllers
|
||||||
EndTime = s.EndTime,
|
EndTime = s.EndTime,
|
||||||
Theme = s.Theme,
|
Theme = s.Theme,
|
||||||
CloudSchoolId = s.CloudSchoolId,
|
CloudSchoolId = s.CloudSchoolId,
|
||||||
|
Stage=s.Stage,
|
||||||
|
//PreviewUrl= videoInfoRes.ContainsKey(s.VideoTaskId.ToString())? videoInfoRes[] :
|
||||||
KnowPoints = kpDic.ContainsKey(s.Id) ? kpDic[s.Id] : []
|
KnowPoints = kpDic.ContainsKey(s.Id) ? kpDic[s.Id] : []
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
|
||||||
|
|
||||||
return Ok(new VideoTaskStageQueryRes()
|
return Ok(new VideoTaskStageQueryRes()
|
||||||
{
|
{
|
||||||
Total = total,
|
Total = total,
|
||||||
Data = data.GroupBy(s=>s.VideoTaskId)
|
Data = data
|
||||||
.Select(s=>new VideoTaskInfoRes()
|
|
||||||
{
|
|
||||||
Stages = s.ToArray(),
|
|
||||||
VideoTaskId =s.Key
|
|
||||||
}).ToArray()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询 视频切片
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="videoTaskId">视频id</param>
|
||||||
|
/// <returns>视频地址</returns>
|
||||||
|
[HttpGet(Name = "GetVideoURL")]
|
||||||
|
public async Task<IActionResult> GetVideoURL(long videoTaskId)
|
||||||
|
{
|
||||||
|
if (videoTaskId ==0)
|
||||||
|
return BadRequest("参数不能为空");
|
||||||
|
var task =await videoTaskDB.GetByIdAsync(videoTaskId);
|
||||||
|
if (task is null)
|
||||||
|
return BadRequest("参数无效");
|
||||||
|
|
||||||
|
var videoInfo = await vodClient.GetPlayInfoAsync(new GetPlayInfoRequest()
|
||||||
|
{
|
||||||
|
VideoId = task.TagId,
|
||||||
|
Formats = "mp4",
|
||||||
|
OutputType = "cdn",
|
||||||
|
AuthTimeout = 3600 * 24 * 12,
|
||||||
|
});
|
||||||
|
if (videoInfo is null || videoInfo.StatusCode != 200 && !videoInfo.Body.PlayInfoList.PlayInfo.Any())
|
||||||
|
return BadRequest("获取存储的视频信息失败!");
|
||||||
|
|
||||||
|
return Ok(videoInfo.Body.PlayInfoList.PlayInfo.First().PlayURL);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -527,7 +527,7 @@ namespace VideoAnalysisCore.Controllers
|
||||||
|
|
||||||
foreach (var deviceId in onlineDevices)
|
foreach (var deviceId in onlineDevices)
|
||||||
{
|
{
|
||||||
var key = RedisExpandKey.BaseKey + "Services:" + deviceId;
|
var key = RedisExpandKey.DeviceTaskLog(deviceId) ;
|
||||||
var tasks = redisManager.Redis.LRange<long>(key, 0, 999);
|
var tasks = redisManager.Redis.LRange<long>(key, 0, 999);
|
||||||
oldTaskArr.AddRange(tasks);
|
oldTaskArr.AddRange(tasks);
|
||||||
}
|
}
|
||||||
|
|
@ -535,7 +535,7 @@ namespace VideoAnalysisCore.Controllers
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 获取指定节点
|
// 获取指定节点
|
||||||
var key = RedisExpandKey.BaseKey + "Services:" + model.DeviceId;
|
var key = RedisExpandKey.DeviceTaskLog(model.DeviceId);
|
||||||
oldTaskArr = redisManager.Redis.LRange<long>(key, 0, 999).ToList();
|
oldTaskArr = redisManager.Redis.LRange<long>(key, 0, 999).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,11 @@ namespace VideoAnalysisCore.Model
|
||||||
[SugarColumn(IsNullable = true)]
|
[SugarColumn(IsNullable = true)]
|
||||||
public GradeEnum? GradeId { get; set; }
|
public GradeEnum? GradeId { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 毕业届
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(IsNullable = true)]
|
||||||
|
public int? GradeYear { get; set; }
|
||||||
|
/// <summary>
|
||||||
/// 教育阶段
|
/// 教育阶段
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable = true)]
|
[SugarColumn(IsNullable = true)]
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,11 @@ namespace VideoAnalysisCore.Model
|
||||||
[SugarColumn(IsNullable = true)]
|
[SugarColumn(IsNullable = true)]
|
||||||
public GradeEnum? GradeId { get; set; }
|
public GradeEnum? GradeId { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 毕业届
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(IsNullable = true)]
|
||||||
|
public int? GradeYear { get; set; }
|
||||||
|
/// <summary>
|
||||||
/// 年级册(上册/下册)
|
/// 年级册(上册/下册)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable = true)]
|
[SugarColumn(IsNullable = true)]
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,11 @@ namespace VideoAnalysisCore.Model
|
||||||
[SugarColumn(IsNullable = true)]
|
[SugarColumn(IsNullable = true)]
|
||||||
public GradeSemesterEnum? GradeSemester { get; set; }
|
public GradeSemesterEnum? GradeSemester { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 毕业届
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(IsNullable = true)]
|
||||||
|
public int? GradeYear { get; set; }
|
||||||
|
/// <summary>
|
||||||
/// 学科网的教材版本Id
|
/// 学科网的教材版本Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long TextBookVersionId { get; set; }
|
public long TextBookVersionId { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace VideoAnalysisCore.Model.蓝鲸智库
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 蓝鲸智库 知识点表
|
/// 蓝鲸智库 知识点表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarTable("knowledgeinfo")]
|
[SugarTable("knowledgeinfo_hy")]
|
||||||
[Tenant("1001")]
|
[Tenant("1001")]
|
||||||
public class KnowledgeInfo
|
public class KnowledgeInfo
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AlibabaCloud.SDK.Vod20170321" Version="3.6.1" />
|
<PackageReference Include="AlibabaCloud.SDK.Vod20170321" Version="3.11.1" />
|
||||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
||||||
<PackageReference Include="Coravel" Version="6.0.2" />
|
<PackageReference Include="Coravel" Version="6.0.2" />
|
||||||
<PackageReference Include="FreeRedis" Version="1.5.5" />
|
<PackageReference Include="FreeRedis" Version="1.5.5" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue