Documentation

Quick Start

The easiest way to get started is to use the URL Generator on the homepage. It provides a simple user interface for configuring all the available options and generates a shareable URL for you.

  1. Visit the homepage.
  2. Select a platform (Twitch or Kick).
  3. Enter a channel name.
  4. Adjust the URL parameters as needed.
  5. Click "Launch Player" to start the player or "Copy URL" to share it.

URL Parameters

The player is configured via URL parameters. The platform is selected via the URL path (e.g., /player/twitch, /player/kick).

ParameterTypeDefaultDescription
channelNamestringrequiredThe channel name(s) for the selected platform. Supports comma-separated values for multi-channel mode (e.g., xqc,pokimane,shroud). Maximum 5 channels. Clips from all channels are shuffled together into a single playlist.
daysnumber900Filter clips from the last N days.
viewsnumber0Minimum view count for clips (0 = no filter).
ignoreCreatorsstringnoneComma-separated list of clip creator usernames to exclude. Matching is case-insensitive (e.g., spammer,botuser).
allowedCreatorsstringnoneComma-separated list of clip creator usernames to include. Only clips from these creators will be shown. Matching is case-insensitive (e.g., favclipmaker,goodeditor).
ignoreKeywordsstringnoneComma-separated regex patterns to exclude from clip titles. Matching is case-insensitive. Plain text works as substring match. Examples: spoiler (contains), ^leak (starts with), drama$ (ends with).
allowedKeywordsstringnoneComma-separated regex patterns - only clips with titles matching at least one pattern are included. Case-insensitive. Examples: highlight, ^best, win$.
shufflestringsmartShuffle strategy: smart, stratified, weighted, random.
volumenumber0.5Initial video volume (0.0 to 1.0).
showLogobooleantrueShow the channel's logo.
showInfobooleantrueShow clip information (title, creator, views).
showTimerbooleantrueShow the countdown timer for the current clip.
showProgressBarbooleantrueShow the progress bar.
transparentBackgroundbooleanfalseMake the background transparent.
showNextClipbooleanfalseShow preview of the upcoming clip.
preloadVideobooleanfalsePreload the next video for smoother transitions.
langstringenPlayer language: en or de.
dateFormatstringdmyDate format: dmy (DD/MM/YYYY) or mdy (MM/DD/YYYY).

Display Sub-Options

Fine-grained control over what information is displayed in the clip info and next clip boxes.

ParameterTypeDefaultDescription
showInfoCategorybooleantrueShow category in clip info.
showInfoViewsbooleantrueShow view count in clip info.
showInfoDurationbooleantrueShow duration in clip info.
showInfoCreatorbooleantrueShow creator name in clip info.
showInfoDatebooleanfalseShow creation date in clip info.
showInfoProgressbooleanfalseShow progress bar inside clip info box.
progressBarPositionstringtopPosition of the progress bar: top or bottom.
showTimerDurationbooleantrueShow total duration alongside countdown timer.
showNextClipCategorybooleantrueShow category in next clip preview.
showNextClipViewsbooleantrueShow view count in next clip preview.
showNextClipDurationbooleantrueShow duration in next clip preview.
showNextClipCreatorbooleantrueShow creator name in next clip preview.
showNextClipDatebooleanfalseShow creation date in next clip preview.
showNextClipProgressbooleanfalseShow progress bar in next clip preview.

Regex Pattern Examples

The ignoreKeywords and allowedKeywords parameters support regular expression (regex) patterns for flexible title filtering. Plain text also works as a simple substring match.

PatternDescriptionMatchesDoesn't Match
spoilerContains "spoiler" anywhere"Big spoiler alert", "SPOILER!""Amazing play"
^spoilerStarts with "spoiler""Spoiler: ending""Big spoiler"
fail$Ends with "fail""Epic fail""fail compilation"
^spoiler.*reveal$Starts with "spoiler", ends with "reveal""Spoiler: big reveal""Spoiler alert"
(spoiler|leak|drama)Contains any of these words"Big drama", "leaked info""Amazing play"
ep(isode)?\s*\d+Matches "ep" or "episode" followed by number"ep 5", "Episode 12""epic moment"
\d4Contains 4-digit number (e.g., year)"Best of 2024""Top 10 plays"

Quick Reference

  • ^ - Start of title
  • $ - End of title
  • . - Any single character
  • .* - Any characters (zero or more)
  • .+ - Any characters (one or more)
  • \d - Any digit (0-9)
  • \s - Any whitespace
  • (a|b) - Match "a" or "b"
  • [abc] - Match any character in brackets
  • ? - Previous item is optional

Note: All patterns are case-insensitive. Invalid regex patterns are silently skipped.

Shuffle System

The shuffle system ensures variety in clip playback using multiple strategies. Each page refresh produces a new random order.

Shuffle Strategies

StrategyDescriptionBest For
smartHybrid approach: analyzes clip data, selects optimal strategy (hybrid for 300+, stratified for 100+, weighted for 30+), always applies creator diversity. Best variety.Most use cases (default)
stratifiedMulti-layer diversity: (1) 8 view-count buckets, (2) time spread mixing old/new clips, (3) random shuffle, (4) creator diversity to prevent same clipper back-to-back.Large playlists (200+ clips)
weightedGives less popular clips a chance while still favoring popular ones. Uses a diversity factor of 0.3, so the lowest clip has 30% weight of the highest.Medium playlists, discovering hidden gems
randomClassic Fisher-Yates shuffle where every clip has equal chance at any position.Small playlists, true randomness

Background Clip Integration

