Most WordPress sites handle a growing video library the same way. You install an offload plugin, point it at an S3 bucket or something like it, and let it copy the files across and rewrite the URLs. Your disk empties, backups get quick again, and your server stops pushing gigabytes at every visitor. For a library of images, that is the whole job done.
Video is where it stops being the whole job. Offloading moves the file but never changes it, so your 900 MB lecture recording is still 900 MB when it lands in the bucket. The student on hotel wifi downloads all of it before the video plays. There are still no captions, and the URL in the page still works for anyone who copies it out.
Getting video off your server properly means dealing with both halves: the storage problem offloading solves, and the delivery, captions and access problems it leaves behind. It also means not losing files on the way. So this article covers what offloading fixes, the three things that break in the week afterwards, and the checks that prove every file arrived before you delete a local copy.
TL;DR
Offloading solves disk, origin bandwidth and distance. It does not solve buffering, mobile data waste, captions, playback measurement or access control, because moving a file does not change the file. Three things break after migration: two plugins both rewriting attachment URLs, hardcoded URLs that were never attachment URLs, and code that reads local file paths. Check counts, then total bytes, then fetch a sample, because matching counts hide a truncated upload. Keep local copies for one full traffic cycle, and insist on a migration that never rewrites saved post content.
What offloading actually changes, and what it leaves alone
An offload plugin copies an attachment to a bucket, rewrites the attachment URL, and gets out of the way. It changes where the bytes are served from. It does not change what the bytes are.
| Problem | Offload to object storage | What it still needs |
|---|---|---|
| Disk filling up on the host | Solved | Nothing |
| Origin bandwidth consumed by video | Solved | Nothing |
| Slow first byte for distant viewers | Solved by the CDN | Nothing |
| Buffering on slow connections | Not addressed | Multiple renditions and a manifest |
| Mobile viewers downloading a desktop-sized file | Not addressed | An adaptive bitrate ladder |
| No captions | Not addressed | A transcription step and a track the player reads |
| No idea whether anyone watched | Not addressed | Playback instrumentation |
| Video is still a public URL | Not addressed | Signed playback or DRM |
If your library is mostly images, the first three rows are the whole problem and offloading finishes it. If it is mostly video, the first three rows are urgent and the last five are why the complaints keep coming after the migration. Bunny Stream is a CDN with video on it works through the difference between a CDN and a video platform. ABR vs MBR covers the rendition question.
The three things that break after a media offload
The failures show up in the week after the migration, and they follow a pattern.
Two plugins rewriting the same URLs. Attachment URL rewriting is a filter, and nothing stops two plugins both hooking it. When an optimiser and an offload plugin disagree about which host owns an attachment, URLs work on and off, usually only for the files in one batch. Run one rewriter, and check for a second before you start rather than after.
URLs that were never attachment URLs. A migration only rewrites the URLs WordPress looks up through the attachment API. It does not touch a URL typed into a page-builder field, pasted into a custom field, set as a theme option, or hardcoded in a template. Those keep pointing at local paths, and they break the moment cleanup deletes them.
Anything reading a file path instead of a URL. Backup routines, image optimisers, PDF generators and some import tools read the local path directly. Once the file is remote, those paths are gone. Most of that code then fails without an error anyone sees. This is the one that surfaces weeks later when a backup turns out to be incomplete.
How to verify a migration before deleting anything
Matching counts proves nothing. A zero-byte upload, a half-finished transfer and a correct file all count as one object.
Work through it in this order, and only delete local copies after the last step passes:
- Compare counts by type. Count the attachments of each MIME type locally, then count the objects at the destination. A mismatch means the migration skipped something, and why it skipped matters more than how many.
- Compare total bytes. A count match with a byte mismatch is a truncated or failed transfer that reported success.
- Fetch a sample over HTTP. Take a random set across the whole library, not the first page, and confirm each returns a
200with a content length matching the source. A403means the bucket permissions are wrong for public reads, and every visitor is getting the same error. - Check the largest files individually. Big files upload in parts and fail differently from small ones, and video is what triggers that path. The mechanics are in how to upload large video files efficiently using chunking.
- Load ten real pages. Real posts, not the media library grid. Include one built in the page builder and one using a custom field, because those are the URLs step one cannot see.
- Keep the local copies for one full traffic cycle. A week covers the weekly cron jobs, the backup, and enough real visitors to surface a broken path.
One more thing to settle first. Some offload tools delete your originals for good when a subscription lapses. Before you delete anything locally, get it in writing: what happens to your files if you stop paying?
Offload plugin or video platform: what comes back
Both approaches move the file off your server. The difference is what you get back at the other end, and for a video library that is the whole decision.
| Offload to object storage | Video platform | |
|---|---|---|
| What arrives | The same file, different host | Renditions, a manifest and a poster |
| Playback on a slow connection | The full file, buffering | Switches down a rendition |
| Player | Whatever you already had | Supplied, with the stream |
| Captions | Not generated | Generated from the audio |
| Access control | Bucket policy, all or nothing | Signed per viewer and per render |
| Playback data | CDN logs, if you parse them | Watch time, drop-off, playback errors |
| Cost shape | Storage plus egress | Storage plus delivery, per minute |
| Best for | Images, documents, downloads | Video people watch rather than download |
Neither column is right for every library. A site that is mostly images with a few clips should offload and stop there. A site where video is the product has the opposite problem: moving the file without changing it leaves the real complaints in place. The ultimate guide to video storage solutions covers the storage side of that decision.
Running the migration without editing a post
Whichever route you take, insist the migration does not rewrite saved post content. That kind of rewrite is quietly destructive. Once the original markup is gone and revisions age out, the only way back is a database restore.
Render-time substitution is the alternative, and it is how the FastPix migration tool works. Posts keep referencing the local attachment, and the player is swapped in when the page renders, in the same pass where WordPress expands shortcodes. Post content, revisions and the editor view are all unchanged, so turning the plugin off returns the site to exactly what it was.
The workflow has one deliberate gate. A scan finds the video attachments and reports back before anything moves. You pick the quality tier and access policy for the batch, then the transfer runs in the background and you can pause and resume it. Cleanup deletes the local files, and it stays locked until every item in the batch has passed verification. Until you run it, you can revert any item.
One choice inside that flow is permanent. The quality tier locks once a file transfers, and DRM depends on it. A batch moved at the wrong tier has to be re-uploaded, not reconfigured.
Running one small batch first is the cheap way to find that out. The free plan covers 10 videos, which is enough to see what comes back before you commit a library.
What to check before you press cleanup
Cleanup is the irreversible step. Everything before it you can undo by deactivating the plugin or reverting an item. After it, the local file is gone and so is your fallback.
- Every item in the batch reports verified, not merely processed or ready.
- You have loaded a page that embeds a migrated video, as a logged-out visitor, in a browser with no cache.
- The largest file in the batch plays from a seek in the middle, not just from the start.
- A backup taken before the migration is stored somewhere the migration cannot touch.
- You have tested what deactivation does on this site, rather than trusting what the documentation says.
- Nothing in the batch is a protected video you might later want to revert. Reverting one returns it to an unprotected file sitting on your server.
Scan your Media Library with the FastPix migration tool
The useful first move is a scan, not a decision. Run the FastPix migration scan before anything transfers. It lists every video attachment and what it would do with each. That tells you how much of your library is really video, and which files cannot be reached from outside the site. Nothing moves until you approve it, and until you run cleanup you can revert any item to its local file. The free plan covers 10 videos, no card required.
Frequently Asked Questions (FAQs)
Does offloading media to S3 make video stream properly?
No. Offloading changes where the file is served from, not what the file is. One file at one bitrate on a CDN is still one file at one bitrate. Adaptive streaming needs the source transcoded into multiple renditions with a manifest, which no offload plugin produces. The same category distinction is made in Bunny Stream is a CDN with video on it.
What breaks after a WordPress media offload migration?
Three things most often. Two plugins both rewriting attachment URLs and disagreeing. Hardcoded URLs in page-builder data and theme options, which were never attachment URLs. And code reading local file paths rather than URLs, such as backups and image optimisers, which fails silently.
How do I verify every file arrived before deleting local copies?
Compare counts by MIME type. Then compare total bytes. Then fetch a random sample over HTTP and check each returns a 200 with the size you expect. Count matching alone is not verification, because a truncated or zero-byte upload still counts as one object. Keep a backup until the site has run for a full traffic cycle.
Can I offload only videos and leave images local?
Yes, and for most sites that is the right split. Images are small and numerous, and a CDN already handles them well. Video creates the storage and bandwidth problem, so filtering the migration by MIME type keeps the change small.
Do I have to edit posts after moving media off the server?
You should not have to. A migration that rewrites saved post content is destructive and hard to reverse, because the original markup is gone once revisions age out. Substituting the URL or player at render time leaves post content, revisions and the editor view unchanged.
What happens to my videos if the offload plugin is deactivated?
It depends on whether local files still exist. If originals were kept, a migrated attachment falls back to its local file and keeps playing. If cleanup already deleted them, post content points at files that are gone. Check the revert path before running cleanup, not after.
How long should I keep local copies after migrating?
At least one full traffic cycle, which for most sites means a week. That covers the weekly cron jobs, at least one backup run, and enough real visitors to surface a path nobody tested.
How do I move a large video library in bulk?
Run it in batches with pause and resume rather than as one job. Check each batch before starting the next. Migrating video libraries in bulk covers the API-level version. The 30-day migration playbook covers a larger move.








