September 25, 2026

Managing a large WordPress video library from WP-CLI

Masroor Ahmed
Masroor Ahmed
AI/ML Engineer

The FastPix plugin has a three-step Connection wizard on its admin screens, and on a single site it is the right tool for the job. You paste the access token ID and the secret key, hit Verify, and the Videos screen fills in behind it. Nothing about that flow is broken.

It stops being the right tool at the second site. An agency with twelve client installs runs that wizard twelve times, and pastes a webhook signing secret by hand twelve times. That is twelve chances to put a secret in the wrong field on the wrong site. A library of 40,000 videos makes the problem sharper, because a full resync started from a browser tab dies with the tab.

Every one of those jobs has a command behind it. This covers the seven wp fastpix subcommands and what each is actually for. It also covers why all of them return before the work finishes, and how to read the scheduler line in wp fastpix status when a queue has stopped draining.

TL;DR

Seven subcommands: status, sync, sync --deep, reindex, prune, doctor, webhook-secret. Every one of them enqueues the same background job the scheduler already runs, so the command returns immediately and a zero exit code means queued rather than finished. The classic silent failure is DISABLE_WP_CRON set to true with no crontab behind it, so nothing drains the queue. wp fastpix status reports that on the scheduler line. webhook-secret makes an unattended deploy possible, because it is the one setting that otherwise forces a human into wp-admin on every site.

What to check before you touch a client site

wp fastpix status is the read-only command, and it is the one to run first on a site you did not set up yourself. It answers four questions at once: is the connection alive, is the database schema current, is anything stuck in the queue, and is anything draining that queue.

bash
$ wp fastpix status

Connection   connected        workspace acme-media
Schema       current          6 tables, FULLTEXT present
Queue        142 pending      0 failed, oldest item 3 minutes old
Scheduler    WP-Cron disabled, no external request seen in 24 hours
Webhook      https://acme.example/wp-json/fastpix/v1/webhook   secret set
Last sweep   2026-09-23 21:04 UTC
What does wp fastpix status report about the queue and the scheduler?

Read the last two lines together. A pending count on its own means nothing, because a healthy site clears a backlog in minutes. A pending count next to a scheduler that has not fired is the whole diagnosis.

The seven commands, and what each one is for

CommandRun it when
wp fastpix statusFirst, on any site you inherit. Connection, schema, queue depth, scheduler health
wp fastpix syncNew media is not showing up and you do not want to wait for the next sweep
wp fastpix sync --deepAfter a webhook outage, a database restore, or a bulk change made outside WordPress
wp fastpix reindexSearch misses videos you know exist, usually after a deep resync or a FULLTEXT repair
wp fastpix pruneYou changed a retention setting and want it applied now rather than at the nightly pass
wp fastpix doctorThe site behaves oddly after a host migration, a PHP upgrade, or a new plugin
wp fastpix webhook-secret <secret>Provisioning a site from a script, or rotating a secret that leaked

status and doctor look similar and are not. status reports current state. doctor re-runs the activation checks, so it tests the environment: WordPress and PHP versions, HTTPS, a reachable REST API, outbound connectivity, and conflicting video plugins. A site that passed those checks in March can fail them in September, because the host moved it to a new PHP build.

Why a command returns before the work is done

None of these commands does the work itself. Each one enqueues a job through Action Scheduler, the same queue the FastPix plugin's own periodic sweeps and webhook receiver already use. The command hands over the job and exits.

Why does a WP-CLI command return before the background job has run?

That design is deliberate, and one consequence of it catches deploy scripts out. A zero exit code from wp fastpix sync means the job was accepted. It does not mean the library is in sync. A deploy script that treats the exit code as completion will report twelve green sites while twelve queues sit untouched.

To confirm the work actually ran, poll the queue instead of trusting the exit code:

bash
wp fastpix sync

for i in $(seq 1 30); do
  wp fastpix status | grep -i '^Queue'
  sleep 20
done

If the pending count has not moved after ten minutes, the sync is not your problem. Nothing is running the queue.

WP-Cron is not cron, and status tells you when that bites

WordPress does not have a timer. WP-Cron fires on a page request, checks which scheduled tasks are overdue, and runs them. On a busy site that approximates a scheduler closely enough that nobody notices the difference.

On a low-traffic client site it does not. A brochure site for a dental practice might get forty visits a day, all of them inside office hours, so the queue moves in bursts and sits idle overnight. That is already slow, and the failure case is worse.

What does DISABLE_WP_CRON do in wp-config.php?

Plenty of managed hosts ship DISABLE_WP_CRON set to true, on the assumption that a real crontab entry will replace it. Sometimes the entry exists. More often a site is moved between hosts or restored from a backup, and the constant survives while the crontab does not. Nothing errors, the queue simply never drains, and on a site nobody visits nobody notices for a week.

Three commands separate the two cases:

bash
wp config get DISABLE_WP_CRON
wp cron test
wp cron event list --due-now

Read the three answers together. A true constant, a wp cron test that reports spawning disabled, and a growing --due-now list mean the crontab was never added. Add it against the site root so the schedule stops depending on traffic:

bash
*/5 * * * * cd /var/www/acme.example && wp cron event run --due-now --quiet

Then re-run wp fastpix status. The scheduler line should change and the pending count should start falling. If jobs are queued but still not moving, wp action-scheduler run drains the Action Scheduler queue directly, which separates a scheduler problem from a job that is failing on every attempt.

Webhooks reduce how much this matters, because the receiver answers immediately and queues the update rather than waiting for a sweep. It does not remove the dependency, since the queued job still needs a worker. Webhooks explained covers the delivery side of that.

Resyncing 40,000 videos without a browser tab

