Détection automatique de la langue parlée avec cURL & open source
Détectez la langue parlée directement à partir de l’audio avec un modèle Whisper multilingue, servi localement par whisper.cpp. cURL envoie l’enregistrement à son point de terminaison HTTP, qui renvoie une langue candidate et une transcription à comparer à l’enregistrement. Une fois le logiciel et le modèle téléchargés, l’inférence s’exécute sur votre ordinateur sans compte ni API cloud.
Configuration requise
Utilisez Linux avec Bash, un shell POSIX (sh), un compilateur C++17,
Make, CMake, cURL, FFmpeg, Python 3 et les commandes habituelles
tar, gzip, dirname,
grep, mktemp et rm.
Installez d’abord les outils manquants avec le gestionnaire de paquets de votre distribution.
Python lit la réponse JSON en utilisant uniquement sa bibliothèque standard.
Ce tutoriel sur CPU utilise la version fixe v1.8.7 de whisper.cpp et
cible un environnement Debian 13 avec Bash 5.2, GCC 14.2, Make 4.4, CMake 3.31, cURL 8.14,
FFmpeg 7.1 et Python 3.12. Les autres plateformes et les chaînes de compilation plus anciennes
sortent du cadre de ce tutoriel. Le modèle multilingue tiny occupe
environ 75 MiB sur disque. Prévoyez de l’espace disque supplémentaire pour les sources et la
compilation, ainsi que plusieurs centaines de mégaoctets de mémoire libre pour l’inférence.
Installation
Depuis un nouveau répertoire de travail, téléchargez la version fixée, compilez son serveur et
téléchargez le modèle multilingue. Choisissez tiny plutôt que le modèle
tiny.en, limité à l’anglais. Les parenthèses maintiennent les options du
shell et les changements de répertoire dans un sous-shell :
(
set -e
for tool in curl tar gzip cmake make c++ ffmpeg python3 sh dirname grep mktemp rm; do
command -v "$tool" >/dev/null || { printf 'Missing tool: %s\n' "$tool" >&2; exit 1; }
done
if [ -e whisper-v1.8.7.tar.gz ] || [ -e whisper.cpp-1.8.7 ]; then
printf 'Use a fresh directory; existing download or source found.\n' >&2
exit 1
fi
curl -q --fail --location --output whisper-v1.8.7.tar.gz \
https://github.com/ggml-org/whisper.cpp/archive/refs/tags/v1.8.7.tar.gz
tar -xzf whisper-v1.8.7.tar.gz
cd whisper.cpp-1.8.7
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
-DGGML_METAL=OFF -DWHISPER_BUILD_SERVER=ON
cmake --build build --config Release --target whisper-server -j 4
sh ./models/download-ggml-model.sh tiny
)
Configurer le serveur de transcription
Une fois l’installation réussie, démarrez le serveur HTTP depuis le même répertoire de travail :
(
cd whisper.cpp-1.8.7 &&
./build/bin/whisper-server --model models/ggml-tiny.bin \
--host 127.0.0.1 --port 8080 --language auto --no-gpu
)
Attendez le message indiquant que le serveur est à l’écoute, puis laissez ce terminal ouvert. Le serveur de cet exemple ne dispose d’aucune authentification : gardez-le lié à l’interface de bouclage et utilisez des enregistrements locaux de confiance. Arrêtez-le avec Ctrl+C lorsque vous avez terminé.
Transcrire de l’audio avec cURL
Dans un second terminal, travaillez dans un répertoire contenant un enregistrement de parole
nommé input.mp3. Utilisez un extrait de confiance qui commence par de la
parole claire dans une seule langue. Convertissez-le au format PCM WAV mono à 16 kHz et 16 bits.
Le bloc refuse un fichier audio.wav existant avant la conversion, et
-n empêche également FFmpeg de l’écraser. Choisissez un nouveau
répertoire pour chaque enregistrement ; FFmpeg 7.1 peut signaler un refus d’écrasement tout en
renvoyant un code de sortie zéro, d’où l’importance de cette vérification explicite.
(
if [ -e audio.wav ]; then
printf 'Existing audio.wav; use a fresh directory.\n' >&2
exit 1
fi
ffmpeg -nostdin -n -i input.mp3 -vn -ar 16000 -ac 1 -c:a pcm_s16le audio.wav
)
Écoutez audio.wav et vérifiez qu’il contient la parole attendue avant de le
téléverser. FFmpeg peut récupérer des parties d’enregistrements endommagés tout en signalant une
réussite ; la conversion seule ne permet pas d’établir que le fichier d’entrée était intact.
Détection de la langue
Enregistrez ce script sous le nom read_language.py à côté de
audio.wav. Il lit la langue déduite de l’audio et affiche la transcription
pour vérification. Il rejette le texte vide et le texte constitué uniquement de marqueurs entre
crochets indiquant l’absence de parole, y compris les résultats répétés
[BLANK_AUDIO] :
import json
import re
import sys
def read_language(path):
with open(path, encoding="utf-8") as handle:
data = json.load(handle)
if not isinstance(data, dict):
raise ValueError("Expected a JSON object")
language = data.get("language")
text = data.get("text")
if not isinstance(language, str) or not language.strip():
raise ValueError("Response has no detected language")
if not isinstance(text, str) or not re.sub(r"\[[^\]]*\]", "", text).strip():
raise ValueError("No speech transcript; language result is inconclusive")
return language.strip(), " ".join(text.split())
def main():
if len(sys.argv) != 2:
raise ValueError("Usage: python3 read_language.py response.json")
language, text = read_language(sys.argv[1])
print(f"Language candidate: {language}")
print(f"Transcript: {text}")
if __name__ == "__main__":
try:
main()
except (OSError, ValueError) as error:
print(f"Cannot read language result: {error}", file=sys.stderr)
sys.exit(1)
Une fois la conversion réussie et le script de lecture enregistré, collez ce bloc de requête. Il attribue à chaque requête son propre fichier de réponse temporaire et ne le lit que si cURL réussit. Le fichier est supprimé à la fin du bloc, y compris en cas d’échec : une réponse précédente ne peut donc pas devenir le résultat de cette requête. La requête dispose de 60 secondes au total, téléversement et inférence compris ; un processeur occupé ou un enregistrement plus long peut dépasser ce délai. Augmentez-le de manière délibérée si nécessaire.
(
set -e
response=$(mktemp ./language-response.XXXXXX)
trap 'rm -f "$response"' EXIT
curl -q --fail --silent --show-error --max-time 60 \
http://127.0.0.1:8080/inference \
--form 'file=@audio.wav;type=audio/wav' \
--form 'language=auto' \
--form 'response_format=verbose_json' \
--form 'no_language_probabilities=true' \
--output "$response" &&
python3 read_language.py "$response"
)
language=auto demande la détection de la langue. La
réponse verbose_json du serveur
comprend language et text ; le format
json simple omet la langue. La traduction est désactivée, et
no_language_probabilities=true évite une seconde passe facultative de détection.
Pour de la parole en anglais, attendez-vous à
Language candidate: english ;
pour l’espagnol, le nom utilisé par le serveur est spanish. Ce sont des
noms de langues, pas des codes ISO. Comparez la transcription affichée à ce que vous entendez.
La vérification des marqueurs n’est qu’un contrôle de cohérence :
Whisper peut inventer des mots,
et une transcription non vide ne confirme ni la présence de parole ni l’exactitude de la langue.
Optimiser les performances
Gardez le serveur en cours d’exécution entre les requêtes pour qu’il puisse réutiliser le modèle
chargé. tiny limite la taille du téléchargement pour les essais locaux,
mais sa transcription peut contenir des erreurs importantes. Vérifiez-la sur des enregistrements
connus avant d’utiliser la langue candidate pour orienter d’autres traitements.
Dans cette version, la détection automatique de la langue commence au décalage zéro et utilise la fenêtre initiale de l’enregistrement, soit environ 30 secondes, plutôt que de reclassifier chaque segment ultérieur. Un long silence initial peut donc produire une langue trompeuse, même si de la parole apparaît plus tard. Utilisez un extrait qui commence par de la parole ; pour les changements de langue, évaluez des extraits distincts. Un résultat pour l’ensemble du fichier ne constitue pas une chronologie de toutes les langues parlées.
Gérer les erreurs
Si l’installation échoue, examinez ses fichiers partiels, corrigez le prérequis manquant et
réessayez dans un nouveau répertoire de travail. Les téléchargements existants et les sources
extraites sont délibérément laissés intacts. Si la conversion échoue, examinez tout fichier
audio.wav partiel avant de le supprimer ou de choisir un autre répertoire.
cURL renvoie un code de sortie non nul en cas d’erreur HTTP, d’échec de connexion ou de
dépassement du délai. Le bloc de requête ignore alors le script de lecture et supprime sa réponse
temporaire. Conservez un fichier audio.wav dont la conversion a réussi et
relancez uniquement le bloc de requête après avoir résolu le problème. Un JSON invalide, des
champs manquants, des transcriptions vides ou constituées uniquement de marqueurs, et des
fichiers illisibles font terminer le script de lecture avec le code de sortie 1.
Si le démarrage échoue, vérifiez le chemin du modèle et si le port 8080 est déjà occupé. Si un téléversement échoue, examinez le terminal du serveur local et confirmez que la conversion WAV a réussi. Ne considérez pas une langue devinée à partir de silence, de musique ou de parole très brève comme une classification fiable.
Pour une transcription hébergée dans un processus de traitement de fichiers, consultez notre Speech Robot.
