{"id":32791508,"url":"https://github.com/zebadrabbit/clippy","last_synced_at":"2026-04-04T04:01:42.253Z","repository":{"id":314660841,"uuid":"1056308125","full_name":"zebadrabbit/Clippy","owner":"zebadrabbit","description":"Create highlight compilations from Twitch clips with ffmpeg (NVENC). Optional Discord channel sourcing and a guided setup wizard.","archived":false,"fork":false,"pushed_at":"2025-11-05T03:18:09.000Z","size":15710,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-05T05:27:45.457Z","etag":null,"topics":["cli","compilation","content-creation","discord","discord-bot","discord-integration","ffmpeg","highlights","media-pipeline","nvenc","python","streaming","twitch","twitch-api","twitch-clips-automation","video-processing","windows","yaml","yt-dlp"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zebadrabbit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"docs/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"docs/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-13T20:12:58.000Z","updated_at":"2025-11-05T03:18:12.000Z","dependencies_parsed_at":"2025-09-13T23:30:34.990Z","dependency_job_id":"1dbe6956-dac4-441d-89de-b0e9dec5908e","html_url":"https://github.com/zebadrabbit/Clippy","commit_stats":null,"previous_names":["zebadrabbit/clippy"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/zebadrabbit/Clippy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zebadrabbit%2FClippy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zebadrabbit%2FClippy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zebadrabbit%2FClippy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zebadrabbit%2FClippy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zebadrabbit","download_url":"https://codeload.github.com/zebadrabbit/Clippy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zebadrabbit%2FClippy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":282823603,"owners_count":26733133,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-05T02:00:05.946Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","compilation","content-creation","discord","discord-bot","discord-integration","ffmpeg","highlights","media-pipeline","nvenc","python","streaming","twitch","twitch-api","twitch-clips-automation","video-processing","windows","yaml","yt-dlp"],"created_at":"2025-11-05T13:01:05.795Z","updated_at":"2026-04-04T04:01:42.231Z","avatar_url":"https://github.com/zebadrabbit.png","language":"Python","readme":"# Twitch Clip Compilation\n\nCreate highlight compilations directly from Twitch clips. Audio is ON by default for intros, static, transitions, and outros. All non-clip assets are normalized to H.264 (yuv420p) with AAC 48 kHz stereo to keep concatenation stable.\n\n## Features\n\n- **Two interfaces**: Interactive Textual TUI (`--tui`) for beginners, full CLI for power users\n- Twitch Helix ingestion with date windows, auto-expand lookback, and nostalgia mode\n- Discord channel ingestion (optional): read clip links curated by your community\n- Duration-based sizing: request compilations by target length (`--target-duration 20`) instead of clip count\n- Auto-expand: fills missing clips from outside the date range (newest to oldest)\n- Nostalgia mode: mixes in random older clips (\u003e6 months) for variety\n- 5 encoding presets (youtube_1080p60, discord_friendly, archive_hq, quick_preview, cpu_only)\n- Min-views filter, weighted selection, and themed colorized logs\n- Creator avatar overlay, transitions, and output finalization to `output/`\n- yt-dlp downloads with retries; `.env` or env-based credentials\n- NVENC-based encoding tuned for fewer artifacts at transitions, with libx264 fallback\n- Resilient audio: loudness normalization for assets, synthesize clean stereo audio if missing\n- Ctrl-C friendly: cooperative shutdown that stops workers and terminates ffmpeg cleanly\n- Save credentials to `.env` from the TUI or CLI (`--save-env`)\n- Summary screen with output paths, compilation lengths, and contributor credits\n\n## Setup (first time, PowerShell on Windows)\n\n```powershell\npython -m venv .venv\n\\.\\.venv\\Scripts\\Activate.ps1\npip install -r requirements.txt\n```\n\nFor the TUI, also install the optional dependency:\n\n```powershell\npip install \"textual\u003e=0.40\"\n```\n\nOr install all optional dependencies at once:\n\n```powershell\npip install -e \".[tui,dev]\"\n```\n\n## Quick Start\n\n### TUI (recommended for first-time users)\n\n```powershell\npython main.py --tui\n```\n\nThe TUI walks you through 6 steps: Source \u003e Credentials \u003e Clip Settings \u003e Quality \u003e Transitions \u003e Review \u0026 Start. It saves credentials to `.env` on request so subsequent runs auto-fill.\n\n### CLI\n\n```powershell\n# By clip count\npython main.py --broadcaster somechannel --clips 12 --compilations 2 --min-views 5\n\n# By target duration (minutes)\npython main.py --broadcaster somechannel --target-duration 20 --compilations 2\n\n# With auto-expand and nostalgia\npython main.py --broadcaster somechannel --clips 12 --compilations 2 --auto-expand --nostalgia\n\n# Auto-confirm\npython main.py --broadcaster somechannel -y\n```\n\n### Discord mode\n\nPrerequisites:\n\n- A Discord bot in your server with permission to read the target channel\n- The \"Message Content Intent\" enabled for your bot in the Discord Developer Portal\n- Bot token saved to `.env` as `DISCORD_TOKEN`\n- Channel ID saved to `.env` as `DISCORD_CHANNEL_ID` (or pass via CLI/TUI)\n\n```powershell\npython main.py --discord --discord-channel-id 123456789012345678 -y\n```\n\nWhat happens: Clippy reads messages from the channel, extracts Twitch clip links, resolves them via Helix, and builds compilations. This lets your Twitch community curate clips collaboratively.\n\n## Configuration\n\n- Precedence: CLI flags \u003e Environment (`.env`) \u003e `clippy.yaml` \u003e built-in defaults.\n- The TUI and setup wizard create `clippy.yaml` and `.env` for you. A commented example remains in `clippy.yaml.example`.\n\nKey env vars:\n\n| Variable | Description |\n|---|---|\n| `TWITCH_CLIENT_ID` | Twitch app client ID for Helix API |\n| `TWITCH_CLIENT_SECRET` | Twitch app client secret |\n| `DISCORD_TOKEN` | Discord bot token (for Discord mode) |\n| `DISCORD_CHANNEL_ID` | Discord channel to read clip links from |\n| `TRANSITIONS_DIR` | Custom transitions folder path |\n\n## CLI Reference\n\nHelp is grouped into logical sections:\n\n```powershell\npython main.py -h\n```\n\nKey flags:\n\n| Flag | Description |\n|---|---|\n| `--tui` | Launch the interactive TUI |\n| `--broadcaster` | Twitch channel name |\n| `--clips` | Clips per compilation (default: 12) |\n| `--compilations` | Number of compilations (default: 2) |\n| `--target-duration` | Target compilation length in minutes (alternative to `--clips`) |\n| `--auto-expand` | Fill missing clips from outside date range |\n| `--no-auto-expand` | Disable auto-expand |\n| `--nostalgia` | Mix in random older clips (\u003e6 months) |\n| `--min-views` | Minimum view count filter |\n| `--preset` | Encoding preset name (use `--list-presets` to see options) |\n| `--nvenc-preset` | NVENC encoder preset (slow, medium, fast, etc.) |\n| `--quality` | Quality tier (low, medium, high, max) |\n| `--format` | Container format (mp4, mkv) |\n| `--save-env` | Save credentials to `.env` for future runs |\n| `-y` / `--yes` | Auto-confirm settings |\n\n## Encoding Presets\n\nUse `--list-presets` to see all available presets:\n\n| Preset | Resolution | FPS | Codec | Use Case |\n|---|---|---|---|---|\n| `youtube_1080p60` | 1920x1080 | 60 | h264_nvenc | YouTube uploads |\n| `discord_friendly` | 1280x720 | 30 | h264_nvenc | Discord file size limits |\n| `archive_hq` | 1920x1080 | 60 | h264_nvenc | High-quality archive (MKV) |\n| `quick_preview` | 1280x720 | 30 | h264_nvenc | Fast preview renders |\n| `cpu_only` | 1920x1080 | 60 | libx264 | Systems without NVENC GPU |\n\nApply a preset and customize:\n\n```powershell\npython main.py --broadcaster somechannel --preset youtube_1080p60 --cq 18\n```\n\n## Outputs\n\n- Final files are moved to `output/` with names like: `\u003cchannel\u003e_\u003cstart\u003e_to_\u003cend\u003e_compilation.mp4` (or `.mkv`).\n- Work-in-progress artifacts live under `cache/` and are cleaned unless `--keep-cache` is set.\n- If a file exists, we auto-suffix with `_1`, `_2`, ... unless `--overwrite-output` is provided.\n- The TUI summary screen shows output paths, compilation lengths, and contributor credits.\n\n## Transitions \u0026 Sequencing\n\n- `transitions/static.mp4` is required and placed between every segment.\n- Sequence: random(optional intro) \u003e static \u003e clip \u003e static \u003e random_chance(transition \u003e static) ... \u003e random(optional outro)\n- All non-clip assets are normalized to `cache/_trans` on first use to ensure uniform codecs and audio (48 kHz stereo). You can force a rebuild with `--rebuild-transitions`.\n\n### Intro/Outro configuration\n\n- Where they live: filenames are relative to your transitions folder (default `transitions/`, or whatever you set with `--transitions-dir` or `TRANSITIONS_DIR`).\n- Configure via `clippy.yaml` under the `assets` section:\n\n```yaml\nassets:\n  static: static.mp4\n  intro:\n    - intro.mp4\n  outro:\n    - outro.mp4\n```\n\n- Override per-run: use `--intro` or `--outro` to force a single file for that run, and `--transition` to force the transition choice when selected.\n\n### Creating and validating transitions\n\n```powershell\n# Import an existing clip as a transition\npython .\\scripts\\import_media.py path\\to\\your\\clip.mp4 --type transition\n\n# Generate multiple transitions from a long video\npython .\\scripts\\make_transitions.py -i .\\long_source.mp4 -n 8\n\n# Validate transitions\npython .\\scripts\\test_transitions.py --normalize --concat-audio-check\n```\n\n## Troubleshooting\n\n- **Seeing only a few clips?** Use `--auto-expand` or `--target-duration` to let Clippy gather more.\n- **Pixelation at cuts?** Try `--quality max` or `--bitrate 16M`.\n- **Concat AAC errors?** Run `python .\\scripts\\test_transitions.py --normalize`.\n- **No NVENC?** Use `--preset cpu_only` or let Clippy auto-detect with `detect_encoder()`.\n- **Duplicate log messages in TUI?** Fixed in v0.5.0 — update to latest.\n\n## Health Check\n\n```powershell\npython .\\scripts\\health_check.py\n```\n\n## Docs\n\n- [Contributing](docs/CONTRIBUTING.md)\n- [Code of Conduct](docs/CODE_OF_CONDUCT.md)\n- [Security Policy](docs/SECURITY.md)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzebadrabbit%2Fclippy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzebadrabbit%2Fclippy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzebadrabbit%2Fclippy/lists"}