# music-lab/tests/test_video_producer.py import os from unittest.mock import patch, MagicMock def test_build_visualizer_cmd(): from app.video_producer import _build_visualizer_cmd cmd = _build_visualizer_cmd( audio_path="/data/music/test.mp3", bg_path="/tmp/bg.jpg", output_path="/data/videos/1/output.mp4", ) assert cmd[0] == "ffmpeg" assert "/data/music/test.mp3" in cmd assert "/data/videos/1/output.mp4" in cmd assert any("showwaves" in str(c) for c in cmd) def test_make_gradient_bg_uses_pillow(tmp_path): from app.video_producer import _make_gradient_bg out = str(tmp_path / "bg.jpg") _make_gradient_bg(1920, 1080, "lo-fi", out) assert os.path.exists(out) assert os.path.getsize(out) > 0 def test_extract_thumbnail_cmd(): from app.video_producer import _build_thumbnail_cmd cmd = _build_thumbnail_cmd("/data/videos/1/output.mp4", "/data/videos/1/thumbnail.jpg") assert cmd[0] == "ffmpeg" assert "00:00:05" in cmd assert "/data/videos/1/thumbnail.jpg" in cmd def test_build_slideshow_cmd_single_image(): from app.video_producer import _build_slideshow_cmd cmd = _build_slideshow_cmd( image_paths=["/tmp/img0.jpg"], audio_path="/tmp/audio.mp3", output_path="/tmp/out.mp4", duration_per_image=30.0, ) assert "ffmpeg" in cmd[0] assert "/tmp/out.mp4" in cmd assert any("copy" in str(c) for c in cmd) def test_build_slideshow_cmd_multiple_images(): from app.video_producer import _build_slideshow_cmd cmd = _build_slideshow_cmd( image_paths=["/tmp/img0.jpg", "/tmp/img1.jpg", "/tmp/img2.jpg"], audio_path="/tmp/audio.mp3", output_path="/tmp/out.mp4", duration_per_image=60.0, ) assert "ffmpeg" in cmd[0] assert any("xfade" in str(c) for c in cmd) assert "/tmp/out.mp4" in cmd 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 init_db() # music_library에 직접 트랙 삽입 import app.db as db_mod with db_mod._conn() as conn: conn.execute( """INSERT INTO music_library (title, genre, audio_url, file_path, provider) VALUES (?, ?, ?, ?, ?)""", ("Test Track", "lo-fi", "/media/music/test.mp3", str(tmp_path / "test.mp3"), "suno"), ) # 빈 mp3 파일 생성 (tmp_path / "test.mp3").write_bytes(b"\x00" * 100) create_video_project({"track_id": 1, "format": "visualizer", "target_countries": ["BR"]}) import app.video_producer as vp 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={ "yt_title": "Chill Beats", "yt_description": "desc", "yt_tags": ["lofi"] }), \ patch("app.video_producer._download_url", return_value=False): mock_run.return_value = MagicMock(returncode=0) vp.produce_video(1) from app.db import get_video_project 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