azure-speech-to-text-rest-py

npx skills add https://github.com/microsoft/skills --skill azure-speech-to-text-rest-py

API REST Azure Speech to Text pour Audio Court

Simple API REST pour la transcription de fichiers audio courts (jusqu'à 60 secondes) en texte parlé. Aucun SDK requis - simplement des requêtes HTTP.

Prérequis

  1. Abonnement Azure - Créer gratuitement
  2. Ressource Speech - Créer dans Azure Portal
  3. Récupérer les identifiants - Après le déploiement, aller à ressource > Clés et Point de terminaison

Variables d'environnement

# Requis
AZURE_SPEECH_KEY=<your-speech-resource-key>
AZURE_SPEECH_REGION=<region>  # e.g., eastus, westus2, westeurope

# Alternative : Utiliser le point de terminaison directement
AZURE_SPEECH_ENDPOINT=https://<region>.stt.speech.microsoft.com

Installation

pip install requests

Démarrage rapide

import os
import requests

def transcribe_audio(audio_file_path: str, language: str = "en-US") -> dict:
    """Transcribe short audio file (max 60 seconds) using REST API."""
    region = os.environ["AZURE_SPEECH_REGION"]
    api_key = os.environ["AZURE_SPEECH_KEY"]

    url = f"https://{region}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1"

    headers = {
        "Ocp-Apim-Subscription-Key": api_key,
        "Content-Type": "audio/wav; codecs=audio/pcm; samplerate=16000",
        "Accept": "application/json"
    }

    params = {
        "language": language,
        "format": "detailed"  # or "simple"
    }

    with open(audio_file_path, "rb") as audio_file:
        response = requests.post(url, headers=headers, params=params, data=audio_file)

    response.raise_for_status()
    return response.json()

# Usage
result = transcribe_audio("audio.wav", "en-US")
print(result["DisplayText"])

Exigences d'audio

Format Codec Fréquence d'échantillonnage Notes
WAV PCM 16 kHz, mono Recommandé
OGG OPUS 16 kHz, mono Taille de fichier réduite

Limitations :

  • Maximum 60 secondes d'audio
  • Pour l'évaluation de la prononciation : maximum 30 secondes
  • Aucun résultat partiel/intermédiaire (final uniquement)

En-têtes Content-Type

# WAV PCM 16kHz
"Content-Type": "audio/wav; codecs=audio/pcm; samplerate=16000"

# OGG OPUS
"Content-Type": "audio/ogg; codecs=opus"

Formats de réponse

Format simple (par défaut)

params = {"language": "en-US", "format": "simple"}
{
  "RecognitionStatus": "Success",
  "DisplayText": "Remind me to buy 5 pencils.",
  "Offset": "1236645672289",
  "Duration": "1236645672289"
}

Format détaillé

params = {"language": "en-US", "format": "detailed"}
{
  "RecognitionStatus": "Success",
  "Offset": "1236645672289",
  "Duration": "1236645672289",
  "NBest": [
    {
      "Confidence": 0.9052885,
      "Display": "What's the weather like?",
      "ITN": "what's the weather like",
      "Lexical": "what's the weather like",
      "MaskedITN": "what's the weather like"
    }
  ]
}

Transfert par chunks (Recommandé)

Pour une latence plus faible, diffuser l'audio par chunks :

import os
import requests

def transcribe_chunked(audio_file_path: str, language: str = "en-US") -> dict:
    """Stream audio in chunks for lower latency."""
    region = os.environ["AZURE_SPEECH_REGION"]
    api_key = os.environ["AZURE_SPEECH_KEY"]

    url = f"https://{region}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1"

    headers = {
        "Ocp-Apim-Subscription-Key": api_key,
        "Content-Type": "audio/wav; codecs=audio/pcm; samplerate=16000",
        "Accept": "application/json",
        "Transfer-Encoding": "chunked",
        "Expect": "100-continue"
    }

    params = {"language": language, "format": "detailed"}

    def generate_chunks(file_path: str, chunk_size: int = 1024):
        with open(file_path, "rb") as f:
            while chunk := f.read(chunk_size):
                yield chunk

    response = requests.post(
        url, 
        headers=headers, 
        params=params, 
        data=generate_chunks(audio_file_path)
    )

    response.raise_for_status()
    return response.json()

Options d'authentification

Option 1 : Clé d'abonnement (Simple)

headers = {
    "Ocp-Apim-Subscription-Key": os.environ["AZURE_SPEECH_KEY"]
}

Option 2 : Bearer Token

import requests
import os

def get_access_token() -> str:
    """Get access token from the token endpoint."""
    region = os.environ["AZURE_SPEECH_REGION"]
    api_key = os.environ["AZURE_SPEECH_KEY"]

    token_url = f"https://{region}.api.cognitive.microsoft.com/sts/v1.0/issueToken"

    response = requests.post(
        token_url,
        headers={
            "Ocp-Apim-Subscription-Key": api_key,
            "Content-Type": "application/x-www-form-urlencoded",
            "Content-Length": "0"
        }
    )
    response.raise_for_status()
    return response.text

# Use token in requests (valid for 10 minutes)
token = get_access_token()
headers = {
    "Authorization": f"Bearer {token}",
    "Content-Type": "audio/wav; codecs=audio/pcm; samplerate=16000",
    "Accept": "application/json"
}

Paramètres de requête

Paramètre Requis Valeurs Description
language Oui en-US, de-DE, etc. Langue du discours
format Non simple, detailed Format de résultat (par défaut : simple)
profanity Non masked, removed, raw Gestion du langage obscène (par défaut : masked)

Valeurs d'état de reconnaissance

Statut Description
Success Reconnaissance réussie
NoMatch Discours détecté mais aucun mot ne correspond
InitialSilenceTimeout Seul le silence détecté
BabbleTimeout Seul le bruit détecté
Error Erreur interne du service

Gestion du langage obscène

# Masquer le langage obscène avec des astérisques (par défaut)
params = {"language": "en-US", "profanity": "masked"}

# Supprimer le langage obscène entièrement
params = {"language": "en-US", "profanity": "removed"}

# Inclure le langage obscène tel quel
params = {"language": "en-US", "profanity": "raw"}

Gestion des erreurs

import requests

def transcribe_with_error_handling(audio_path: str, language: str = "en-US") -> dict | None:
    """Transcribe with proper error handling."""
    region = os.environ["AZURE_SPEECH_REGION"]
    api_key = os.environ["AZURE_SPEECH_KEY"]

    url = f"https://{region}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1"

    try:
        with open(audio_path, "rb") as audio_file:
            response = requests.post(
                url,
                headers={
                    "Ocp-Apim-Subscription-Key": api_key,
                    "Content-Type": "audio/wav; codecs=audio/pcm; samplerate=16000",
                    "Accept": "application/json"
                },
                params={"language": language, "format": "detailed"},
                data=audio_file
            )

        if response.status_code == 200:
            result = response.json()
            if result.get("RecognitionStatus") == "Success":
                return result
            else:
                print(f"Recognition failed: {result.get('RecognitionStatus')}")
                return None
        elif response.status_code == 400:
            print(f"Bad request: Check language code or audio format")
        elif response.status_code == 401:
            print(f"Unauthorized: Check API key or token")
        elif response.status_code == 403:
            print(f"Forbidden: Missing authorization header")
        else:
            print(f"Error {response.status_code}: {response.text}")

        return None

    except requests.exceptions.RequestException as e:
        print(f"Request failed: {e}")
        return None

Version asynchrone

import os
import aiohttp
import asyncio

async def transcribe_async(audio_file_path: str, language: str = "en-US") -> dict:
    """Async version using aiohttp."""
    region = os.environ["AZURE_SPEECH_REGION"]
    api_key = os.environ["AZURE_SPEECH_KEY"]

    url = f"https://{region}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1"

    headers = {
        "Ocp-Apim-Subscription-Key": api_key,
        "Content-Type": "audio/wav; codecs=audio/pcm; samplerate=16000",
        "Accept": "application/json"
    }

    params = {"language": language, "format": "detailed"}

    async with aiohttp.ClientSession() as session:
        with open(audio_file_path, "rb") as f:
            audio_data = f.read()

        async with session.post(url, headers=headers, params=params, data=audio_data) as response:
            response.raise_for_status()
            return await response.json()

# Usage
result = asyncio.run(transcribe_async("audio.wav", "en-US"))
print(result["DisplayText"])

Langues supportées

Codes de langue courants (voir liste complète) :

Code Langue
en-US Anglais (États-Unis)
en-GB Anglais (Royaume-Uni)
de-DE Allemand
fr-FR Français
es-ES Espagnol (Espagne)
es-MX Espagnol (Mexique)
zh-CN Chinois (Mandarin)
ja-JP Japonais
ko-KR Coréen
pt-BR Portugais (Brésil)

Bonnes pratiques

  1. Utiliser WAV PCM 16kHz mono pour la meilleure compatibilité
  2. Activer le transfert par chunks pour une latence plus faible
  3. Mettre en cache les tokens d'accès pendant 9 minutes (valides pendant 10)
  4. Spécifier la langue correcte pour une reconnaissance précise
  5. Utiliser le format détaillé quand vous avez besoin de scores de confiance
  6. Gérer toutes les valeurs de RecognitionStatus dans le code de production

Quand NE PAS utiliser cette API

Utiliser le Speech SDK ou l'API Batch Transcription à la place quand vous avez besoin de :

  • Audio plus long que 60 secondes
  • Transcription streaming en temps réel
  • Résultats partiels/intermédiaires
  • Traduction vocale
  • Modèles de discours personnalisés
  • Transcription par batch de nombreux fichiers

Fichiers de référence

Fichier Contenu
references/pronunciation-assessment.md Paramètres d'évaluation de la prononciation et notation

Skills similaires