style: auto-format with black + isort + prettier [skip ci-format-check]
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m43s
AI Code Review / AI Code Review (pull_request) Failing after 2m10s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 2m11s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m51s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 34s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 52s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 30s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 59s
CI/CD Pipeline / Validate - Code Quality (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled

This commit is contained in:
CI Bot
2026-08-20 02:54:23 +00:00
parent 773dafe5a8
commit a5bc9a3ea6
2 changed files with 40 additions and 36 deletions
@@ -539,7 +539,9 @@ export function useCanvasPlayer(
try {
await Promise.race([
decoder.flush(),
new Promise((_, reject) => setTimeout(() => reject(new Error("flush timeout 10s")), 10_000)),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("flush timeout 10s")), 10_000),
),
])
console.log(`[useCanvasPlayer] Segment ${meta.assetId}: flush complete`)
} catch (e) {
+37 -35
View File
@@ -237,60 +237,62 @@ def ingest_asset(job_id: str) -> dict:
# ── HEVC 自动转码为 1080p H.264 ──────────────────────────────
# 浏览器 WebCodecs 硬件解码 HEVC 输出黑帧,上传时自动转码
# 失败时降级使用原始文件,不阻塞上传流程
if (
media_type == "video"
and extract_success
and local_file
and local_file.exists()
):
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,
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",
"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",
"-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,
_cmd,
capture_output=True,
text=True,
timeout=300,
)
if (
_proc.returncode == 0
and _tc_tmp.exists()
and _tc_tmp.stat().st_size > 0
):
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)
)
_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,
)
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],
job_id,
_new_key[:80],
)
else:
logger.warning(
@@ -298,12 +300,11 @@ def ingest_asset(job_id: str) -> dict:
job_id,
)
else:
_tail = (
_proc.stderr[-300:] if _proc.stderr else ""
)
_tail = _proc.stderr[-300:] if _proc.stderr else ""
logger.warning(
"FFmpeg 转码失败 rc=%s,降级原始文件: job_id=%s",
_proc.returncode, job_id,
_proc.returncode,
job_id,
)
except subprocess.TimeoutExpired:
logger.warning(
@@ -313,7 +314,8 @@ def ingest_asset(job_id: str) -> dict:
except Exception as _e:
logger.warning(
"HEVC 转码异常(降级原始文件): job_id=%s err=%s",
job_id, _e,
job_id,
_e,
)
finally:
if _tc_tmp and _tc_tmp.exists():