Process WordPress Video Uploads with FFmpeg Micro (No Plugin Required)

WordPress doesn't process video. Upload an MP4 through the media library and WordPress stores it as-is. No compression, no transcoding, no resolution adjustment. If you need to compress video uploads, resize them to 720p, or convert to a web-friendly codec, you're on your own.
Quick Answer
You can process WordPress video uploads by hooking into the add_attachment action and sending the file URL to the FFmpeg Micro REST API using wp_remote_post(). FFmpeg Micro is a cloud API that lets you add video processing to any app with a single HTTP call, no FFmpeg installation, no server management. The processed file downloads back to your media library automatically.
Why WordPress Has No Built-In Video Processing
WordPress is a CMS, not a media pipeline. The media library accepts uploads and generates image thumbnails, but it skips video entirely. There's no transcoding queue, no codec selection, no compression settings.
Developers typically solve this three ways. Install FFmpeg on the server and call it with exec(). Use a plugin like JW Player, Cloudflare Stream, or Mux that handles video through a SaaS platform. Or build a custom integration with an external API.
Installing FFmpeg directly on a shared hosting environment is usually impossible. Managed WordPress hosts like WP Engine and Flywheel block shell access. And even on a VPS, maintaining FFmpeg across OS updates adds operational overhead that most WordPress projects don't need.
Plugins solve the processing problem but introduce their own costs. Cloudflare Stream charges per minute of stored and delivered video. Mux bills per minute of encoding. JW Player requires a subscription. For sites that just need to compress uploads before serving them, these tools are overkill.
How to Process Video Uploads in WordPress with a REST API
The pattern is simple: register a WordPress hook that fires on every new upload, check if it's a video, and POST the file URL to FFmpeg Micro for processing.
Register the Upload Hook
add_action('add_attachment', 'ffmpeg_micro_process_video');
function ffmpeg_micro_process_video($attachment_id) {
$mime_type = get_post_mime_type($attachment_id);
if (strpos($mime_type, 'video/') !== 0) {
return;
}
$file_url = wp_get_attachment_url($attachment_id);
$job_id = ffmpeg_micro_submit_transcode($file_url);
if ($job_id) {
update_post_meta($attachment_id, '_ffmpeg_micro_job_id', $job_id);
wp_schedule_single_event(time() + 30, 'ffmpeg_micro_check_job', [$attachment_id]);
}
}
Submit the Transcode Job
function ffmpeg_micro_submit_transcode($video_url) {
$api_key = defined('FFMPEG_MICRO_API_KEY') ? FFMPEG_MICRO_API_KEY : '';
$response = wp_remote_post('https://api.ffmpeg-micro.com/v1/transcodes', [
'headers' => [
'Authorization' => 'Bearer ' . $api_key,
'Content-Type' => 'application/json',
],
'body' => wp_json_encode([
'inputs' => [['url' => $video_url]],
'outputFormat' => 'mp4',
'preset' => [
'quality' => 'medium',
'resolution' => '1080p',
],
]),
'timeout' => 30,
]);
if (is_wp_error($response)) {
error_log('FFmpeg Micro error: ' . $response->get_error_message());
return null;
}
$body = json_decode(wp_remote_retrieve_body($response), true);
return $body['id'] ?? null;
}
Poll for Completion and Replace the File
WordPress cron handles the polling. When the job finishes, the processed video downloads back to the uploads directory and replaces the original attachment.
add_action('ffmpeg_micro_check_job', 'ffmpeg_micro_poll_and_replace');
function ffmpeg_micro_poll_and_replace($attachment_id) {
$job_id = get_post_meta($attachment_id, '_ffmpeg_micro_job_id', true);
$api_key = defined('FFMPEG_MICRO_API_KEY') ? FFMPEG_MICRO_API_KEY : '';
$response = wp_remote_get(
"https://api.ffmpeg-micro.com/v1/transcodes/{$job_id}",
[
'headers' => ['Authorization' => 'Bearer ' . $api_key],
'timeout' => 15,
]
);
if (is_wp_error($response)) {
return;
}
$job = json_decode(wp_remote_retrieve_body($response), true);
if ($job['status'] === 'completed') {
$dl_response = wp_remote_get(
"https://api.ffmpeg-micro.com/v1/transcodes/{$job_id}/download?url=true",
['headers' => ['Authorization' => 'Bearer ' . $api_key]]
);
$dl_data = json_decode(wp_remote_retrieve_body($dl_response), true);
$tmp_file = download_url($dl_data['url']);
if (!is_wp_error($tmp_file)) {
$file_array = [
'name' => basename(get_attached_file($attachment_id)),
'tmp_name' => $tmp_file,
];
$new_file = wp_handle_sideload($file_array, ['test_form' => false]);
update_attached_file($attachment_id, $new_file['file']);
}
} elseif ($job['status'] === 'failed') {
error_log("FFmpeg Micro job {$job_id} failed for attachment {$attachment_id}");
} else {
wp_schedule_single_event(time() + 30, 'ffmpeg_micro_check_job', [$attachment_id]);
}
}
Add your API key to wp-config.php:
define('FFMPEG_MICRO_API_KEY', 'your-api-key-here');
This entire integration lives in your theme's functions.php or a custom plugin file. No third-party WordPress plugin required.
WooCommerce Product Video Processing
If you're running WooCommerce and sellers upload product demo videos, the same pattern applies. Hook into the product save action and process any attached video files.
add_action('woocommerce_process_product_meta', function ($product_id) {
$video_id = get_post_meta($product_id, '_product_video_id', true);
if ($video_id && strpos(get_post_mime_type($video_id), 'video/') === 0) {
ffmpeg_micro_process_video($video_id);
}
});
This keeps product videos compressed without requiring sellers to pre-process their uploads.
Common Pitfalls
WordPress cron isn't real cron. wp_schedule_single_event only fires on page visits. On low-traffic sites, jobs can sit unpolled for minutes or hours. Fix this by setting up a system cron that hits wp-cron.php every minute, or use the WP-CLI wp cron event run command.
PHP timeout on large downloads. When the processed video downloads back to WordPress, large files can exceed PHP's max_execution_time. Set 'timeout' => 300 on the download_url call, and increase PHP's limits if you're handling files over 500MB.
Missing error handling. The code above logs errors but doesn't notify anyone. Add wp_mail() calls on failure, or integrate with a monitoring service. Silent failures on video processing are hard to debug after the fact.
File permissions. The WordPress uploads directory needs write permissions for wp_handle_sideload to replace the original file. This is rarely an issue, but locked-down server configs can block the replacement silently.
FAQ
Can I use FFmpeg Micro with WordPress on shared hosting?
Yes. Because the video processing happens on FFmpeg Micro's infrastructure, your WordPress host only needs to make outbound HTTP requests. There's nothing to install on the server. This works on shared hosting, managed WordPress hosts, and any environment that can run PHP.
How long does video processing take through the API?
Processing time depends on the video length, resolution, and output settings. A 5-minute 1080p video with the "medium" quality preset typically completes in 1-3 minutes. The polling approach handles this by checking the job status every 30 seconds until it finishes.
What video formats does FFmpeg Micro support for output?
FFmpeg Micro supports MP4, WebM, and MOV output formats. For WordPress, MP4 with H.264 (libx264) is the best choice because every browser and device supports it natively. You can also encode to VP9 or AV1 through WebM if you want smaller files for modern browsers.
Do I need to upload the video to FFmpeg Micro first?
Not if your video is already publicly accessible. WordPress media URLs are public by default, so you can pass the wp_get_attachment_url() directly to the API. For private or restricted files, use the three-step upload flow: request a presigned URL, PUT the file to cloud storage, then confirm the upload before transcoding.
Can I use custom FFmpeg flags instead of presets?
Yes. Replace the preset field with an options array to pass specific FFmpeg flags. For example, to set a custom CRF value and audio bitrate:
{
"inputs": [{"url": "https://example.com/video.mp4"}],
"outputFormat": "mp4",
"options": [
{"option": "-crf", "argument": "28"},
{"option": "-c:v", "argument": "libx264"},
{"option": "-c:a", "argument": "aac"},
{"option": "-b:a", "argument": "96k"}
]
}
This gives you full control over codecs, bitrates, and filters without being locked into preset configurations.
Start Processing WordPress Videos
Every video uploaded to your WordPress site is an opportunity to save bandwidth and improve load times. The integration above takes under 30 minutes to set up and handles compression automatically from that point forward.
Get a free FFmpeg Micro API key at ffmpeg-micro.com and start processing WordPress uploads in under 30 minutes.
About Javid Jamae
Founder & CEO at FFmpeg Micro
Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.
You might also like

How to Use FFmpeg with PHP (No Installation Required)
Process video in PHP without installing FFmpeg. Complete guide with cURL and Guzzle examples for transcoding, resizing, and format conversion via API.

Add Video Processing to Your Vercel + Supabase App in 10 Minutes
Add video processing to a Vercel + Supabase app using FFmpeg Micro API. Upload, transcode, and store results in 10 minutes flat.

Getting Started with FFmpeg Micro: 5 API Examples
Learn how to use the FFmpeg Micro API with 5 practical examples: transcode video, resize to 720p, extract audio, add watermarks, and generate thumbnails.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free