Automation and FFmpeg
The commands API lets you define FFmpeg presets, queue conversions, inspect logs, stop running work, and optionally run post-conversion automation such as VMAF checks and conditional source deletion.
Command preset model
CommandPreset documents the conversion recipe saved in MongoDB.
| Field | Purpose |
|---|---|
name | Human-readable preset name. |
description | Optional description shown to users. |
argument_template | FFmpeg argument template. Must contain both {input} and {output}. |
output_suffix | Suffix added before the output extension. Defaults to .converted. |
output_extension | Output file extension. Normalized to a real extension such as .mkv. |
is_enabled | Enables or disables the preset for execution. |
check_vmaf_score_after_running | If true, the backend runs post-conversion VMAF analysis. |
delete_input_file_after_running | If true, the backend attempts to delete the source file after success. |
delete_input_only_if_vmaf_is_larger_than | Optional threshold from 0 to 100 for conditional source deletion. |
Example preset
{
"name": "AV1 1080p",
"description": "Convert the source to AV1 and keep audio unchanged.",
"argument_template": "-hide_banner -y -i {input} -c:v av1_qsv -b:v 3M -c:a copy {output}",
"output_suffix": ".converted",
"output_extension": ".mkv",
"is_enabled": true,
"check_vmaf_score_after_running": true,
"delete_input_file_after_running": false,
"delete_input_only_if_vmaf_is_larger_than": null
}
Preset management endpoints
| Endpoint | Purpose |
|---|---|
GET /api/commands | List all presets. |
POST /api/commands | Create a preset. |
PUT /api/commands/{id} | Replace an existing preset. |
DELETE /api/commands/{id} | Remove a preset. |
Validation rules worth knowing:
argument_templatemust include both{input}and{output}- presets with
delete_input_only_if_vmaf_is_larger_thanmust keep the threshold between0and100 - a disabled preset cannot be run
Running a preset
POST /api/commands/{id}/run
{
"input_path": "D:\\Media\\Movies\\Movie.mkv"
}
The backend will:
- load the preset
- verify the input file exists
- build an output path from the preset suffix and extension
- prevent in-place conversion
- reserve the input and output files so conflicting jobs cannot run at the same time
- enqueue the job in the tracker
The response is 202 Accepted and includes the generated process_id, resolved output_path, and display-ready FFmpeg arguments.
Process lifecycle endpoints
| Endpoint | Purpose |
|---|---|
GET /api/commands/processes | List queued, running, and finished jobs. |
GET /api/commands/processes/{processId} | Return one job with stdout and stderr logs. |
POST /api/commands/processes/{processId}/kill | Stop a running job or cancel a queued one. Optional delete_output=true removes the output file if possible. |
DELETE /api/commands/processes/{processId} | Remove a finished record. Running or queued records cannot be deleted. |
POST /api/commands/processes/clear-completed | Bulk-remove completed entries. |
Queue and persistence behavior
- jobs are stored in MongoDB collection
ffmpeg_jobs - queue state survives backend restarts
- concurrency is capped by
FFMPEG_MAX_PARALLEL_PROCESSES - file reservations prevent overlapping work on the same input or output path
- logs are persisted and exposed through the details endpoint
Post-run automation
When either check_vmaf_score_after_running or delete_input_file_after_running is enabled, the backend starts a background post-run automation workflow after the conversion is accepted.
That workflow:
- waits for the conversion job to finish
- skips follow-up work if the conversion failed
- optionally runs a VMAF comparison between input and output
- optionally deletes the source file
- respects
delete_input_only_if_vmaf_is_larger_thanwhen a threshold is configured
This makes it possible to implement safer transcode pipelines where deletion only happens after a measured quality check.
Execution modes
Local mode
Set:
FFMPEG_EXECUTION_MODE=local
Use this when the backend host already has direct access to FFmpeg and the media library.
Docker mode
Set:
FFMPEG_EXECUTION_MODE=docker
FFMPEG_WORKER_PROFILE=cpu
Use this when you want worker containers for isolation or hardware-specific profiles.
Requirements:
- mount the Docker socket into the backend container
- make media paths visible to both the backend and worker containers
- mount
/dev/driwhen using Intel or AMD profiles
Worker profiles
| Profile | Behavior |
|---|---|
cpu | No GPU-specific flags or device mounts. |
intel | Passes /dev/dri and is intended for Intel acceleration workflows. |
amd | Passes /dev/dri for AMD acceleration workflows. |
nvidia | Uses GPU flags and NVIDIA runtime environment variables. |
Operational tips
- Start with
localmode unless you specifically need worker containers. - Keep media mounts consistent if the backend itself runs in Docker.
- Poll the process details endpoint when you need logs for a job details page.
- Use
clear-completedor targeted delete to keep the process history manageable.