parent
c39fbb7501
commit
17f75c975e
|
|
@ -49,6 +49,7 @@ namespace VideoAnalysisRazor.Layouts
|
||||||
Name = "课堂指标",
|
Name = "课堂指标",
|
||||||
Key = "EvaluationProject",
|
Key = "EvaluationProject",
|
||||||
Icon = "question-circle",
|
Icon = "question-circle",
|
||||||
|
HideInMenu = true,
|
||||||
},
|
},
|
||||||
new MenuDataItem
|
new MenuDataItem
|
||||||
{
|
{
|
||||||
|
|
@ -63,6 +64,14 @@ namespace VideoAnalysisRazor.Layouts
|
||||||
Name = "视频任务预览",
|
Name = "视频任务预览",
|
||||||
Key = "VideoTaskShow",
|
Key = "VideoTaskShow",
|
||||||
HideInMenu = true,
|
HideInMenu = true,
|
||||||
|
},
|
||||||
|
new MenuDataItem
|
||||||
|
{
|
||||||
|
Path = "/NodeSubscriptionPage",
|
||||||
|
Name = "文件订阅",
|
||||||
|
Key = "NodeSubscriptionPage",
|
||||||
|
Icon="clock-circle",
|
||||||
|
HideInMenu = false,
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
@page "/NodeSubscriptionPage"
|
||||||
|
@using AntDesign
|
||||||
|
@using AntDesign.TableModels
|
||||||
|
@using System.ComponentModel.DataAnnotations
|
||||||
|
@using SqlSugar
|
||||||
|
@using VideoAnalysisCore.Model
|
||||||
|
@using UserCenter.Model.Enum
|
||||||
|
|
||||||
|
<Table @ref="_table" Loading="tableLoading" TItem="NodeSubscription" ScrollY="600px"
|
||||||
|
PageSize="20" Total="_total" DataSource="_dataSource" @bind-SelectedRows="_selectedRows" OnChange="OnChange">
|
||||||
|
<TitleTemplate>
|
||||||
|
<Flex Justify="end" Gap="10">
|
||||||
|
</Flex>
|
||||||
|
</TitleTemplate>
|
||||||
|
<ColumnDefinitions Context="row">
|
||||||
|
|
||||||
|
<ActionColumn Title="操作" Width="130px">
|
||||||
|
<Button Type="primary" @onclick="()=> StartEdit(row)">编辑</Button>
|
||||||
|
</ActionColumn>
|
||||||
|
<PropertyColumn Property="c=>c.Id" Width="130px" Filterable="true" Sortable="true" />
|
||||||
|
<PropertyColumn Property="c=>c.Subject" Filterable="true" Width="130px" />
|
||||||
|
<PropertyColumn Property="c=>c.TaskType" Width="230px" Filterable="true" />
|
||||||
|
<PropertyColumn Property="c=>c.NodeId" Width="130px" Filterable="true" />
|
||||||
|
<PropertyColumn Property="c=>c.Enable" Width="100px" Filterable="true" />
|
||||||
|
<PropertyColumn Property="c=>c.LastId" Width="200px" />
|
||||||
|
<PropertyColumn Property="c=>c.CreateTime" />
|
||||||
|
</ColumnDefinitions>
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
@{
|
||||||
|
RenderFragment modelfooter = @<Template>
|
||||||
|
<Button OnClick="@EditOnOkAsync" @key="@( "submit" )"
|
||||||
|
Type="primary"
|
||||||
|
Loading="@modalBtnLoading">
|
||||||
|
提交
|
||||||
|
</Button>
|
||||||
|
<Button OnClick="()=>modalShow = false" @key="@( "back" )">取消</Button>
|
||||||
|
</Template>;
|
||||||
|
}
|
||||||
|
|
||||||
|
<Modal Title="@("编辑订阅节点")" Visible="modalShow" Width="650"
|
||||||
|
Footer="@modelfooter">
|
||||||
|
<Form @ref="form" Model="rowData" LabelAlign="AntLabelAlignType.Left">
|
||||||
|
<GridRow>
|
||||||
|
<GridCol Span="24">
|
||||||
|
<FormItem Label="是否启用">
|
||||||
|
<Switch Rows="1" @bind-Value="@context.Enable" />
|
||||||
|
</FormItem>
|
||||||
|
</GridCol>
|
||||||
|
</GridRow>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
using AntDesign;
|
||||||
|
using AntDesign.TableModels;
|
||||||
|
using FreeRedis;
|
||||||
|
using Learn.VideoAnalysis.Controllers.Dto;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
|
using SqlSugar;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using UserCenter.Model;
|
||||||
|
using UserCenter.Model.Enum;
|
||||||
|
using VideoAnalysisCore.Common;
|
||||||
|
using VideoAnalysisCore.Model.Enum;
|
||||||
|
using VideoAnalysisCore.Model;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Learn.VideoAnalysis.Components.Pages
|
||||||
|
{
|
||||||
|
public partial class NodeSubscriptionPage : ComponentBase
|
||||||
|
{
|
||||||
|
|
||||||
|
[Inject] private ConfirmService ComfirmService { get; set; } = default!;
|
||||||
|
[Inject] private ModalService ModalService { get; set; } = default!;
|
||||||
|
[Inject] private Repository<NodeSubscription> criteria { get; set; } = default!;
|
||||||
|
[Inject] private INotificationService _notice { get; set; } = default!;
|
||||||
|
|
||||||
|
|
||||||
|
IEnumerable<NodeSubscription> _selectedRows = [];
|
||||||
|
ITable _table;
|
||||||
|
IForm? form;
|
||||||
|
|
||||||
|
List<NodeSubscription> _dataSource = null;
|
||||||
|
RefAsync<int> _total = 0;
|
||||||
|
|
||||||
|
bool tableLoading = false;
|
||||||
|
Table<NodeSubscription> tableRef;
|
||||||
|
List<NodeSubscription> _editSource = null;
|
||||||
|
|
||||||
|
|
||||||
|
bool modalShow =false;
|
||||||
|
bool modalBtnLoading = false;
|
||||||
|
NodeSubscription rowData;
|
||||||
|
SubjectEnum editSubject;
|
||||||
|
|
||||||
|
async void SubjectEnumSelect()
|
||||||
|
{
|
||||||
|
_editSource = await criteria.GetListAsync(x => x.Subject == editSubject);
|
||||||
|
await this.InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
void EditAddRow()
|
||||||
|
{
|
||||||
|
if (form is not null && form.Validate())
|
||||||
|
{
|
||||||
|
var data = rowData;
|
||||||
|
data.Subject = editSubject;
|
||||||
|
if (_editSource is null)
|
||||||
|
_editSource = new() { data };
|
||||||
|
else
|
||||||
|
_editSource.Add(data);
|
||||||
|
rowData = new();
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 新增或者修改
|
||||||
|
/// </summary>
|
||||||
|
void StartEdit(NodeSubscription data)
|
||||||
|
{
|
||||||
|
rowData = data?? new();
|
||||||
|
modalShow = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task EditOnOkAsync()
|
||||||
|
{
|
||||||
|
var data = rowData;
|
||||||
|
modalBtnLoading = true;
|
||||||
|
await criteria.DeleteAsync(s => s.Subject == editSubject);
|
||||||
|
await criteria.InsertRangeAsync(_editSource);
|
||||||
|
|
||||||
|
_table.ReloadData();
|
||||||
|
modalShow = false;
|
||||||
|
modalBtnLoading = false;
|
||||||
|
StateHasChanged();
|
||||||
|
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 分页 查询 筛选 时
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query"></param>
|
||||||
|
async void OnChange(QueryModel<NodeSubscription> query)
|
||||||
|
{
|
||||||
|
tableLoading = true;
|
||||||
|
List<IConditionalModel> where = default!;
|
||||||
|
if (query.FilterModel != null && ((query.FilterModel?.Count() ?? 0) > 0))
|
||||||
|
{
|
||||||
|
where = query.ToSqlSugerWhere();
|
||||||
|
}
|
||||||
|
_dataSource = await criteria.AsQueryable()
|
||||||
|
.Where(where)
|
||||||
|
.ToPageListAsync(query.PageIndex, query.PageSize, _total);
|
||||||
|
tableLoading = false;
|
||||||
|
StateHasChanged();
|
||||||
|
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 删除行
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="row"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
async Task Delete(NodeSubscription row)
|
||||||
|
{
|
||||||
|
if (!await Comfirm($"确定要删除这条数据吗? [{row.NodeId}]?"))
|
||||||
|
return;
|
||||||
|
await criteria.DeleteByIdAsync(row.Id);
|
||||||
|
_table.ReloadData();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> Comfirm(string message)
|
||||||
|
{
|
||||||
|
return await ComfirmService.Show(message, "提示", ConfirmButtons.YesNo, ConfirmIcon.Warning) == ConfirmResult.Yes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
input[aria-hidden="true"] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.displayNone {
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
.ant-table-pagination {
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Learn.VideoAnalysis.Expand
|
||||||
provider.UseScheduler(scheduler =>
|
provider.UseScheduler(scheduler =>
|
||||||
{
|
{
|
||||||
//每5分钟执行一次 未处理视频扫描
|
//每5分钟执行一次 未处理视频扫描
|
||||||
//scheduler.Schedule<NodeSubscriptionJob>().EveryFiveMinutes();
|
scheduler.Schedule<NodeSubscriptionJob>().EveryFiveMinutes();
|
||||||
//每天两点
|
//每天两点
|
||||||
scheduler.Schedule<TaskFileClearJob>().DailyAtHour(2);
|
scheduler.Schedule<TaskFileClearJob>().DailyAtHour(2);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ namespace Learn.VideoAnalysis.Expand
|
||||||
foreach (var t in entityTypes)
|
foreach (var t in entityTypes)
|
||||||
{
|
{
|
||||||
Console.Write($"【1】{entityTypes.Count()}/{(++i).ToString().PadLeft(totalCount, '0')} 执行 {t.FullName}".PadRight(60, ' '));
|
Console.Write($"【1】{entityTypes.Count()}/{(++i).ToString().PadLeft(totalCount, '0')} 执行 {t.FullName}".PadRight(60, ' '));
|
||||||
DbScoped.SugarScope.CodeFirst.InitTables(t);
|
DbScoped.Sugar.CodeFirst.InitTables(t);
|
||||||
Console.WriteLine($"【√】");
|
Console.WriteLine($"【√】");
|
||||||
}
|
}
|
||||||
Console.WriteLine($"【1】数量{entityTypes.Count()} 执行完毕");
|
Console.WriteLine($"【1】数量{entityTypes.Count()} 执行完毕");
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,9 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Content Update="Components\Pages\NodeSubscriptionPage.razor">
|
||||||
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
|
</Content>
|
||||||
<Content Update="Components\Pages\Login.razor">
|
<Content Update="Components\Pages\Login.razor">
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ namespace Learn.VideoAnalysis
|
||||||
|
|
||||||
//³õʼ»¯ ²å¼þ
|
//³õʼ»¯ ²å¼þ
|
||||||
builder.Services.AddSqlSugarExpand();
|
builder.Services.AddSqlSugarExpand();
|
||||||
|
builder.Services.AddDownloadFileExpand(2);
|
||||||
builder.Services.AddAlibabaCloudVod();
|
builder.Services.AddAlibabaCloudVod();
|
||||||
builder.Services.AddRedisExpand();
|
builder.Services.AddRedisExpand();
|
||||||
builder.Services.AddSpeakerAI();
|
builder.Services.AddSpeakerAI();
|
||||||
|
|
@ -93,6 +94,7 @@ namespace Learn.VideoAnalysis
|
||||||
builder.Services.Configure<ProSettings>(builder.Configuration.GetSection("ProSettings"));
|
builder.Services.Configure<ProSettings>(builder.Configuration.GetSection("ProSettings"));
|
||||||
|
|
||||||
builder.Services.AddHttpClient();
|
builder.Services.AddHttpClient();
|
||||||
|
builder.Services.AddHttpContextAccessor();
|
||||||
builder.Services.AddSingleton<ChatGPTClient>();
|
builder.Services.AddSingleton<ChatGPTClient>();
|
||||||
builder.Services.AddSingleton<DeepSeekGPTClient>();
|
builder.Services.AddSingleton<DeepSeekGPTClient>();
|
||||||
//builder.Services.AddSingleton<IBserGPT, KIMI_GPT>();
|
//builder.Services.AddSingleton<IBserGPT, KIMI_GPT>();
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE
|
||||||
public static async Task Audio2WAV16KAsync(string task)
|
public static async Task Audio2WAV16KAsync(string task)
|
||||||
{
|
{
|
||||||
Task = task;
|
Task = task;
|
||||||
var filePath = await DbScoped.SugarScope
|
var filePath = await DbScoped.Sugar
|
||||||
.Queryable<VideoTask>()
|
.Queryable<VideoTask>()
|
||||||
.Where(s => s.Id == long.Parse(task))
|
.Where(s => s.Id == long.Parse(task))
|
||||||
.Select(s=>s.LocalMediaPath).FirstAsync();
|
.Select(s=>s.LocalMediaPath).FirstAsync();
|
||||||
|
|
|
||||||
|
|
@ -112,15 +112,17 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
|
|
||||||
var resFormat = """[{"StartTime":开始秒(number),"Theme":主题(string),"Content":内容总结(string)}]""";
|
var resFormat = """[{"StartTime":开始秒(number),"Theme":主题(string),"Content":内容总结(string)}]""";
|
||||||
var postMessages =
|
var postMessages =
|
||||||
$"你的任务是分析视频字幕内容并提取出中国高考考试试题方法点,然后分析出<知识块>,来帮助学生快速了解视频字幕的内容" +
|
$"你的任务是分析视频字幕内容并提取出中国高考考试试题方法点,然后分析出<知识块>来帮助学生快速了解视频字幕的内容。" +
|
||||||
$"通过阅读并理解字幕内容.然后识别出{subject}学科中属于{fileNameInfoRes.授课章节}章节相关的时间段。" +
|
$"通过阅读并理解字幕内容.然后识别出{subject}学科中属于{fileNameInfoRes.授课章节}章节相关的时间段。" +
|
||||||
$"关联合并知识内容相似的知识点来合并为<知识块>。" +
|
$"关联合并知识内容相似的知识点来合并为<知识块>。" +
|
||||||
$"分配空余未使用的时间段到内容相近的<知识块>时间区间来获取更加详细的上下文,但是请避免<知识块>之间时间重合。" +
|
$"分配空余未使用的时间段到内容相近的<知识块>时间区间来获取更加详细的上下文,但是请避免<知识块>之间时间重合。" +
|
||||||
$"字幕格式(开始秒:结束秒:内容|下一段字幕).以下是包含时间的视频字幕文本。字幕列表 {captions.Captions}。" +
|
$"字幕格式(开始秒:结束秒:内容|下一段字幕).以下是包含时间的视频字幕文本。" +
|
||||||
$"最后请检查某些<知识块>之间的过渡是否自然,如果<知识块>时长超过500秒则考虑拆封为两个更加贴切的<知识块>.或者<知识块>时长小于30秒则考虑合并<知识块>到相邻的<知识块>)。" +
|
$"字幕列表 {captions.Captions}。" +
|
||||||
|
$"最后请检查某些<知识块>之间的过渡是否自然,如果<知识块>时长超过500秒则考虑拆封为两个更加贴切的<知识块>。" +
|
||||||
|
$"请检查<知识块>时长小于30秒则考虑合并<知识块>到相邻的<知识块>)。" +
|
||||||
$"输出内容只返回json格式({resFormat})";
|
$"输出内容只返回json格式({resFormat})";
|
||||||
|
|
||||||
Console.WriteLine(DateTime.Now + "=>开始分析视频内容");
|
Console.WriteLine(DateTime.Now + "=>1.开始分析视频内容");
|
||||||
|
|
||||||
questionRes = await ChatAsync<VideoKnowRes[]>(task, postMessages, null);
|
questionRes = await ChatAsync<VideoKnowRes[]>(task, postMessages, null);
|
||||||
|
|
||||||
|
|
@ -130,46 +132,17 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
|
|
||||||
var thems = JsonSerializer.Serialize(questionRes.Adapt<VideoKnowQueryDto[]>());// string.Join(',', questionRes.Select(s => s.StartTime + "->" + s.Theme));
|
var thems = JsonSerializer.Serialize(questionRes.Adapt<VideoKnowQueryDto[]>());// string.Join(',', questionRes.Select(s => s.StartTime + "->" + s.Theme));
|
||||||
var checkResFormat1 = """[{"StartTime":开始秒(number),"KnowPoint":知识点名称(string),"KnowPointId":知识点Id(string)}]""";
|
var checkResFormat1 = """[{"StartTime":开始秒(number),"KnowPoint":知识点名称(string),"KnowPointId":知识点Id(string)}]""";
|
||||||
var knowStr = string.Join(',', knowledgeInfos.Select(s => s.Name));
|
|
||||||
var knowMessages =
|
var knowMessages =
|
||||||
$"我针对视频<{title}>分析出了一些视频的知识片段,现在需要你帮我将每个片段分配恰当的知识点(单个片段允许多个知识点用逗号','分割)。" +
|
$"我针对视频<{title}>分析出了一些视频的知识片段,现在需要你帮我将每个片段分配恰当的知识点(单个片段允许多个知识点用逗号','分割)。" +
|
||||||
$"这是我的分段 {thems}。" +
|
$"这是我的分段 {thems}。" +
|
||||||
$"提供的知识点名称({knows})。 格式 (方法点Id|方法点名称) " +
|
$"提供的知识点名称({knows})。 格式 (方法点Id|方法点名称) " +
|
||||||
$"最后请确保分配的知识点是用户提供的,否则片段知识点值留空!。" +
|
$"最后请确保分配的知识点是用户提供的,否则片段知识点值留空!。" +
|
||||||
$"输出内容只返回json格式({checkResFormat1})";
|
$"输出内容只返回json格式({checkResFormat1})";
|
||||||
Console.WriteLine(DateTime.Now + "=>开始分析视频内容知识点");
|
Console.WriteLine(DateTime.Now + "=>2.开始分析视频内容知识点");
|
||||||
var konwRes = await ChatAsync<VideoKnowRes[]>(task, knowMessages, null);
|
var konwRes = await ChatAsync<VideoKnowRes[]>(task, knowMessages, null);
|
||||||
|
|
||||||
|
for (int i = 0; i < konwRes.Count(); i++)
|
||||||
var checkResFormat = """{"Score":打分(number),"Evaluation":评价(string)""";//,"Data":优化后的分段(array)}""";
|
questionRes[i].KnowPoint = konwRes[i].KnowPoint;
|
||||||
var checkMessage = "我为视频的讲解内容做了一些分段,你能帮我检查下这些分段的时间,主题,知识点分配是否合理符合实际吗?" +
|
|
||||||
$"请给出你的打分(0-100,70分及格)以及打分原因" +//,并且给出优化后的分段 分段格式(${checkResFormat1})" +
|
|
||||||
//$"如果不合理的话强帮我修改优化他们(注意优化知识点时只允许使用已存在的知识点不允许杜撰猜测捏造)" +
|
|
||||||
$"这是我的分段 {thems}." +
|
|
||||||
$"后续的内容是包含时间戳的视频字幕的固定格式文本。" +
|
|
||||||
$"字幕格式(说话人:开始秒:结束秒:内容|下一段字幕).以下是包含时间的视频字幕文本。字幕列表 {captions.Captions}。" +
|
|
||||||
$"最后输出格式为json({checkResFormat})";
|
|
||||||
|
|
||||||
Console.WriteLine(DateTime.Now + "=>开始检查视频分段结果");
|
|
||||||
var checkRes = await ChatAsync<CheckMessageDto>(task, checkMessage, null);
|
|
||||||
if (checkRes != null && checkRes.Score >= 80 && questionRes.Count() == checkRes.Data.Count())
|
|
||||||
{
|
|
||||||
for (int i = 0; i < checkRes.Data.Count(); i++)
|
|
||||||
{
|
|
||||||
questionRes[i].Theme = checkRes.Data[i].Theme;
|
|
||||||
questionRes[i].StartTime = checkRes.Data[i].StartTime;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
Console.WriteLine(DateTime.Now + $"=>{task} 得分过低/分段长度不匹配 得分{checkRes?.Score} 长度 {questionRes.Count()}/{checkRes.Data.Count()}");
|
|
||||||
Console.WriteLine(checkRes.Evaluation);
|
|
||||||
Console.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
for (int i = 0; i < questionRes.Length; i++)
|
for (int i = 0; i < questionRes.Length; i++)
|
||||||
{
|
{
|
||||||
var item = questionRes[i];
|
var item = questionRes[i];
|
||||||
|
|
@ -178,6 +151,36 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
else
|
else
|
||||||
item.EndTime = (int)(questionRes[i + 1]?.StartTime ?? 0) - 1;
|
item.EndTime = (int)(questionRes[i + 1]?.StartTime ?? 0) - 1;
|
||||||
}
|
}
|
||||||
|
thems = JsonSerializer.Serialize(questionRes.Adapt<VideoKnowQueryDto[]>());
|
||||||
|
var checkResFormat = """{"Score":打分(number),"Evaluation":评价(string)""";//,"Data":优化后的分段(array)}""";
|
||||||
|
var checkMessage = "我为视频的讲解内容做了一些分段,希望你能通读字幕内容后检查下的分段是否符合我的要求?" +
|
||||||
|
$"检查这些分段的时间是否合理 与相邻的时间段间隔是否处于合理区间30~900秒之间?" +
|
||||||
|
$"分段的主题内容,知识点分配是否合理符合实际吗?" +
|
||||||
|
$"请给出你的打分(0-100,70分及格)以及打分原因。" +
|
||||||
|
$"这是我的分段 {thems}。" +
|
||||||
|
$"后续的内容是包含时间戳的视频字幕的固定格式文本。" +
|
||||||
|
$"字幕格式(说话人:开始秒:结束秒:内容|下一段字幕).以下是包含时间的视频字幕文本。字幕列表 {captions.Captions}。" +
|
||||||
|
$"最后输出格式为json({checkResFormat})";
|
||||||
|
|
||||||
|
Console.WriteLine(DateTime.Now + "=>3.开始检查视频分段结果");
|
||||||
|
var checkRes = await ChatAsync<CheckMessageDto>(task, checkMessage, null);
|
||||||
|
if (checkRes != null && checkRes.Score >= 80)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine(DateTime.Now + $"=>{task} 得分过低/分段长度不匹配 得分{checkRes?.Score} ");
|
||||||
|
Console.WriteLine(checkRes.Evaluation);
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
if (questionRes.Any(s => s.KeepTime < 30))
|
||||||
|
{
|
||||||
|
Console.WriteLine(DateTime.Now + "=>视频分段过短!! 重新进行AI分析");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//todo 未包含的知识点片段 如何处理
|
//todo 未包含的知识点片段 如何处理
|
||||||
var insertData = questionRes
|
var insertData = questionRes
|
||||||
|
|
|
||||||
|
|
@ -262,13 +262,16 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
||||||
Console.WriteLine(DateTime.Now + "=> SenseVoice 字幕数量"+ res.Count);
|
Console.WriteLine(DateTime.Now + "=> SenseVoice 字幕数量"+ res.Count);
|
||||||
|
|
||||||
var captionsStr = JsonSerializer.Serialize(res);
|
var captionsStr = JsonSerializer.Serialize(res);
|
||||||
await DbScoped.SugarScope
|
await DbScoped.Sugar
|
||||||
.Updateable<VideoTask>()
|
.Updateable<VideoTask>()
|
||||||
.SetColumns(it => it.Captions == captionsStr)
|
.SetColumns(it => it.Captions == captionsStr)
|
||||||
.Where(it => it.Id == long.Parse(task))
|
.Where(it => it.Id == long.Parse(task))
|
||||||
.ExecuteCommandAsync();
|
.ExecuteCommandAsync();
|
||||||
await RedisExpand.Redis.HMSetAsync(RedisExpandKey.Task(task), "Captions", res);
|
await RedisExpand.Redis.HMSetAsync(RedisExpandKey.Task(task), "Captions", res);
|
||||||
//RedisExpand.InsertChannel(Enum.RedisChannelEnum.ParsingSpeaker, task);
|
//RedisExpand.InsertChannel(Enum.RedisChannelEnum.ParsingSpeaker, task);
|
||||||
|
//分析完成视频字幕后继续接收任务
|
||||||
|
RedisExpand.NewTask();
|
||||||
|
|
||||||
RedisExpand.InsertChannel(RedisChannelEnum.ChatModelAnalysis, task);
|
RedisExpand.InsertChannel(RedisChannelEnum.ChatModelAnalysis, task);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
||||||
var res = segments.Select(s => new OfflineSpeakerRes(s));
|
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 = JsonSerializer.Serialize(res);
|
var speakerStr = JsonSerializer.Serialize(res);
|
||||||
DbScoped.SugarScope
|
DbScoped.Sugar
|
||||||
.Updateable<VideoTask>()
|
.Updateable<VideoTask>()
|
||||||
.SetColumns(it => it.Speaker == speakerStr)
|
.SetColumns(it => it.Speaker == speakerStr)
|
||||||
.Where(it => it.Id == long.Parse(task));
|
.Where(it => it.Id == long.Parse(task));
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using AntDesign;
|
using AntDesign;
|
||||||
using Downloader;
|
using Downloader;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using SqlSugar.IOC;
|
using SqlSugar.IOC;
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -8,22 +9,35 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using VideoAnalysisCore.Job;
|
||||||
using VideoAnalysisCore.Model;
|
using VideoAnalysisCore.Model;
|
||||||
using VideoAnalysisCore.Model.Enum;
|
using VideoAnalysisCore.Model.Enum;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.Common
|
namespace VideoAnalysisCore.Common
|
||||||
{
|
{
|
||||||
|
public static class DownloadFileExpand
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化下载器
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="DownloadSpeed">下载速度mb/s 默认8</param>
|
||||||
|
public static void AddDownloadFileExpand(this IServiceCollection services, int DownloadSpeed)
|
||||||
|
{
|
||||||
|
DownloadFile.DownloadSpeed = DownloadSpeed;
|
||||||
|
services.AddSingleton<DownloadFile>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DownloadFile
|
public class DownloadFile
|
||||||
{
|
{
|
||||||
static DownloadConfiguration Opt { get; set; } = default!;
|
static DownloadConfiguration Opt { get; set; } = default!;
|
||||||
/// <summary>
|
public static int DownloadSpeed { get; set; } = default!;
|
||||||
/// 初始化下载器
|
private readonly Repository<VideoTask> videoTaskDB;
|
||||||
/// </summary>
|
|
||||||
/// <param name="DownloadSpeed">下载速度mb/s 默认8</param>
|
public DownloadFile(Repository<VideoTask> videoTaskDB)
|
||||||
static void Init(int DownloadSpeed = 8)
|
|
||||||
{
|
{
|
||||||
Opt = new DownloadConfiguration()
|
Opt = new DownloadConfiguration()
|
||||||
{
|
{
|
||||||
|
|
@ -77,6 +91,7 @@ namespace VideoAnalysisCore.Common
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
this.videoTaskDB = videoTaskDB;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据 Content-Type 映射文件后缀
|
// 根据 Content-Type 映射文件后缀
|
||||||
|
|
@ -103,15 +118,15 @@ namespace VideoAnalysisCore.Common
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="task"></param>
|
/// <param name="task"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static async Task RunTask(string task)
|
public async Task RunTask(string task)
|
||||||
{
|
{
|
||||||
if (Opt is null)
|
|
||||||
Init();
|
|
||||||
var taskId = long.Parse(task);
|
var taskId = long.Parse(task);
|
||||||
//获取资源文件 地址
|
//获取资源文件 地址
|
||||||
var fileUrl =await DbScoped.SugarScope.Queryable<VideoTask>()
|
var taskInfo =await videoTaskDB.AsQueryable()
|
||||||
.Where(s => s.Id == taskId)
|
.Where(s => s.Id == taskId).FirstAsync();
|
||||||
.Select(s=>s.MediaUrl).FirstAsync();
|
if (taskInfo is null || string.IsNullOrEmpty(taskInfo.MediaName) || taskInfo.MediaName.Contains("教研"))
|
||||||
|
throw new Exception($"任务为null/是教研视频/没有视频课程名称");
|
||||||
|
var fileUrl = taskInfo.MediaUrl;
|
||||||
if (string.IsNullOrEmpty(fileUrl))
|
if (string.IsNullOrEmpty(fileUrl))
|
||||||
throw new Exception($"任务id[{task}] 资源地址无效 {fileUrl}");
|
throw new Exception($"任务id[{task}] 资源地址无效 {fileUrl}");
|
||||||
|
|
||||||
|
|
@ -128,8 +143,8 @@ namespace VideoAnalysisCore.Common
|
||||||
var outputPath = Path.Combine(localPath, task + fileExtension);
|
var outputPath = Path.Combine(localPath, task + fileExtension);
|
||||||
if (!Directory.Exists(localPath)) Directory.CreateDirectory(localPath);
|
if (!Directory.Exists(localPath)) Directory.CreateDirectory(localPath);
|
||||||
|
|
||||||
await DbScoped.SugarScope
|
await videoTaskDB
|
||||||
.Updateable<VideoTask>()
|
.AsUpdateable()
|
||||||
.SetColumns(it => it.LocalMediaPath == outputPath)
|
.SetColumns(it => it.LocalMediaPath == outputPath)
|
||||||
.Where(it => it.Id == long.Parse(task))
|
.Where(it => it.Id == long.Parse(task))
|
||||||
.ExecuteCommandAsync();
|
.ExecuteCommandAsync();
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ namespace VideoAnalysisCore.Common
|
||||||
if (gptRes is null)
|
if (gptRes is null)
|
||||||
throw new Exception("未能读取到GPT处理结果");
|
throw new Exception("未能读取到GPT处理结果");
|
||||||
|
|
||||||
var taskData = await DbScoped.SugarScope.Queryable<VideoTask>()
|
var taskData = await DbScoped.Sugar.Queryable<VideoTask>()
|
||||||
.FirstAsync(s => s.Id == tId);
|
.FirstAsync(s => s.Id == tId);
|
||||||
if (taskData.Captions == "[]")
|
if (taskData.Captions == "[]")
|
||||||
taskData.Captions = (await Redis.HMGetAsync(RedisExpandKey.Task(task), "Captions")).First();
|
taskData.Captions = (await Redis.HMGetAsync(RedisExpandKey.Task(task), "Captions")).First();
|
||||||
|
|
@ -193,7 +193,7 @@ namespace VideoAnalysisCore.Common
|
||||||
taskData.ChatAnalysisScore = gptRes?.Assessment?.Merit?.Sum(s => s.Score) ?? 0;
|
taskData.ChatAnalysisScore = gptRes?.Assessment?.Merit?.Sum(s => s.Score) ?? 0;
|
||||||
taskData.ErrorMessage = string.Empty;
|
taskData.ErrorMessage = string.Empty;
|
||||||
taskData.LastEnum = RedisChannelEnum.EndTask;
|
taskData.LastEnum = RedisChannelEnum.EndTask;
|
||||||
await DbScoped.SugarScope.Updateable(taskData)
|
await DbScoped.Sugar.Updateable(taskData)
|
||||||
.UpdateColumns(it => new
|
.UpdateColumns(it => new
|
||||||
{
|
{
|
||||||
it.ChatAnalysis,
|
it.ChatAnalysis,
|
||||||
|
|
@ -205,9 +205,7 @@ namespace VideoAnalysisCore.Common
|
||||||
it.LastEnum,
|
it.LastEnum,
|
||||||
}).ExecuteCommandAsync();
|
}).ExecuteCommandAsync();
|
||||||
|
|
||||||
|
//NewTask();
|
||||||
await Redis.DelAsync(RedisExpandKey.IDTask);
|
|
||||||
await ReceivingTaskAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -218,8 +216,16 @@ namespace VideoAnalysisCore.Common
|
||||||
if (Redis is null) throw new Exception("redis未初始化");
|
if (Redis is null) throw new Exception("redis未初始化");
|
||||||
|
|
||||||
SubscribeList.Add(RedisChannelEnum.DownloadFile,
|
SubscribeList.Add(RedisChannelEnum.DownloadFile,
|
||||||
(msg) => { TouchChannel(RedisChannelEnum.DownloadFile, msg, DownloadFile.RunTask); });
|
(msg) => { TouchChannel(RedisChannelEnum.DownloadFile, msg,
|
||||||
|
(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.SeparateAudio,
|
SubscribeList.Add(RedisChannelEnum.SeparateAudio,
|
||||||
(msg) => { TouchChannel(RedisChannelEnum.SeparateAudio, msg, FFMPGEHandle.Audio2WAV16KAsync); });
|
(msg) => { TouchChannel(RedisChannelEnum.SeparateAudio, msg, FFMPGEHandle.Audio2WAV16KAsync); });
|
||||||
|
|
@ -247,6 +253,19 @@ namespace VideoAnalysisCore.Common
|
||||||
await ReceivingTaskAsync();
|
await ReceivingTaskAsync();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 重新执行新任务
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static void NewTask()
|
||||||
|
{
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Redis.DelAsync(RedisExpandKey.IDTask);
|
||||||
|
await ReceivingTaskAsync();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 重新接收新任务
|
/// 重新接收新任务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -297,7 +316,7 @@ namespace VideoAnalysisCore.Common
|
||||||
|
|
||||||
Redis.HMSet(RedisExpandKey.Task(taskID), "ErrorMessage", error);
|
Redis.HMSet(RedisExpandKey.Task(taskID), "ErrorMessage", error);
|
||||||
|
|
||||||
return await DbScoped.SugarScope.Updateable<VideoTask>()
|
return await DbScoped.Sugar.Updateable<VideoTask>()
|
||||||
.SetColumns(it => it.ErrorMessage == error)//SetColumns是可以叠加的 写2个就2个字段赋值
|
.SetColumns(it => it.ErrorMessage == error)//SetColumns是可以叠加的 写2个就2个字段赋值
|
||||||
.Where(it => it.Id == taskID)
|
.Where(it => it.Id == taskID)
|
||||||
.ExecuteCommandAsync() == 1;
|
.ExecuteCommandAsync() == 1;
|
||||||
|
|
@ -323,10 +342,14 @@ namespace VideoAnalysisCore.Common
|
||||||
{
|
{
|
||||||
Redis.HMSet(RedisExpandKey.Task(taskId), "LastEnum", key);
|
Redis.HMSet(RedisExpandKey.Task(taskId), "LastEnum", key);
|
||||||
Redis.HMSet(RedisExpandKey.Task(taskId), "Progress", 0);
|
Redis.HMSet(RedisExpandKey.Task(taskId), "Progress", 0);
|
||||||
await DbScoped.SugarScope.Updateable<VideoTask>()
|
lock (Redis)
|
||||||
|
{
|
||||||
|
DbScoped.Sugar.Updateable<VideoTask>()
|
||||||
.SetColumns(it => it.LastEnum == key)
|
.SetColumns(it => it.LastEnum == key)
|
||||||
.Where(it => it.Id == tID)
|
.Where(it => it.Id == tID)
|
||||||
.ExecuteCommandAsync();
|
.ExecuteCommand();
|
||||||
|
|
||||||
|
}
|
||||||
await action(taskId);
|
await action(taskId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,15 +23,15 @@ namespace VideoAnalysisCore.Common
|
||||||
var t = typeof(T);
|
var t = typeof(T);
|
||||||
if (CID.ContainsKey(t))
|
if (CID.ContainsKey(t))
|
||||||
{
|
{
|
||||||
base.Context = DbScoped.SugarScope.GetConnectionScope(CID[t]);
|
base.Context = DbScoped.Sugar.GetConnectionScope(CID[t]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var c = t.GetCustomAttribute<TenantAttribute>();
|
var c = t.GetCustomAttribute<TenantAttribute>();
|
||||||
if (!CID.ContainsKey(typeof(T)))
|
if (!CID.ContainsKey(typeof(T)))
|
||||||
CID.Add(typeof(T), c?.configId);
|
CID.Add(typeof(T), c?.configId);
|
||||||
base.Context = c != null
|
base.Context = c != null
|
||||||
? DbScoped.SugarScope.GetConnectionScope(c.configId)
|
? DbScoped.Sugar.GetConnectionScope(c.configId)
|
||||||
: DbScoped.SugarScope;
|
: DbScoped.Sugar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,12 @@ namespace VideoAnalysisCore.Model
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 绑定学科
|
/// 绑定学科
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayName("绑定学科")]
|
[DisplayName("任务类型")]
|
||||||
public TaskTypeEnum TaskType { get; set; }
|
public TaskTypeEnum TaskType { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 学科
|
/// 学科
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DisplayName("学科")]
|
||||||
public SubjectEnum Subject { get; set; }
|
public SubjectEnum Subject { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否启用
|
/// 是否启用
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,8 @@ namespace VideoAnalysisCore.Model
|
||||||
/// 创建时间
|
/// 创建时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime CreateTime { get; set; } = DateTime.Now;
|
public DateTime CreateTime { get; set; } = DateTime.Now;
|
||||||
|
[SugarColumn( IsNullable = true)]
|
||||||
|
public DateTime EndTime { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开始时间轴
|
/// 开始时间轴
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue