# Introducing bunny-xblock: Open edX Modern Video Pipeline

https://cubite.io/blogs/open-edx-bunny-xblock-modern-video-pipeline

**By:** Amir Tadrisi
**Updated:** 2026-05-14

The Open edX Bunny XBlock closes the 5-year video-pipeline gap with Studio-native upload, token auth, and Bunny.net Stream underneath.

# Introducing bunny-xblock: Open edX Finally Has a Modern Video Pipeline Again

Open edX has been without a first-party video pipeline since September 2020, when VEDA - the original edx-video-pipeline - was deprecated via DEPR-107. For five years, self-hosted operators have lived in a workaround zone: unlisted YouTube embeds, Vimeo iframes, custom S3 pipelines, or generic embed XBlocks that don't actually upload anything.

Today we're releasing the Open edX Bunny XBlock - an open-source XBlock that turns Open edX Studio into a Studio-native video pipeline again. Drop a file into a unit. Watch the upload stream directly to Bunny.net Stream, transcode, and come back with a signed, hotlink-protected player. No YouTube. No copy-paste iframes. No bespoke S3 plumbing.

This article walks through what's in v0.1.0, what's not, how it installs in two Tutor commands, and the honest production-readiness story. By the end you'll know whether to install it tomorrow, contribute to it, or watch from the sidelines.

---

## Open edX Has Been Without a Real Video Pipeline for 5 Years

Here's the part most operators have forgotten or never knew. Open edX once had a real video encoding pipeline - VEDA (edx-video-pipeline). It transcoded uploads, pushed to multiple delivery targets, and integrated with Studio. Then in 2020, the edX team filed DEPR-107 and planned its removal after September 25, 2020. The repository now lives under edx-unsupported/edx-video-pipeline - archived, untouched.

No first-party community replacement ever shipped.

Studio still has a "Video Uploads" tab, but if you read the official documentation carefully, the workflow ends with files being "transferred to multiple hosting services (YouTube CMS and Amazon AWS)" — that's edX.org's hosted infrastructure. Self-hosted operators don't get that pipeline. They get an upload tab pointing at services they don't have.

The practical result, for half a decade: every self-hosted Open edX team has been improvising. That's the gap bunny-xblock closes — the first community-maintained VEDA replacement for Open edX with a Studio-native upload workflow.

---

## What Operators Have Been Doing Instead (And Why It Hurts)

If you've run a self-hosted Open edX instance for any length of time, you've probably tried one of these. Each one is a workaround, not a solution.

| Approach | Setup cost | Security | Studio-native upload | Analytics | Vendor risk |
| --- | --- | --- | --- | --- | --- |
| YouTube unlisted embed | Zero | None (no DRM, public-ish URLs) | No — paste a URL | None | Brand bleed, ads, recommendation hijack |
| Vimeo iframe | Low | Limited | No — paste a URL | Vimeo's, not edX | Bending Spoons acquisition + Jan 2026 layoffs |
| Custom S3 + bespoke XBlock | High | Whatever you build | Yes (if you build it) | Whatever you build | None — but you maintain it |
| bunny-xblock | Two Tutor commands | Token auth + Bunny's DRM stack | Yes — drag-and-drop in Studio | Custom (events don't fire in v0.1.0) | Single vendor (Bunny) |

A few honest reads:

YouTube unlisted is what most courses ship with, and it's the worst option for paid or professional content. No DRM, ad/brand risk, and unlisted URLs leak the second a learner shares them.

Custom S3 setups work, but every team reinvents the wheel. We've watched five different Cubite customers build five subtly different S3 + ffmpeg + custom-XBlock pipelines. That's exactly the duplication an open-source XBlock is supposed to end.

---

## What bunny-xblock Actually Ships (v0.1.0) — And What Bunny Adds Underneath

This is the most important section. The positioning of this project depends on being precise: the XBlock ships the bridge. Bunny Stream ships the platform features underneath. Conflating them oversells what we built and undersells what you get.

In the XBlock:

- Direct TUS upload to Bunny — Studio uploads stream through the browser straight to Bunny via the TUS resumable upload protocol. The LMS server never sees the bytes. A 2GB lecture file over slow WiFi survives a flaky connection.
- Real-time upload progress — visual progress indicators in the Studio editor while a file is climbing toward Bunny.
- Encoding-status webhooks — Bunny calls back to your LMS when transcoding finishes. Studio shows "Processing on Bunny…" → "Ready" without manual refresh.
- Token authentication — every embed URL is SHA256-signed with a 6-hour TTL. Every upload signature is short-lived (1-hour TTL). External requests to the iframe URL get a 401.
- Fernet-encrypted credential storage — Bunny library ID, API key, security key, and CDN hostname are stored encrypted in the database, with the key derived from Django's SECRET_KEY via HKDF.
- Auto-generated thumbnails — Bunny generates a poster image during transcode; the XBlock uses it as a click-to-load preview, lazy-loading the video iframe on user intent.
- Signed iframe playback with HLS fallback — vanilla iframe rendering (which supports AirPlay) with HLS fallback for iOS Safari.
- Studio replace / delete workflow — swap an existing video or remove it cleanly, with the Bunny-side asset cleaned up.

