GitHub Copilot ChatGPT Claude Codex CLI Cursor opencode Skill Text

azure-speech-to-text-rest-py

Azure Speech to Text REST API for short audio (Python). Use for simple speech recognition of audio files up to 60 seconds without the Speech SDK. Triggers: "speech to text REST", "short audio transcription", "speech recognition REST API", "STT REST", "recognize speech REST". DO N

Ciza · 0 points · 20 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download microsoft-skills-.github_plugins_azure-sdk-python_skills_azure-speech-to-text-rest-py-e58528d.zip · 6 KB
Part of microsoft/skills — 195 skills

Install

skills CLI npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-python/skills/azure-speech-to-text-rest-py
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
Git git clone https://github.com/microsoft/skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Azure Speech to Text REST API for Short Audio

Simple REST API for speech-to-text transcription of short audio files (up to 60 seconds). No SDK required - just HTTP requests.

Prerequisites

  1. Azure subscription - Create one free
  2. Speech resource - Create in Azure Portal
  3. Get credentials - After deployment, go to resource > Keys and Endpoint

Environment Variables

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

# Alternative: Use endpoint directly
AZURE_SPEECH_ENDPOINT=https://<region>.stt.speech.microsoft.com

Installation

pip install requests

Authentication & Lifecycle

🔑 Two rules apply to every code sample below:

  1. Two auth modes are supported. Use a subscription key (Ocp-Apim-Subscription-Key header) for quick access, or a Microsoft Entra token (including one acquired with DefaultAzureCredential) via the Authorization request header (see "Option 2" below). Never hardcode credentials in source.
  2. Use context managers for files and HTTP resources so file handles and network connections are released deterministically:
    • Sync: with open(...) as f: and (when reusing connections) with requests.Session() as session:
    • Async: async with aiohttp.ClientSession() as session:

Snippets may abbreviate this setup, but production code should always follow both rules.

Quick Start

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"])

Audio Requirements

Format Codec Sample Rate Notes
WAV PCM 16 kHz, mono Recommended
OGG OPUS 16 kHz, mono Smaller file size

Limitations:

  • Maximum 60 seconds of audio
  • For pronunciation assessment: maximum 30 seconds
  • No partial/interim results (final only)

Content-Type Headers

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

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

Response Formats

Simple Format (default)

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

Detailed Format

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"
    }
  ]
}

Chunked Transfer (Recommended)

For lower latency, stream audio in 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()

Authentication Options

Option 1: Subscription Key (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"
}

Query Parameters

Parameter Required Values Description
language Yes en-US, de-DE, etc. Language of speech
format No simple, detailed Result format (default: simple)
profanity No masked, removed, raw Profanity handling (default: masked)

Recognition Status Values

Status Description
Success Recognition succeeded
NoMatch Speech detected but no words matched
InitialSilenceTimeout Only silence detected
BabbleTimeout Only noise detected
Error Internal service error

Profanity Handling

# Mask profanity with asterisks (default)
params = {"language": "en-US", "profanity": "masked"}

# Remove profanity entirely
params = {"language": "en-US", "profanity": "removed"}

# Include profanity as-is
params = {"language": "en-US", "profanity": "raw"}

Error Handling

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

Async Version

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"])

Supported Languages

Common language codes (see full list):

Code Language
en-US English (US)
en-GB English (UK)
de-DE German
fr-FR French
es-ES Spanish (Spain)
es-MX Spanish (Mexico)
zh-CN Chinese (Mandarin)
ja-JP Japanese
ko-KR Korean
pt-BR Portuguese (Brazil)

Best Practices

  1. Pick sync OR async and stay consistent. Do not mix azure.xxx sync clients with azure.xxx.aio async clients in the same call path. Choose one mode per module.
  2. Use context managers for files and HTTP resources. Use with open(...) as f: and (when reusing connections) with requests.Session() as session: for sync code, or async with aiohttp.ClientSession() as session: for async code.
  3. Use WAV PCM 16kHz mono for best compatibility
  4. Enable chunked transfer for lower latency
  5. Cache access tokens for 9 minutes (valid for 10)
  6. Specify the correct language for accurate recognition
  7. Use detailed format when you need confidence scores
  8. Handle all RecognitionStatus values in production code

