mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-09 18:29:59 +00:00
3b3f992834
Rarely media files may have one or multiple empty streams when they are badly formatted. The extract metadata code would crash when that happened. We now avoid crashing and create a clean file from the bad one to make sure API calls with that data works properly (observed some failures otherwise in my tests).
156 lines
4.7 KiB
Python
156 lines
4.7 KiB
Python
"""Unit tests for the file service."""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
from unittest.mock import Mock
|
|
|
|
import pytest
|
|
|
|
from summary.core import file_service
|
|
from summary.core.file_service import (
|
|
MediaInfo,
|
|
extract_audio_from_media,
|
|
get_media_info,
|
|
)
|
|
|
|
BASE_PATH = Path(__file__).parent.parent / "assets"
|
|
|
|
MEDIA_INFO_SAMPLE_VISIO = MediaInfo(
|
|
path=BASE_PATH / "video-sample-visio.mp4",
|
|
has_audio=True,
|
|
has_video=True,
|
|
audio_duration_seconds=5.34059,
|
|
audio_codec_name="aac",
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"media_info",
|
|
[
|
|
MediaInfo(
|
|
path=BASE_PATH / "audio-sample-android-chrome.webm",
|
|
has_audio=True,
|
|
has_video=False,
|
|
audio_duration_seconds=2.2795,
|
|
audio_codec_name="opus",
|
|
),
|
|
MediaInfo(
|
|
path=BASE_PATH / "audio-sample-android-firefox.ogg",
|
|
has_audio=True,
|
|
has_video=False,
|
|
audio_duration_seconds=2.3025,
|
|
audio_codec_name="opus",
|
|
),
|
|
MediaInfo(
|
|
path=BASE_PATH / "audio-sample-android.m4a",
|
|
has_audio=True,
|
|
has_video=False,
|
|
audio_duration_seconds=1.38,
|
|
audio_codec_name="aac",
|
|
),
|
|
MediaInfo(
|
|
path=BASE_PATH / "audio-sample-chromium.webm",
|
|
has_audio=True,
|
|
has_video=False,
|
|
audio_duration_seconds=2.65,
|
|
audio_codec_name="opus",
|
|
),
|
|
MediaInfo(
|
|
path=BASE_PATH / "audio-sample-firefox.ogg",
|
|
has_audio=True,
|
|
has_video=False,
|
|
audio_duration_seconds=2.0865,
|
|
audio_codec_name="opus",
|
|
),
|
|
MediaInfo(
|
|
path=BASE_PATH / "audio-sample-ios-browser.webm",
|
|
has_audio=True,
|
|
has_video=False,
|
|
audio_duration_seconds=2.6229,
|
|
audio_codec_name="opus",
|
|
),
|
|
MediaInfo(
|
|
path=BASE_PATH / "audio-sample-ios.m4a",
|
|
has_audio=True,
|
|
has_video=False,
|
|
audio_duration_seconds=1.408,
|
|
audio_codec_name="aac",
|
|
),
|
|
MediaInfo(
|
|
path=BASE_PATH / "audio-sample-mac-os-safari.webm",
|
|
has_audio=True,
|
|
has_video=False,
|
|
audio_duration_seconds=2.3049,
|
|
audio_codec_name="opus",
|
|
),
|
|
MEDIA_INFO_SAMPLE_VISIO,
|
|
],
|
|
)
|
|
def test_validate_media_info_supports_all_used_file_formats(
|
|
media_info: MediaInfo,
|
|
) -> None:
|
|
"""Validate media_info for different files that the service can handle."""
|
|
res = get_media_info(media_info.path)
|
|
assert res.has_audio == media_info.has_audio
|
|
assert res.has_video == media_info.has_video
|
|
assert res.audio_codec_name == media_info.audio_codec_name
|
|
if res.has_audio:
|
|
assert res.audio_duration_seconds == pytest.approx(
|
|
media_info.audio_duration_seconds, 1e-3
|
|
)
|
|
else:
|
|
assert res.audio_duration_seconds is None
|
|
|
|
|
|
def test_media_info_invalid_file() -> None:
|
|
"""Test that media_info returns correct values for invalid files."""
|
|
assert get_media_info(Path(__file__)) == MediaInfo(
|
|
path=Path(__file__),
|
|
has_audio=False,
|
|
has_video=False,
|
|
audio_duration_seconds=None,
|
|
audio_codec_name=None,
|
|
)
|
|
|
|
|
|
def test_media_info_ignores_empty_stream_entry(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
"""Test stream parsing when ffprobe returns an empty stream object."""
|
|
ffprobe_payload = {
|
|
"programs": [],
|
|
"stream_groups": [],
|
|
"streams": [
|
|
{"codec_name": "vorbis", "codec_type": "audio"},
|
|
{},
|
|
],
|
|
}
|
|
|
|
run_mock = Mock(
|
|
return_value=Mock(stdout=json.dumps(ffprobe_payload), stderr="", returncode=0)
|
|
)
|
|
monkeypatch.setattr(file_service.subprocess, "run", run_mock)
|
|
monkeypatch.setattr(
|
|
file_service, "get_media_duration_seconds", Mock(return_value=2.5)
|
|
)
|
|
|
|
media_info = get_media_info(BASE_PATH / "audio-sample-android-firefox.ogg")
|
|
|
|
assert media_info.has_audio is True
|
|
assert media_info.has_video is False
|
|
assert media_info.has_bad_stream is True
|
|
assert media_info.audio_codec_name == "vorbis"
|
|
assert media_info.audio_duration_seconds == 2.5
|
|
|
|
|
|
def test_extract_audio_from_video():
|
|
"""Test that extract_audio_from_video can extract audio from a video file."""
|
|
path = None
|
|
# A bit of cleanup logic since this is not a generator
|
|
try:
|
|
path = extract_audio_from_media(MEDIA_INFO_SAMPLE_VISIO)
|
|
assert path.name.endswith(".m4a")
|
|
except Exception as e:
|
|
pytest.fail(f"Failed to extract audio from video: {e}")
|
|
finally:
|
|
if path and path.exists():
|
|
path.unlink()
|