When additional clips are fetched in the background, they are shuffled into the remaining unwatched portion of the playlist rather than simply appended to the end. This ensures new clips are mixed throughout your viewing experience.

Clip Pool Size

  • Twitch initial load: ~600-800 unique clips (3 pages × 4 time filters, deduplicated)
  • Max clips: Configurable up to 2000 clips with background fetching

Multi-Channel Mode

The player supports fetching and playing clips from multiple channels simultaneously. Clips from all specified channels are merged into a single playlist and shuffled together.

Usage

Pass comma-separated channel names in the channelName parameter:

/player/twitch?channelName=xqc,pokimane,shroud

Features

  • Maximum 5 channels: If more than 5 channels are provided, only the first 5 are used
  • Parallel fetching: Clips from all channels are fetched simultaneously for faster loading
  • Automatic deduplication: Duplicate clips (same clip ID) are automatically removed
  • Partial failure handling: If some channels fail to load, the player continues with clips from successful channels
  • Channel badges: When multi-channel mode is active, the clip info and next clip boxes display a badge showing which channel the clip is from

Backward Compatibility

Single-channel URLs continue to work exactly as before. The multi-channel feature is fully backward compatible.

API Architecture

This application uses a proxy pattern to securely access platform APIs while avoiding CORS issues and protecting API credentials.

Twitch API

  • ClipsCards__User: Uses Twitch's persisted query for fetching clips with multiple time filters (LAST_DAY, LAST_WEEK, LAST_MONTH, ALL_TIME)
  • Multi-criteria fetching: Fetches 3-4 different time periods simultaneously for better clip diversity
  • Smart pagination: Continues with primary filter in background loading

Kick API

  • Cloudflare Worker Proxy: Bypasses Cloudflare bot detection by routing requests through Cloudflare Workers
  • HLS Manifest Patching: Patches Kick's HLS playlists to use absolute URLs for playback

Health Check

The application provides a health check endpoint at /api/health. This endpoint monitors the status of platform APIs and services.

Response Fields:

  • status: Overall status - ok or service_unavailable
  • platforms: Status of Twitch and Kick APIs (up/down)
  • services.kickProxyWorker: Cloudflare Worker status (up/down/not_configured)
  • timestamp: ISO 8601 timestamp

Example Response

{
  "status": "ok",
  "platforms": {
    "twitch": "up",
    "kick": "up"
  },
  "services": {
    "kickProxyWorker": {
      "status": "up"
    }
  },
  "timestamp": "2025-01-21T10:00:00.000Z",
  "_links": {
    "self": "https://clips.example.com/api/health",
    "docs": "https://clips.example.com/docs"
  }
}

API Endpoints

GET /api/twitch/clips

Fetch Twitch clips using ClipsCards__User operation

Query Parameters:
  • channelName (required): Twitch channel name
  • cursor (optional): Pagination cursor
  • filter (optional): LAST_DAY | LAST_WEEK | LAST_MONTH | ALL_TIME
  • days (optional): Auto-determine filter from days
Example Response:
{
  "edges": [
    {
      "cursor": "eyJpZCI6IjEyMzQ1Njc4OTAifQ==",
      "node": {
        "id": "1234567890",
        "slug": "ClipSlugHere",
        "title": "Amazing Play!",
        "viewCount": 15420,
        "createdAt": "2025-01-20T10:30:00Z",
        "durationSeconds": 30,
        "thumbnailURL": "https://clips-media-assets2.twitch.tv/...",
        "broadcaster": {
          "displayName": "ChannelName",
          "login": "channelname"
        },
        "curator": {
          "displayName": "ClipCreator",
          "login": "clipcreator"
        }
      }
    }
  ],
  "pageInfo": {
    "hasNextPage": true,
    "hasPreviousPage": false,
    "endCursor": "eyJpZCI6IjEyMzQ1Njc4OTAifQ=="
  }
}

GET /api/twitch/playback

Get authenticated playback URL for a Twitch clip

Query Parameters:
  • slug (required): Twitch clip slug
Example Response:
{
  "url": "https://production.assets.clips.twitchcdn.net/AT-cm%7C123456.mp4?sig=abc123...&token=eyJhbG..."
}

GET /api/kick/clips

Fetch Kick clips (via Cloudflare Worker proxy if configured)

Query Parameters:
  • channelName (required): Kick channel name
  • cursor (optional): Pagination cursor
Example Response:
{
  "clips": [
    {
      "id": "clip_abc123-def456-ghi789",
      "clip_url": "https://clips.kick.com/clips/...",
      "thumbnail_url": "https://clips.kick.com/clips/...",
      "title": "Epic Moment",
      "view_count": 8532,
      "liked": false,
      "likes": 145,
      "duration": 45,
      "created_at": "2025-01-20T15:45:30.000000Z",
      "video_url": "https://clips.kick.com/clips/.../abc123.m3u8",
      "creator": {
        "username": "viewer123",
        "profile_pic": "https://files.kick.com/images/user/..."
      },
      "channel": {
        "username": "channelname",
        "slug": "channelname"
      }
    }
  ],
  "cursor": "next_page_cursor_here"
}

GET /api/kick/manifest

Patch Kick HLS manifest for playback

Query Parameters:
  • url (required): Kick HLS manifest URL (encoded)
Example Response:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
https://stream.kick.com/video/path/segment0.ts
#EXTINF:10.0,
https://stream.kick.com/video/path/segment1.ts
#EXTINF:8.5,
https://stream.kick.com/video/path/segment2.ts
#EXT-X-ENDLIST

Content-Type: application/vnd.apple.mpegurl