fix(music-lab): xfade offset 누적 오차 수정 + 테스트 보강
- _build_slideshow_cmd: offset 공식을 `duration_per_image * i - xd * i`로 수정 (누적 전환 오차 제거) - _generate_metadata: genre 빈 문자열일 때 yt_tags에 빈 문자열 삽입 방지 - test: VIDEO_DATA_DIR 패치를 monkeypatch로 교체 (자동 복원 보장) - test: xfade offset 값 검증 테스트 추가 (29.00, 58.00) - test: 미사용 import 제거 (pytest, sqlite3) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -84,7 +84,7 @@ def _build_slideshow_cmd(
|
||||
filter_str = ";".join(filter_parts)
|
||||
prev = "v0"
|
||||
for i in range(1, n):
|
||||
offset = max(0.0, duration_per_image * i - xd)
|
||||
offset = max(0.0, duration_per_image * i - xd * i)
|
||||
nxt = "out" if i == n - 1 else f"xf{i}"
|
||||
filter_str += (
|
||||
f";[{prev}][v{i}]xfade=transition=fade:"
|
||||
@@ -159,7 +159,7 @@ def _generate_metadata(genre: str, moods: list, lyrics: str, target_countries: l
|
||||
start, end = text.find("{"), text.rfind("}") + 1
|
||||
return json.loads(text[start:end])
|
||||
except Exception:
|
||||
return {"yt_title": f"{genre or 'Music'} - Chill Beats", "yt_description": "", "yt_tags": [genre]}
|
||||
return {"yt_title": f"{genre or 'Music'} - Chill Beats", "yt_description": "", "yt_tags": [genre] if genre else []}
|
||||
|
||||
|
||||
def _render_visualizer(track: dict, proj: dict, output_path: str) -> None:
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# music-lab/tests/test_video_producer.py
|
||||
import os
|
||||
from unittest.mock import patch, MagicMock
|
||||
import pytest
|
||||
|
||||
|
||||
def test_build_visualizer_cmd():
|
||||
@@ -59,10 +58,9 @@ def test_build_slideshow_cmd_multiple_images():
|
||||
assert "/tmp/out.mp4" in cmd
|
||||
|
||||
|
||||
def test_produce_video_visualizer_calls_ffmpeg(tmp_db, tmp_path):
|
||||
def test_produce_video_visualizer_calls_ffmpeg(tmp_db, tmp_path, monkeypatch):
|
||||
"""produce_video가 visualizer 포맷으로 FFmpeg를 호출하는지 확인."""
|
||||
from app.db import init_db, create_video_project
|
||||
import sqlite3
|
||||
|
||||
init_db()
|
||||
|
||||
@@ -82,7 +80,7 @@ def test_produce_video_visualizer_calls_ffmpeg(tmp_db, tmp_path):
|
||||
create_video_project({"track_id": 1, "format": "visualizer", "target_countries": ["BR"]})
|
||||
|
||||
import app.video_producer as vp
|
||||
vp.VIDEO_DATA_DIR = str(tmp_path / "videos")
|
||||
monkeypatch.setattr("app.video_producer.VIDEO_DATA_DIR", str(tmp_path / "videos"))
|
||||
|
||||
with patch("app.video_producer.subprocess.run") as mock_run, \
|
||||
patch("app.video_producer._generate_metadata", return_value={
|
||||
@@ -96,3 +94,18 @@ def test_produce_video_visualizer_calls_ffmpeg(tmp_db, tmp_path):
|
||||
proj = get_video_project(1)
|
||||
assert proj["status"] == "done"
|
||||
assert mock_run.called
|
||||
|
||||
|
||||
def test_build_slideshow_cmd_offset_calculation():
|
||||
from app.video_producer import _build_slideshow_cmd
|
||||
imgs = ["/tmp/img0.jpg", "/tmp/img1.jpg", "/tmp/img2.jpg"]
|
||||
cmd = _build_slideshow_cmd(imgs, "/tmp/audio.mp3", "/tmp/out.mp4", duration_per_image=30.0)
|
||||
# filter_complex 문자열 추출
|
||||
fc_idx = cmd.index("-filter_complex")
|
||||
fc = cmd[fc_idx + 1]
|
||||
# xfade이 2번 등장해야 함 (이미지 3개 → 전환 2번)
|
||||
assert fc.count("xfade") == 2
|
||||
# 첫 번째 xfade offset: 30*1 - 1*1 = 29.0
|
||||
assert "offset=29.00" in fc
|
||||
# 두 번째 xfade offset: 30*2 - 1*2 = 58.0
|
||||
assert "offset=58.00" in fc
|
||||
|
||||
Reference in New Issue
Block a user