Search by

shadowfiend / whisper

shadowfiendthenevermore

PHP manager for multiple instance of whispers

v0.1.1 2026-09-10 16:40 UTC

This package is auto-updated.

Last update: 2026-09-10 17:13:29 UTC


README

Whisper is a PHP library for managing multiple audio transcription providers through a single API. It handles provider registration and selection, accepts file paths or custom audio sources The package provides the integration layer rather than a built-in connection to a specific external Whisper service.

Features

  • Register and select named transcription providers.
  • Transcribe a local file or any custom AudioSourceInterface implementation.
  • Work with Transcript class and fields: text, duration, language, metadata, and timed segments.
  • Whisper service works with psr streams

Requirements

  • PHP 8.4 or later
  • Composer

Installation

Install the package with Composer:

composer require shadowfiend/whisper

How to use it

Basic usage of your own whisper provider

Register a provider, select it by name, and pass an audio file to transcribe():

<?php

use Sf\Whisper\Whisper;

$provider = new YourWhisperProvider();
$provider->setOptions([
    'api_key' => env('whisper_service_api_key'), // If your WhisperProvider should us API key
    'model' => 'whisper-1', // Whatever else in your options for whisper provider
]);

$whisper = new Whisper();
$whisper->addProvider('default', $provider);

$transcript = $whisper
    ->useProvider('default')
    ->transcribe('/path/to/audio.mp3');

echo $transcript->getText();

A string passed to transcribe() is automatically converted to a FileAudioSource. You can also select a provider through the magic __get method:

$transcript = $whisper->default->transcribe('/path/to/audio.mp3');

// Examples of registered providers, you should add it in your app before through addProvider()
$transcript = $whisper->openai->transcribe('/path/to/audio.mp3');
$transcript = $whisper->google->transcribe('/path/to/audio.mp3');
$transcript = $whisper->local->transcribe('/path/to/audio.mp3');

Usage of Transcript

Every provider returns a Transcript. Besides casting it to a string, you can inspect all available result data:

By default Transcript works with fields:

  • text
  • segments TranscriptSegment[] by default
  • duration 0 by default
  • language
  • metadata
echo (string) $transcript;
echo $transcript->getText();

$duration = $transcript->getDuration();
$language = $transcript->getLanguage();
$metadata = $transcript->getMeta();

foreach ($transcript->getSegments() as $segment) {
    echo sprintf(
        "[%s - %s] %s\n",
        $segment->getStart(),
        $segment->getEnd(),
        $segment->getText(),
    );
}

Providers can preserve timing information by adding TranscriptSegment objects:

use Sf\Whisper\Transcript;
use Sf\Whisper\TranscriptSegment;

$transcript = Transcript::create('Hello world', duration: 1.8)
    ->addSegment(new TranscriptSegment('Hello', start: 0.0, end: 0.7))
    ->addSegment(new TranscriptSegment(' world', start: 0.7, end: 1.8));

How to create custom whisper provider

Create a provider by extending AbstractWhisperProvider and implementing doTranscribe(). The method receives a PSR-7 stream opened at the beginning of the audio.

Note

Do not close stream inside of doTranscribe method because AbstractWhisperProvider always closes the stream after transcription.

<?php

use Psr\Http\Message\StreamInterface;
use Sf\Whisper\Providers\AbstractWhisperProvider;
use Sf\Whisper\Transcript;

final class YourWhisperProvider extends AbstractWhisperProvider
{
    protected function doTranscribe(StreamInterface $audio): Transcript
    {
        $audioContents = $audio->getContents();

        // Send $audioContents to your transcription service and map its response.
        $response = callYourTranscriptionService($audioContents, $this->options);

        $transcript = $Transcript::create(
            text: $response['text'],
            duration: $response['duration'],
        );

        // If you have segments you can use addSegment() or addSegments()
        $transcript->setSegments(TranscriptSegment[]);
    }
}

Note

Provider-specific configuration is available through setOptions() and getOptions().

Custom Audio Sources

Implement AudioSourceInterface when audio does not come from a local file. Each extract() call must return a new PSR-7 stream positioned at the beginning.

<?php

use GuzzleHttp\Psr7\Utils;
use Psr\Http\Message\StreamInterface;
use Sf\Whisper\Sources\AudioSourceInterface;

final class MemoryAudioSource implements AudioSourceInterface
{
    public function __construct(
        private readonly string $contents
    )
    {
    }

    public function extract(): StreamInterface
    {
        return Utils::streamFor($this->contents);
    }
}

$transcript = $whisper->transcribe(new MemoryAudioSource($audioContents));

Custom Error Exceptions

  • WhisperException is thrown when transcription is requested before selecting a provider.
  • TranscribeException wraps any exception thrown by a provider and keeps the original exception as previous.

Mock Components

MockWhisperProvider and MockAudioSource are included for tests and examples. They exchange predefined JSON data and do not transcribe real audio.

use Sf\Whisper\Providers\MockWhisperProvider;
use Sf\Whisper\Sources\MockAudioSource;
use Sf\Whisper\Whisper;

$whisper = new Whisper();
$whisper->addProvider('mock', new MockWhisperProvider());

$transcript = $whisper->useProvider('mock')->transcribe(new MockAudioSource());

echo $transcript->getText(); // Hello from mock i am mock

Development

Development commands run in Docker through Make:

make install
make install-hooks
make lint
make test
  • make install builds the development image and installs Composer dependencies into vendor/.
  • make install-hooks enables the repository's Git hooks after cloning. The pre-push hook runs the same build, lint, and test checks as CI.
  • make lint runs PHPStan at the maximum level over src/ and tests/.
  • make test builds the image and runs the PHPUnit test suite.

License

This project is available under the MIT License.