Files
Kyoo/transcoder/tests/hls_validation/conftest.py
T
2026-04-30 02:03:47 +02:00

134 lines
3.7 KiB
Python

from __future__ import annotations
import os
import shutil
import uuid
from dataclasses import dataclass
import pytest
from .hls_utils import (
ByteCache,
build_master_url,
fetch_text,
parse_master_playlist,
parse_media_playlist,
)
@dataclass(frozen=True)
class TestConfig:
base_url: str
media_path: str
client_prefix: str
max_segments: int
max_variant_playlists: int
max_audio_playlists: int
timeout_seconds: float
headers: dict[str, str]
@pytest.fixture(scope="session")
def test_config() -> TestConfig:
media_path = os.getenv("TRANSCODER_MEDIA_PATH", "").strip()
if not media_path:
raise pytest.UsageError(
"TRANSCODER_MEDIA_PATH is required (absolute path as seen by transcoder)"
)
api_key = os.getenv("TRANSCODER_API_KEY", "").strip()
headers: dict[str, str] = {}
if api_key:
headers["X-Api-Key"] = api_key
return TestConfig(
base_url=os.getenv(
"TRANSCODER_BASE_URL", "http://localhost:7666/video"
).strip(),
media_path=media_path,
client_prefix=os.getenv("TRANSCODER_CLIENT_ID_PREFIX", "hls-test").strip(),
max_segments=max(3, int(os.getenv("TRANSCODER_MAX_SEGMENTS", "14"))),
max_variant_playlists=max(
1, int(os.getenv("TRANSCODER_MAX_VARIANT_PLAYLISTS", "3"))
),
max_audio_playlists=max(
0, int(os.getenv("TRANSCODER_MAX_AUDIO_PLAYLISTS", "2"))
),
timeout_seconds=float(os.getenv("TRANSCODER_TIMEOUT_SECONDS", "40")),
headers=headers,
)
@pytest.fixture(scope="session", autouse=True)
def ensure_ffprobe_available() -> None:
if shutil.which("ffprobe") is None:
raise pytest.UsageError("ffprobe is required in PATH")
@pytest.fixture(scope="session")
def byte_cache() -> ByteCache:
return ByteCache()
@pytest.fixture
def client_id(test_config: TestConfig) -> str:
return f"{test_config.client_prefix}-{uuid.uuid4().hex[:12]}"
@pytest.fixture
def master_context(test_config: TestConfig, client_id: str) -> dict:
master_url = build_master_url(
test_config.base_url, test_config.media_path, client_id
)
master_text = fetch_text(
master_url,
timeout_seconds=test_config.timeout_seconds,
headers=test_config.headers,
)
variants, audios = parse_master_playlist(
master_text, master_url=master_url, client_id=client_id
)
if not variants:
raise AssertionError(f"No variants discovered in master playlist: {master_url}")
dedup_variants = list({v.url: v for v in variants}.values())
dedup_audios = list({a.url: a for a in audios}.values())
return {
"master_url": master_url,
"variants": dedup_variants,
"audios": dedup_audios,
"client_id": client_id,
}
@pytest.fixture
def media_playlists(master_context: dict, test_config: TestConfig) -> dict:
variant_playlists = []
for variant in master_context["variants"][: test_config.max_variant_playlists]:
text = fetch_text(
variant.url,
timeout_seconds=test_config.timeout_seconds,
headers=test_config.headers,
)
variant_playlists.append(
parse_media_playlist(text, variant.url, master_context["client_id"])
)
audio_playlists = []
for audio in master_context["audios"][: test_config.max_audio_playlists]:
text = fetch_text(
audio.url,
timeout_seconds=test_config.timeout_seconds,
headers=test_config.headers,
)
audio_playlists.append(
parse_media_playlist(text, audio.url, master_context["client_id"])
)
return {
"variants": variant_playlists,
"audios": audio_playlists,
}