Skip to main content

Summary

Compact audio player featuring a modern “iMessage-style” voice note pill. Includes waveform visualization, play/pause controls, optional looping, and optional client-side Whisper transcription (inspired by Xenova/whisper-web). State is typically stored as a URL string to the audio file — the transcript is shown in the UI only and is not written back to field state.

Basic usage

Dynamic Audio (from State)

Static Audio (Fixed Source)

With client-side transcription

Install the Whisper runtime once per app first — see Installing the Whisper runtime. Without it the player still works; Transcribe stays soft-disabled. See Speech-to-text (Whisper) for model, language, and full details.

State & validation

Stored value

State is an HTTP(S) or root-relative audio URL string. URLs containing credentials, control characters or unsafe schemes are rejected. This field plays a URL; it does not upload or store the audio file.

Validation rules (built-in)

Ensures the state is a valid media URL string.

Configuration API

Methods accept closures as well as the displayed values, unless noted.

Speech-to-text (Whisper)

Enable optional client-side speech-to-text on any AudioField that has a playable audio URL. The Quantized switch selects q8 weights; disabling it selects fp32. Inference uses the WASM backend and does not require WebGPU or cross-origin isolation. Transcription runs entirely in the user’s browser via @huggingface/transformers — no server API key, no upload of audio to your backend for STT.
When transcription is enabled and the Whisper runtime is installed, the field renders:
  1. Transcribe Audio — fetches the audio URL, decodes it with Web Audio, runs Whisper, and shows the result below the player.
  2. Settings (gear) — submenu for model, language, task, Multilingual, and Quantized toggles (same UX pattern as Xenova/whisper-web).
If the runtime is missing, the audio player still works. The Transcribe UI is soft-disabled and the field shows an install CTA with php artisan fff:whisper:install.

Installing the Whisper runtime

The browser ONNX / WASM runtime (~15 MB) is not included in the Composer package and is not published by php artisan filament:assets. Only apps that use ->transcription() need it.
Important: filament:assets syncs Flex Fields CSS/JS and small static media (beeps, NPS emoji, etc.). It never installs Whisper. Use the commands below.
One-time install
What this does:
  1. Downloads the pinned @huggingface/transformers 4.3.1 browser bundle and its matching ONNX WASM/loader from the jsDelivr npm CDN.
  2. Verifies each file with SHA-256 against the package manifest (WhisperRuntimeManifest).
  3. Writes them to public/filament-flex-fields-assets/whisper/4.3.1/.
  4. Writes public/filament-flex-fields-assets/whisper/4.3.1/.installed.json (version + hashes + timestamp).
  5. Does not install source maps (.map files are excluded on purpose).
After a successful install, hard-refresh the admin panel and use ->transcription() as usual.
Inspect status
Shows package pin, public directory, whether files are present, and any missing or SHA-256-mismatched files.
CI / deploy gate
When your app requires transcription in production, fail the pipeline if the runtime is missing or corrupt:
Exit code 0 = verified. Exit code 1 = missing or invalid (print includes the fix command).
Re-download
Re-fetches all files even when the current install already verifies. Use after a failed partial download, disk restore, or when upgrading Flex Fields to a release that pins a new transformers version (hashes change — status will report mismatches until you reinstall).
Command reference
Files on disk
The field resolves the installed runtime URLs automatically. Each runtime version has its own directory so cached modules and already-open pages cannot mix different runtime versions. The manifest also pins the matching onnxruntime-web release; its .mjs loader and .wasm file are installed together.
Deploy notes
  • Run fff:whisper:install on each environment that needs transcription (or copy the verified public/filament-flex-fields-assets/whisper/4.3.1/ directory as a build artifact).
  • Commit the whisper directory only if your deploy strategy requires it; many teams install during CI/CD instead.
  • Do not expect composer install or filament:assets alone to restore Whisper after an upgrade.
  • Upgrading from an older Flex Fields release that bundled Whisper in Composer: remove any stale vendor/public copies from the old layout, then run fff:whisper:install once.
Network requirements for install
The install command needs outbound HTTPS to the jsDelivr npm CDN (cdn.jsdelivr.net/npm/@huggingface/transformers@…). Air-gapped hosts must vendor the verified files into public/filament-flex-fields-assets/whisper/4.3.1/ by another channel, then confirm with fff:whisper:install --check. Install access must allow both the pinned @huggingface/transformers and onnxruntime-web npm packages. Model weights (Hugging Face) are still downloaded in the browser on first Transcribe — that is separate from this artisan install.

Transcript is not field state

The transcript appears in .fff-audio-field__transcript for the current page session. It is not saved to the Eloquent attribute / form state. To persist text, bind a separate field (for example Textarea) or use server-side transcription on VoiceNoteRecorderField via Media OS.

How it works

Progress during the first model load shows the downloading file and percentage (for example encoder_model.onnx 42%). Model load times out after 10 minutes — enable Quantized or pick a smaller model on slow connections.

Requirements & limitations

Configuration API (transcription)

Methods accept closures as well as the displayed values, unless noted. Invalid tasks throw InvalidArgumentException at config evaluation time.

Global defaults (config/filament-flex-fields.php)

These config keys apply when the matching field method is not set:
Field-level defaults when you call ->transcription() without extra methods:

Model catalog & settings toggles

Models and filtering follow whisper-web’s AudioManager: The settings menu lists models with approximate download size, for example Xenova/whisper-tiny (41 MB). The Language submenu exposes the full Whisper ISO 639-1 catalog (90+ languages plus Auto detect), aligned with whisper-web.

Real-world examples

Polish voice note with fixed language
English-only, quantized distil model
Transcribe button only (no user-facing settings)
Translate foreign audio to English

Troubleshooting

User-facing copy is translatable under filament-flex-fields::default.audio.transcription_* in resources/lang.

Real-world examples

Post-Recording Preview

Fixed Demo Track


Playground

/admin/flex-fields/audio-field Two sections: See Playground for setup.

CSS classes (reference)

Keyboard, layout and resource use

Focus the waveform and use Left/Right to seek by five seconds, Home for the beginning and End for the end. Seeking follows RTL direction. The play button supports normal button keyboard activation. Read-only and disabled fields block interaction. The compact player keeps its existing appearance in all three sizes. Waveform bar count adapts to the available width. Provide waveform() when you already have peaks to avoid fetching audio for analysis. Without custom peaks, the initial display uses a deterministic waveform; real analysis is lazy and never delays playback. Automatic analysis skips tracks whose known duration exceeds ten minutes and limits downloads to 32 MB. Only playing audio runs a progress animation. Removing the field stops playback and cancels owned requests, gestures, observers and timers. Inactive tabs and modals use the FLEX activation lifecycle; merely scrolling the field out of view does not stop it. Whisper is optional. Changing the source or removing the field cancels its pending fetch and discards obsolete results. An already running native model inference may continue internally; it cannot update a disposed field. Model weights remain subject to browser caching and memory limits. For long recordings or centralized processing, use a server transcription provider with Voice Note Recorder instead.
Last modified on October 16, 2026