throw
This commit is contained in:
1 parent
d5ef56c3ed
commit
9fbd222b23
2 files changed
+14
-10
No files matched your search
+6
-4
@@ -20,10 +20,12 @@ is an `if TYPE_CHECKING:` block to break a circular type-only reference.
|
||||
|
||||
"Don't swallow into None" is a general principle at every level, including call
|
||||
sites. An operation that fails must **let the exception propagate** — never catch
|
||||
it and return `None` / an empty / degraded result. BPM/beat analysis is integral:
|
||||
`_mixxx_analyze` raises rather than returning None, and every `Analysis.analyze`
|
||||
call site (in `anlz.py`, `cli.py`, `collection/core.py`) lets failures abort the
|
||||
run (including not catching around `ThreadPoolExecutor` `fut.result()`).
|
||||
it and return `None` / an empty / degraded result. BPM/beat analysis and waveform
|
||||
extraction are integral: `_mixxx_analyze` raises rather than returning None,
|
||||
`_decode_pcm` raises (`RuntimeError`) if ffmpeg is missing or fails to decode
|
||||
rather than returning an empty array, and every `Analysis.analyze` call site (in
|
||||
`anlz.py`, `cli.py`, `collection/core.py`) lets failures abort the run (including
|
||||
not catching around `ThreadPoolExecutor` `fut.result()`).
|
||||
|
||||
Reserve `None` returns for *legitimate absence* (e.g. a cache miss in
|
||||
`Analysis.load`), never for *failure*. The one tolerated catch is a genuinely
|
||||
|
||||
@@ -123,11 +123,12 @@ def _project_pqtz(beatgrid: list[float], bpm: float) -> list[Beat]:
|
||||
def _decode_pcm(path: Path) -> np.ndarray:
|
||||
"""Decode `path` to a 1D float32 numpy array of mono PCM at SAMPLE_RATE.
|
||||
|
||||
Returns an empty array on ffmpeg failure.
|
||||
Raises `RuntimeError` if ffmpeg is missing or fails to decode — waveform
|
||||
extraction is integral, so a failure here is fatal rather than swallowed
|
||||
into an empty array (which would yield a waveform-less ANLZ).
|
||||
"""
|
||||
if not shutil.which("ffmpeg"):
|
||||
logger.warning("ffmpeg not on PATH; cannot extract waveform")
|
||||
return np.empty(0, dtype=np.float32)
|
||||
raise RuntimeError("ffmpeg not on PATH; cannot extract waveform")
|
||||
proc = subprocess.run(
|
||||
["ffmpeg", "-nostdin", "-v", "error",
|
||||
"-i", str(path),
|
||||
@@ -135,9 +136,10 @@ def _decode_pcm(path: Path) -> np.ndarray:
|
||||
capture_output=True,
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
logger.warning("ffmpeg failed for {}: {}", path.name,
|
||||
proc.stderr.decode("utf-8", "replace").strip())
|
||||
return np.empty(0, dtype=np.float32)
|
||||
raise RuntimeError(
|
||||
f"ffmpeg failed for {path.name}: "
|
||||
f"{proc.stderr.decode('utf-8', 'replace').strip()}"
|
||||
)
|
||||
return np.frombuffer(proc.stdout, dtype=np.float32)
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user