/docs · SignalLab · Practical
Détection du clipping en streaming à grande échelle
Comment détecter le clipping dans l’audio dès l’ingestion, sans décoder le fichier entier.
Si vous exploitez une plateforme audio (diffusion, archivage, transcription), vous ingérez beaucoup de fichiers. Beaucoup d’entre eux clippent. La plupart des outils de QA en amont soit ne le détectent pas, soit ne le détectent qu’au décodage complet, ce qui signifie que vous gaspillez du calcul sur chaque fichier défectueux avant même de savoir qu’il l’est.
Il existe une approche plus simple : détecter le clipping pendant le décodage, en mode streaming. Voici le schéma qui fonctionne.
L’approche naïve (et pourquoi elle est lente)
samples = decode(audio_file)
clipping_count = sum(1 for s in samples if abs(s) > 0.99)
Cela nécessite de décoder entièrement le fichier en mémoire. Pour un podcast de plusieurs heures, c’est un coût non négligeable, et vous ne savez si le fichier clippe qu’après avoir fait le travail.
Détection en streaming
La version streaming traite les blocs au fur et à mesure qu’ils sortent du décodeur :
def stream_clipping_check(decoder, threshold=0.99, run_length=3):
"""
Decode in blocks and stop early if hopeless.
Returns (total_clips, regions) or raises if catastrophic.
"""
total = 0
regions = []
current_run = 0
current_region_start = None
sample_index = 0
for block in decoder.blocks(): # generator yielding numpy arrays
for v in block:
if abs(v) > threshold:
if current_run == 0:
current_region_start = sample_index
current_run += 1
if current_run == run_length:
total += 1
else:
if current_run >= run_length:
regions.append((current_region_start, sample_index))
current_run = 0
current_region_start = None
sample_index += 1
# Early-exit if catastrophic
if total > 1000:
raise CatastrophicClippingError(f"{total} clip events, abandoning analysis")
return total, regions
Deux choses à remarquer :
- Filtrage par run-length : un seul échantillon à -0.99 n’est pas du clipping, c’est un pic. Le vrai clipping se manifeste par plusieurs échantillons consécutifs collés au plafond. Exiger
run_length=3(trois échantillons consécutifs au-dessus du seuil) élimine 90 % des faux positifs. - Early-exit : si vous trouvez plus de quelques centaines d’événements de clipping, le fichier est inutilisable. Abandonnez et passez le reste. Le système en aval peut le signaler et continuer.
Ce que signifie réellement le « clipping »
Au sens strict, le clipping survient lorsque le signal analogique a dépassé ce que l’ADC pouvait représenter et a été tronqué au plafond. En pratique, dans le domaine numérique :
- Hard clipping : des échantillons consécutifs à exactement ±1.0 (en float) ou au maximum entier.
- Soft clipping : des échantillons consécutifs au-dessus de ~0.95 avec une faible pente. Généralement un artefact d’un compresseur ou d’un limiteur à la source.
- Intersample clipping : des pics qui dépassent 0 dBFS entre les échantillons après reconstruction. Invisibles dans une mesure dans le domaine échantillon ; nécessitent du suréchantillonnage pour être détectés.
Un détecteur robuste gère les trois. Pour la QA à l’ingestion, les deux premiers sont essentiels. Le troisième est un cas « à traiter comme un avertissement, pas comme une erreur ».
Les seuils qui fonctionnent
Après avoir exécuté ceci sur quelques centaines de milliers de fichiers en production :
- Seuil
0.99: correspond au « vrai » clipping en 16 bits et 24 bits sans faux positifs dus à la marge du float. run_length=3: capture le clipping réel aux fréquences d’échantillonnage courantes (44.1k/48k) sans manquer d’événements réels.total > 1000: un seuil de catastrophe pour un fichier court typique (moins de 30 minutes). À augmenter pour les fichiers plus longs.- Region merging : les zones situées à moins de ~50 échantillons (~1 ms à 48k) doivent être fusionnées en un seul événement. Sinon, un clip prolongé est rapporté comme des centaines de micro-événements.
Pourquoi c’est important
Une vérification du clipping en streaming vous coûte quelques cycles CPU par échantillon, s’exécute en parfaite synchronisation avec le décodage et vous permet de rejeter les fichiers défectueux avant qu’un outil en aval ne les touche. À l’échelle d’une archive audio, c’est la différence entre un coût d’infrastructure notable et un coût qui passe inaperçu.
C’est aussi un bon rappel que « faire l’analyse » et « faire la partie peu coûteuse de l’analyse » sont des choix différents. Beaucoup de problèmes de QA audio ont une forme peu coûteuse et compatible avec le streaming.
Sur le même sujet
More in SignalLab docs
- Intro
Un schéma de tags utile pour les archives audio
Ce qu’il faut mettre dans vos métadonnées audio pour que les outils en aval puissent vraiment s’en servir.
- Deep
Segmentation des tours de parole : la stack pragmatique
La diarisation est un problème de ML difficile. La segmentation des tours de parole, la version économique, est suffisamment résolue pour être utilisée partout.