{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# \ud83d\ude80 OpenSource Clipping \u2014 Quick Start Notebook\n", "\n", "> **\u26a1 Quick Start**: If you just want to get up and running as fast as possible,\n", "> simply run all cells from top to bottom. The only thing you need to change is\n", "> the **YouTube URL** and your **API Key** in the Configuration section below.\n", "\n", "---\n", "\n", "## What is this?\n", "\n", "This notebook is a **minimal, beginner-friendly** implementation of\n", "[OpenSource Clipping](https://github.com/NaufalRizqullah/opensource-clipping) \u2014\n", "an AI-powered tool that automatically transforms long-form videos into\n", "cinematic short-form highlight clips with:\n", "\n", "- \ud83c\udfaf AI-curated highlight moments (powered by Google Gemini)\n", "- \ud83c\udf99\ufe0f Word-level transcription (powered by Faster-Whisper)\n", "- \ud83d\udcf1 Smart face-tracking auto-framing for vertical (9:16) format\n", "- \ud83d\udcac Karaoke-style animated subtitles\n", "- \ud83c\udfac Cinematic hook teaser intro with glitch transition\n", "\n", "## How to use this notebook\n", "\n", "| Step | Section | What to do |\n", "|------|---------|------------|\n", "| 1 | **Setup** | Run the setup cells to clone the repo & install dependencies |\n", "| 2 | **Configuration** | Set your YouTube URL, API key, and clip preferences |\n", "| 3 | **Run** | Execute the pipeline \u2014 sit back and wait for your clips! |\n", "| 4 | **Download** | Download the generated clips from the `outputs/` folder |\n", "\n", "### \u26a0\ufe0f Requirements\n", "\n", "- **Runtime**: Set your Colab runtime to **T4 GPU** (`Runtime > Change runtime type > T4 GPU`)\n", "- **API Key**: You need a free [Google Gemini API Key](https://aistudio.google.com/apikey)\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Setup \u2014 Clone Repository & Install Dependencies\n", "\n", "This section clones the OpenSource Clipping repository and installs all\n", "required Python packages. It also installs **FFmpeg** (needed for video\n", "processing) and **Deno** (used internally by some modules).\n", "\n", "> \ud83d\udca1 **Tip**: This cell only needs to run once per Colab session." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "# 1a. Clone the repository into the current working directory\n", "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "!rm -rf ./* ./.*\n", "!git clone https://github.com/NaufalRizqullah/opensource-clipping.git ." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%capture\n", "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "# 1b. Install system dependencies (FFmpeg + Deno) and Python packages\n", "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "import os\n", "\n", "# FFmpeg \u2014 required for video encoding/decoding\n", "!apt-get -qq update\n", "!apt-get -qq install -y ffmpeg\n", "\n", "# Deno \u2014 used by internal subtitle rendering modules\n", "!curl -fsSL https://deno.land/install.sh | sh\n", "os.environ[\"PATH\"] += \":/root/.deno/bin\"\n", "\n", "# Python dependencies\n", "!pip install -r requirements.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Configuration \u2014 Set Your Preferences\n", "\n", "This is the **only section you need to edit**. Configure the following:\n", "\n", "| Parameter | Description | Default |\n", "|-----------|-------------|---------|\n", "| `YOUTUBE_URL` | The YouTube video URL you want to clip | *(required)* |\n", "| `TOTAL_CLIPS` | How many highlight clips to generate | `3` |\n", "| `WHISPER_MODEL` | Whisper model size for transcription accuracy | `large-v3` |\n", "| `WHISPER_DEVICE` | Device for Whisper inference (`cuda` or `cpu`) | `cuda` |\n", "| `WHISPER_COMPUTE_TYPE` | Compute precision (`float16` for Colab T4, `float32` for CPU) | `float16` |\n", "\n", "### Whisper Model Options\n", "\n", "| Model | Speed | Accuracy | VRAM |\n", "|-------|-------|----------|------|\n", "| `tiny` | \u26a1\u26a1\u26a1\u26a1\u26a1 | \u2605\u2606\u2606\u2606\u2606 | ~1 GB |\n", "| `base` | \u26a1\u26a1\u26a1\u26a1 | \u2605\u2605\u2606\u2606\u2606 | ~1 GB |\n", "| `small` | \u26a1\u26a1\u26a1 | \u2605\u2605\u2605\u2606\u2606 | ~2 GB |\n", "| `medium` | \u26a1\u26a1 | \u2605\u2605\u2605\u2605\u2606 | ~5 GB |\n", "| `large-v3` | \u26a1 | \u2605\u2605\u2605\u2605\u2605 | ~10 GB |\n", "\n", "> \ud83d\udca1 **Recommendation**: Use `large-v3` with `float16` on Colab T4 GPU for best\n", "> results. If you're on a free Kaggle notebook or CPU-only environment, use\n", "> `small` or `medium` with `float32`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n", "# CONFIGURATION \u2014 Edit the values below to match your preferences\n", "# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n", "\n", "# \u2500\u2500 YouTube URL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "# Paste the YouTube video URL you want to generate clips from.\n", "YOUTUBE_URL = \"https://www.youtube.com/watch?v=YOUR_VIDEO_ID\" # <-- CHANGE THIS\n", "\n", "# \u2500\u2500 Total Clips \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "# Number of highlight clips to generate from the video.\n", "# More clips = longer processing time. Start small (1-3) for testing.\n", "TOTAL_CLIPS = 3\n", "\n", "# \u2500\u2500 Whisper Configuration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "# These control the speech-to-text transcription step.\n", "WHISPER_MODEL = \"large-v3\" # Model size (see table above)\n", "WHISPER_DEVICE = \"cuda\" # \"cuda\" for GPU, \"cpu\" for CPU-only\n", "WHISPER_COMPUTE_TYPE = \"float16\" # \"float16\" for Colab T4, \"float32\" for CPU/Kaggle\n", "\n", "# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n", "# OPTIONAL \u2014 Advanced settings (safe to leave as defaults)\n", "# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n", "\n", "ASPECT_RATIO = \"9:16\" # Output aspect ratio: \"9:16\", \"16:9\", \"1:1\"\n", "FONT_STYLE = \"HORMOZI\" # Subtitle style: \"DEFAULT\", \"HORMOZI\", \"CINEMATIC\", \"STORYTELLER\"\n", "HOOK_DURATION = 3 # Hook teaser duration in seconds\n", "WORDS_PER_SUBTITLE = 5 # Max words per subtitle group\n", "\n", "print(\"\u2705 Configuration loaded!\")\n", "print(f\" URL : {YOUTUBE_URL}\")\n", "print(f\" Total Clips : {TOTAL_CLIPS}\")\n", "print(f\" Whisper Model : {WHISPER_MODEL} ({WHISPER_DEVICE}, {WHISPER_COMPUTE_TYPE})\")\n", "print(f\" Aspect Ratio : {ASPECT_RATIO}\")\n", "print(f\" Font Style : {FONT_STYLE}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. API Key Setup\n", "\n", "Your **Google Gemini API Key** is required for the AI analysis step.\n", "The recommended way is to store it in **Colab Secrets**:\n", "\n", "1. Click the \ud83d\udd11 **Key icon** in the left sidebar of Colab\n", "2. Add a new secret named `GOOGLE_API_KEY`\n", "3. Paste your API key as the value\n", "4. Toggle the **\"Notebook access\"** switch ON\n", "\n", "> \ud83d\udd17 Get a free API key at: https://aistudio.google.com/apikey\n", "\n", "**Optional keys** (for extra features):\n", "- `PEXELS_API_KEY` \u2014 Enables automatic B-roll stock footage ([get one here](https://www.pexels.com/api/))\n", "- `HF_TOKEN` \u2014 Enables split-screen / camera-switch mode ([get one here](https://huggingface.co/settings/tokens))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "# Load API keys from Colab Secrets and create the .env file\n", "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "from google.colab import userdata\n", "from pathlib import Path\n", "\n", "# Required\n", "GOOGLE_API_KEY = userdata.get(\"GOOGLE_API_KEY\") or \"\"\n", "\n", "# Optional \u2014 leave blank if you don't have them\n", "PEXELS_API_KEY = userdata.get(\"PEXELS_API_KEY\") or \"\"\n", "HF_TOKEN = userdata.get(\"HF_TOKEN\") or \"\"\n", "\n", "# Write the .env file so the pipeline can read the keys\n", "env_text = f\"\"\"# Auto-generated by Quick Start notebook\n", "GOOGLE_API_KEY={GOOGLE_API_KEY}\n", "PEXELS_API_KEY={PEXELS_API_KEY}\n", "HF_TOKEN={HF_TOKEN}\n", "\"\"\"\n", "Path(\".env\").write_text(env_text, encoding=\"utf-8\")\n", "\n", "# Status check\n", "print(\"\ud83d\udd11 API Key Status:\")\n", "print(f\" GOOGLE_API_KEY : {'\u2705 Set' if GOOGLE_API_KEY else '\u274c Missing (required!)'}\")\n", "print(f\" PEXELS_API_KEY : {'\u2705 Set' if PEXELS_API_KEY else '\u26aa Not set (optional)'}\")\n", "print(f\" HF_TOKEN : {'\u2705 Set' if HF_TOKEN else '\u26aa Not set (optional)'}\")\n", "\n", "if not GOOGLE_API_KEY:\n", " print(\"\\n\u26a0\ufe0f WARNING: GOOGLE_API_KEY is missing!\")\n", " print(\" Add it to Colab Secrets (\ud83d\udd11 icon in sidebar) before running the pipeline.\")\n", " print(\" Get your free key at: https://aistudio.google.com/apikey\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Run the Pipeline \ud83c\udfac\n", "\n", "This cell runs the full AI clipping pipeline:\n", "\n", "1. **Download** \u2014 Downloads the YouTube video\n", "2. **Transcribe** \u2014 Converts speech to text using Faster-Whisper\n", "3. **Analyze** \u2014 Google Gemini AI picks the most engaging moments\n", "4. **Render** \u2014 Generates clips with face-tracking, subtitles, and hook teasers\n", "\n", "> \u23f1\ufe0f **Estimated time**: 5\u201315 minutes depending on video length and number of clips.\n", "\n", "> \u26a0\ufe0f Make sure you have set the `YOUTUBE_URL` in the Configuration section above!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "# YouTube Cookies Setup (Optional) - Solves yt-dlp 403 Forbidden errors\n", "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "import os\n", "import shutil\n", "\n", "COOKIES_PATH = os.path.abspath(\"youtube_cookies.txt\")\n", "cookie_candidates = [\n", " \"/kaggle/input/datasets/muhammadnaufal/tiktok-secret-cookies/youtube_cookies.txt\",\n", " \"/content/youtube_cookies.txt\",\n", " COOKIES_PATH,\n", "]\n", "\n", "source_cookie = next((p for p in cookie_candidates if os.path.isfile(p)), None)\n", "YT_COOKIES_ARG = \"\"\n", "\n", "if source_cookie:\n", " if os.path.realpath(source_cookie) != os.path.realpath(COOKIES_PATH):\n", " shutil.copy(source_cookie, COOKIES_PATH)\n", " print(f\"\u2705 YouTube cookies aktif: {COOKIES_PATH}\")\n", " YT_COOKIES_ARG = f\"--yt-cookies {COOKIES_PATH}\"\n", "else:\n", " print(\"\u2139\ufe0f youtube_cookies.txt tidak ditemukan. Download akan dicoba tanpa cookies.\")\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "# Execute the OpenSource Clipping pipeline with your configuration\n", "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "\n", "!python main.py \\\n", " --url \"{YOUTUBE_URL}\" \\\n", " --clips {TOTAL_CLIPS} \\\n", " --ratio \"{ASPECT_RATIO}\" \\\n", " --font-style \"{FONT_STYLE}\" \\\n", " --hook-duration {HOOK_DURATION} \\\n", " --words-per-sub {WORDS_PER_SUBTITLE} \\\n", " --whisper-model \"{WHISPER_MODEL}\" \\\n", " --whisper-device \"{WHISPER_DEVICE}\" \\\n", " --whisper-compute-type \"{WHISPER_COMPUTE_TYPE}\" \\\n", " {YT_COOKIES_ARG}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. View & Download Results\n", "\n", "After the pipeline completes, your clips are saved in the `outputs/` folder.\n", "Run the cells below to preview and download them." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "# List all generated output files\n", "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "import os\n", "\n", "outputs_dir = \"outputs\"\n", "if os.path.exists(outputs_dir):\n", " files = os.listdir(outputs_dir)\n", " video_files = [f for f in files if f.endswith(\".mp4\")]\n", " print(f\"\ud83c\udfac Generated {len(video_files)} clip(s):\\n\")\n", " for f in sorted(files):\n", " size_mb = os.path.getsize(os.path.join(outputs_dir, f)) / (1024 * 1024)\n", " icon = \"\ud83c\udfa5\" if f.endswith(\".mp4\") else \"\ud83d\uddbc\ufe0f\" if f.endswith((\".jpg\", \".png\")) else \"\ud83d\udcc4\"\n", " print(f\" {icon} {f} ({size_mb:.1f} MB)\")\n", "else:\n", " print(\"\u274c No outputs found. Make sure the pipeline ran successfully.\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "# Download all output files as a ZIP archive\n", "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", "import shutil\n", "from google.colab import files\n", "\n", "if os.path.exists(outputs_dir) and os.listdir(outputs_dir):\n", " zip_name = \"clipping_outputs\"\n", " shutil.make_archive(zip_name, \"zip\", outputs_dir)\n", " print(f\"\ud83d\udce6 Created {zip_name}.zip \u2014 downloading now...\")\n", " files.download(f\"{zip_name}.zip\")\n", "else:\n", " print(\"\u274c No outputs to download.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## \ud83d\udcd6 Troubleshooting\n", "\n", "| Problem | Solution |\n", "|---------|----------|\n", "| `GOOGLE_API_KEY not found` | Add your API key to Colab Secrets (\ud83d\udd11 sidebar) |\n", "| `CUDA out of memory` | Use a smaller Whisper model (`small` or `medium`) |\n", "| `float16 not supported` | Change `WHISPER_COMPUTE_TYPE` to `float32` |\n", "| Pipeline takes too long | Reduce `TOTAL_CLIPS` to `1` for testing |\n", "| No B-roll footage | Add `PEXELS_API_KEY` to Colab Secrets |\n", "\n", "## \ud83d\udd17 Links\n", "\n", "- **GitHub**: [NaufalRizqullah/opensource-clipping](https://github.com/NaufalRizqullah/opensource-clipping)\n", "- **Full Documentation**: See the [README](https://github.com/NaufalRizqullah/opensource-clipping/blob/main/README.md) for all CLI options\n", "- **Get Gemini API Key**: [aistudio.google.com/apikey](https://aistudio.google.com/apikey)\n", "- **Get Pexels API Key**: [pexels.com/api](https://www.pexels.com/api/)" ] } ], "metadata": { "accelerator": "GPU", "colab": { "gpuType": "T4", "provenance": [], "toc_visible": true }, "kernelspec": { "display_name": "Python 3", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 0 }