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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user