fix(P0): unified横屏pad取整+错误日志增强+legacy导入+素材created_at #522
Executable → Regular
+1
@@ -71,6 +71,7 @@ def _to_asset_response(item, storage_service=None) -> AssetResponse:
|
||||
status=item.status.value,
|
||||
classification_status=item.classification_status.value,
|
||||
quality_score=item.quality_score,
|
||||
created_at=item.created_at.isoformat() if item.created_at else None,
|
||||
uploaded_by_user_id=item.uploaded_by_user_id,
|
||||
tag_ids=getattr(item, "tag_ids", []),
|
||||
)
|
||||
|
||||
@@ -50,6 +50,7 @@ class AssetResponse(BaseModel):
|
||||
status: str
|
||||
classification_status: str
|
||||
quality_score: float | None = None
|
||||
created_at: str
|
||||
uploaded_by_user_id: str
|
||||
tag_ids: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
@@ -258,12 +258,12 @@ class RenderAdapter:
|
||||
plan_id,
|
||||
job_id,
|
||||
exc.returncode,
|
||||
stderr_text[:3000],
|
||||
stderr_text[-2000:] if len(stderr_text) > 2000 else stderr_text,
|
||||
)
|
||||
return RenderAdapterResult(
|
||||
success=False,
|
||||
error_message=f"FFmpeg渲染失败(exit={exc.returncode}): {stderr_text[:200]}",
|
||||
error_detail=stderr_text[:3000],
|
||||
error_detail=stderr_text[-2000:] if len(stderr_text) > 2000 else stderr_text,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.exception(
|
||||
|
||||
@@ -1008,7 +1008,7 @@ class UnifiedRenderService:
|
||||
else:
|
||||
# main / broll: 等比缩放 + 居中留黑边(保持原始比例,不裁剪内容)
|
||||
filters.append(f"scale={self.output_width}:{self.output_height}" ":force_original_aspect_ratio=decrease")
|
||||
filters.append(f"pad={self.output_width}:{self.output_height}:(ow-iw)/2:(oh-ih)/2:black")
|
||||
filters.append(f"pad={self.output_width}:{self.output_height}:trunc((ow-iw)/2):trunc((oh-ih)/2):black")
|
||||
|
||||
# 调色滤镜
|
||||
color_grade = ColorGradeConfig.from_dict(clip.config.get("color_grade"))
|
||||
@@ -1112,12 +1112,15 @@ class UnifiedRenderService:
|
||||
try:
|
||||
run_ffmpeg(command)
|
||||
except subprocess.CalledProcessError as e:
|
||||
stderr_text = (e.stderr or "").strip()
|
||||
stderr_tail = stderr_text[-1500:] if len(stderr_text) > 1500 else stderr_text
|
||||
logger.error(
|
||||
"直通渲染失败: plan_id=%s clip=%s exit_code=%d\nvf=%s",
|
||||
"直通渲染失败: plan_id=%s clip=%s exit_code=%d\nvf=%s\nstderr(last 1500):\n%s",
|
||||
self.plan.id,
|
||||
clip.clip_id,
|
||||
e.returncode,
|
||||
vf_str[:2000],
|
||||
stderr_tail,
|
||||
)
|
||||
raise
|
||||
|
||||
@@ -1342,7 +1345,7 @@ class UnifiedRenderService:
|
||||
filters.append(
|
||||
f"scale={self.output_width}:{self.output_height}" ":force_original_aspect_ratio=decrease"
|
||||
)
|
||||
filters.append(f"pad={self.output_width}:{self.output_height}:(ow-iw)/2:(oh-ih)/2:black")
|
||||
filters.append(f"pad={self.output_width}:{self.output_height}:trunc((ow-iw)/2):trunc((oh-ih)/2):black")
|
||||
|
||||
# 调色滤镜(每个 clip 独立的 color grade 配置)
|
||||
color_grade = ColorGradeConfig.from_dict(clip.config.get("color_grade"))
|
||||
@@ -1576,12 +1579,15 @@ class UnifiedRenderService:
|
||||
try:
|
||||
run_ffmpeg(command)
|
||||
except subprocess.CalledProcessError as e:
|
||||
# 额外记录 filter_complex,方便排查滤镜链构建问题
|
||||
# 额外记录 filter_complex + stderr,方便排查滤镜链构建问题
|
||||
stderr_text = (e.stderr or "").strip()
|
||||
stderr_tail = stderr_text[-1500:] if len(stderr_text) > 1500 else stderr_text
|
||||
logger.error(
|
||||
"渲染失败: plan_id=%s exit_code=%d\nfilter_complex:\n%s",
|
||||
"渲染失败: plan_id=%s exit_code=%d\nfilter_complex:\n%s\nstderr(last 1500):\n%s",
|
||||
self.plan.id,
|
||||
e.returncode,
|
||||
filter_complex[:5000],
|
||||
stderr_tail,
|
||||
)
|
||||
raise
|
||||
|
||||
|
||||
@@ -1801,7 +1801,7 @@ class TestConcatNormalizeVideoResolution:
|
||||
# 必须用 pad(留黑边),不能用 crop(裁剪)
|
||||
assert "force_original_aspect_ratio=decrease" in fc, "main 层应使用 decrease 模式(等比缩放到画布内)"
|
||||
assert "pad=" in fc, "main 层应有 pad 滤镜(留黑边到目标分辨率)"
|
||||
assert "(ow-iw)/2:(oh-ih)/2:black" in fc, "pad 应该居中+黑边"
|
||||
assert "trunc((ow-iw)/2):trunc((oh-ih)/2):black" in fc, "pad 应该居中取整+黑边"
|
||||
# 注意:background 层也用 crop,但 main/broll 应该用 pad
|
||||
# 检查第一个 [0:v] 处理链(第一个 clip 是 main)
|
||||
first_v_chain = fc.split("[v0]")[0]
|
||||
|
||||
Reference in New Issue
Block a user