style: auto-format with black + isort + prettier [skip ci-format-check]
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 41s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m37s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 1m40s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m43s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m50s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m57s
AI Code Review / AI Code Review (pull_request) Failing after 2m9s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m23s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m11s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m12s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m18s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 6m33s
CI/CD Pipeline / CI Gate (pull_request) Failing after 5s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 790h8m19s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 790h8m20s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 790h8m21s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 790h8m21s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 790h15m34s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 790h8m21s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 790h15m35s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 790h14m53s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 790h15m37s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 790h14m54s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 790h14m54s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 790h15m33s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 790h15m36s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 790h41m51s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 790h49m4s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 790h49m8s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 41s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m37s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 1m40s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m43s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m50s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m57s
AI Code Review / AI Code Review (pull_request) Failing after 2m9s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m23s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m11s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m12s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m18s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 6m33s
CI/CD Pipeline / CI Gate (pull_request) Failing after 5s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 790h8m19s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 790h8m20s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 790h8m21s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 790h8m21s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 790h15m34s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 790h8m21s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 790h15m35s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 790h14m53s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 790h15m37s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 790h14m54s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 790h14m54s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 790h15m33s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 790h15m36s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 790h41m51s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 790h49m4s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 790h49m8s
This commit is contained in:
@@ -1559,9 +1559,10 @@ def generate_video(self, task_id: str) -> dict:
|
||||
_cover_session = SessionLocal()
|
||||
try:
|
||||
from packages.adapters.sqlalchemy_impl.models import GenerationTaskModel
|
||||
_cover_model = _cover_session.query(GenerationTaskModel).filter(
|
||||
GenerationTaskModel.id == task_id
|
||||
).first()
|
||||
|
||||
_cover_model = (
|
||||
_cover_session.query(GenerationTaskModel).filter(GenerationTaskModel.id == task_id).first()
|
||||
)
|
||||
if _cover_model:
|
||||
_cover_model.cover_url = cover_url
|
||||
_cover_session.commit()
|
||||
|
||||
@@ -207,8 +207,8 @@ def ingest_asset(job_id: str) -> dict:
|
||||
thumbnail_url = None
|
||||
if media_type == "video" and extract_success:
|
||||
try:
|
||||
from video_processing.thumbnail_generator import extract_first_frame
|
||||
from video_processing.oss_helpers import upload_to_oss
|
||||
from video_processing.thumbnail_generator import extract_first_frame
|
||||
|
||||
frame_path = extract_first_frame(str(local_file))
|
||||
thumb_storage_key = f"assets/{job.project_id}/thumbnails/{job_id}.jpg"
|
||||
|
||||
@@ -404,9 +404,7 @@ def _call_ai_cover_service(
|
||||
plan_id,
|
||||
cover_type,
|
||||
)
|
||||
raise RuntimeError(
|
||||
f"封面数据不可用 (plan_id={plan_id})。请重新生成预览视频以触发封面自动提取。"
|
||||
)
|
||||
raise RuntimeError(f"封面数据不可用 (plan_id={plan_id})。请重新生成预览视频以触发封面自动提取。")
|
||||
|
||||
|
||||
def run_generate_cover(
|
||||
|
||||
@@ -25,7 +25,7 @@ class TestExtractFirstFrame(unittest.TestCase):
|
||||
with tempfile.NamedTemporaryFile(suffix=".mp4") as video:
|
||||
Path(video.name).write_bytes(b"fake video")
|
||||
result = extract_first_frame(video.name)
|
||||
|
||||
|
||||
self.assertTrue(Path(result).exists())
|
||||
# 验证 ffmpeg 被调用
|
||||
mock_run.assert_called()
|
||||
@@ -43,7 +43,7 @@ class TestExtractFirstFrame(unittest.TestCase):
|
||||
with tempfile.NamedTemporaryFile(suffix=".mp4") as video:
|
||||
Path(video.name).write_bytes(b"fake video")
|
||||
result = extract_first_frame(video.name, seek_ratio=0.5)
|
||||
|
||||
|
||||
self.assertTrue(Path(result).exists())
|
||||
# 50% of 10s = 5s
|
||||
cmd = mock_run.call_args[0][0]
|
||||
@@ -63,10 +63,10 @@ class TestExtractFirstFrame(unittest.TestCase):
|
||||
Path(video.name).write_bytes(b"fake video")
|
||||
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as out:
|
||||
pass # just get a path
|
||||
|
||||
|
||||
# Create the file so ffmpeg "succeeds"
|
||||
mock_run.side_effect = lambda *a, **k: Path(out.name).write_bytes(b"fake image")
|
||||
|
||||
|
||||
result = extract_first_frame(video.name, output_path=out.name)
|
||||
self.assertEqual(result, out.name)
|
||||
Path(out.name).unlink(missing_ok=True)
|
||||
@@ -80,7 +80,7 @@ class TestExtractFirstFrame(unittest.TestCase):
|
||||
with tempfile.NamedTemporaryFile(suffix=".mp4") as video:
|
||||
Path(video.name).write_bytes(b"fake video")
|
||||
result = extract_first_frame(video.name)
|
||||
|
||||
|
||||
cmd = mock_run.call_args[0][0]
|
||||
vf_idx = cmd.index("-vf") + 1
|
||||
vf_filter = cmd[vf_idx]
|
||||
@@ -98,7 +98,7 @@ class TestExtractFirstFrame(unittest.TestCase):
|
||||
with tempfile.NamedTemporaryFile(suffix=".mp4") as video:
|
||||
Path(video.name).write_bytes(b"fake video")
|
||||
result = extract_first_frame(video.name, width=640)
|
||||
|
||||
|
||||
cmd = mock_run.call_args[0][0]
|
||||
vf_idx = cmd.index("-vf") + 1
|
||||
vf_filter = cmd[vf_idx]
|
||||
@@ -113,7 +113,7 @@ class TestExtractFirstFrame(unittest.TestCase):
|
||||
|
||||
with tempfile.NamedTemporaryFile(suffix=".mp4") as video:
|
||||
Path(video.name).write_bytes(b"fake video")
|
||||
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
extract_first_frame(video.name)
|
||||
|
||||
@@ -124,14 +124,14 @@ class TestRenderAdapterCoverUrl(unittest.TestCase):
|
||||
def test_result_has_cover_url_field(self):
|
||||
"""RenderAdapterResult 包含 cover_url 字段."""
|
||||
from video_processing.render_adapter import RenderAdapterResult
|
||||
|
||||
|
||||
result = RenderAdapterResult(success=True, cover_url="https://example.com/cover.jpg")
|
||||
self.assertEqual(result.cover_url, "https://example.com/cover.jpg")
|
||||
|
||||
def test_result_cover_url_defaults_empty(self):
|
||||
"""cover_url 默认为空字符串."""
|
||||
from video_processing.render_adapter import RenderAdapterResult
|
||||
|
||||
|
||||
result = RenderAdapterResult(success=True)
|
||||
self.assertEqual(result.cover_url, "")
|
||||
|
||||
|
||||
@@ -340,20 +340,20 @@ class TestThumbnailInDedupHelpers:
|
||||
mock_dedup.check_batch_duplicate.return_value = None
|
||||
|
||||
result = create_video_record_and_dedup(
|
||||
generation_task_id="task-thumb-reuse",
|
||||
project_id="proj-1",
|
||||
batch_id="",
|
||||
file_url="https://oss.example.com/video.mp4",
|
||||
file_size=1024,
|
||||
duration=10.0,
|
||||
video_path="/tmp/fake.mp4",
|
||||
mode="edit_plan",
|
||||
session=session,
|
||||
width=1280,
|
||||
height=720,
|
||||
fps=25.0,
|
||||
thumbnail_url=pre_thumb_url,
|
||||
)
|
||||
generation_task_id="task-thumb-reuse",
|
||||
project_id="proj-1",
|
||||
batch_id="",
|
||||
file_url="https://oss.example.com/video.mp4",
|
||||
file_size=1024,
|
||||
duration=10.0,
|
||||
video_path="/tmp/fake.mp4",
|
||||
mode="edit_plan",
|
||||
session=session,
|
||||
width=1280,
|
||||
height=720,
|
||||
fps=25.0,
|
||||
thumbnail_url=pre_thumb_url,
|
||||
)
|
||||
|
||||
assert result == 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user