wp fastpix sync is an incremental sweep. It looks for new media and recent changes, which is cheap and safe to run often. wp fastpix sync --deep is the full reconciliation: every record in the local registry checked against the platform.

Run the deep version after anything that could have lost events. That covers a webhook endpoint that returned errors for a few hours, a staging database restored over production, or a bulk change made outside WordPress. The deep sweep is resumable, so an interrupted run continues rather than starting over.

The queue model does the heavy lifting here. The command returns as soon as the job is accepted, so a 40,000-video resync needs no held terminal, no tmux session and no browser tab left open on a laptop lid. Start it, disconnect, and check back with status.

bash
wp fastpix sync --deep
wp fastpix status | grep -i '^Queue'

Search is a separate index, so a deep resync can leave it behind. Run wp fastpix reindex afterwards if transcript search matters on that site. Transcript search needs MySQL or MariaDB with InnoDB FULLTEXT support. Without it, title search still works and the schema line in status says so. Moving a library in the first place is a different job from reconciling one. Migrating video libraries in bulk covers the batch mechanics, and moving a Media Library off your server covers what changes when the files leave.

Deploying the same setup to twelve client sites

webhook-secret is the command the whole loop depends on. Every other part of provisioning can be scripted with core WP-CLI, but the signing secret is a value the admin screens normally own. Setting it from the command line removes the last human step.

bash
#!/usr/bin/env bash
set -uo pipefail

for SITE in /var/www/clients/*/public_html; do
  SECRET="$(openssl rand -base64 32)"

  if ! wp --path="$SITE" fastpix doctor; then
    echo "FAILED checks: $SITE" >&2
    continue
  fi

  wp --path="$SITE" fastpix webhook-secret "$SECRET"
  wp --path="$SITE" fastpix sync
  wp --path="$SITE" fastpix status
done

A secret passed as an argument lands in shell history and shows up in the process list. Generate it per site inside the loop, as above, and keep the values in whatever secret store the rest of your infrastructure uses. Rotating one later is the same command again.

Two details save time on a fleet. doctor runs before anything else, so a site with the wrong PHP version fails loudly instead of half-provisioning. And prune belongs on its own schedule rather than in the deploy, because retention is a per-client policy. Per-learner analytics data defaults to a 90-day window, and a client with a stricter rule wants that applied the day the setting changes, not at the nightly pass. WordPress video analytics covers what is being retained.

Test a loop like this before pointing it at client work. The free plan covers 10 videos with no card, enough to provision a local install end to end.

Running commands across a multisite network

The plugin runs per site, not network-wide. Network activation is refused, because each site keeps its own connection, its own library and its own capabilities. That is a deliberate boundary, and it means a network needs the same loop as a fleet of separate installs.

bash
NETWORK=/var/www/network

for URL in $(wp --path="$NETWORK" site list --field=url); do
  wp --path="$NETWORK" --url="$URL" fastpix status
done

wp site list --field=url returns one URL per line, and wp --url= targets a single site inside the network. Every subcommand accepts the same pair, so the deploy loop above works unchanged once you swap path iteration for URL iteration. Each site still needs its own webhook secret, because each has its own receiver endpoint.

Run status across every site you manage

Run wp fastpix status across every install you look after, and read the scheduler line on each one. A site with a high pending count and a quiet scheduler is already losing video updates, and it will not tell you any other way. The FastPix WP-CLI reference lists the full flag set, and the developer hooks cover what you can change in code rather than in Settings.

Frequently Asked Questions (FAQs)

Why does wp fastpix sync finish instantly on a large library?

Because the command enqueues a background job rather than doing the work inline. Every wp fastpix subcommand hands the job to Action Scheduler, the same queue the plugin's own scheduled sweeps use. A zero exit code means the job was accepted, not that the library is in sync. Re-run wp fastpix status and watch the pending count fall.

Why is nothing syncing even though the plugin says it is connected?

The usual cause is a scheduler that never fires. If DISABLE_WP_CRON is true in wp-config.php and no crontab entry was added to replace it, nothing drains the queue. The scheduler line in wp fastpix status reports this, and WP-Cron plus wp cron test confirms it independently.

What is the difference between wp fastpix sync and sync --deep?

Plain sync is an incremental sweep for new media and recent changes, cheap enough to run often. --deep is a full reconciliation of every record in the local registry against the platform. A deep resync is resumable, so an interrupted run picks up where it stopped rather than starting the library over.

Can I set the webhook signing secret from the command line?

wp fastpix webhook-secret <secret> writes it without an admin round trip, which is what makes an unattended deploy possible. Generate the value per site rather than sharing one across a fleet. A command-line argument is also visible in shell history and in the process list while it runs.

How do I run plugin commands across a WordPress multisite network?

Enumerate the sites with wp site list --field=url, then pass each URL back with wp --url=. The plugin runs per site and network activation is refused, because each site keeps its own connection, library and capabilities. Each site therefore needs its own connection and its own webhook secret.

What does wp fastpix doctor check that status does not?

status reports current state: connection, schema, queue depth, scheduler health. doctor re-runs the activation checks, covering WordPress and PHP versions, HTTPS, a reachable REST API, outbound connectivity and conflicting video plugins. Run it after a host migration or a PHP upgrade.

When should I run wp fastpix reindex?

After a deep resync, after repairing a FULLTEXT index, or whenever search misses videos you know are in the library. The search index is separate from the video registry, so reconciling one does not rebuild the other.

Does wp fastpix prune delete my videos?

No. It applies your retention settings to locally stored data, such as per-learner analytics records, which default to a 90-day window. Video on the FastPix platform is not touched by it.

Share

Stay Ahead of Video
Streaming Trends

Start shipping video today.