Skip to content

Multi-CDN Setup

Lunar Stream provides multiple CDN endpoints for redundancy and optimal performance.

Multi-CDN Architecture

CDN Failover Flow

Available CDN Endpoints

Each livestream has multiple HLS URLs from different CDN providers:

CDNURL PatternRegion
Originhttps://stream.lunarstream.kozow.com/live/{streamKey}/hls.m3u8Primary
BunnyCDNhttps://zlmediakit-cdn.b-cdn.net/live/{streamKey}/hls.m3u8Global
Gcorehttps://gcore-zlmediakit.lunarstream.kozow.com/live/{streamKey}/hls.m3u8Global

Getting CDN URLs

When you retrieve a livestream, the response includes all available CDN URLs:

bash
curl -X GET "https://api.lunarstream.kozow.com/api/v1/livestream/LIVESTREAM_ID?projectId=PROJECT_ID" \
  -H "ls-api-key: YOUR_API_KEY"

Response:

json
{
  "data": {
    "id": "d926da37-56ae-4212-83bc-f20d9de64d6b",
    "streamKey": "ee04affe2a669854052102fe762bd715",
    "hlsPaths": [
      "https://stream.lunarstream.kozow.com/live/ee04affe2a669854052102fe762bd715/hls.m3u8",
      "https://zlmediakit-cdn.b-cdn.net/live/ee04affe2a669854052102fe762bd715/hls.m3u8",
      "https://gcore-zlmediakit.lunarstream.kozow.com/live/ee04affe2a669854052102fe762bd715/hls.m3u8"
    ]
  }
}

Implementing CDN Failover

JavaScript Implementation

javascript
class MultiCDNPlayer {
  constructor(hlsPaths) {
    this.cdnUrls = hlsPaths;
    this.currentIndex = 0;
    this.maxRetries = 3;
  }

  getCurrentUrl() {
    return this.cdnUrls[this.currentIndex];
  }

  switchToNextCDN() {
    if (this.currentIndex < this.cdnUrls.length - 1) {
      this.currentIndex++;
      console.log(`Switching to CDN: ${this.getCurrentUrl()}`);
      return true;
    }
    return false;
  }

  reset() {
    this.currentIndex = 0;
  }
}

// Usage with Video.js
const cdnPlayer = new MultiCDNPlayer(hlsPaths);
const player = videojs('video-player');

player.src({ src: cdnPlayer.getCurrentUrl(), type: 'application/x-mpegURL' });

player.on('error', () => {
  if (cdnPlayer.switchToNextCDN()) {
    player.src({ src: cdnPlayer.getCurrentUrl(), type: 'application/x-mpegURL' });
    player.play();
  } else {
    console.error('All CDNs failed');
  }
});

React Hook Implementation

javascript
import { useState, useCallback } from 'react';

function useMultiCDN(hlsPaths) {
  const [currentIndex, setCurrentIndex] = useState(0);

  const currentUrl = hlsPaths[currentIndex];
  const hasMoreCDNs = currentIndex < hlsPaths.length - 1;

  const switchToNextCDN = useCallback(() => {
    if (hasMoreCDNs) {
      setCurrentIndex(prev => prev + 1);
      return true;
    }
    return false;
  }, [hasMoreCDNs]);

  const reset = useCallback(() => {
    setCurrentIndex(0);
  }, []);

  return { currentUrl, switchToNextCDN, reset, hasMoreCDNs };
}

// Usage
const StreamPlayer = ({ hlsPaths }) => {
  const { currentUrl, switchToNextCDN } = useMultiCDN(hlsPaths);

  const handleError = () => {
    if (!switchToNextCDN()) {
      console.error('All CDNs failed');
    }
  };

  return (
    <video src={currentUrl} onError={handleError} controls />
  );
};

Best Practices

1. CDN Selection Strategy

javascript
// Prioritize CDNs based on user location or performance
function selectOptimalCDN(hlsPaths, userRegion) {
  const cdnPriority = {
    'asia': ['gcore', 'bunny', 'origin'],
    'europe': ['bunny', 'gcore', 'origin'],
    'default': ['origin', 'bunny', 'gcore']
  };

  const priority = cdnPriority[userRegion] || cdnPriority['default'];

  return hlsPaths.sort((a, b) => {
    const aIndex = priority.findIndex(cdn => a.includes(cdn));
    const bIndex = priority.findIndex(cdn => b.includes(cdn));
    return aIndex - bIndex;
  });
}

2. Health Checking

javascript
async function checkCDNHealth(url) {
  try {
    const response = await fetch(url, { method: 'HEAD' });
    return response.ok;
  } catch {
    return false;
  }
}

async function findHealthyCDN(hlsPaths) {
  for (const url of hlsPaths) {
    if (await checkCDNHealth(url)) {
      return url;
    }
  }
  return null;
}

3. Performance Monitoring

Track CDN performance to optimize future selections:

javascript
function trackCDNPerformance(cdnUrl, loadTime, errors) {
  // Send to your analytics
  analytics.track('cdn_performance', {
    cdn: new URL(cdnUrl).hostname,
    loadTime,
    errors
  });
}

Released under the MIT License.