When NOT to Use This API

Use the Speech SDK or Batch Transcription API instead when you need:

  • Audio longer than 60 seconds
  • Real-time streaming transcription
  • Partial/interim results
  • Speech translation
  • Custom speech models
  • Batch transcription of many files

Reference Files

File Contents
references/pronunciation-assessment.md Pronunciation assessment parameters and scoring
Files (skills)
  • references
    • pronunciation-assessment.md 7.6 KB
      # Pronunciation Assessment
      
      Evaluate pronunciation quality of speech input using the REST API for short audio.
      
      ## Limitations
      
      - Maximum 30 seconds of audio (vs 60 seconds for regular transcription)
      - Requires reference text to compare against
      
      ## Headers
      
      Add the `Pronunciation-Assessment` header with Base64-encoded JSON parameters:
      
      ```python
      import base64
      import json
      import os
      import requests
      
      def transcribe_with_pronunciation_assessment(
          audio_file_path: str,
          reference_text: str,
          language: str = "en-US"
      ) -> dict:
          """Transcribe with pronunciation assessment."""
          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"
          
          # Build pronunciation assessment parameters
          pron_params = {
              "ReferenceText": reference_text,
              "GradingSystem": "HundredMark",
              "Granularity": "Word",
              "Dimension": "Comprehensive",
              "EnableProsodyAssessment": True
          }
          
          # Base64 encode the JSON
          pron_header = base64.b64encode(
              json.dumps(pron_params).encode("utf-8")
          ).decode("utf-8")
          
          headers = {
              "Ocp-Apim-Subscription-Key": api_key,
              "Content-Type": "audio/wav; codecs=audio/pcm; samplerate=16000",
              "Accept": "application/json",
              "Pronunciation-Assessment": pron_header
          }
          
          params = {"language": language, "format": "detailed"}
          
          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_with_pronunciation_assessment(
          "greeting.wav",
          "Good morning.",
          "en-US"
      )
      
      # Access pronunciation scores
      if result["RecognitionStatus"] == "Success":
          nbest = result["NBest"][0]
          print(f"Accuracy: {nbest['AccuracyScore']}")
          print(f"Fluency: {nbest['FluencyScore']}")
          print(f"Prosody: {nbest.get('ProsodyScore', 'N/A')}")
          print(f"Completeness: {nbest['CompletenessScore']}")
          print(f"Overall: {nbest['PronScore']}")
      ```
      
      ## Parameters
      
      | Parameter | Required | Description |
      |-----------|----------|-------------|
      | `ReferenceText` | **Yes** | Text the pronunciation is evaluated against |
      | `GradingSystem` | No | `FivePoint` (0-5) or `HundredMark` (0-100). Default: `FivePoint` |
      | `Granularity` | No | `Phoneme`, `Word`, or `FullText`. Default: `Phoneme` |
      | `Dimension` | No | `Basic` (accuracy only) or `Comprehensive`. Default: `Basic` |
      | `EnableMiscue` | No | Enable omission/insertion detection. Default: `False` |
      | `EnableProsodyAssessment` | No | Enable prosody scoring. Default: `False` |
      | `ScenarioId` | No | GUID for custom point system |
      
      ## Grading Systems
      
      ### FivePoint (Default)
      - Returns floating-point scores from 0.0 to 5.0
      
      ### HundredMark
      - Returns floating-point scores from 0.0 to 100.0
      - More intuitive for most applications
      
      ## Granularity Levels
      
      ### Phoneme (Default)
      Shows scores at full-text, word, and phoneme levels:
      ```json
      {
        "AccuracyScore": 95.0,
        "Words": [
          {
            "Word": "good",
            "AccuracyScore": 100.0,
            "Phonemes": [
              {"Phoneme": "g", "AccuracyScore": 100.0},
              {"Phoneme": "uh", "AccuracyScore": 95.0},
              {"Phoneme": "d", "AccuracyScore": 100.0}
            ]
          }
        ]
      }
      ```
      
      ### Word
      Shows scores at full-text and word levels only.
      
      ### FullText
      Shows score at full-text level only.
      
      ## Response with Pronunciation Assessment
      
      ```json
      {
        "RecognitionStatus": "Success",
        "Offset": 700000,
        "Duration": 8400000,
        "DisplayText": "Good morning.",
        "SNR": 38.76819,
        "NBest": [
          {
            "Confidence": 0.98503506,
            "Lexical": "good morning",
            "Display": "Good morning.",
            "AccuracyScore": 100.0,
            "FluencyScore": 100.0,
            "ProsodyScore": 87.8,
            "CompletenessScore": 100.0,
            "PronScore": 95.1,
            "Words": [
              {
                "Word": "good",
                "Offset": 700000,
                "Duration": 2600000,
                "AccuracyScore": 100.0,
                "ErrorType": "None",
                "Feedback": {
                  "Prosody": {
                    "Break": {
                      "ErrorTypes": ["None"],
                      "BreakLength": 0
                    },
                    "Intonation": {
                      "ErrorTypes": [],
                      "Monotone": {
                        "Confidence": 0.0
                      }
                    }
                  }
                }
              },
              {
                "Word": "morning",
                "Offset": 3400000,
                "Duration": 5700000,
                "AccuracyScore": 100.0,
                "ErrorType": "None"
              }
            ]
          }
        ]
      }
      ```
      
      ## Score Definitions
      
      | Score | Description |
      |-------|-------------|
      | `AccuracyScore` | How closely phonemes match native speaker pronunciation |
      | `FluencyScore` | How well speech matches native speaker's use of silent breaks |
      | `ProsodyScore` | Naturalness including stress, intonation, speaking speed, rhythm |
      | `CompletenessScore` | Ratio of pronounced words to reference text |
      | `PronScore` | Overall pronunciation quality (weighted aggregate) |
      
      ## Error Types
      
      When `EnableMiscue` is true, words include `ErrorType`:
      
      | ErrorType | Description |
      |-----------|-------------|
      | `None` | Word pronounced correctly |
      | `Omission` | Word in reference was skipped |
      | `Insertion` | Extra word not in reference |
      | `Mispronunciation` | Word pronounced incorrectly |
      
      ## Complete Example with All Features
      
      ```python
      import base64
      import json
      import os
      import requests
      
      def full_pronunciation_assessment(
          audio_path: str,
          reference_text: str,
          language: str = "en-US"
      ) -> None:
          """Full pronunciation assessment with detailed output."""
          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"
          
          pron_params = {
              "ReferenceText": reference_text,
              "GradingSystem": "HundredMark",
              "Granularity": "Word",
              "Dimension": "Comprehensive",
              "EnableMiscue": True,
              "EnableProsodyAssessment": True
          }
          
          pron_header = base64.b64encode(
              json.dumps(pron_params).encode()
          ).decode()
          
          headers = {
              "Ocp-Apim-Subscription-Key": api_key,
              "Content-Type": "audio/wav; codecs=audio/pcm; samplerate=16000",
              "Accept": "application/json",
              "Pronunciation-Assessment": pron_header
          }
          
          with open(audio_path, "rb") as f:
              response = requests.post(
                  url,
                  headers=headers,
                  params={"language": language, "format": "detailed"},
                  data=f
              )
          
          response.raise_for_status()
          result = response.json()
          
          if result["RecognitionStatus"] != "Success":
              print(f"Recognition failed: {result['RecognitionStatus']}")
              return
          
          nbest = result["NBest"][0]
          
          print(f"\n=== Overall Scores ===")
          print(f"Accuracy:     {nbest['AccuracyScore']:.1f}")
          print(f"Fluency:      {nbest['FluencyScore']:.1f}")
          print(f"Prosody:      {nbest.get('ProsodyScore', 'N/A')}")
          print(f"Completeness: {nbest['CompletenessScore']:.1f}")
          print(f"Overall:      {nbest['PronScore']:.1f}")
          
          print(f"\n=== Word-Level Analysis ===")
          for word in nbest["Words"]:
              error = word.get("ErrorType", "None")
              accuracy = word.get("AccuracyScore", 0)
              marker = "" if error == "None" else f" [{error}]"
              print(f"  {word['Word']}: {accuracy:.1f}{marker}")
      
      # Usage
      full_pronunciation_assessment(
          "user_speech.wav",
          "The quick brown fox jumps over the lazy dog.",
          "en-US"
      )
      ```
      
  • SKILL.md 11.8 KB
    ---
    name: azure-speech-to-text-rest-py
    description: |-
      Azure Speech to Text REST API for short audio (Python). Use for simple speech recognition of audio files up to 60 seconds without the Speech SDK.
      Triggers: "speech to text REST", "short audio transcription", "speech recognition REST API", "STT REST", "recognize speech REST".
      DO NOT USE FOR: Long audio (>60 seconds), real-time streaming, batch transcription, custom speech models, speech translation. Use Speech SDK or Batch Transcription API instead.
    license: MIT
    metadata:
      author: Microsoft
      version: "1.0.0"
    ---
    
    # Azure Speech to Text REST API for Short Audio
    
    Simple REST API for speech-to-text transcription of short audio files (up to 60 seconds). No SDK required - just HTTP requests.
    
    ## Prerequisites
    
    1. **Azure subscription** - [Create one free](https://azure.microsoft.com/free/)
    2. **Speech resource** - Create in [Azure Portal](https://portal.azure.com/#create/Microsoft.CognitiveServicesSpeechServices)
    3. **Get credentials** - After deployment, go to resource > Keys and Endpoint
    
    ## Environment Variables
    
    ```bash
    # Required
    AZURE_SPEECH_KEY=<your-speech-resource-key>
    AZURE_SPEECH_REGION=<region>  # e.g., eastus, westus2, westeurope
    
    # Alternative: Use endpoint directly
    AZURE_SPEECH_ENDPOINT=https://<region>.stt.speech.microsoft.com
    ```
    
    ## Installation
    
    ```bash
    pip install requests
    ```
    
    ## Authentication & Lifecycle
    
    > **🔑 Two rules apply to every code sample below:**
    >
    > 1. **Two auth modes are supported.** Use a subscription key (`Ocp-Apim-Subscription-Key` header) for quick access, or a Microsoft Entra token (including one acquired with `DefaultAzureCredential`) via the `Authorization` request header (see "Option 2" below). Never hardcode credentials in source.
    > 2. **Use context managers for files and HTTP resources** so file handles and network connections are released deterministically:
    >    - Sync: `with open(...) as f:` and (when reusing connections) `with requests.Session() as session:`
    >    - Async: `async with aiohttp.ClientSession() as session:`
    >
    > Snippets may abbreviate this setup, but production code should always follow both rules.
    
    ## Quick Start
    
    ```python
    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"])
    ```
    
    ## Audio Requirements
    
    | Format | Codec | Sample Rate | Notes |
    |--------|-------|-------------|-------|
    | WAV | PCM | 16 kHz, mono | **Recommended** |
    | OGG | OPUS | 16 kHz, mono | Smaller file size |
    
    **Limitations:**
    - Maximum 60 seconds of audio
    - For pronunciation assessment: maximum 30 seconds
    - No partial/interim results (final only)
    
    ## Content-Type Headers
    
    ```python
    # WAV PCM 16kHz
    wav_headers = {
        "Content-Type": "audio/wav; codecs=audio/pcm; samplerate=16000"
    }
    
    # OGG OPUS
    ogg_headers = {
        "Content-Type": "audio/ogg; codecs=opus"
    }
    ```
    
    ## Response Formats
    
    ### Simple Format (default)
    
    ```python
    params = {"language": "en-US", "format": "simple"}
    ```
    
    ```json
    {
      "RecognitionStatus": "Success",
      "DisplayText": "Remind me to buy 5 pencils.",
      "Offset": "1236645672289",
      "Duration": "1236645672289"
    }
    ```
    
    ### Detailed Format
    
    ```python
    params = {"language": "en-US", "format": "detailed"}
    ```
    
    ```json
    {
      "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"
        }
      ]
    }
    ```
    
    ## Chunked Transfer (Recommended)
    
    For lower latency, stream audio in chunks:
    
    ```python
    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()
    ```
    
    ## Authentication Options
    
    ### Option 1: Subscription Key (Simple)
    
    ```python
    headers = {
        "Ocp-Apim-Subscription-Key": os.environ["AZURE_SPEECH_KEY"]
    }
    ```
    
    ### Option 2: Bearer Token
    
    ```python
    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"
    }
    ```
    
    ## Query Parameters
    
    | Parameter | Required | Values | Description |
    |-----------|----------|--------|-------------|
    | `language` | **Yes** | `en-US`, `de-DE`, etc. | Language of speech |
    | `format` | No | `simple`, `detailed` | Result format (default: simple) |
    | `profanity` | No | `masked`, `removed`, `raw` | Profanity handling (default: masked) |
    
    ## Recognition Status Values
    
    | Status | Description |
    |--------|-------------|
    | `Success` | Recognition succeeded |
    | `NoMatch` | Speech detected but no words matched |
    | `InitialSilenceTimeout` | Only silence detected |
    | `BabbleTimeout` | Only noise detected |
    | `Error` | Internal service error |
    
    ## Profanity Handling
    
    ```python
    # Mask profanity with asterisks (default)
    params = {"language": "en-US", "profanity": "masked"}
    
    # Remove profanity entirely
    params = {"language": "en-US", "profanity": "removed"}
    
    # Include profanity as-is
    params = {"language": "en-US", "profanity": "raw"}
    ```
    
    ## Error Handling
    
    ```python
    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
    ```
    
    ## Async Version
    
    ```python
    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"])
    ```
    
    ## Supported Languages
    
    Common language codes (see [full list](https://learn.microsoft.com/azure/ai-services/speech-service/language-support)):
    
    | Code | Language |
    |------|----------|
    | `en-US` | English (US) |
    | `en-GB` | English (UK) |
    | `de-DE` | German |
    | `fr-FR` | French |
    | `es-ES` | Spanish (Spain) |
    | `es-MX` | Spanish (Mexico) |
    | `zh-CN` | Chinese (Mandarin) |
    | `ja-JP` | Japanese |
    | `ko-KR` | Korean |
    | `pt-BR` | Portuguese (Brazil) |
    
    ## Best Practices
    
    1. **Pick sync OR async and stay consistent.** Do not mix `azure.xxx` sync clients with `azure.xxx.aio` async clients in the same call path. Choose one mode per module.
    2. **Use context managers for files and HTTP resources.** Use `with open(...) as f:` and (when reusing connections) `with requests.Session() as session:` for sync code, or `async with aiohttp.ClientSession() as session:` for async code.
    3. **Use WAV PCM 16kHz mono** for best compatibility
    4. **Enable chunked transfer** for lower latency
    5. **Cache access tokens** for 9 minutes (valid for 10)
    6. **Specify the correct language** for accurate recognition
    7. **Use detailed format** when you need confidence scores
    8. **Handle all RecognitionStatus values** in production code
    
    ## When NOT to Use This API
    
    Use the Speech SDK or Batch Transcription API instead when you need:
    
    - Audio longer than 60 seconds
    - Real-time streaming transcription
    - Partial/interim results
    - Speech translation
    - Custom speech models
    - Batch transcription of many files
    
    ## Reference Files
    
    | File | Contents |
    |------|----------|
    | [references/pronunciation-assessment.md](references/pronunciation-assessment.md) | Pronunciation assessment parameters and scoring |
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related