import subprocess
import sys

import numpy as np

SR = 48_000
WINDOW = SR // 100  # 10 milliseconds
source = sys.argv[1]
threshold_db = float(sys.argv[2]) if len(sys.argv) > 2 else -35.0

decoded = subprocess.run(
    ["ffmpeg", "-v", "error", "-i", source, "-vn", "-ac", "1",
     "-ar", str(SR), "-f", "s16le", "-"],
    capture_output=True,
    check=True,
)
x = np.frombuffer(decoded.stdout, dtype="<i2").astype(np.int32)
if not x.size:
    raise ValueError("No decoded audio samples")

def level_db(samples):
    rms = np.sqrt(np.mean((samples / 32768.0) ** 2))
    return 20 * np.log10(rms + 1e-9)

def loudest(start, end):
    start, end = max(0, start), min(len(x), end)
    return max(
        (level_db(x[i:i + WINDOW])
         for i in range(start, end - WINDOW + 1, WINDOW)),
        default=-200.0,
    )

# Widen to int32 before abs(): abs(-32768) overflows an int16.
near_zero = (np.abs(x) <= 1).astype(np.int8)
edges = np.diff(np.concatenate(([0], near_zero, [0])))
runs = []
for start, end in zip(np.flatnonzero(edges == 1), np.flatnonzero(edges == -1)):
    if end - start < int(0.004 * SR):
        continue
    if runs and start - runs[-1][1] < int(0.006 * SR):
        runs[-1][1] = end
    else:
        runs.append([start, end])

radius = int(0.3 * SR)
for start, end in runs:
    duration_ms = (end - start) * 1000 / SR
    if (15 <= duration_ms <= 500
            and loudest(start - radius, start) > threshold_db
            and loudest(end, end + radius) > threshold_db):
        print(f"candidate at {start / SR:.3f}s: {duration_ms:.0f}ms")
