PlanOpticon

planopticon / tests / test_audio_extractor.py
Blame History Raw 115 lines
1
"""Tests for the audio extractor module."""
2
3
import tempfile
4
from pathlib import Path
5
from unittest.mock import MagicMock, patch
6
7
import numpy as np
8
9
from video_processor.extractors.audio_extractor import AudioExtractor
10
11
12
class TestAudioExtractor:
13
"""Test suite for AudioExtractor class."""
14
15
def test_init(self):
16
"""Test initialization of AudioExtractor."""
17
# Default parameters
18
extractor = AudioExtractor()
19
assert extractor.sample_rate == 16000
20
assert extractor.mono is True
21
22
# Custom parameters
23
extractor = AudioExtractor(sample_rate=44100, mono=False)
24
assert extractor.sample_rate == 44100
25
assert extractor.mono is False
26
27
@patch("subprocess.run")
28
def test_extract_audio(self, mock_run):
29
"""Test audio extraction from video."""
30
# Mock the subprocess.run call
31
mock_result = MagicMock()
32
mock_result.returncode = 0
33
mock_run.return_value = mock_result
34
35
with tempfile.TemporaryDirectory() as temp_dir:
36
# Create a dummy video file
37
video_path = Path(temp_dir) / "test_video.mp4"
38
with open(video_path, "wb") as f:
39
f.write(b"dummy video content")
40
41
# Extract audio
42
extractor = AudioExtractor()
43
44
# Test with default output path
45
output_path = extractor.extract_audio(video_path)
46
assert output_path == video_path.with_suffix(".wav")
47
48
# Test with custom output path
49
custom_output = Path(temp_dir) / "custom_audio.wav"
50
output_path = extractor.extract_audio(video_path, custom_output)
51
assert output_path == custom_output
52
53
# Verify subprocess.run was called with correct arguments
54
mock_run.assert_called()
55
args, kwargs = mock_run.call_args
56
assert "ffmpeg" in args[0]
57
assert "-i" in args[0]
58
assert str(video_path) in args[0]
59
60
@patch("soundfile.info")
61
def test_get_audio_properties(self, mock_sf_info):
62
"""Test getting audio properties."""
63
# Mock soundfile.info
64
mock_info = MagicMock()
65
mock_info.duration = 10.5
66
mock_info.samplerate = 16000
67
mock_info.channels = 1
68
mock_info.format = "WAV"
69
mock_info.subtype = "PCM_16"
70
mock_sf_info.return_value = mock_info
71
72
with tempfile.TemporaryDirectory() as temp_dir:
73
# Create a dummy audio file
74
audio_path = Path(temp_dir) / "test_audio.wav"
75
with open(audio_path, "wb") as f:
76
f.write(b"dummy audio content")
77
78
# Get properties
79
extractor = AudioExtractor()
80
props = extractor.get_audio_properties(audio_path)
81
82
# Verify properties
83
assert props["duration"] == 10.5
84
assert props["sample_rate"] == 16000
85
assert props["channels"] == 1
86
assert props["format"] == "WAV"
87
assert props["subtype"] == "PCM_16"
88
assert props["path"] == str(audio_path)
89
90
def test_segment_audio(self):
91
"""Test audio segmentation."""
92
# Create a dummy audio array (1 second at 16kHz)
93
audio_data = np.ones(16000)
94
sample_rate = 16000
95
96
extractor = AudioExtractor()
97
98
# Test with 500ms segments, no overlap
99
segments = extractor.segment_audio(
100
audio_data, sample_rate, segment_length_ms=500, overlap_ms=0
101
)
102
103
# Should produce 2 segments of 8000 samples each
104
assert len(segments) == 2
105
assert len(segments[0]) == 8000
106
assert len(segments[1]) == 8000
107
108
# Test with 600ms segments, 100ms overlap
109
segments = extractor.segment_audio(
110
audio_data, sample_rate, segment_length_ms=600, overlap_ms=100
111
)
112
113
# Should produce 2 segments (with overlap)
114
assert len(segments) == 2
115

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button