An interactive demo application showcasing Cloudflare Stream's video capabilities, built with Cloudflare Workers and TypeScript.
Generate signed URLs for protected video content with granular access controls:
- Token Expiration - Set tokens to expire from 1 minute to 24 hours
- Geo-Restrictions - Allow or block specific countries using ISO 3166-1 Alpha-2 codes
- IP Allowlisting - Restrict playback to specific IP ranges (CIDR notation)
- Download Control - Enable/disable MP4 downloads per token
- Auto-Enable Privacy - Automatically enables
requireSignedURLswhen generating tokens
Try it: Use example video ID
911637687cf6595368a55aa984d2365din the demo
Transform videos from any origin via URL parameters - no upload required:
- Frame Extraction - Extract still images at specific timestamps
- Video Clipping - Create preview clips with custom start time and duration
- Resizing - Scale videos to specific dimensions with various fit modes
- Spritesheets - Generate sprite images from multiple frames
- Audio Extraction - Extract audio tracks from videos
- Stream Player - Adaptive bitrate streaming with HLS/DASH support
- Live Streaming - WebRTC, RTMPS, and SRT protocols
- Video Analytics - Views, engagement, and geographic data
- Direct Uploads - One-time upload URLs with TUS resumable support
Set STREAM_CUSTOMER_CODE in wrangler.jsonc:
Find your customer code in Stream URLs: customer-{CODE}.cloudflarestream.com
Generate a signing key first:
curl --request POST \
"https://api.cloudflare.com/client/v4/accounts/{account_id}/stream/keys" \
--header "Authorization: Bearer <API_TOKEN>"Then set the secrets:
# For signed URL generation
wrangler secret put STREAM_SIGNING_KEY_ID
wrangler secret put STREAM_SIGNING_KEY_JWK
# For video privacy controls (optional but recommended)
wrangler secret put STREAM_API_TOKEN
wrangler secret put STREAM_ACCOUNT_ID| Secret | Description |
|---|---|
STREAM_SIGNING_KEY_ID |
Key ID from /stream/keys API response |
STREAM_SIGNING_KEY_JWK |
Base64-encoded JWK from /stream/keys API response |
STREAM_API_TOKEN |
Cloudflare API token with Stream:Edit permission |
STREAM_ACCOUNT_ID |
Your Cloudflare Account ID (32-character hex string) |
Important:
STREAM_ACCOUNT_IDis your Cloudflare Account ID, NOT the Stream customer code. Find it in your Cloudflare Dashboard URL:dash.cloudflare.com/{account_id}/.... It's a 32-character hexadecimal string likea1b2c3d4e5f67890a1b2c3d4e5f67890.
- Navigate to the Secure Video Playback demo
- Enter your Stream video ID (or click "Use example" for a quick test)
- The demo automatically checks if
requireSignedURLsis enabled on the video - Configure token settings:
- Expiration time
- Download permissions
- Geo-restrictions or IP allowlisting
- Click Generate Signed URL - this will:
- Automatically enable
requireSignedURLson the video (if the checkbox is checked) - Generate a signed JWT token
- Automatically enable
- Use the generated URLs for iframe embed, HLS/DASH manifests, or thumbnails
Note: The "Auto-enable privacy" checkbox is on by default, ensuring your video is actually protected when you generate a signed URL.
- Navigate to the Media Transformations demo
- Enter a source video URL (must be publicly accessible MP4)
- Configure your zone domain
- Select transformation options:
- Mode (video, frame, spritesheet, audio)
- Dimensions and fit mode
- Time and duration
- Click Generate URL to create the transformation URL
| Endpoint | Method | Description |
|---|---|---|
/api/generate-token |
POST | Generate a signed token for video playback |
/api/set-video-privacy |
POST | Enable/disable requireSignedURLs on a video |
/api/video-info |
GET | Get video info including privacy status |
/api/config |
GET | Check if the worker is properly configured |
/api/health |
GET | Health check endpoint |
curl -X POST https://your-worker.workers.dev/api/generate-token \
-H "Content-Type: application/json" \
-d '{
"videoId": "911637687cf6595368a55aa984d2365d",
"expiresInMinutes": 60,
"downloadable": false,
"restrictionType": "allowCountries",
"countries": ["US", "CA"]
}'cf-stream-demo/
├── src/
│ ├── index.ts # Worker entry point with API routes
│ ├── stream.ts # Signed token generation utilities
│ └── env.d.ts # TypeScript declarations for env/secrets
├── public/
│ ├── index.html # Homepage with feature overview
│ ├── secure-video.html # Signed URL demo interface
│ ├── transform.html # Media transformations demo
│ └── styles.css # All styles (responsive)
├── test/
│ └── index.spec.ts # Vitest tests
├── wrangler.jsonc # Wrangler configuration
├── tsconfig.json # TypeScript configuration
├── vitest.config.mts # Vitest configuration
└── package.json # Dependencies and scripts
- Cloudflare Stream Documentation
- Securing Your Stream
- Media Transformations
- Stream API Reference
- Stream Copy API - Upload videos via URL
- Webhooks - Track video processing status
- Workers Documentation
For full customization and building serverless, scalable real-time video applications:
- Cloudflare Realtime (Calls) - WebRTC-based real-time communication
This demo is for educational purposes only and is not officially endorsed by Cloudflare. It demonstrates Cloudflare Stream capabilities using publicly available APIs and documentation. Use at your own risk.
This project is not affiliated with, officially maintained by, or sponsored by Cloudflare, Inc. Cloudflare and the Cloudflare logo are trademarks of Cloudflare, Inc.
{ "vars": { "STREAM_CUSTOMER_CODE": "your-customer-code" } }