Aller au contenu
Se connecter

/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 :

  1. 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.
  2. 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