From 068010b0594680dd7f6919e61c5db8b0e6c6079a Mon Sep 17 00:00:00 2001 From: CI Bot Date: Thu, 20 Aug 2026 15:48:10 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=BB=9F=E4=B8=80=E7=B4=A0=E6=9D=90?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E4=B8=BA=E5=8D=95=E4=B8=80=20ingest=20?= =?UTF-8?q?=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端改动: 1. POST /assets 拒绝视频类型(必须走 ingest-jobs) 2. HEVC 转码超时从 300s 改为 900s(支持大文件) 3. 添加 HDR→SDR 转换参数(colorspace/primaries/transfer=bt709) 4. 转码前检查磁盘空间(< 2GB 时拒绝任务) 前端无需修改: - 当前 uploadAssetDirect 已统一走 ingest-jobs 流程 - completeDirectUpload → _submit_ingest_job → Worker 处理 - 视频上传后自动进入转码+入库流程 --- apps/api/app/api/routes/assets.py | 7 +++++++ apps/worker/worker_app/tasks/ingest.py | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/apps/api/app/api/routes/assets.py b/apps/api/app/api/routes/assets.py index 0ea6e54cc..161ffa36c 100755 --- a/apps/api/app/api/routes/assets.py +++ b/apps/api/app/api/routes/assets.py @@ -684,6 +684,13 @@ def create_asset( asset_library_repository: Any = Depends(get_asset_library_repository), project_repository: Any = Depends(get_project_repository), ) -> AssetResponse: + # 视频素材必须走 ingest-jobs 接口(统一上传路径,Worker 会自动处理 HEVC 转码) + if request.mime_type and request.mime_type.startswith("video"): + raise HTTPException( + status_code=400, + detail="视频素材请使用 ingest-jobs 接口上传,Worker 会自动处理 HEVC 转码和元数据提取" + ) + # 先获取素材库,用于推导 project_id(前端可能不传) library = asset_library_repository.get(request.library_id) if library is None: diff --git a/apps/worker/worker_app/tasks/ingest.py b/apps/worker/worker_app/tasks/ingest.py index a7f06ec89..64bc9ab58 100755 --- a/apps/worker/worker_app/tasks/ingest.py +++ b/apps/worker/worker_app/tasks/ingest.py @@ -1,3 +1,4 @@ +import shutil import subprocess import tempfile from datetime import datetime, timezone @@ -248,6 +249,12 @@ def ingest_asset(job_id: str) -> dict: _tc_tmp = None _needs_rotation = False try: + # 检查磁盘空间(大文件转码需要至少 2GB 可用空间) + _disk_usage = shutil.disk_usage("/tmp") + _free_gb = _disk_usage.free / (1024**3) + if _free_gb < 2: + raise RuntimeError(f"磁盘空间不足 ({_free_gb:.1f}GB < 2GB),无法处理大文件") + # 检测视频是否有 rotation 元数据(竖屏视频) _probe_cmd = [ "ffprobe", @@ -301,7 +308,13 @@ def ingest_asset(job_id: str) -> dict: "-crf", "18", "-vf", - _vf, + _vf + ",format=yuv420p", + "-colorspace", + "bt709", + "-color_primaries", + "bt709", + "-color_trf", + "bt709", "-pix_fmt", "yuv420p", "-level", @@ -326,7 +339,7 @@ def ingest_asset(job_id: str) -> dict: stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, text=True, - timeout=300, + timeout=900, ) if _proc.returncode == 0 and _tc_tmp.exists() and _tc_tmp.stat().st_size > 0: from video_processing.oss_helpers import upload_to_oss