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
Install
npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-python/skills/azure-speech-to-text-rest-py
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
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
- Azure subscription - Create one free
- Speech resource - Create in Azure Portal
- 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:
- Two auth modes are supported. Use a subscription key (
Ocp-Apim-Subscription-Keyheader) for quick access, or a Microsoft Entra token (including one acquired withDefaultAzureCredential) via theAuthorizationrequest header (see "Option 2" below). Never hardcode credentials in source.- 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
- Pick sync OR async and stay consistent. Do not mix
azure.xxxsync clients withazure.xxx.aioasync clients in the same call path. Choose one mode per module. - 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, orasync with aiohttp.ClientSession() as session:for async code. - Use WAV PCM 16kHz mono for best compatibility
- Enable chunked transfer for lower latency
- Cache access tokens for 9 minutes (valid for 10)
- Specify the correct language for accurate recognition
- Use detailed format when you need confidence scores
- 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.
Reviews (0)
No reviews yet.
No comments yet.