feat(aihr): support video upload with asr transcript and keyframe ocr

新增 AihrVideoService:ffmpeg 抽音轨按5分钟分段调 asr 转写([mm:ss]
时间戳),30s间隔(≤40帧)抽关键帧调 vision 提取画面文字(重复画面去重),
合并文本复用既有归类/切片/向量化链路。视频只走异步队列(同步接口
拒绝),≤500MB/≤60分钟,同时只加工1个,卡死判定放宽到120分钟;无
asr/vision 结果按「待处理」落库不报错。前端 accept/筛选/文案与
overview 类型徽标同步。端到端验证:30s培训视频语音逐字转写+画面
四要点完整提取,自动归类投诉处理SOP。
This commit is contained in:
2026-07-04 00:24:24 +08:00
parent 90e96322bb
commit fe1eef3905
6 changed files with 321 additions and 31 deletions
+12 -6
View File
@@ -290,10 +290,12 @@ import {
} from '@/api/aihr/processing';
import { uploadKnowledgeDocAsync, listUploadItems, retryUploadItem, type UploadItem } from '@/api/aihr/sop';
const acceptTypes = '.txt,.md,.markdown,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.jpg,.jpeg,.png,.gif,.webp,.bmp';
const acceptTypes = '.txt,.md,.markdown,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.jpg,.jpeg,.png,.gif,.webp,.bmp,.mp4,.mov,.avi,.mkv,.webm,.m4v';
const autoCategory = '__auto__';
const supportedPattern = /\.(txt|md|markdown|pdf|doc|docx|xls|xlsx|ppt|pptx|jpg|jpeg|png|gif|webp|bmp)$/i;
const supportedPattern = /\.(txt|md|markdown|pdf|doc|docx|xls|xlsx|ppt|pptx|jpg|jpeg|png|gif|webp|bmp|mp4|mov|avi|mkv|webm|m4v)$/i;
const videoPattern = /\.(mp4|mov|avi|mkv|webm|m4v)$/i;
const maxFileSize = 100 * 1024 * 1024;
const maxVideoSize = 500 * 1024 * 1024;
const browserBatchWarnCount = 20;
const browserBatchWarnSize = 200 * 1024 * 1024;
@@ -319,7 +321,7 @@ let importPollTimer: ReturnType<typeof window.setTimeout> | undefined;
let batchPollTimer: ReturnType<typeof window.setTimeout> | undefined;
const statusTabs = ['全部', '等待解析', '解析中', '已完成', '失败'];
const fileTypes = ['全部', 'Word', 'PDF', 'PPT', 'Excel', '图片'];
const fileTypes = ['全部', 'Word', 'PDF', 'PPT', 'Excel', '图片', '视频'];
const seedOverview: ProcessingOverview = {
metrics: [
@@ -488,13 +490,15 @@ async function handlePickedFiles(event: Event) {
}
async function uploadFiles(files: File[]) {
const readyFiles = files.filter((file) => supportedPattern.test(file.name) && file.size > 0 && file.size <= maxFileSize);
const readyFiles = files.filter(
(file) => supportedPattern.test(file.name) && file.size > 0 && file.size <= (videoPattern.test(file.name) ? maxVideoSize : maxFileSize)
);
if (readyFiles.length === 0) {
ElMessage.warning('仅支持非空且 100MB 内的 txt/md/pdf/Word/Excel/PPT/图片文件');
ElMessage.warning('仅支持非空的 txt/md/pdf/Word/Excel/PPT/图片(100MB内)或视频(500MB内)文件');
return;
}
if (readyFiles.length < files.length) {
ElMessage.warning(`已跳过 ${files.length - readyFiles.length} 个不支持、空文件或超过 100MB 的文件`);
ElMessage.warning(`已跳过 ${files.length - readyFiles.length} 个不支持、空文件或超限文件(文档/图片 100MB、视频 500MB)`);
}
const totalSize = readyFiles.reduce((sum, file) => sum + file.size, 0);
@@ -772,6 +776,7 @@ function fileShort(type: string) {
if (type === 'Excel') return 'X';
if (type === 'PPT') return 'P';
if (type === '图片') return '图';
if (type === '视频') return '视';
return 'T';
}
@@ -781,6 +786,7 @@ function fileBadgeClass(type: string) {
if (type === 'Excel') return 'excel';
if (type === 'PPT') return 'ppt';
if (type === '图片') return 'image';
if (type === '视频') return 'ppt';
return 'text';
}
</script>