From Bunny Stream (configured in the Bunny dashboard, applies automatically):

- Adaptive bitrate HLS encoding — multiple resolutions, free, automatic.
- MediaCage — Bunny's free baseline anti-download DRM that blocks naive scraping and most screen-recorder tooling. See Bunny's MediaCage docs.
- Enterprise multi-DRM — Widevine, FairPlay, PlayReady for premium or regulated content.
- Domain allowlist / referrer restrictions — via Bunny's pull-zone hotlink-protection settings (Bunny security options).
- AI-generated captions / transcription — Bunny Stream produces VTT/SRT files attached to videos.
- Video chapters — configured in the Bunny dashboard, surfaced in the Bunny player.
- Dynamic watermarking — overlays the learner's identifier as a forensic deterrent (premium plans).
- Global delivery — 119 PoPs, 250 Tbps backbone, $0.005/GB delivery, $0.01/GB storage, free encoding (bunny.net/stream).

---

## How It Looks in Studio and for Learners

The point of "Studio-native" is that the workflow disappears. Course authors don't think about upload pipelines; they think about lessons.

Course author flow (Studio):

- Create a library in Bunny and activate authentication
- Setup the bunny credentials in the Open edX Django Admin

- Add a Bunny Video component to a unit (after enabling bunny_video in Advanced Module List — one-time).

- Drag a file onto the component. Progress bar fills in real time as bytes stream directly to Bunny.

- Status shows "Processing on Bunny…" — encoding runs while you continue editing other components.

- Status flips to "Ready". The signed player appears in the preview pane.

Learner flow:

1. Lesson page loads with a click-to-load poster image (auto-generated thumbnail). No iframe loads yet — no third-party requests until the learner taps play.
2. Click → signed iframe loads → HLS adaptive playback begins. The signed URL expires after 6 hours; any attempt to embed the iframe outside the LMS returns 401.

---

## How to Install bunny-xblock on Your Open edX Instance

If your deployment runs on Tutor, installation is two commands. No fork edits, no INSTALLED_APPS changes, no environment-file surgery.

Step 1 — Add the XBlock to Tutor's pip requirements:

tutor config save --append OPENEDX_EXTRA_PIP_REQUIREMENTS=xblock-bunny

Step 2 — Launch:

tutor local launch

Step 3 — Configure Bunny credentials at https://your-lms-domain/admin/xblock_bunny/bunnyconfiguration/. You'll need:

- Library ID — from your Bunny Stream library
- API Key — from Bunny account settings
- Security Key — for Token Authentication (enable it in Bunny first)
- CDN Hostname — your Bunny Pull Zone URL

Step 4 — Enable the block in Studio: Settings → Advanced Settings → add bunny_video to the Advanced Module List. Save.

Step 5 — Register the webhook in your Bunny dashboard, pointing at your LMS webhook URL (the format is documented in the repository README). This is what flips Studio status from "Processing" to "Ready" automatically.

Step 6 — Smoke test. Create a course unit, add a Bunny Video component, upload a 30-second test clip, verify:

- Upload progress fills in Studio
- Encoding status transitions to Ready within a couple minutes
- Signed iframe renders on the learner-facing page
- A direct curl of the iframe URL from an unauthorized origin returns 401

Compatibility today: Sumac, Teak, Ulmo. Tutor 19.x through 21.x. Python 3.11. Django 4.2 LTS. Verawood compatibility is expected — Verawood ships June 9, 2026 and the XBlock is designed against the same Django/Python lineage — but we'll re-verify and tag a compatible release after the official Verawood cut.

---

## The Bottom Line

Five years is a long time for a learning platform to be without a native video pipeline. The Open edX Bunny XBlock closes that gap with Studio-native upload, signed-URL playback, and a clean delegation to Bunny.net Stream for everything underneath — DRM, captions, chapters, allowlists, global delivery.

The shape of the project is intentional:

- The XBlock ships the bridge. Apache-2.0, public repo, two-command Tutor install.
- Bunny ships the platform. Every Bunny Stream feature is one dashboard toggle away.
- Cubite ships the integration — for teams that would rather not own this surface, we install, configure, and support the whole pipeline on managed Open edX hosting.

If you've been improvising with YouTube embeds or maintaining a custom S3 pipeline, the cost of trying this is two Tutor commands and a 30-second test clip. The cost of not trying it is another year of improvising.
