rsm-cdn tester

Drop an image or video here, or choose a file.

Preview

Upload something to preview it here.

Integration

1. Upload (POST /upload)

Multipart form upload. Field name is file. The response tells you where the asset will live.

curl -X POST https://cdn.example.com/upload \
  -H "x-api-key: <UPLOAD_KEY>" \
  -F "file=@/path/to/clip.mp4"

# image response (ready immediately):
{"url":"https://cdn.example.com/i/<guid>.jpg","status":"ready","kind":"image"}

# video response (HLS transcode is running in the background):
{"url":"https://cdn.example.com/<guid>/index.m3u8","status":"processing","kind":"video"}

2. Serve (GET any returned url)

Every GET requires x-api-key from CDN_API_KEYS. Use it as an Authorization-style header; image/video tags need a fetch-then-blob step or an HLS player with xhrSetup.

curl -H "x-api-key: <CDN_KEY>" https://cdn.example.com/i/<guid>.jpg -o out.jpg

3. Video progress (GET m3u8 url with ?status)

Poll the same URL you'll eventually play, just append ?status (or ?done). Returns JSON; status is one of processing, ready, failed, unknown.

curl -H "x-api-key: <CDN_KEY>" "https://cdn.example.com/<guid>/index.m3u8?status"

# in flight:
{"guid":"…","status":"processing","percent":42.1,"elapsed_seconds":8.4,
 "duration_seconds":20.0,"out_seconds":8.42,"speed":1.15,"eta_seconds":10.06}

# done:
{"guid":"…","status":"ready","percent":100}

# failed (stays for 60s after failure, then 404):
{"guid":"…","status":"failed","error":"ffmpeg: exit status 1\n…"}

4. Minimal polling loop (JS)

async function upload(file, uploadKey, cdnKey) {
  const fd = new FormData();
  fd.append('file', file);
  const r = await fetch('/upload', {
    method: 'POST',
    headers: { 'x-api-key': uploadKey },
    body: fd,
  });
  if (!r.ok) throw new Error('upload ' + r.status);
  const { url, kind, status } = await r.json();

  if (status === 'ready') return { url, kind };

  while (true) {
    await new Promise(r => setTimeout(r, 1500));
    const s = await (await fetch(url + '?status', {
      headers: { 'x-api-key': cdnKey },
    })).json();
    if (s.status === 'ready') return { url, kind };
    if (s.status === 'failed') throw new Error(s.error);
    // optionally surface s.percent / s.eta_seconds in your UI here
  }
}

5. Playing the video

Since <video> can't set custom headers, use hls.js with xhrSetup:

const hls = new Hls({
  xhrSetup: xhr => xhr.setRequestHeader('x-api-key', CDN_KEY),
});
hls.loadSource(url);
hls.attachMedia(document.querySelector('video'));