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.
- Visit the homepage.
- Select a platform (Twitch or Kick).
- Enter a channel name.
- Adjust the URL parameters as needed.
- 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).
| Parameter | Type | Default | Description |
|---|---|---|---|
channelName | string | required | The 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. |
days | number | 900 | Filter clips from the last N days. |
views | number | 0 | Minimum view count for clips (0 = no filter). |
ignoreCreators | string | none | Comma-separated list of clip creator usernames to exclude. Matching is case-insensitive (e.g., spammer,botuser). |
allowedCreators | string | none | Comma-separated list of clip creator usernames to include. Only clips from these creators will be shown. Matching is case-insensitive (e.g., favclipmaker,goodeditor). |
ignoreKeywords | string | none | Comma-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). |
allowedKeywords | string | none | Comma-separated regex patterns - only clips with titles matching at least one pattern are included. Case-insensitive. Examples: highlight, ^best, win$. |
shuffle | string | smart | Shuffle strategy: smart, stratified, weighted, random. |
volume | number | 0.5 | Initial video volume (0.0 to 1.0). |
showLogo | boolean | true | Show the channel's logo. |
showInfo | boolean | true | Show clip information (title, creator, views). |
showTimer | boolean | true | Show the countdown timer for the current clip. |
showProgressBar | boolean | true | Show the progress bar. |
transparentBackground | boolean | false | Make the background transparent. |
showNextClip | boolean | false | Show preview of the upcoming clip. |
preloadVideo | boolean | false | Preload the next video for smoother transitions. |
lang | string | en | Player language: en or de. |
dateFormat | string | dmy | Date 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.
| Parameter | Type | Default | Description |
|---|---|---|---|
showInfoCategory | boolean | true | Show category in clip info. |
showInfoViews | boolean | true | Show view count in clip info. |
showInfoDuration | boolean | true | Show duration in clip info. |
showInfoCreator | boolean | true | Show creator name in clip info. |
showInfoDate | boolean | false | Show creation date in clip info. |
showInfoProgress | boolean | false | Show progress bar inside clip info box. |
progressBarPosition | string | top | Position of the progress bar: top or bottom. |
showTimerDuration | boolean | true | Show total duration alongside countdown timer. |
showNextClipCategory | boolean | true | Show category in next clip preview. |
showNextClipViews | boolean | true | Show view count in next clip preview. |
showNextClipDuration | boolean | true | Show duration in next clip preview. |
showNextClipCreator | boolean | true | Show creator name in next clip preview. |
showNextClipDate | boolean | false | Show creation date in next clip preview. |
showNextClipProgress | boolean | false | Show 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.
| Pattern | Description | Matches | Doesn't Match |
|---|---|---|---|
spoiler | Contains "spoiler" anywhere | "Big spoiler alert", "SPOILER!" | "Amazing play" |
^spoiler | Starts 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" |
\d4 | Contains 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
| Strategy | Description | Best For |
|---|---|---|
smart | Hybrid 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) |
stratified | Multi-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) |
weighted | Gives 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 |
random | Classic 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,shroudFeatures
- 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 -
okorservice_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 namecursor(optional): Pagination cursorfilter(optional): LAST_DAY | LAST_WEEK | LAST_MONTH | ALL_TIMEdays(optional): Auto-determine filter from days
{
"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
{
"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 namecursor(optional): Pagination cursor
{
"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)
#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-ENDLISTContent-Type: application/vnd.apple.mpegurl