Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Transcription Pipeline

A focused audio transcription service built with Python 3.12.10, FastAPI, and Faster-Whisper. Upload a WAV or MP3 file and receive a structured JSON response containing the full transcription text plus per-segment timestamps. Long recordings are automatically split into 30-second chunks and reassembled with correct global timestamps.


Table of Contents


Requirements

Requirement Version
Operating System Windows 10 / Windows 11
Python 3.12.10
FFmpeg 4.x or newer
pip latest

Architecture Overview

app/
├── main.py                  # FastAPI app factory, lifespan, health check
├── config/
│   └── settings.py          # All configuration via Pydantic BaseSettings + .env
├── api/
│   └── routes/
│       └── transcription.py # POST /transcribe endpoint
├── audio/
│   └── processor.py         # Validation, format conversion, chunking (pydub + FFmpeg)
├── transcription/
│   └── service.py           # Faster-Whisper inference and chunk orchestration
├── models/
│   └── schemas.py           # Pydantic request/response schemas
└── utils/
    └── file_utils.py        # Temporary file helpers

Request Flow

Client ──(MP3 / WAV)──► POST /transcribe
                              │
                        Validate file extension, MIME type, size
                              │
                        Save to Windows temp directory
                              │
                        Convert to 16 kHz mono WAV  ◄── pydub + FFmpeg
                              │
                        Measure total duration
                              │
                        Split into 30-second chunks
                              │
                        Transcribe each chunk  ◄── Faster-Whisper
                              │
                        Offset timestamps + merge all segments
                              │
                        Delete all temp files
                              │
                        JSON response ──► Client

Installation

Step 1 — Install Python 3.12.10

Download and install Python 3.12.10 from the official website:

https://www.python.org/downloads/release/python-31210/

During installation:

  • Check "Add Python to PATH"
  • Check "Install pip"

Verify after installation:

python --version
# Expected: Python 3.12.10

pip --version
# Expected: pip 24.x.x from ...

Step 2 — Install FFmpeg on Windows

FFmpeg is required by pydub for audio decoding and encoding. It must be installed and accessible on your Windows PATH.

winget (recommended, built into Windows 10/11):

winget install --id Gyan.FFmpeg -e --source winget

OR

Manually download:

  1. Download the full build from https://www.gyan.dev/ffmpeg/builds/
  2. Extract the ZIP to C:\ffmpeg
  3. Add C:\ffmpeg\bin to your Windows System PATH:
    • Open Start → search "Environment Variables"
    • Click "Environment Variables"
    • Under System variables, select Path → click Edit
    • Click New → enter C:\ffmpeg\bin
    • Click OK on all dialogs

After any installation method — close and reopen PowerShell, then verify:

ffmpeg -version

You must see version output similar to:

ffmpeg version 8.1.2-full_build-www.gyan.dev Copyright (c) 2000-2026 the FFmpeg developers

If ffmpeg -version fails, FFmpeg is not on PATH — see Troubleshooting.


Step 3 — Clone the Repository

git clone https://github.com/SyntaxilitY/Transcription-speech-to-text-Pipeline-Flask-Python.git
cd Transcription-speech-to-text-Pipeline-Flask-Python

Step 4 — Create and Activate a Virtual Environment

# Create virtual environment
python -m venv .venv

# Activate it
.venv\Scripts\activate

Your prompt will change to show (.venv) when the environment is active.


Step 5 — Install Python Dependencies

pip install --upgrade pip
pip install -r requirements.txt

This installs all required packages including FastAPI, Faster-Whisper, pydub, and Uvicorn.


Step 6 — Create the .env Configuration File

copy .env.example .env

Open .env in any text editor and configure it. See Configuration for all available options.


Configuration

All settings are managed through the .env file in the project root.

Full .env Reference

# ── Application ────────────────────────────────────────────────────────────
APP_NAME=Transcription Pipeline
APP_VERSION=1.0.0

# Set to true during development to enable debug logging and auto-reload
APP_DEBUG=false

# ── Server ─────────────────────────────────────────────────────────────────
HOST=0.0.0.0
PORT=8000

# ── Faster-Whisper Model ───────────────────────────────────────────────────
# Model size controls the trade-off between speed and accuracy.
# Options: tiny | base | small | medium | large | large-v2 | large-v3
# Recommendation for Windows CPU: base or small
WHISPER_MODEL_SIZE=base

# Device to run inference on.
# Options: cpu | cuda
# Use cpu unless you have an NVIDIA GPU with CUDA installed.
WHISPER_DEVICE=cpu

# Compute type (quantization).
# Use float32 on Windows CPU — int8 can cause the server to hang on Windows.
# Options: float32 | float16 | int8_float16 | int8
WHISPER_COMPUTE_TYPE=float32

# Language of the audio.
# Leave blank for automatic detection (recommended).
# Set to a language code to force a specific language: en | fr | de | es | etc.
WHISPER_LANGUAGE=

# Beam size for decoding. Higher values improve accuracy but are slower.
WHISPER_BEAM_SIZE=5

# ── Audio Processing ───────────────────────────────────────────────────────
# Duration of each audio chunk in milliseconds.
# Long files are split into chunks of this size before transcription.
CHUNK_DURATION_MS=30000

# Target sample rate in Hz. Whisper requires 16000 — do not change this.
TARGET_SAMPLE_RATE=16000

# Maximum allowed upload size in bytes. Default is 500 MB.
MAX_FILE_SIZE_BYTES=524288000

# ── FFmpeg ─────────────────────────────────────────────────────────────────
# Leave blank if FFmpeg is on your Windows PATH.
# Set this to the full path of ffmpeg.exe if the app cannot find it.
#
# To find your FFmpeg path, run in PowerShell:
#   where ffmpeg
#
# Then paste the result here. Example:
# FFMPEG_PATH=C:\Users\YourName\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-8.1.2-full_build\bin\ffmpeg.exe
FFMPEG_PATH=

# ── Temporary Files ────────────────────────────────────────────────────────
# Directory for temporary audio files created during processing.
# Leave blank to use the Windows default:
#   C:\Users\<YourName>\AppData\Local\Temp\transcription_pipeline
# Do NOT set this to a Unix-style path like /tmp — it does not exist on Windows.
TEMP_DIR=

Important Configuration Notes

Setting Detail
WHISPER_COMPUTE_TYPE Always use float32 on Windows CPU. Setting int8 causes the server to hang silently on Windows during startup.
WHISPER_LANGUAGE Leave the value completely blank for auto-detection. Do not wrap it in quotes.
FFMPEG_PATH Only needed if ffmpeg -version works in one terminal but the app reports FFmpeg not found.
TEMP_DIR Leave blank. The app resolves the correct Windows temp path automatically using Python's tempfile.gettempdir().

Running the Service

Important: Always run the service from the same PowerShell window where ffmpeg -version works. Do not switch terminals between verifying FFmpeg and starting the app.

Development Mode

# Make sure your virtual environment is active
.venv\Scripts\activate

# Run with auto-reload (set APP_DEBUG=true in .env first)
python -m app.main

Production Mode

.venv\Scripts\activate

uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 1

Why --workers 1? The Faster-Whisper model is loaded into memory once at startup and shared across all requests. Using multiple workers would cause each worker process to load its own copy of the model, multiplying memory usage with no benefit on a single-model setup.

Expected Startup Output

INFO | === Transcription Pipeline starting up ===
INFO | FFmpeg configured  → C:\...\ffmpeg.exe
INFO | FFprobe configured → C:\...\ffprobe.exe
INFO | Loading TranscriptionService — this may take 10-30 seconds...
INFO | Loading Faster-Whisper model: size=base  device=cpu  compute_type=float32
INFO | Faster-Whisper model loaded successfully.
INFO | TranscriptionService ready.
INFO | === Startup complete. Ready to accept requests. ===
INFO | Application startup complete.
INFO | Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

The first run downloads the Whisper model from HuggingFace (~145 MB for base). Subsequent starts use the locally cached model and are much faster.

Verify the Service Is Running

Open a second PowerShell window and run:

curl http://localhost:8000/health

Expected response:

{
  "status": 200,
  "code": "HTTP_200_OK",
  "message": "Service is healthy.",
  "data": {
    "service": "Transcription Pipeline",
    "version": "1.0.0",
    "model": "base",
    "device": "cpu"
  }
}

Interactive API Documentation

With the service running, open either of these URLs in your browser:


API Reference

POST /transcribe

Transcribe an uploaded audio file. Returns the full transcription text and per-segment timestamps.

Request

Field Type Required Description
file binary (multipart/form-data) WAV or MP3 audio file, maximum 500 MB

Supported Audio Formats

Format Accepted MIME Types
WAV audio/wav, audio/x-wav
MP3 audio/mpeg, audio/mp3

Example — PowerShell (curl)

curl -X POST http://localhost:8000/transcribe `
  -F "file=@C:\path\to\your\recording.mp3"

Example — Python

import httpx

with open(r"C:\path\to\your\recording.mp3", "rb") as f:
    response = httpx.post(
        "http://localhost:8000/transcribe",
        files={"file": ("recording.mp3", f, "audio/mpeg")},
    )

data = response.json()
print(data["data"]["full_text"])

for segment in data["data"]["segments"]:
    print(f"[{segment['start']:.2f}s → {segment['end']:.2f}s]  {segment['text']}")

Successful Response 200 OK

{
  "status": 200,
  "code": "HTTP_200_OK",
  "message": "Audio transcribed successfully.",
  "data": {
    "filename": "recording.mp3",
    "duration_seconds": 125.48,
    "language": "en",
    "language_probability": 0.9987,
    "full_text": "Hello, this is a sample transcription of the uploaded audio file.",
    "segments": [
      {
        "segment_id": 0,
        "start": 0.0,
        "end": 3.48,
        "text": "Hello, this is a sample transcription",
        "confidence": 0.9241
      },
      {
        "segment_id": 1,
        "start": 3.48,
        "end": 6.92,
        "text": "of the uploaded audio file.",
        "confidence": 0.9108
      }
    ],
    "chunk_count": 5
  }
}

Response Fields

Field Type Description
filename string Original uploaded filename
duration_seconds float Total audio duration in seconds
language string Detected or forced language as ISO 639-1 code (e.g. en)
language_probability float Confidence of language detection, range 0.0 – 1.0
full_text string Complete transcription as a single concatenated string
segments array List of timed transcription segments
segments[].segment_id integer Zero-based index of this segment
segments[].start float Segment start time in seconds from the beginning of the file
segments[].end float Segment end time in seconds from the beginning of the file
segments[].text string Transcribed text for this segment
segments[].confidence float Transcription confidence score, range 0.0 – 1.0
chunk_count integer Number of 30-second chunks the file was divided into

Error Responses

HTTP Status Code Cause
400 HTTP_400_BAD_REQUEST Uploaded file is empty
413 HTTP_413_REQUEST_ENTITY_TOO_LARGE File exceeds 500 MB
422 HTTP_422_UNPROCESSABLE_ENTITY Unsupported format or undecodable audio
500 HTTP_500_INTERNAL_SERVER_ERROR Unexpected server-side error

GET /health

Lightweight liveness check. Confirms the service is running and returns the active model configuration.

curl http://localhost:8000/health

Model Selection Guide

The model is set via WHISPER_MODEL_SIZE in .env. It is downloaded automatically on first run and cached at:

C:\Users\<YourName>\.cache\huggingface\hub
Model Disk Size RAM Usage Speed on CPU Accuracy
tiny ~75 MB ~125 MB Very fast Low
base ~145 MB ~210 MB Fast Good — recommended default
small ~465 MB ~600 MB Moderate Better
medium ~1.5 GB ~2 GB Slow High
large-v3 ~3 GB ~4 GB Very slow Best — GPU recommended

For Windows CPU with limited RAM, base is the best starting point. Switch to small if accuracy is more important than speed.


Project Structure

