|
2 | 2 | # SPDX-License-Identifier: MIT |
3 | 3 |
|
4 | 4 |
|
| 5 | +import subprocess |
5 | 6 | from io import BytesIO |
6 | 7 | from pathlib import Path |
7 | 8 | from typing import override |
|
17 | 18 |
|
18 | 19 | from tagstudio.core.enums import Theme |
19 | 20 | from tagstudio.core.media_types import MediaTypes |
| 21 | +from tagstudio.core.utils.ffmpeg_status import FfmpegStatus |
| 22 | +from tagstudio.core.utils.silent_subprocess import silent_run |
| 23 | +from tagstudio.core.utils.types import unwrap |
20 | 24 | from tagstudio.previews.base_preview import RENDER, BasePreview |
21 | 25 | from tagstudio.previews.effects import apply_overlay_color |
22 | | -from tagstudio.previews.vendored.pydub.audio_segment import ( |
23 | | - _AudioSegment as AudioSegment, # pyright: ignore[reportPrivateUsage] |
24 | | -) |
25 | 26 | from tagstudio.qt.views.styles.palette import UiColor |
26 | 27 |
|
27 | 28 | logger = structlog.get_logger(__name__) |
28 | 29 |
|
| 30 | +_WAVEFORM_SAMPLE_RATE = 8000 # Good enough for the waveforms while still being small bits of data |
| 31 | + |
29 | 32 |
|
30 | 33 | class AudioPreview(BasePreview): |
31 | 34 | media_type_name = "audio" |
@@ -120,8 +123,13 @@ def audio_waveform_thumb(filepath: Path, theme: Theme, size: tuple[int, int]) -> |
120 | 123 |
|
121 | 124 | try: |
122 | 125 | bar_count: int = 32 |
123 | | - audio = AudioSegment.from_file(filepath, filepath.suffix.lower()[1:]) # pyright: ignore[reportUnknownVariableType] |
124 | | - data = np.frombuffer(buffer=audio._data, dtype=f"<i{audio.sample_width}") |
| 126 | + command = [unwrap(FfmpegStatus.which()), "-nostdin", "-v", "error", "-i", str(filepath)] |
| 127 | + command += ["-vn", "-ac", "1", "-ar", str(_WAVEFORM_SAMPLE_RATE), "-f", "s16le", "-"] |
| 128 | + ffmpeg = silent_run( |
| 129 | + command, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, close_fds=False |
| 130 | + ) |
| 131 | + ffmpeg.check_returncode() |
| 132 | + data = np.frombuffer(buffer=ffmpeg.stdout, dtype="<i2") |
125 | 133 | # Bars are twice as wide as the gaps between them, with double gaps at the edges |
126 | 134 | bar_margin: float = size_scaled / (bar_count * 3 + 3) |
127 | 135 | line_width: float = bar_margin * 2 |
@@ -162,7 +170,7 @@ def audio_waveform_thumb(filepath: Path, theme: Theme, size: tuple[int, int]) -> |
162 | 170 |
|
163 | 171 | current_x = current_x + line_width + bar_margin |
164 | 172 |
|
165 | | - im.resize(size, Resampling.BILINEAR) |
| 173 | + im = im.resize(size, Resampling.BILINEAR) |
166 | 174 | im = apply_overlay_color(im, UiColor.GREEN, theme) |
167 | 175 |
|
168 | 176 | except Exception as e: |
|
0 commit comments