diff --git a/apps/worker/worker_app/tasks/ingest.py b/apps/worker/worker_app/tasks/ingest.py index 6449b8d0f..3f1f50e6c 100755 --- a/apps/worker/worker_app/tasks/ingest.py +++ b/apps/worker/worker_app/tasks/ingest.py @@ -233,6 +233,94 @@ def ingest_asset(job_id: str) -> dict: job_id, thumb_err, ) + + # ── HEVC 自动转码为 1080p H.264 ────────────────────────────── + # 浏览器 WebCodecs 硬件解码 HEVC 输出黑帧,上传时自动转码 + # 失败时降级使用原始文件,不阻塞上传流程 + if ( + media_type == "video" + and extract_success + and local_file + and local_file.exists() + ): + codec = (metadata.get("codec") or "").lower() + if codec in ("hevc", "h265", "hvh1"): + logger.info( + "检测到 HEVC 编码 (codec=%s),启动转码: job_id=%s", + codec, job_id, + ) + _tc_tmp = None + try: + _tc_tmp = Path(tempfile.mktemp(suffix="_h264.mp4")) + _cmd = [ + "ffmpeg", "-y", + "-i", str(local_file), + "-c:v", "libx264", + "-preset", "fast", + "-crf", "18", + "-vf", + "scale='if(gt(ih,1080),-2,iw)':'if(gt(ih,1080),1080,ih)'", + "-pix_fmt", "yuv420p", + "-c:a", "aac", + "-b:a", "128k", + "-movflags", "+faststart", + str(_tc_tmp), + ] + _proc = subprocess.run( + _cmd, capture_output=True, text=True, timeout=300, + ) + if ( + _proc.returncode == 0 + and _tc_tmp.exists() + and _tc_tmp.stat().st_size > 0 + ): + from video_processing.oss_helpers import upload_to_oss + + _p = Path(job.storage_key) + _new_key = str( + _p.parent / (_p.stem + "_h264" + _p.suffix) + ) + _url = upload_to_oss(_tc_tmp, _new_key) + if _url: + job.storage_key = _new_key + metadata, extract_success = ( + extract_media_metadata( + str(_tc_tmp), media_type, + ) + ) + logger.info( + "HEVC→H.264 转码完成: job_id=%s key=%s", + job_id, _new_key[:80], + ) + else: + logger.warning( + "转码文件上传 OSS 失败,使用原始文件: job_id=%s", + job_id, + ) + else: + _tail = ( + _proc.stderr[-300:] if _proc.stderr else "" + ) + logger.warning( + "FFmpeg 转码失败 rc=%s,降级原始文件: job_id=%s", + _proc.returncode, job_id, + ) + except subprocess.TimeoutExpired: + logger.warning( + "FFmpeg 转码超时 (300s),降级原始文件: job_id=%s", + job_id, + ) + except Exception as _e: + logger.warning( + "HEVC 转码异常(降级原始文件): job_id=%s err=%s", + job_id, _e, + ) + finally: + if _tc_tmp and _tc_tmp.exists(): + try: + _tc_tmp.unlink() + except OSError: + pass finally: if local_file and local_file.exists(): try: