whisper-flow

dimastatzMIT活跃维护

基于 OpenAI Whisper 的实时语音转写框架,接收连续音频流分块并即时输出增量转写结果,不用等整段音频上传完再处理。

Whisper-Flow is a framework designed to enable real-time transcription of audio content using OpenAI’s Whisper model. Rather than processing entire files after upload (“batch mode”), Whisper-Flow accepts a continuous stream of audio chunks and produces incremental transcripts immediately.

v1.4.0发布于 2026-11-01 05:19 UTC1,007star140fork同步于 2026-11-10 17:53 UTC

怎么上手

由 README 提炼,执行前请确认
git clone https://github.com/dimastatz/whisper-flow.git
cd whisper-flow
./run.sh -local
source .venv/bin/activate
./run.sh -run-server
硬件要求按 README 说明

README 未明确给出显存要求;基准测试在 M1 芯片、16GB 内存的 MacBook Air 上运行,默认模型为 tiny.en.pt。

支持 Apple Silicon有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

把 OpenAI Whisper 从批处理改造成流式实时转写服务,边收音频块边出增量文本

基于 OpenAI Whisper 的实时语音转写框架,接收连续音频流分块并即时输出增量转写结果,不用等整段音频上传完再处理。

核心能力

  • 按 WebSocket 接收 16kHz 单声道 int16 PCM 二进制帧
  • 用滚动窗口切分语音段,返回带 is_partial 标记的增量结果
  • 支持 start/flush/stop 控制会话并指定模型、语言与词表提示
  • 提供 /ready 健康检查与 /transcribe_pcm_chunk 批量转写接口
  • 可作为 Python 库嵌入自己的 FastAPI 应用

容易踩的坑

需先安装 PortAudio 系统依赖(macOS 用 brew install portaudio,Linux 装 portaudio19-dev),否则 PyAudio 装不上;默认模型 tiny.en.pt 需提前下载到 whisperflow/models/ 目录;服务默认监听 8181 端口,而 ./run.sh -docker 启动的容器映射到 8888 端口。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

