ffmpegwordpressphpvideo-processingapibucket-outcome

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

·Javid Jamae·6 min read
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.

Software EngineeringVideo ProcessingFFmpegCloud ArchitectureAPI DesignAutomation

Ready to process videos at scale?

Start using FFmpeg Micro's simple API today. No infrastructure required.

Get Started Free