1 line
20 KiB
JSON
1 line
20 KiB
JSON
{"repo": "adzibilal/simbioclip", "files": {"README.md": {"2d336a00d7d3a3cf71c75106f4dc9ffa9b0b9b89": {"t": 1785674373.4510891, "n": 18616, "h": "912ec7ab16747499", "c": "# SimbioClip\n\nAI video clipper self-hosted — ubah video panjang jadi shorts vertikal dengan caption otomatis. Tanpa biaya langganan.\n\n<img width=\"1600\" height=\"803\" alt=\"image\" src=\"https://github.com/user-attachments/assets/1fedf842-c73c-4440-8d2d-c5fb5eed3fd6\" />\n\n<img width=\"1901\" height=\"912\" alt=\"image\" src=\"https://github.com/user-attachments/assets/4d92ea0a-711e-4b49-bbd4-72449cf0b11c\" />\n\n> **Open Source Project** — This project is open source and still under active development. There may be bugs and issues. Feel free to contribute, report issues, or submit Pull Requests on [GitHub](https://github.com/adzibilal/simbioclip).\n\n## Fitur\n\n- Download video dari URL (YouTube, dll. via yt-dlp) **atau** upload file\n- Speech-to-text dengan timestamp per kata (mode API router atau faster-whisper lokal di CPU)\n- Deteksi momen terbaik via LLM (skor + hook + judul), **momen lucu/ketawa diprioritaskan lebih dulu**\n- Render clip vertikal (9:16 / 1:1 / 4:5 / 16:9) dengan caption ter-burn\n- Layout: Auto, Center Crop, Talking Head, Split Cam, Podcast, Inset, Face Track, **BG Blur** (background blur + konten 4:5 tajam + judul menetap)\n- Gaya caption: Bold Pop, Karaoke, Neon, Minimal, Podcast\n- Edit per-clip: rerender dengan layout/caption berbeda, trim akurat per-frame, **thumbnail cover intro** custom\n- Pilihan resolusi download (360p–4K / Best)\n- Dashboard web dengan update live (HTMX) + antrean job async (Redis + RQ)\n\n## Arsitektur\n\n```\n ┌──────────────┐\n │ Browser │\n │ (Dashboard) │\n └──────┬───────┘\n │\n ┌──────▼───────┐\n │ FastAPI API │\n │ (main.py) │\n └──┬───────┬───┘\n │ │\n ┌────────▼─┐ ┌──▼──────────┐\n │ Redis │ │ Worker │\n │ (queue) │ │ (RQ worker) │\n └──────────┘ └──┬──────────┘\n │\n ┌───────────────────────┬┴──────────────────┐\n │ │ │\n ┌────▼────┐ ┌──────▼──────┐ ┌──────▼──────┐\n │ yt-dlp │ │ LLM │ │ FFmpeg │\n │Download │ │ Router │ │ Render │\n └─────────┘ └─────────────┘ └─────────────┘\n```\n\n- **API** — FastAPI: menerima job, menyajikan dashboard, streaming status live\n- **Worker** — RQ worker: menjalankan pipeline (download → transcribe → deteksi momen → classify → diarize → render)\n- **Redis** — antrean job + penyimpanan state\n- **LLM Router** — endpoint apa pun yang kompatibel OpenAI; deteksi momen pakai LLM murah/gratis\n\n## Prasyarat\n\n- **Docker** dan **Docker Compose** (satu-satunya syarat wajib — ffmpeg, yt-dlp, font, Chrome sudah ada di dalam image)\n- Server/mesin dengan **RAM ≥ 2 GB** (STT mode `router`) atau **RAM ≥ 4 GB** (STT mode `local` menjalankan Whisper di CPU)\n- **Endpoint LLM kompatibel OpenAI** untuk deteksi momen (opsi gratis: [Groq](https://console.groq.com), [OpenRouter](https://openrouter.ai), atau LiteLLM sendiri) — lihat **[Cara Dapat API Key LLM Gratis](#cara-dapat-api-key-llm-gratis)**\n- *(Opsional tapi disarankan)* **cookies YouTube** format Netscape untuk melewati deteksi bot / pembatasan usia\n\n---\n\n## Instalasi di VPS\n\nDari VPS Ubuntu/Debian kosong, lengkap dari awal sampai jalan.\n\n### 1. Pasang Docker\n\n```bash\n# Pasang Docker Engine + plugin Compose (script resmi)\ncurl -fsSL https://get.docker.com | sh\n\n# Agar bisa pakai docker tanpa sudo (logout & login lagi setelahnya)\nsudo usermod -aG docker \"$USER\"\nnewgrp docker\n\ndocker --version && docker compose version\n```\n\n### 2. Clone proyek\n\n```bash\ngit clone https://github.com/adzibilal/simbioclip.git\ncd simbioclip\n```\n\n### 3. Konfigurasi environment\n\n```bash\ncp .env.example .env\nnano .env # isi API_TOKEN dan LLM_ROUTERS (lihat bagian \"Konfigurasi\")\n```\n\nMinimal yang wajib diisi:\n\n- `API_TOKEN` — password login dashboard/API (buat yang kuat)\n- `LLM_ROUTERS` — minimal satu router kompatibel OpenAI (key Groq/OpenRouter)\n\n### 4. (Opsional) Tambahkan cookies YouTube\n\nLihat **[Cookies YouTube](#cookies-youtube)**. Di VPS, biasanya cookies di-export dari laptop lalu disalin ke server:\n\n```bash\n# dari laptop\nscp cookies.txt user@ip-vps-anda:/path/ke/simbioclip/cookies.txt\n```\n\n### 5. Build & jalankan\n\n```bash\n./run.sh # ambil GPG key, build image, jalankan stack\n# setara dengan: docker compose build && docker compose up -d\n```\n\nAPI berjalan di port **8000**. Cek:\n\n```bash\ncurl http://localhost:8000/healthz # -> ok\n./run.sh status # status & health kontainer\n./run.sh logs # log live\n```\n\n### 6. Buka aksesnya\n\n- **Tes cepat:** buka firewall port 8000 (`ufw allow 8000`) lalu akses `http://IP_VPS_ANDA:8000`.\n- **Produksi:** taruh di belakang reverse proxy (Caddy / Nginx / Traefik) dengan HTTPS yang mengarah ke `127.0.0.1:8000`, dan tutup port 8000 dari publik. Atau pakai **[Coolify](#deploy-dengan-coolify)**.\n\n> Data (hasil download, clip, thumbnail) tersimpan di volume Docker `clip_data` dan tetap ada setelah restart. State Redis ada di `redis_data`.\n\n---\n\n## Instalasi di Local\n\nUntuk development atau jalan di mesin sendiri.\n\n1. **Pasang Docker Desktop** (macOS/Windows) atau Docker Engine (Linux).\n2. Clone dan konfigurasi:\n\n ```bash\n git clone https://github.com/adzibilal/simbioclip.git\n cd simbioclip\n cp .env.example .env\n # edit .env: API_TOKEN + LLM_ROUTERS\n ```\n\n3. *(Opsional)* taruh `cookies.txt` di root proyek — lihat **[Cookies YouTube](#cookies-youtube)**.\n4. Jalankan:\n\n ```bash\n ./run.sh\n ```\n\n5. Buka **http://localhost:8000** dan login dengan `API_TOKEN` Anda.\n\nPerintah dev yang berguna (lihat `./run.sh help`):\n\n```bash\n./run.sh logs worker # pantau worker\n./run.sh restart # restart api + worker (tanpa rebuild)\n./run.sh rebuild # rebuild penuh --no-cache (setelah ubah kode)\n./run.sh shell worker # masuk shell kontainer worker\n```\n\n> **Perubahan kode** (Python/template) di-bake ke dalam image, jadi rebuild setelah mengedit:\n> `docker compose up -d --build`. File `.env` dan `cookies.txt` dibaca live (tidak perlu rebuild).\n\n---\n\n## Konfigurasi\n\nEdit `.env`. Yang paling penting:\n\n### `LLM_ROUTERS` (wajib)\n\nArray JSON berisi endpoint-endpoint kompatibel OpenAI. Dicoba **berurutan** sebagai fallback (jika satu gagal/kena limit, lanjut ke berikutnya).\n\n```json\n[\n {\"base_url\": \"https://api.groq.com/openai/v1\", \"api_key\": \"gsk_xxx\", \"model\": \"llama-3.3-70b-versatile\"},\n {\"base_url\": \"https://openrouter.ai/api/v1\", \"api_key\": \"sk-or-xxx\", \"model\": \"google/gemini-2.0-flash-exp:free\"}\n]\n```\n\nTulis dalam satu baris di `.env`:\n\n```\nLLM_ROUTERS=[{\"base_url\":\"https://api.groq.com/openai/v1\",\"api_key\":\"gsk_xxx\",\"model\":\"llama-3.3-70b-versatile\"}]\n```\n\n### Speech-to-text (`STT_MODE`)\n\n- `STT_MODE=local` — menjalankan faster-whisper di CPU dalam kontainer. Tanpa API key, tapi butuh **RAM ≥ 4 GB** dan lebih lambat.\n- `STT_MODE=router` — mengalihkan transkripsi ke API kompatibel-Whisper. Isi `STT_BASE_URL`, `STT_API_KEY`, `STT_MODEL` (Whisper gratis dari Groq `whisper-large-v3-turbo` sangat bagus; untuk OpenAI pakai `STT_MODEL=whisper-1`).\n\n---\n\n## Cara Dapat API Key LLM Gratis\n\nSimbioClip butuh setidaknya satu endpoint LLM kompatibel-OpenAI untuk deteksi momen. Berikut beberapa penyedia gratis dan tipsnya. **Catatan:** nama model sering berubah — selalu cek daftar model terbaru di dashboard masing-masing penyedia.\n\n### Groq — rekomendasi (cepat & gratis)\n\n1. Buka **https://console.groq.com** lalu daftar (bisa pakai Google/GitHub).\n2. Menu **API Keys** → **Create API Key** → salin (formatnya `gsk_...`).\n3. Pakai di `.env`:\n - `base_url`: `https://api.groq.com/openai/v1`\n - `model` (LLM): `llama-3.3-70b-versatile` (kualitas bagus) atau `llama-3.1-8b-instant` (cepat & hemat)\n4. **Bonus:** Groq juga menyediakan **Whisper gratis** untuk STT. Set:\n ```\n STT_MODE=router\n STT_BASE_URL=https://api.groq.com/openai/v1\n STT_API_KEY=gsk_xxx\n STT_MODEL=whisper-large-v3-turbo\n STT_MODEL_FALLBACK=whisper-large-v3\n ```\n5. Groq punya **rate limit harian** — kalau sering kena limit, tambahkan router lain sebagai cadangan (lihat di bawah).\n\n### OpenRouter — banyak model gratis\n\n1. Buka **https://openrouter.ai** → daftar.\n2. Menu **Keys** → **Create Key** → salin (formatnya `sk-or-...`).\n3. Pakai di `.env`:\n - `base_url`: `https://openrouter.ai/api/v1`\n - `model`: pilih yang berakhiran **`:free`**, misalnya `google/gemini-2.0-flash-exp:free` atau `meta-llama/llama-3.3-70b-instruct:free` (cek halaman **Models** → filter \"Free\").\n\n### Google AI Studio (Gemini)\n\n1. Buka **https://aistudio.google.com/app/apikey** → **Create API key** (gratis).\n2. Pakai endpoint kompatibel-OpenAI dari Google:\n - `base_url`: `https://generativelanguage.googleapis.com/v1beta/openai/`\n - `model`: `gemini-2.0-flash` atau `gemini-1.5-flash`\n\n### Penyedia gratis lain\n\nCerebras, Mistral (free tier), Together (kredit trial), GitHub Models — semuanya kompatibel-OpenAI, tinggal masukkan `base_url`, `api_key`, `model` masing-masing ke dalam array `LLM_ROUTERS`.\n\n### Menyusun banyak router (fallback otomatis)\n\n`LLM_ROUTERS` adalah **array** — sistem mencoba router pertama, dan kalau gagal atau kena rate-limit ia otomatis lanjut ke router berikutnya. Susun beberapa penyedia gratis sekaligus supaya tahan terhadap limit harian:\n\n```\nLLM_ROUTERS=[{\"base_url\":\"https://api.groq.com/openai/v1\",\"api_key\":\"gsk_xxx\",\"model\":\"llama-3.3-70b-versatile\"},{\"base_url\":\"https://openrouter.ai/api/v1\",\"api_key\":\"sk-or-xxx\",\"model\":\"meta-llama/llama-3.3-70b-instruct:free\"},{\"base_url\":\"https://generativelanguage.googleapis.com/v1beta/openai/\",\"api_key\":\"AIza_xxx\",\"model\":\"gemini-2.0-flash\"}]\n```\n\n> Urutkan dari yang paling cepat/berkualitas di depan. Anda boleh menumpuk hingga banyak router (mis. 9) sebagai rantai cadangan.\n\n---\n\n## Cookies YouTube\n\nYouTube makin sering memblokir IP server (\"Sign in to confirm you're not a bot\") dan mengunci sebagian video. Memberi cookies akun yang sudah login akan mengatasinya. Metode yang andal dan didukung adalah **`cookies.txt` format Netscape** yang di-mount ke kontainer (sudah otomatis tersambung di `docker-compose.yaml` → `COOKIES_FILE=/app/cookies.txt`).\n\n### Langkah 1 — Export cookies dari browser\n\n1. Login ke **youtube.com** di Chrome atau Firefox.\n2. Pasang ekstensi **“Get cookies.txt LOCALLY”** ([Chrome Web Store](https://chromewebstore.google.com/) — cari nama persisnya).\n3. Di tab YouTube, klik ekstensi → **Export** → terunduh file `cookies.txt` (format Netscape).\n\n### Langkah 2 — Salin ke proyek\n\nFile **harus** bernama `cookies.txt` dan berada di **root proyek** (di-mount ke `/app/cookies.txt`):\n\n```bash\n# local\ncp ~/Downloads/cookies.txt ./cookies.txt\n\n# VPS (dari laptop)\nscp ~/Downloads/cookies.txt user@ip-vps-anda:/path/ke/simbioclip/cookies.txt\n```\n\n### Langkah 3 — Terapkan\n\nFile cookies dibaca **live** saat download — tidak perlu rebuild. Kalau kontainer sudah jalan sebelum file ada, cukup restart agar mount-nya segar:\n\n```bash\n./run.sh restart\n```\n\n> **Catatan**\n> - Cookies YouTube punya masa berlaku — kalau download mulai gagal dengan error autentikasi, export ulang dan ganti `cookies.txt`.\n> - `cookies.txt` di-git-ignore; jangan pernah di-commit. Perlakukan seperti password.\n> - Cookies opsional untuk banyak video publik, tapi wajib untuk video dengan batasan usia dan untuk menghindari deteksi bot pada IP server yang sibuk.\n\n---\n\n## Langkah demi Langkah: Membuat Clip Pertama\n\n> Lakukan **[Cookies YouTube](#cookies-youtube)** dulu kalau clip dari YouTube.\n\n1. **Buka dashboard** → `http://localhost:8000` (local) atau URL VPS Anda.\n2. **Login** dengan `API_TOKEN` Anda.\n3. **Tambahkan sumber** — tempel **Video URL** (mis. link YouTube) atau **upload** file video mentah.\n - *(Opsional)* klik **Preview** untuk mengambil judul/durasi sebelum diproses.\n4. **Pilih opsi:**\n\n | Opsi | Fungsinya |\n |------|-----------|\n | **Max clips** | Berapa banyak clip yang dihasilkan (1–15). |\n | **Layout** | Gaya framing: `Auto`, `Podcast`, `Talking Head`, `Center Crop`, `Game Stream`, **`BG Blur`**. |\n | **Ratio** | Rasio aspek output: `9:16`, `1:1`, `4:5`, `16:9`. |\n | **Lang** | Bahasa caption/transkrip (`ID`, `EN`, `ES`, atau `Auto`). |\n | **Caption** | Gaya subtitle: `Bold Pop`, `Karaoke`, `Neon`, `Minimal`, `Podcast`. |\n | **Duration** | Rentang target durasi clip (mis. `45–60s`). |\n | **Res** | Resolusi download sumber (`Best`, `4K`…`360p`). |\n\n5. **Submit.** Job berjalan melalui pipeline secara live: **download → transcribe → moments → classify → diarize → render**. Pantau progres di kartu job.\n6. **Tinjau clip.** Tiap clip jadi menampilkan preview, skor, hook, dan layout yang terdeteksi.\n7. **Sempurnakan (opsional):**\n - **Rerender** satu clip dengan **layout** atau **gaya caption** berbeda (ini cara termudah menerapkan **BG Blur** ke satu clip).\n - **Trim** — penyesuaian awal/akhir akurat per-frame, non-destruktif.\n - **Thumbnail** — upload gambar custom; ia ditambahkan sebagai **cover intro** singkat (~0,2 dtk) di depan clip. Caption tetap aman.\n - **Edit** teks judul/hook.\n8. **Download** clip-nya, atau ambil thumbnail JPG yang dibuat otomatis.\n\n### Tentang layout **BG Blur**\n\nBackground blur memenuhi frame, dengan crop **4:5** konten yang tajam di tengah, **judul clip menetap di atas**, dan **subtitle di bawah**. Pilih sebagai Layout saat membuat job, atau **Rerender** clip yang sudah ada lalu pilih **BG Blur**.\n\n### Deteksi momen \"funny-first\"\n\nDetektor momen memburu momen **lucu / ketawa** lebih dulu (lelucon, punchline, orang ngakak), dan hanya mengisi sisa slot dengan momen kuat lain (insight, cerita, hot take) ketika momen lucu tidak cukup.\n\n---\n\n## Deploy dengan Coolify\n\nPakai ini kalau ingin HTTPS + domain terkelola di VPS.\n\n1. Coolify → **Projects** → **+ New Project** → `simbioclip`\n2. **+ New Resource** → **Docker Compose**\n3. Source **GitHub** → pilih `adzibilal/simbioclip`, branch `main`\n4. **Compose file path**: `docker-compose.coolify.yaml`\n5. Isi environment variables (`API_TOKEN`, `LLM_ROUTERS`, `STT_*`) di tab **Environment**\n6. Set domain untuk service **api** di tab **Domains** (compose sudah mendeklarasikan `SERVICE_FQDN_API_8000`)\n7. **Deploy**\n\n> Compose Coolify **tidak** mem-bind-mount `cookies.txt`. Untuk memakai cookies di sana, tambahkan entri persistent storage yang memetakan sebuah `cookies.txt` ke `/app/cookies.txt`, lalu set `COOKIES_FILE=/app/cookies.txt` di tab Environment.\n\n---\n\n## Variabel Environment\n\n| Variabel | Default | Deskripsi |\n|----------|---------|-----------|\n| `API_TOKEN` | `super-secret-admin-token` | Token auth dashboard & API. **Wajib diganti.** |\n| `REDIS_URL` | `redis://redis:6379/0` | String koneksi Redis |\n| `LLM_ROUTERS` | array JSON | Daftar router kompatibel-OpenAI untuk deteksi momen (dicoba berurutan) |\n| `STT_MODE` | `local` | `router` (API) atau `local` (faster-whisper di CPU) |\n| `STT_BASE_URL` | `\"\"` | URL dasar API STT (mode router) |\n| `STT_API_KEY` | `\"\"` | API key STT (mode router) |\n| `STT_MODEL` | `whisper-large-v3-turbo` | Model STT utama |\n| `STT_MODEL_FALLBACK` | `whisper-large-v3` | Model STT cadangan |\n| `LLM_TIMEOUT` | `240` | Timeout per request LLM (detik) |\n| `LLM_MAX_RETRIES` | `1` | Maksimum retry LLM |\n| `COOKIES_FILE` | `/app/cookies.txt` (compose) | Path ke cookies.txt format Netscape |\n| `CONCURRENT_FRAGMENTS` | `5` | Jumlah fragment download paralel (yt-dlp) |\n| `ARIA2C_ENABLED` | `true` | Pakai downloader eksternal aria2c (16 koneksi paralel) |\n| `ARIA2C_CONNECTIONS` | `16` | Koneksi aria2c per file |\n| `THROTTLED_RATE` | `200M` | Ambang bypass throttle yt-dlp |\n\n## Endpoint API\n\n| Method | Path | Auth | Deskripsi |\n|--------|------|------|-----------|\n| `POST` | `/login` | - | Login (form `token`) |\n| `GET` | `/` | Cookie | Dashboard |\n| `GET` | `/healthz` | - | Health check |\n| `POST` | `/preview` | Bearer | Preview metadata video |\n| `POST` | `/jobs` | Bearer | Buat job baru |\n| `GET` | `/jobs/{id}` | Bearer | Status job + clip |\n| `DELETE` | `/jobs/{id}` | Bearer | Hapus job |\n| `POST` | `/jobs/{id}/retry` | Bearer | Ulangi job |\n| `POST` | `/jobs/{id}/retry/{step}` | Bearer | Ulangi dari step tertentu |\n| `POST` | `/jobs/{id}/rerender` | Bearer | Render ulang semua clip |\n| `POST` | `/jobs/{id}/clips/{cid}/rerender` | Bearer | Render ulang satu clip |\n| `POST` | `/jobs/{id}/clips/{cid}/trim` | Bearer | Trim sebuah clip |\n| `POST` | `/api/jobs/{id}/clips/{cid}/custom-thumbnail` | Bearer | Upload thumbnail cover custom |\n| `GET` | `/jobs/{id}/clips/{cid}` | Bearer | Download sebuah clip |\n| `POST` | `/cleanup` | Bearer | Hapus job lama |\n\n### Contoh: buat job via API\n\n```bash\ncurl -X POST https://clip.example.com/jobs \\\n -H \"Authorization: Bearer $API_TOKEN\" \\\n -F \"source_url=https://youtube.com/watch?v=xxxx\" \\\n -F \"max_clips=8\" \\\n -F \"layout_mode=bg_blur\" \\\n -F \"aspect_ratio=9:16\" \\\n -F \"caption_style=karaoke_highlight\" \\\n -F \"clip_duration=45-60\" \\\n -F \"download_resolution=1080p\"\n```\n\n## Tahapan Pipeline\n\n| Step | Deskripsi | Bisa diulang |\n|------|-----------|--------------|\n| `download` | Download video via yt-dlp (pakai cookies bila ada) | Ya |\n| `transcribe` | Speech-to-text + pembersihan | Ya |\n| `moments` | LLM menilai momen layak-clip (funny-first) | Ya |\n| `classify` | Deteksi tipe konten / layout | Ya |\n| `diarize` | Identifikasi giliran bicara | Ya |\n| `render` | Reframe + burn caption + thumbnail cover opsional | Ya |\n\n## Pemecahan Masalah (Troubleshooting)\n\n- **`Sign in to confirm you're not a bot` / download gagal** → tambah atau perbarui **[cookies.txt](#cookies-youtube)**.\n- **Tidak ada clip / hasil kosong** → pastikan `LLM_ROUTERS` JSON-nya valid dan key-nya berfungsi; pantau `./run.sh logs worker`.\n- **Worker kena OOM di STT mode `local`** → ganti ke `STT_MODE=router`, atau beri RAM lebih ke worker (compose membatasi di 6 GB).\n- **Peringatan `cookies.txt is a directory`** → `run.sh` memperbaikinya otomatis, tapi pastikan Anda menyalin *file*, bukan membuat folder.\n- **Sudah ubah kode tapi tidak berubah** → rebuild: `docker compose up -d --build` (kode di-bake ke image).\n\n## Pengembangan (Development)\n\n```bash\n./run.sh rebuild # rebuild penuh tanpa cache\n./run.sh logs # pantau semua log\n./run.sh shell worker # shell di dalam worker\n./run.sh restart # restart service tanpa rebuild\n./run.sh clean # hapus kontainer, image, dan volume clip_data\n```\n"}}}} |