4 个版本v1.4.0
  1. v1.4.0最新正式版2026-11-01 · 2026-11-01 05:19 UTC

    Highlights

    Bounded audio backlog per session (#64, #65)

    While transcription was busy, every incoming WebSocket audio frame was queued without limit. WF_MAX_WINDOW_CHUNKS only applied after audio left the queue, so a client sending faster than real time, or a slow model, could grow server memory without bound.

    Each session now refuses audio once its queue holds WF_MAX_WINDOW_CHUNKS frames or WF_MAX_QUEUED_BYTES bytes, and the server closes the socket with the new close code 4001 (audio backlog full). Audio still queued at that point is discarded.

    • WF_MAX_QUEUED_BYTES: new, default 8388608 (8 MiB, about 4 minutes of 16 kHz int16 audio)
    • Flush and stop markers bypass the limit, so they still go through when the queue is full

    This is an additive protocol change. PROTOCOL_VERSION stays at 1. See docs/protocol.md.

    Full changelog: https://github.com/dimastatz/whisper-flow/compare/v1.3.0...v1.4.0

    Install

    pip install -U whisperflow==1.4.0
    

    PyPI: https://pypi.org/project/whisperflow/1.4.0/

  2. v1.3.02026-10-10 · 2026-10-10 04:22 UTC
    查看更新说明

    Highlights

    Model replicas for concurrent sessions (#52)

    A Whisper model isn't thread-safe, but every session used to share one model, so two simultaneous sessions could corrupt each other's output or crash. get_model() now returns a pool of model replicas. Each replica runs one transcription at a time on a dedicated executor.

    • WF_MODEL_REPLICAS: number of replicas (default 1, which runs transcriptions one at a time)
    • WF_TRANSCRIBE_WORKERS: transcription executor size (default 8)

    Committed prefix (#52)

    Once a segment's uncommitted audio passes WF_COMMIT_AFTER_MS, words that two consecutive partials agree on are committed. Their audio leaves the window, and their text is sent at the start of every later result and passed to Whisper as context. Long segments re-transcribe less audio, and their start stops changing.

    • WF_COMMIT_AFTER_MS (default 4000) and WF_COMMIT_MARGIN_MS (default 1000)
    • WF_COMMIT_PREFIX=0 turns it off

    This is an additive protocol change. PROTOCOL_VERSION stays at 1. See docs/protocol.md.

    Other changes

    • CI builds the package on every PR, and tag pushes no longer try to upload to PyPI (#51)
    • Fixed test_transcribe_streaming, which was mostly testing the error path (#53)

    Install

    pip install -U whisperflow==1.3.0
    

    PyPI: https://pypi.org/project/whisperflow/1.3.0/

    Full changelog: https://github.com/dimastatz/whisper-flow/compare/v1.2.1...v1.3.0

  3. v1.2.12026-10-08 · 2026-10-08 04:35 UTC

    这个版本没有写更新说明。

  4. 1.0-RCpre-release2024-08-10 · 2024-08-10 19:04 UTC

    这个版本没有写更新说明。

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    About The Project

    OpenAI Whisper

    OpenAI Whisper is a versatile speech recognition model designed for general use. Trained on a vast and varied audio dataset, Whisper can handle tasks such as multilingual speech recognition, speech translation, and language identification. It is commonly used for batch transcription, where you provide the entire audio or video file to Whisper, which then converts the speech into text. This process is not done in real-time; instead, Whisper processes the files and returns the text afterward, similar to handing over a recording and receiving the transcript later.

    Whisper Flow

    Using Whisper Flow, you can generate real-time transcriptions for your media content. Unlike batch transcriptions, where media files are uploaded and processed, streaming media is delivered to Whisper Flow in real time, and the service returns a transcript immediately.

    What is Streaming

    Streaming content is sent as a series of sequential data packets, or 'chunks,' which Whisper Flow transcribes on the spot. The benefits of using streaming over batch processing include the ability to incorporate real-time speech-to-text functionality into your applications and achieving faster transcription times. However, this speed may come at the expense of accuracy in some cases.

    Stream Windowing

    In scenarios involving time-streaming, it's typical to perform operations on data within specific time frames known as temporal windows. One common approach is using the tumbling window technique, which involves gathering events into segments until a certain condition is met.

    Streaming Results

    Whisper Flow splits the audio stream into segments based on natural speech patterns, like speaker changes or pauses. The transcription is sent back as a series of events, with each response containing more transcribed speech until the entire segment is complete.

    TranscriptEndTimeIsPartial
    Reality0.55True
    Reality is created1.05True
    Reality is created by the1.50True
    Reality is created by the mind2.15True
    Reality is created by the mind2.65False
    we can3.05True
    we can change3.45True
    we can change reality4.05True
    we can change reality by changing4.45True
    we can change reality by changing our mind5.05True
    we can change reality by changing our mind5.55False

    WebSocket Protocol

    Clients stream audio to /ws as binary frames (16 kHz, mono, int16 PCM) and receive JSON results shaped like {"is_partial": bool, "data": {"text": ...}, "time": ms}. Optional JSON text frames control the session: start (model, language, vocabulary prompt), flush and stop. A segment becomes final after a pause in speech, when its text stops changing, at the window cap, or on flush/stop. GET /ready reports protocol_version and the available models.

    The full contract, including close codes, endpointing settings, and how to add models, is in docs/protocol.md.

    Benchmarking

    The evaluation metrics for comparing the performance of Whisper Flow are Word Error Rate (WER) and latency. Latency is measured as the time between two subsequent partial results, with the goal of achieving sub-second latency. We're not starting from scratch, as several quality benchmarks have already been performed for different ASR engines. I will rely on the research article "Benchmarking Open Source and Paid Services for Speech to Text" for guidance. For benchmarking the current implementation of Whisper Flow, I use LibriSpeech.

    | Partial | Latency | Result |
    
    True  175.47  when we took
    True  185.14  When we took her.
    True  237.83  when we took our seat.
    True  176.42  when we took our seats.
    True  198.59  when we took our seats at the
    True  186.72  when we took our seats at the
    True  210.04  when we took our seats at the breakfast.
    True  220.36  when we took our seats at the breakfast table.
    True  203.46  when we took our seats at the breakfast table.
    True  242.63  When we took our seats at the breakfast table, it will
    True  237.41  When we took our seats at the breakfast table, it was with
    True  246.36  When we took our seats at the breakfast table, it was with the
    True  278.96  When we took our seats at the breakfast table, it was with the feeling.
    True  285.03  When we took our seats at the breakfast table, it was with the feeling of being.
    True  295.39  When we took our seats at the breakfast table, it was with the feeling of being no
    True  270.88  When we took our seats at the breakfast table, it was with the feeling of being no longer
    True  320.43  When we took our seats at the breakfast table, it was with the feeling of being no longer looked
    True  303.66  When we took our seats at the breakfast table, it was with the feeling of being no longer looked upon.
    True  470.73  When we took our seats at the breakfast table, it was with the feeling of being no longer
    True  353.25  When we took our seats at the breakfast table, it was with the feeling of being no longer looked upon as connected.
    True  345.74  When we took our seats at the breakfast table, it was with the feeling of being no longer looked upon as connected in any way.
    True  368.66  When we took our seats at the breakfast table, it was with the feeling of being no longer looked upon as connected in any way with the
    True  400.25  When we took our seats at the breakfast table, it was with the feeling of being no longer looked upon as connected in any way with this case.
    True  382.71  When we took our seats at the breakfast table, it was with the feeling of being no longer looked upon as connected in any way with this case.
    False 405.02  When we took our seats at the breakfast table, it was with the feeling of being no longer looked upon as connected in any way with this case.
    

    When running this benchmark on a MacBook Air with an M1 chip and 16GB of RAM, we achieve impressive performance metrics. The latency is consistently well below 500ms, ensuring real-time responsiveness. Additionally, the word error rate is around 7%, demonstrating the accuracy of the transcription.

    Latency Stats:
    count     26.000000
    mean     275.223077
    std       84.525695
    min      154.700000
    25%      205.105000
    50%      258.620000
    75%      339.412500
    max      470.700000
    

    Prerequisites

    Before installing WhisperFlow, ensure you have the following:

    • Python: 3.8 or higher (tested with Python 3.12)
    • PortAudio: Required for PyAudio (audio I/O library)
    Installing PortAudio

    macOS (using Homebrew):

    brew install portaudio
    

    Linux (Ubuntu/Debian):

    sudo apt-get install portaudio19-dev
    

    Linux (Fedora/RHEL):

    sudo dnf install portaudio-devel
    

    Windows: PortAudio is typically bundled with PyAudio wheels on Windows. If you encounter issues, refer to the PyAudio documentation.

    How To Use it

    Quick Start

    Get WhisperFlow running in under 5 minutes:

    # Clone the repository
    git clone https://github.com/dimastatz/whisper-flow.git
    cd whisper-flow
    
    # Setup environment, install dependencies, and run tests
    ./run.sh -local
    
    # Activate the virtual environment
    source .venv/bin/activate
    
    # Start the server on port 8181
    ./run.sh -run-server
    

    The server will be available at http://localhost:8181. Visit http://localhost:8181/health to verify it's running.


    Development Setup

    For contributors and developers:

    1. Initial Setup

    # Clone and enter the directory
    git clone https://github.com/dimastatz/whisper-flow.git
    cd whisper-flow
    
    # Setup environment: creates .venv, installs dependencies, runs tests
    ./run.sh -local
    

    What -local does:

    • Creates a fresh virtual environment (.venv)
    • Installs all dependencies from requirements.txt
    • Runs black formatter on code
    • Runs pylint linter (requires 9.9/10 score)
    • Runs all unit tests (requires 95% coverage)

    2. Running Tests

    # Activate environment
    source .venv/bin/activate
    
    # Run tests only (formatting + linting + unit tests)
    ./run.sh -test
    

    3. Running the Server

    # Activate environment
    source .venv/bin/activate
    
    # Start the FastAPI server on port 8181
    ./run.sh -run-server
    

    The server provides:

    • WebSocket endpoint: ws://localhost:8181/ws - Real-time streaming transcription
    • Health check: GET http://localhost:8181/health - Server status
    • Batch transcription: POST http://localhost:8181/transcribe_pcm_chunk - Process PCM audio files

    4. Running Benchmarks

    # Activate environment
    source .venv/bin/activate
    
    # Run benchmark tests (starts server, runs tests, stops server)
    ./run.sh -benchmark
    

    This measures transcription latency and word error rate (WER) using LibriSpeech test data.


    Docker Deployment

    Using Docker

    # Build and run the Docker container
    ./run.sh -docker
    

    What -docker does:

    • Stops and removes any existing whisperflow-container
    • Removes the old whisperflow-image
    • Builds a fresh Docker image with all dependencies
    • Runs the container on port 8888

    Manual Docker Setup

    # Build the image
    docker build -t whisperflow-image --file Dockerfile.test .
    
    # Run the container
    docker run --name whisperflow-container -p 8181:8181 -d whisperflow-image
    
    # Check logs
    docker logs whisperflow-container
    
    # Stop the container
    docker stop whisperflow-container
    

    Using as a Python Library

    Install WhisperFlow as a package to integrate real-time transcription into your own applications:

    Installation

    pip install whisperflow
    

    Basic Usage

    Create a WebSocket endpoint for real-time streaming transcription:

    from fastapi import FastAPI, WebSocket
    import whisperflow.streaming as st
    import whisperflow.transcriber as ts
    
    app = FastAPI()
    
    @app.websocket("/ws")
    async def websocket_endpoint(websocket: WebSocket):
        # Load the Whisper model (default: tiny.en.pt)
        model = ts.get_model()
        
        # Define transcription callback
        async def transcribe_async(chunks: list):
            return await ts.transcribe_pcm_chunks_async(model, chunks)
        
        # Define response callback
        async def send_back_async(data: dict):
            await websocket.send_json(data)
        
        try:
            await websocket.accept()
            
            # Create transcription session
            session = st.TranscribeSession(transcribe_async, send_back_async)
            
            # Process incoming audio chunks
            while True:
                message = await websocket.receive()
                if message["type"] == "websocket.disconnect":
                    break
                if message.get("bytes") is not None:
                    session.add_chunk(message["bytes"])
                elif message.get("text") == '{"type": "flush"}':
                    await session.flush()
        finally:
            # Client disconnected or an error occurred
            await session.stop()
    

    API Reference

    Transcriber Module (whisperflow.transcriber):

    • get_model(file_name="tiny.en.pt") - Load a Whisper model
    • list_models() - Names of the model files in whisperflow/models/
    • transcribe_pcm_chunks(model, chunks, lang="en", prompt=None) - Synchronous transcription; prompt is an optional vocabulary hint (Whisper initial_prompt)
    • transcribe_pcm_chunks_async(model, chunks, lang="en", prompt=None) - Async transcription

    Streaming Module (whisperflow.streaming):

    • TranscribeSession(transcribe_fn, send_back_fn) - Create a streaming session
    • session.add_chunk(audio_data) - Add audio chunk for processing
    • session.flush() - Finalize queued audio and send it as a final result
    • session.stop() - Stop the transcription session

    Audio Format Requirements

    WhisperFlow expects PCM audio data with the following specifications:

    • Sample Rate: 16 kHz
    • Channels: Mono (1 channel)
    • Format: 16-bit signed integer (int16)

    Available Commands

    All commands are available through ./run.sh:

    CommandDescription
    ./run.sh -localSetup environment, install dependencies, run tests
    ./run.sh -testRun formatter, linter, and unit tests
    ./run.sh -run-serverStart the FastAPI server on port 8181
    ./run.sh -benchmarkRun performance benchmark tests
    ./run.sh -dockerBuild and run Docker container

    Roadmap
    • Release v1.0-RC - Includes transcription streaming implementation.
    • Release v1.1 - Bug fixes and implementation of the most requested changes.
    • Release v1.2 - WebSocket control frames (start/flush/stop), per-session model, language and vocabulary prompt, silence endpointing, and a versioned wire protocol (docs/protocol.md).
    • Release v1.3 - Prepare the package for integration with the py-speech package.