FFmpeg Media
This module handles video processing within Drupal, automatically converting uploaded videos into various formats, generating thumbnails, and creating adaptive streams. It integrates seamlessly with the Media Library and allows for flexible configuration through profiles and plugins, offering features like transcription and extensibility for developers.
FFmpeg Media brings end-to-end video processing to Drupal. Upload a video through Media Library, and FFmpeg Media handles the rest — transcoding, thumbnail generation, adaptive streaming, and output delivery — all within Drupal's own content model.
Built for Drupal 11.3+ and 12, the module wraps FFmpeg 8 in a service-oriented architecture with queue-based processing, conversion profiles, formatter-based configuration, and a plugin system that ships 8 codecs, 7 output formats, and 13 processors out of the box. Every component is extensible through standard Drupal plugin APIs.
Editors keep their familiar Drupal workflows. Developers get clean service boundaries, event-driven integration points, and a full Drush command surface. Operations teams get health probes, Prometheus metrics, and queue visibility. FFmpeg Media is designed for the entire team.
At a glance
- Platform: Drupal 11.3+ / 12, PHP 8.5+, FFmpeg 8.x + ffprobe
- Plugins: 8 codecs · 7 output formats · 13 processors — all extensible
- Outputs: MP4, WebM, MKV, FLV, JXL, plus HLS & DASH adaptive streaming
- 6 optional submodules: streaming, player, UI, image, whisper, advanced
- Drupal-native: the Media upload UX is unchanged; conversion runs after save
How it works
- Upload or select a source video via Drupal Media.
- Configure conversion on Manage Display using the FFmpeg field formatter.
- Queue processing runs via cron, Drush, or worker processes.
- FFmpeg generates the configured outputs (for example MP4/WebM/HLS/DASH).
- Outputs are stored and tracked for retrieval, playback, and operations.
Why FFmpeg Media
- Drupal-native workflow: no replacement of the core Media upload UX.
- Queue safety: deduplication, retry/backoff, dead-letter handling, per-media locks, stuck-process recovery, lost-item reconciliation, and stalled-worker detection — built on Advanced Queue.
- Profile-based conversion: consistent output behavior per bundle/field.
- Modular architecture: enable only the submodules you need.
- Operational visibility: a status-report check for the FFmpeg/FFprobe binaries and version, plus health probes, metrics, progress endpoints, and Drush tooling.
Core features
- Queue-based transcoding with standard and large-file routing.
- Conversion profiles as config entities (container, codec, quality, processors) — deployable via configuration sync and validated on import.
- Hardware-acceleration detection with automatic software fallback.
- Field-formatter based conversion configuration on Manage Display.
- Progressive outputs: MP4, WebM, MKV, FLV, JXL.
- Adaptive streaming (submodule): HLS and DASH.
- Processors: thumbnails, GIFs, segment previews, HDR tone-mapping, watermarking, subtitle burn-in, audio normalization, manifests, metadata, and more.
Player and editorial UX
- Optional Vidstack-based player submodule (local-first loading by default, GDPR-friendly).
- Optional UI submodule with dashboard, status pages, and poster selection.
- Server-rendered poster overlay that stays visible until playback starts.
Third-party formatter support
- Automatic injection of converted sources into any third-party video formatter (e.g. Video.js) via
hook_media_view_alter(). - Public
VideoSourceResolverservice for custom formatters to access converted outputs, poster thumbnails, and subtitle tracks. - No code changes needed in third-party modules — converted sources replace originals transparently.
Whisper transcription (optional)
ffmpeg_media_whisperuses the whisper.cpp CLI (whisper-cli).- Two-step pipeline: FFmpeg audio extraction + transcription to SRT/VTT.
- Transcription runs on a cron queue, so a long job never blocks the request.
What this module does not do
- It does not replace Drupal core upload handling.
- It does not bundle FFmpeg/ffprobe binaries.
- It is not a managed SaaS video platform.
Requirements
- Drupal 11.3+ or Drupal 12
- PHP 8.5+
- FFmpeg 8.x and ffprobe available on the host/container
- Core modules: Media, File
- Contrib module: Advanced Queue — pulled in automatically by Composer; powers the conversion queues
Production setups should run queue workers (cron/Drush), ensure writable output storage, and monitor queue/system health. The status report shows whether FFmpeg/FFprobe are reachable and which version is in use.
Quick start
Fastest path: drush recipe modules/contrib/ffmpeg_media/recipes/ffmpeg_media_quickstart creates a ready-to-use Video media type with playback and auto-conversion in one command (an adaptive-streaming variant ships alongside it). Manual setup:
- Enable the module:
drush en ffmpeg_media - Verify binaries:
drush ffmpeg:status - Create/edit conversion profiles at
/admin/config/media/ffmpeg-media/profiles - Open Manage Display for your media bundle.
- Add the FFmpeg formatter to the source field.
- Enable auto-convert and choose a profile.
- Upload a test video.
- Process the queue:
drush ffmpeg:process
Whisper setup (optional)
Install whisper.cpp and whisper-cli:
git clone https://github.com/ggml-org/whisper.cpp.git cd whisper.cpp cmake -B build cmake --build build --config Release sudo cmake --install build --config Release
Download a model and verify the CLI:
./models/download-ggml-model.sh base.en whisper-cli --help
Then configure the path/model at /admin/config/media/ffmpeg-media/whisper. Optional advanced path: build FFmpeg with --enable-whisper and verify via ffmpeg -filters | grep whisper.
Submodules
- ffmpeg_media_streaming — HLS/DASH outputs and streaming settings.
- ffmpeg_media_player — Vidstack-based playback formatters.
- ffmpeg_media_ui — dashboard, status, poster selection, queue tools.
- ffmpeg_media_image — thumbnails, GIFs, segment previews.
- ffmpeg_media_whisper — transcription/subtitles via the whisper.cpp CLI.
- ffmpeg_media_advanced — two-pass, HDR, watermark, subtitle burn-in, audio helpers.
Drush commands
Conversion, queue management, monitoring, and maintenance:
- Conversion:
ffmpeg:convert,ffmpeg:convert-all,ffmpeg:reconvert,ffmpeg:requeue-missing - Queue:
ffmpeg:process,ffmpeg:queue-clear,ffmpeg:queue-pause,ffmpeg:queue-resume,ffmpeg:queue-reconcile - Monitoring:
ffmpeg:status,ffmpeg:info,ffmpeg:progress,ffmpeg:processes,ffmpeg:dead-letters - Maintenance:
ffmpeg:kill-stuck,ffmpeg:cleanup,ffmpeg:integrity-check,ffmpeg:generate-thumbnails - Whisper submodule:
ffmpeg:transcribe
Production guidance
- Tune concurrency based on CPU, memory, and storage throughput.
- Keep health probes and metrics integrated into monitoring.
- Run integrity checks periodically.
- Use environment variables for sensitive credentials.
Security notes
- Array-based process execution for FFmpeg/ffprobe — no shell, no command injection.
- Path validation and stream-wrapper constraints for file operations.
- Role/permission-gated operations and API endpoints.
- Token-hardened, fail-closed health-probe model for production deployments.
Developer extensibility
- Plugin types: codec, output, processor.
- Service-based architecture with DI/autowiring.
- Conversion lifecycle events for custom integrations.
- Public
VideoSourceResolverInterfacefor programmatic access to converted outputs.
FAQ
Does this replace Drupal Media uploads?
No. Uploads remain Drupal-native; FFmpeg Media starts after save.
Do I need all submodules?
No. Enable only the capabilities you need.
Can it run without the UI submodule?
Yes. Core workflows are available via formatter config and Drush.
Can I use GPU acceleration?
Yes. Hardware detection with software fallback is built in; exact encoder availability depends on your FFmpeg build and host hardware.
Does it work with third-party players like Video.js?
Yes. Converted sources are automatically injected into any third-party video formatter — no configuration needed.