from __future__ import annotations import asyncio import uuid from types import SimpleNamespace from cpv3.infrastructure.storage.types import FileInfo from cpv3.modules.media import service as media_service from cpv3.modules.tasks import service as task_service def test_extract_ffmpeg_out_time_ms_prefers_out_time_us() -> None: assert media_service._extract_ffmpeg_out_time_ms( { "out_time_us": "2500000", "out_time_ms": "1000000", } ) == 2500.0 def test_extract_ffmpeg_out_time_ms_supports_legacy_out_time_ms_field() -> None: assert media_service._extract_ffmpeg_out_time_ms( { "out_time_ms": "1250000", } ) == 1250.0 def test_extract_ffmpeg_out_time_ms_returns_none_for_invalid_values() -> None: assert media_service._extract_ffmpeg_out_time_ms( { "out_time_us": "N/A", } ) is None def test_media_convert_actor_emits_precise_progress_updates(monkeypatch) -> None: sent_events: list[task_service.TaskWebhookEvent] = [] async def fake_convert_to_mp4( _storage: object, *, file_key: str, out_folder: str, on_progress, ) -> FileInfo: assert file_key == "uploads/source.mov" assert out_folder == "projects/1" on_progress("converting", 0.0) on_progress("converting", 50.0) on_progress("uploading", None) return FileInfo( file_path="projects/1/converted/output.mp4", file_url="https://example.com/output.mp4", file_size=1234, filename="output.mp4", ) monkeypatch.setattr(media_service, "convert_to_mp4", fake_convert_to_mp4) monkeypatch.setattr(task_service, "_run_async", asyncio.run) monkeypatch.setattr(task_service, "_raise_if_job_cancelled", lambda _job_id: None) monkeypatch.setattr(task_service, "_get_storage_service", lambda: object()) monkeypatch.setattr(task_service, "PROGRESS_CONVERT_THROTTLE_SECONDS", 0.0) monkeypatch.setattr( task_service, "_send_webhook_event", lambda _url, event: sent_events.append(event), ) task_service.media_convert_actor.fn( job_id=str(uuid.uuid4()), webhook_url="http://backend.test/api/tasks/webhook/job-1/", file_key="uploads/source.mov", out_folder="projects/1", output_format="mp4", ) progress_events = [ (event.progress_pct, event.current_message) for event in sent_events if event.progress_pct is not None ] assert progress_events == [ (5.0, "Подготовка файла"), (10.0, "Конвертация видео"), (52.5, "Конвертация видео"), (95.0, "Загрузка результата"), (99.0, "Сохранение результата"), (100.0, "Завершено"), ]