Host vertical videos with JSON API endpoints, auto-generated thumbnails, and real metadata extraction. No backend required.
Pure static files served via GitHub Pages. No server setup, no infrastructure costs.
Thumbnails automatically generated from video frames using ffmpeg.
Accurate video data extracted via ffprobe: duration, bitrate, FPS, dimensions.
Vertical videos (1080x1920) perfect for mobile and social media.
RESTful-style API endpoints for videos, feeds, and playlists.
Public CDN with CORS enabled for easy cross-origin requests.
Simple JSON endpoints for accessing video data
Returns complete catalog with video metadata, sources, and thumbnails.
{
"version": 1,
"updated_at": "2025-12-09T15:00:00Z",
"videos": [
{
"id": "4761249",
"slug": "mobile-short-01",
"title": "Mobile Portrait Short 01",
"duration_seconds": 5.91,
"fps": 30,
"size_bytes": 3786660,
"tags": ["vertical", "mobile", "short"],
"sources": [{
"quality": "1080p",
"codec": "h264",
"url": "https://trebla-io.github.io/fox-cdn/videos/mobile-short-01/video.mp4"
}],
"thumbnail": {
"url": "https://trebla-io.github.io/fox-cdn/videos/mobile-short-01/thumbnail.jpg"
}
}
]
}
Returns ordered feed of video IDs for sequential playback.
{
"version": 1,
"feed": [
{ "video_id": "mobile-short-01", "position": 1 },
{ "video_id": "mobile-short-02", "position": 2 },
{ "video_id": "mobile-short-03", "position": 3 }
]
}
Returns curated playlists organized by video length and characteristics.
{
"playlists": [
{
"id": "short-videos",
"title": "Short Videos",
"description": "Quick clips under 10 seconds",
"videos": ["mobile-short-01", "mobile-short-02"]
}
]
}
Get started in minutes with these examples
async function fetchVideos() {
const res = await fetch(
"https://trebla-io.github.io/fox-cdn/api/videos.json"
);
if (!res.ok) {
throw new Error("Failed to fetch videos");
}
const data = await res.json();
return data.videos;
}
// Usage
const videos = await fetchVideos();
console.log(`Found ${videos.length} videos`);
async function playVideo(slug: string) {
const videos = await fetchVideos();
const video = videos.find(v => v.slug === slug);
if (!video) {
throw new Error(`Video not found: ${slug}`);
}
const videoElement = document.createElement('video');
videoElement.src = video.sources[0].url;
videoElement.poster = video.thumbnail.url;
videoElement.autoplay = true;
videoElement.loop = video.meta.loop;
videoElement.muted = video.meta.mute_default;
document.body.appendChild(videoElement);
return videoElement;
}
// Play a short video
playVideo('mobile-short-01');
async function loadPlaylist(playlistId: string) {
const [playlists, videos] = await Promise.all([
fetch("https://trebla-io.github.io/fox-cdn/api/playlists.json")
.then(r => r.json()),
fetchVideos()
]);
const playlist = playlists.playlists.find(
p => p.id === playlistId
);
if (!playlist) {
throw new Error(`Playlist not found: ${playlistId}`);
}
return playlist.videos.map(slug =>
videos.find(v => v.slug === slug)
);
}
// Load short videos playlist
const shortVideos = await loadPlaylist('short-videos');
10 vertical videos organized by length
Stream-ready CDN with embeddable player and direct video access