Discourse Video Stream adds seamless Cloudflare Stream integration for uploading and embedding high-quality, long-form video content in your Discourse site.
Overview
This plugin provides a complete workflow for handling large video files with adaptive bitrate streaming, allowing your users to upload videos directly from the composer and play them back with automatic quality adjustment based on their network conditions.
Key Features
Composer Integration: Optional toolbar button for direct video uploads from the composer
Automatic Upload Interception: Videos exceeding a configurable size threshold are automatically uploaded to Cloudflare Stream instead of local storage
Resumable Uploads: Built on tus-js-clientfor reliable uploads of files well beyond 200 MB with automatic resume on connection issues
Secure Proxy: Server-side endpoint generates short-lived Cloudflare Stream upload URLs, keeping your API credentials safe
Custom BBCode: Simple [video-stream id="..."]syntax for embedding videos
Adaptive Streaming: Shaka Player integration with DASH manifests for smooth playback across varying network speeds
Playback Controls: Built-in UI for resolution selection and playback speed control
Installation
Add the plugin to your app.yml:
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/xfalcox/discourse-video-stream.git
Then rebuild your container:
./launcher rebuild app
Configuration
Navigate to Admin → Settings → Video streaming and configure:
| Setting | Description | Default |
|---|---|---|
| video_stream_enabled | Enable the video streaming plugin | false |
| video_stream_account_id | Your Cloudflare account identifier | - |
| video_stream_api_token | API token with Stream:Edit permissions | - |
| video_stream_customer_subdomain | Your Cloudflare Stream domain (e.g., customer-xxxxx.cloudflarestream.com) | - |
| video_stream_allowed_extensions | Comma-separated list of allowed video formats | mp4,webm,mov |
| video_stream_max_file_size | Maximum file size in MB (1-2000) | 500 |
| video_stream_intercept_native_uploads | Automatically intercept large video uploads | true |
| video_stream_intercept_threshold_mb | Size threshold in MB for automatic interception (1-2000) | 10 |
Getting Cloudflare Stream Credentials
- Log into your Cloudflare dashboard
- Navigate to Stream under your account
- Copy your Account ID from the Stream overview
- Create an API token with Stream:Edit permissions
- Note your Customer subdomain from the Stream settings
Usage
Once configured, users have two ways to upload videos:
Automatic Interception
When a user drags and drops or selects a video file that exceeds the video_stream_intercept_threshold_mb setting, the plugin automatically handles it via Cloudflare Stream instead of local storage. You need to allow video file extensions on the allowed extension settings for this to work.
Manual Upload
Users can click the composer toolbar’s pop-up menu (
) and select the video upload option to explicitly upload to Cloudflare Stream.
Both methods insert a [video-stream id=“video_id”] BBCode tag that renders as an adaptive streaming player with resolution and speed controls.
Why Cloudflare Stream?
We have support for doing the same using AWS in code, and with Mux in GitHub - discourse/discourse-video, so a cheaper alternative sounded like a good idea.
Requirements
- Active Cloudflare account with Stream enabled
Source & Support
- Repository: GitHub - xfalcox/discourse-video-stream
Screenshots
Demo
Visit my test site and upload some videos
https://discourse-on-a-pi5.falco.dev/t/test-video-upload-plugin/20?u=falco
Note: This is not an official plugin.

