Search by

displace / ext-whisper

ericmann

PHP 8.3+ native, in-process speech-to-text via whisper.cpp: 16kHz WAV in, text + timestamped segments out.

Package info

github.com/DisplaceTech/ext-whisper

Language:Rust

Type:php-ext

Ext name:ext-whisper

pkg:composer/displace/ext-whisper

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 3

Open Issues: 6

v0.1.3 2026-10-29 18:54 UTC

This package is auto-updated.

Last update: 2026-10-29 18:55:22 UTC


README

Local speech-to-text for PHP, in-process.
16kHz WAV in, text + timestamped segments out — no Python sidecar, no remote API, no audio leaving the box.

CI PHP 8.3 / 8.4 / 8.5 MIT License Documentation

Status

Feature-complete for its scope. Maintained: dependency updates and new-model support ship as patch/minor releases — see the CHANGELOG. Last verified: PHP 8.3/8.4/8.5 (NTS on macOS arm64 + Linux x86_64; ZTS 8.4/8.5 on Linux), whisper-rs 0.16.0 (whisper.cpp 1.8.3), ggml-tiny.en, 2026-10-29.

Remaining ideas are tracked as future issues. Co-maintainers welcome — if you run this in production and want a say in where it goes, open an issue or a PR.

What is ext-whisper?

ext-whisper is a PHP 8.3+ extension that loads a whisper.cpp model and runs speech-to-text in the PHP process, on CPU. Written in Rust on top of ext-php-rs and whisper-rs.

  • 🎙️ Transcription with timestamps — full text plus time-aligned segments, offsets in seconds.
  • 🧾 Contracts-shaped output — segment rows match Displace\AI\Contracts\Transcriber exactly; the adapter is two lines.
  • 🧰 Actionable errors — a non-conforming WAV throws with the precise ffmpeg one-liner that fixes it.
  • 🌍 Multilingual + translate — ['language' => 'de'] hints, ['translate' => true] to English (multilingual models).
  • 🧵 Thread-safe by construction — one model handle, a fresh whisper state per call, no shared mutable state.
  • 🤫 Quiet by default — whisper.cpp's stderr firehose is silenced; EXT_WHISPER_LOG=1 restores it.

Quick start

mkdir -p models
curl -L -o models/ggml-tiny.en.bin \
    https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.en.bin

make build
php -d extension=$PWD/target/debug/libwhisper.so examples/transcribe.php \
    models/ggml-tiny.en.bin tests/fixtures/jfk.wav
<?php
use Displace\Whisper\Model;

$model  = Model::load('models/ggml-tiny.en.bin');
$result = $model->transcribe('audio/meeting.wav');

echo $result->text(), PHP_EOL;

foreach ($result->segments() as $s) {
    printf("[%6.2fs → %6.2fs] %s\n", $s['start'], $s['end'], $s['text']);
}

$model->close();

Input must be 16kHz mono 16-bit PCM WAV; everything else converts in one line (ffmpeg -i in.mp3 -ar 16000 -ac 1 -c:a pcm_s16le out.wav) and the error messages carry that exact command.

Documentation

whisper.displace.tech — install, audio preparation, the full API surface. Built from docs/ with mdbook, deployed on every push to main.

Part of a stack

Transcribe → chunk → embed → search → answer, entirely on your hardware:

Stage Package What it does
Transcribe ext-whisper (this repo) Speech-to-text over whisper.cpp
Chunk ai-toolkit Text chunkers and packed-vector math, pure PHP
Embed · rerank · answer ext-infer Local LLM chat, embeddings and reranking over llama.cpp
Search ext-turbovec Compressed in-memory vector search (TurboQuant)
Integrate ai-contracts The interfaces frameworks code against
Reference app rag-over-markdown The whole pipeline over a folder of markdown

Every package links the others; the extensions share one scaffold, ext-template.

For ext-whisper specifically: transcribe → chunk → embed → search is a searchable audio archive, entirely on your hardware, and the ai-contracts Transcriber interface is the integration surface.

Compatibility

macOS arm64 Linux x86_64 Linux arm64 Windows
PHP 8.3 ✅ ✅ ✅ —
PHP 8.4 ✅ ✅ ✅ —
PHP 8.5 ✅ ✅ ✅ —

ZTS is enabled in composer.json and CI runs the PHPT suite on ZTS PHP 8.4/8.5 (Linux) weekly; release binaries are NTS-only.

Roadmap

Shipped   Model::load() / transcribe() / close() · Transcription with seconds-offset segments in the ai-contracts shape · strict WAV reader with ffmpeg-hint errors · typed exceptions · Rust unit tests + PHPT suite · CI matrix · PIE binaries + license manifest.

Remaining ideas (audio decoding via symphonia, word-level timestamps, detected language, progress callback, …) live as future issues, each with its reasoning. PLAN.md holds the design notes.

Deliberately out of scope (v0.1)

Audio decoding (mp3/m4a/ogg — the ffmpeg one-liner is the API; symphonia-based decoding is a v0.2 candidate) · streaming / realtime transcription · speaker diarization · word-level timestamps · GPU-default builds (CPU-first platform-wide; use_gpu exists for custom builds) · Windows.

Writing about this

The stack's launch series ran Sept 22 – Oct 1, 2026; everything else is at eric.mann.blog/writing.

License

MIT © 2026 Eric Mann / Displace Technologies. Statically links whisper.cpp (MIT, © The ggml authors) — see THIRD-PARTY-NOTICES.md.