directus-extension-transcode-video-operation
v1.2.0
Published
Transcode uploaded videos to adaptive HLS streams with multiple quality levels (240p, 480p, 720p, 1080p, 4K)
Maintainers
Readme
Transcode Video Operation
A Directus custom operation that transcodes uploaded videos to adaptive HLS streams with multiple quality levels for optimal playback across different devices and network conditions.
Overview
This extension adds a custom operation to Directus Flows that automatically transcodes video files into HLS format with multiple quality levels (240p, 480p, 720p, 1080p, 4K). The operation creates adaptive streaming playlists, extracts a thumbnail, and organizes all transcoded assets in Directus folders.
Features
- Adaptive HLS Streaming: Transcodes videos to HLS format with multiple quality levels
- Smart Quality Selection: Automatically prevents upscaling - only transcodes qualities equal to or lower than source resolution
- Multiple Quality Levels: Supports 240p, 480p, 720p, 1080p, and 2160p (4K)
- Automatic Thumbnail Extraction: Extracts thumbnail image at 1 second from video
- High Bit Depth Support: Automatically detects and converts 10-bit videos to 8-bit for maximum compatibility
- Folder Organization: Automatically creates and organizes transcoded files in Directus folders
- Video Metadata Extraction: Extracts dimensions, duration, and orientation information
- Cloud Storage Support: Works with local storage, S3, GCS, Azure, and other cloud storage adapters
- Automatically downloads source files from cloud storage for processing
- Uploads transcoded files to specified storage location
- Cleans up temporary local files when using cloud storage
- Flexible Storage Configuration: Choose where transcoded files are stored:
- Environment default (first configured storage)
- Same as source file
- Custom storage location
Requirements
- HLS Capable Video Player: The default HTML5 player won't play it. You need a player with HLS streaming support. For Directus Data Studio you can install the Streaming Video Player extension
- FFmpeg: FFmpeg must be installed and available in the system PATH
- Installation:
apt-get install ffmpeg(Debian/Ubuntu) orbrew install ffmpeg(macOS) - Verify:
ffmpeg -versionandffprobe -version - Docker: For Docker deployments (https://directus.io/docs/self-hosting/deploying#docker-compose-examples):
- Add build configuration to your
docker-compose.yml:directus: build: context: . dockerfile: Dockerfile - Create a
Dockerfilein the same directory with:FROM directus/directus:11.13.2 USER root RUN apk add --no-cache ffmpeg RUN ffmpeg -version && ffprobe -version USER node - Rebuild and restart your containers:
docker compose up --build -d
- Add build configuration to your
- Installation:
Installation
Via Directus Marketplace
- Open your Directus project
- Navigate to Settings → Extensions
- Click Browse Marketplace
- Search for "Transcode Video Operation"
- Click Install
Manual Installation
- Install package
npm install directus-extension-transcode-video-operation- Build the extension:
npm run build- Copy the
distfolder to your Directus extensions directory:
directus/extensions/directus-extension-transcode-video-operation/- Restart your Directus instance
Usage
Setting Up a Flow
- Navigate to Settings → Flows
- Create a new flow or edit an existing one
- Add a trigger (e.g., Event Hook for file uploads)
- Add the Transcode Video Operation
- Configure the operation parameters (see Configuration below)
- Save and activate the flow
Operation Parameters
File (required): The Directus file to transcode
- Accepts: File UUID (string) or Directus File Object
- Use
{{ $last }}to reference the file from a previous operation - Example:
{{ $trigger.body.key }}for event hook triggers - Example:
{{ $last.video }}for file object from collection
Folder (optional): The Directus folder where transcoded files will be stored
- Uses Directus folder selector interface with create capabilities
- If not provided, a new folder will be created automatically
- A subfolder with the video filename will be created automatically
- All transcoded segments, playlists, and thumbnails will be stored in this folder structure
Quality Levels (optional, default: all qualities): Select which quality levels to transcode
- Available: 240p, 480p, 720p, 1080p, 2160p (4K)
- Only qualities equal to or lower than source resolution will be transcoded (no upscaling)
- Example: A 1080p source video will only transcode 240p, 480p, 720p, and 1080p (4K will be skipped)
Storage Adapter (optional, default:
Environment Configuration (First One)): Where transcoded files should be stored- Environment Configuration (First One): Uses the first configured storage location from environment variables
- Same as Source File: Stores transcoded files in the same storage location as the source file
- Other: Allows specifying a custom storage location name (must match one of your configured
STORAGE_LOCATIONS)
Target Storage Location (optional): Custom storage location name
- Only visible when "Storage Adapter" is set to "Other"
- Must match one of your configured storage locations (e.g.,
local,s3,gcs) - Example: If you have
STORAGE_LOCATIONS="local,s3", you can specifys3here
Thread Count (optional, default:
1): Number of CPU threads to use for encoding1= Single-threaded encoding (default, most compatible)2+= Use specific number of threads (e.g.,4for 4 threads)0= Use all available CPU cores (fastest, but may impact system performance)- Note: More threads = faster encoding, but higher CPU usage
Process Priority (optional, default:
19): CPU priority (nice value) for transcoding process- Range: 0 (default/highest priority) to 19 (lowest priority)
- Lower values = higher CPU priority (may impact system performance)
- Higher values = lower CPU priority (better for background processing)
- Recommended: Use
19when transcoding might impact system performance - Note: Only works on Unix-like systems (Linux, macOS). On Windows, this setting is ignored with a warning.
Playlist Reference Type (optional, default:
id): How playlists should reference segmentsid(default): Uses Directus file IDs - playlists reference segments as/assets/:file_idto run against /assets endpointfilename_disk: Uses original filenames - playlists reference segments by filename (useful for custom streaming servers)
Example Flow Configuration (Collection Item Trigger)
Trigger: Manual trigger
- Collections:
your_collection - Asynchronous:
enabled
Read Data: Read your_collection with video field query:
- IDs:
{{$trigger.body.keys[0]}} - Query:
{
"fields": "*,video.*"
}Transcode Video Operation:
- File:
{{ $last.video }} - Folder:
{{ $last.video.folder }}(or select/create via folder picker) - Quality Levels:
["240p", "480p", "720p", "1080p"] - Storage Adapter:
Same as Source File(orEnvironment Configuration (First One), orOtherwith custom storage) - Thread Count:
1(or0for all cores,4for 4 threads, etc.) - Process Priority:
19(or0for higher priority) - Playlist Reference Type:
id
Update Data: Update your_collection with payload:
{
"stream_link": "/assets/{{$last.master.id}}",
"image": "{{$last.metadata.thumbnail}}"
}Collection Flow Example (sets stream link field in directus file)
Output Structure
The operation creates the following files in the specified virtual folder:
folder/
└── video-filename/
├── video-filename_240p.m3u8 # 240p quality playlist
├── video-filename_240p_000.ts # 240p segments
├── video-filename_240p_001.ts
├── video-filename_480p.m3u8 # 480p quality playlist
├── video-filename_480p_000.ts # 480p segments
├── video-filename_720p.m3u8 # 720p quality playlist
├── video-filename_720p_000.ts # 720p segments
├── video-filename_1080p.m3u8 # 1080p quality playlist
├── video-filename_1080p_000.ts # 1080p segments
├── video-filename_playlist.m3u8 # Master playlist (references all qualities)
└── video-filename_thumb.jpg # Thumbnail imageOperation Response
The operation returns a JSON object with:
{
"master": {
"id": "file-uuid",
"filename_disk": "video-filename_playlist.m3u8"
},
"metadata": {
"availableQualities": [240, 480, 720, 1080],
"dimensions": {
"width": 1920,
"height": 1080,
"isVertical": false
},
"duration": 125000,
"thumbnail": "thumbnail-file-uuid"
},
"files": [
{
"filename_disk": "video-filename_240p.m3u8",
"id": "file-uuid-1"
},
{
"filename_disk": "video-filename_thumb.jpg",
"id": "file-uuid-2"
}
// ... more files
]
}How It Works
- File Input Processing:
- If file is a UUID string, fetches the full file object from Directus
- If file is already a file object, uses it directly
- Source File Handling:
- Local Storage: Uses file directly from disk
- Cloud Storage: Downloads source file to temporary location for processing
- Storage Configuration: Determines target storage location based on user selection
- Resolves storage driver (local vs. cloud) from environment configuration
- File Validation: Checks that the input file exists and is accessible
- Metadata Extraction: Uses
ffprobeto get video dimensions, duration, and bit depth - Quality Filtering: Filters out quality levels that would require upscaling
- Bit Depth Detection: Detects 10-bit videos and adds pixel format conversion
- Transcoding: Uses
ffmpegto transcode each quality level sequentially- Creates HLS segments (
.tsfiles) and quality playlists (.m3u8) - Uses H.264 codec with optimized settings for each quality
- Applies process priority (nice value) on Unix-like systems
- Creates HLS segments (
- Master Playlist: Generates master playlist with bandwidth and resolution metadata
- Thumbnail Extraction: Extracts thumbnail at 1 second mark (if not already exists)
- Folder Creation: Creates Directus virtual folder structure for organization
- File Upload:
- Checks for existing files to prevent duplicates
- For cloud storage: Uploads files and cleans up local copies
- For local storage: Files remain on disk
- Cleanup:
- Removes temporary downloaded source file (if from cloud storage)
- Removes local transcoded files (if target storage is cloud)
Technical Details
Encoding Settings
- Codec: H.264 (libx264)
- Profile: Main (maximum compatibility)
- Audio: AAC, 48kHz
- Segment Duration: 4 seconds
- Playlist Type: VOD (Video on Demand)
- CRF: 20 (constant rate factor for quality)
- Process Priority: Configurable nice value (0-19) for CPU priority control
Storage Handling
- Local Storage: Files are created directly on disk and registered in Directus
- Cloud Storage:
- Source files are downloaded via HTTP to temporary location for FFmpeg processing
- Transcoded files are uploaded to cloud storage via Directus FilesService
- Temporary local files are automatically cleaned up after upload
- Storage Detection: Automatically detects storage driver type from environment configuration
Quality Bitrates
- 240p: 400 kbps video, 64 kbps audio
- 480p: 1400 kbps video, 128 kbps audio
- 720p: 2800 kbps video, 128 kbps audio
- 1080p: 5000 kbps video, 192 kbps audio
- 2160p (4K): 20000 kbps video, 192 kbps audio
Upscaling Prevention
The operation automatically detects the source video resolution and only transcodes quality levels that are equal to or lower than the source. For example:
- 1080p source: Only transcodes 240p, 480p, 720p, 1080p (skips 4K)
- 720p source: Only transcodes 240p, 480p, 720p (skips 1080p and 4K)
- 4K source: Transcodes all available quality levels
Integration with Streaming Video Player
This operation works seamlessly with the Streaming Video Player extension (available in Directus Marketplace):
- Transcode videos using this operation
- Store the master playlist reference in a string field
- Use the Streaming Video Player interface to play the HLS stream
License
MIT