transcription-pipeline/
├── app/
│   ├── __init__.py
│   ├── main.py                      # FastAPI application, lifespan, health check
│   ├── config/
│   │   ├── __init__.py
│   │   └── settings.py              # Pydantic BaseSettings — reads from .env
│   ├── api/
│   │   ├── __init__.py
│   │   └── routes/
│   │       ├── __init__.py
│   │       └── transcription.py     # POST /transcribe route handler
│   ├── audio/
│   │   ├── __init__.py
│   │   └── processor.py             # Audio validation, FFmpeg setup, conversion, chunking
│   ├── transcription/
│   │   ├── __init__.py
│   │   └── service.py               # Faster-Whisper model lifecycle and inference pipeline
│   ├── models/
│   │   ├── __init__.py
│   │   └── schemas.py               # Pydantic request and response schemas
│   └── utils/
│       ├── __init__.py
│       └── file_utils.py            # Temp file creation, cleanup helpers
├── .env                             # Your local configuration (do not commit)
├── .env.example                     # Configuration template
├── requirements.txt                 # All Python dependencies with pinned versions
├── Dockerfile                       # Container build instructions
└── README.md                        # This file

Troubleshooting

Couldn't find ffmpeg or avconv — defaulting to ffmpeg, but may not work

pydub cannot find FFmpeg. This warning appears at startup and will cause transcription to fail with [WinError 2].

Step 1 — Find the exact path of your FFmpeg installation:

where ffmpeg

Step 2 — Set FFMPEG_PATH in .env to that exact path:

FFMPEG_PATH=C:\Users\YourName\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-8.1.2-full_build\bin\ffmpeg.exe

Step 3 — Restart the service.


[WinError 2] The system cannot find the file specified

Same cause as above. FFmpeg is installed but the terminal running the service cannot locate it. Set FFMPEG_PATH in .env as shown above.


'' is not a valid language code

WHISPER_LANGUAGE in .env is being read as an empty string "" instead of None. This happens when the line is present but has no value.

The setting is already handled defensively in the code, but if you see this error ensure your .env has:

# Option 1 — auto-detect (recommended)
WHISPER_LANGUAGE=

# Option 2 — force a specific language
WHISPER_LANGUAGE=en

Do not add quotes around the value.


Server hangs on startup and never prints Application startup complete

Cause: WHISPER_COMPUTE_TYPE=int8 in .env. On Windows CPU, int8 causes CTranslate2 to hang silently during model initialisation.

Fix — change to float32 in .env:

WHISPER_COMPUTE_TYPE=float32

Restart the service. Startup should complete within 30 seconds.


ModuleNotFoundError: No module named 'main'

The service was started with the wrong command.

# Wrong
python app/main.py

# Correct — always use the -m flag from the project root
python -m app.main

ERR_CONNECTION_REFUSED on http://localhost:8000

The server did not complete startup. Check the PowerShell window running the service for error messages. Common causes and fixes:

Cause Fix
FFmpeg not found Set FFMPEG_PATH in .env
int8 compute type hanging Set WHISPER_COMPUTE_TYPE=float32 in .env
Port 8000 already in use Change PORT in .env or stop the process using port 8000
Virtual environment not activated Run .venv\Scripts\activate first

Check if port 8000 is already in use:

netstat -ano | findstr :8000

If a process is listed, stop it or change PORT=8001 in .env.


Model downloads on every startup

The model is cached by HuggingFace Hub after the first download. If it re-downloads every time, the cache directory may be missing or unwritable.

Check the cache location:

# Open the HuggingFace cache directory in Explorer
explorer "$env:USERPROFILE\.cache\huggingface\hub"

If the directory is empty or missing, the download will happen again on the next startup. This is normal for a first run only.


Transcription is slow

Expected behaviour on CPU. Options to improve speed:

  1. Use a smaller model — change WHISPER_MODEL_SIZE=tiny in .env
  2. Reduce WHISPER_BEAM_SIZE=1 in .env for fastest decoding
  3. If you have an NVIDIA GPU, set WHISPER_DEVICE=cuda and WHISPER_COMPUTE_TYPE=float16 in .env

About

A focused audio transcription REST API built with Python 3.12, FastAPI, and Faster-Whisper. Upload WAV or MP3 files and receive structured JSON responses with full transcription text and per-segment timestamps. Long recordings are automatically chunked and reassembled.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages