Introduction

Cloudflare Stream provides video hosting, encoding, and delivery infrastructure. Stream handles video upload, transcoding to multiple formats, storage, and adaptive bitrate delivery. Errors can occur at any stage: upload failures (file format, size limits), transcoding issues (unsupported codecs), playback errors (manifest problems, DRM), and delivery failures (bandwidth, regional restrictions). Understanding which stage fails helps target the fix.

Symptoms

  • Video upload fails with format or size error
  • Uploaded video stuck in "processing" or "pending" status
  • Playback returns error or blank player
  • Video quality options not appearing
  • Stream playback buffered or stalled
  • Error messages: "Video not found", "Playback error", "Upload failed"
  • DRM-protected content not playing
  • Regional restrictions blocking playback

Common Causes

  • Unsupported video format or codec
  • Video file exceeds size limits
  • Upload URL or tus protocol issue
  • Transcoding stuck or failed
  • Manifest (HLS/DASH) generation error
  • Incorrect video UID or token
  • Playback token expired or invalid
  • Missing or incorrect DRM configuration
  • Viewer's network blocking Stream domains
  • CORS or content policy restrictions

Step-by-Step Fix

  1. 1.Check video upload status:

Navigate to: Stream > Videos in Cloudflare Dashboard

``` # Video states: # - pending: Upload in progress # - processing: Transcoding active # - ready: Available for playback # - error: Upload or transcoding failed

# If stuck in pending/processing for extended time, issue exists ```

  1. 1.Verify video file format and codec:

```bash # Check video properties ffprobe -v error -show_format -show_streams input.mp4

# Cloudflare Stream supports: # - Formats: MP4, MOV, AVI, MKV, WebM, FLV # - Video codecs: H.264, H.265/HEVC, VP8, VP9 # - Audio codecs: AAC, MP3, Opus, Vorbis

# Unsupported codecs cause transcoding failures ```

  1. 1.Check file size limits:

``` # Stream upload limits: # - Single file: 10GB (Enterprise can be higher) # - Tus upload chunks: recommended 5-50MB

# For large files, use tus resumable uploads ```

  1. 1.Use proper upload method:

```bash # Direct upload (small files): curl -X POST \ -F file=@video.mp4 \ -H "Authorization: Bearer API_TOKEN" \ https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/stream/videos

# Tus resumable upload (large files): # 1. Create upload session curl -X POST \ -H "Authorization: Bearer API_TOKEN" \ -H "Tus-Resumable: 1.0.0" \ -H "Upload-Length: FILE_SIZE" \ -H "Upload-Metadata: filename dXBsb2FkXzEubXA0,name ZmlsZW5hbWU" \ https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/stream/videos

# 2. Upload chunks to returned URL ```

  1. 1.Check video processing logs:

```bash # Via API - check video details curl -X GET "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/stream/videos/VIDEO_UID" \ -H "Authorization: Bearer API_TOKEN"

# Look for: # - status: ready/error # - error message if failed # - transcoding progress percentage ```

  1. 1.Verify video UID and playback URL:

```html <!-- Standard player embed --> <stream src="VIDEO_UID" controls></stream> <script src="https://embed.videodelivery.net/embed/rkx9ast1.js"></script>

<!-- Or HLS/DASH manifest directly --> https://customer-ACCOUNT_ID.cloudflarestream.com/VIDEO_UID/manifest/video.m3u8 https://customer-ACCOUNT_ID.cloudflarestream.com/VIDEO_UID/manifest/video.mpd ```

  1. 1.Check playback token validity:

```bash # For signed URLs (token-required playback) curl -X POST "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/stream/videos/VIDEO_UID/token" \ -H "Authorization: Bearer API_TOKEN" \ -H "Content-Type: application/json" \ --data '{"expiresIn": 3600}'

# Returns token for signed playback URL # Use token in URL: https://customer-ACCOUNT_ID.cloudflarestream.com/VIDEO_UID/token/TOKEN_VALUE/manifest/video.m3u8 ```

  1. 1.Test manifest accessibility:

```bash # Check HLS manifest curl -I https://customer-ACCOUNT_ID.cloudflarestream.com/VIDEO_UID/manifest/video.m3u8

# Should return 200 OK with m3u8 content

# Check individual segment curl -I https://customer-ACCOUNT_ID.cloudflarestream.com/VIDEO_UID/manifest/360p/video.mp4 ```

  1. 1.Debug player errors:
javascript
// In player JavaScript, catch errors
const player = document.querySelector('stream');
player.addEventListener('error', (event) => {
  console.error('Stream error:', event.detail);
  // Check error type:
  // - network: Connection failed
  // - decode: Codec not supported
  // - source: Video not found or invalid
});
  1. 1.Check DRM configuration:

```bash # For DRM-protected content: curl -X GET "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/stream/videos/VIDEO_UID" \ -H "Authorization: Bearer API_TOKEN"

# Check drm field in response # DRM requires proper license server and key configuration

// Player DRM configuration const player = new StreamPlayer({ drm: { type: 'fairplay', // or 'playready', 'widevine' licenseUrl: 'https://license.server.com' } }); ```

  1. 1.Verify domain access:

```bash # Stream domains must be accessible curl -I https://customer-ACCOUNT_ID.cloudflarestream.com/

# If blocked, check: # - Corporate firewall blocking stream domains # - Regional restrictions # - DNS resolution for cloudflarestream.com ```

  1. 1.Check CORS configuration:

```bash # For cross-origin playback curl -I https://customer-ACCOUNT_ID.cloudflarestream.com/VIDEO_UID/manifest/video.m3u8 \ -H "Origin: https://your-website.com"

# Should return proper CORS headers: # Access-Control-Allow-Origin: * ```

  1. 1.Enable Stream analytics:

Navigate to: Stream > Analytics

bash
# Monitor:
# - Views per video
# - Bandwidth usage
# - Playback errors
# - Geographic distribution
  1. 1.Test with sample video:

```bash # Upload known-good test video curl -X POST \ -F file=@test.mp4 \ -H "Authorization: Bearer API_TOKEN" \ https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/stream/videos

# If test video works, issue is with specific source video # If test video fails, account/configuration issue ```

Verification

After applying fixes:

  1. 1.Video shows "Ready" status in Stream dashboard
  2. 2.HLS/DASH manifest accessible via curl
  3. 3.Player loads and plays video without errors
  4. 4.Multiple quality options available in player
  5. 5.Playback token generates valid signed URLs
  6. 6.Video plays across different browsers and devices
  7. 7.Stream analytics shows playback views