尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
Piattaforma SaaS proprietaria per la generazione automatica di YouTube Shorts da video lunghi: upload → trascrizione → analisi AI → clip 9:16 con editing automatico e sottotitoli sincronizzati → download. Fase 1 (MVP): upload → transcript → AI clip detection → selezione clip → verticalizzazione 9:16 → captions → editing automatico di base → render → preview → download → pubblicazione su YouTube. Non implementati in questa fase: pagamenti, mobile app, team, scheduling social, multi-lingua avanzato, AI B-roll, avatar AI.查看完整 README ↗
Piattaforma SaaS proprietaria per la generazione automatica di YouTube Shorts da video lunghi: upload → trascrizione → analisi AI → clip 9:16 con editing automatico e sottotitoli sincronizzati → download.
Fase 1 (MVP): upload → transcript → AI clip detection → selezione clip → verticalizzazione 9:16 → captions → editing automatico di base → render → preview → download → pubblicazione su YouTube. Non implementati in questa fase: pagamenti, mobile app, team, scheduling social, multi-lingua avanzato, AI B-roll, avatar AI.
apps/
web/ Next.js 14 (App Router) — dashboard, auth, upload, API route "leggere". Deploy: Vercel.
worker/ Node.js — pipeline di elaborazione video (ffmpeg, Whisper, Claude). Deploy: container separato
(Railway/Fly.io/VPS/qualsiasi host che esegua Docker o Node) — MAI su Vercel.
packages/
shared/ Tipi e zod schema condivisi (Transcript, Clip, EDL, Template, Job status).
db/ Schema SQL Supabase/Postgres + client tipizzato.
Il frontend e le API route leggere (creazione progetto, signed URL, creazione render job) girano su Vercel. Il worker interroga la coda (tabella Postgres, claim atomico via SELECT ... FOR UPDATE SKIP LOCKED esposto come funzione RPC) e fa tutto il lavoro pesante: estrazione audio, trascrizione, analisi AI, rendering ffmpeg. Frontend e worker comunicano solo attraverso il database e lo storage — nessuna chiamata diretta tra i due, quindi il worker scala e si sostituisce in autonomia.
Interfacce pensate per essere sostituite (Fase 1 usa l'implementazione più semplice/economica, dietro un contratto chiaro):
TranscriptionProvider → OpenAIWhisperProvider (Whisper API, default) oppure LocalFasterWhisperProvider (faster-whisper self-hosted sulla GPU locale, gratis, stessi timestamp a livello di parola — vedi apps/worker/whisper-server/README.md), selezionabile via TRANSCRIPTION_PROVIDER=openai|local.StorageProvider → R2StorageProvider (Cloudflare R2, compatibile S3). Un'implementazione SupabaseStorageProvider alternativa esiste ancora nel codice ma non è usata di default: il piano Free di Supabase Storage limita ogni file a 50MB, troppo poco per video sorgente.FaceTracker → ReactionCamFaceTracker: rilevamento volto reale (ONNX, Ultra-Light-Fast-Generic-Face-Detector, ~1.2MB, onnxruntime-node — binari precompilati, nessuna compilazione nativa richiesta) su alcuni frame campionati della clip. Se trova un volto piccolo e stabile vicino a un bordo (webcam in sovraimpressione su gameplay/reaction) produce un layout split-screen (webcam sopra, contenuto sotto); se trova un volto "normale" centra il crop su di esso; altrimenti ricade su CenterCropFaceTracker (crop centrato statico). Modello in apps/worker/models/.RenderEngine.youtube scope, serve anche a videos.update per l'annullamento programmazione) + coda dedicata (youtube_publish_jobs, stesso pattern di render_jobs). Il worker carica il file su YouTube via googleapis — mai da Vercel. Titolo/descrizione/hashtag sono precompilati dall'AI (generati nello stesso passaggio di ranking, nessuna chiamata extra) e modificabili prima di pubblicare.clips.format = 'longform'): a differenza degli Shorts, niente crop 9:16/zoom/sottotitoli — un secondo passaggio AI (longform-candidates.ts/longform-ranking.ts) individua segmenti coerenti per ARGOMENTO (5-20 min) invece di finestre hook-payoff, e il render (render-longform-clip.ts) è solo trim + card testuale dei crediti allo streamer originale in apertura/chiusura, output orizzontale nella risoluzione nativa. L'ingestion riusa download-youtube.ts as-is (yt-dlp supporta i VOD Twitch nativamente). I VOD arrivano dalla tab Feed seguendo canali Twitch (followed_twitch_channels, nessun OAuth richiesto — vedi sezione 3b).corepack enable && corepack prepare pnpm@latest --activate)ffmpeg -version deve funzionare)yt-dlp --version deve funzionare) — usato per l'import da link YouTubepackages/db/migrations/0001_init.sqlpackages/db/migrations/0002_queue_functions.sqlpackages/db/migrations/0003_add_downloading_status.sqlpackages/db/migrations/0004_youtube_publishing.sqlpackages/db/migrations/0005_clip_caption.sqlpackages/db/migrations/0006_youtube_scheduled_publish.sqlpackages/db/migrations/0007_followed_channels.sqlpackages/db/migrations/0008_clip_badges.sqlpackages/db/migrations/0009_youtube_stats.sqlpackages/db/migrations/0010_project_auto_generate.sqlpackages/db/migrations/0011_cancel_jobs.sqlpackages/db/migrations/0012_voiceover_jobs.sqlpackages/db/migrations/0013_youtube_publish_cancel.sqlpackages/db/migrations/0014_longform_twitch.sqlpackages/db/migrations/0015_video_claim_stale_timeout.sqlpackages/db/migrations/0016_video_streamer_login.sqlpackages/db/migrations/0017_thumbnail_jobs.sqlpackages/db/migrations/0018_thumbnail_reacted_video_url.sqlpackages/db/migrations/0019_worker_control.sqlURL e anon public key (servono al frontend). Vai su Project Settings → API → Service role e copia anche quella (serve solo al worker).clipforge-media) → Location: Automatic.dash.cloudflare.com/<ACCOUNT_ID>/r2).[
{
"AllowedOrigins": ["http://localhost:3000", "https://il-tuo-dominio.vercel.app"],
"AllowedMethods": ["PUT", "GET"],
"AllowedHeaders": ["*"],
"MaxAgeSeconds": 3600
}
]
(senza questo, l'upload diretto dal browser viene bloccato dal CORS — l'import da YouTube non ne ha bisogno, passa tutto dal worker)http://localhost:3000/api/youtube/callback
https://il-tuo-dominio.vercel.app/api/youtube/callback
Nota sulla quota: da giugno 2026 videos.insert ha un bucket dedicato separato dal resto della quota, 100 upload/giorno gratis (1 unità a chiamata in quel bucket) — molto più permissivo del vecchio limite (~6/giorno, quando l'upload costava 1.600 delle 10.000 unità condivise).
A differenza di YouTube, Twitch non richiede un flusso OAuth per-utente per leggere canali/VOD pubblici: basta un'app registrata una volta.
http://localhost (non viene mai usato, Twitch lo richiede comunque per registrare l'app), Category: Application Integration.Nessun URI di redirect reale, nessuna schermata di consenso, nessun "utente di test": le chiamate (risoluzione canale, lista VOD) usano un app access token server-to-server richiesto al volo dal backend web (apps/web/src/lib/twitch-scan.ts).
pnpm --filter esegue ogni app nella propria cartella, quindi servono due file separati (non uno alla radice) — .env.example alla radice resta solo come riferimento con la lista completa delle variabili:
cp .env.example apps/worker/.env
cp .env.example apps/web/.env.local
Compila entrambi con i valori di Supabase/R2/Anthropic/OpenAI (apps/web/.env.local non ha bisogno delle variabili solo-worker come ANTHROPIC_API_KEY/OPENAI_API_KEY/SUPABASE_SERVICE_ROLE_KEY, ma lasciarle non fa danno). Non committare mai questi file (sono già in .gitignore).
pnpm install
Servono due processi separati (frontend e worker), in due terminali:
pnpm dev:web # http://localhost:3000
pnpm dev:worker # poll continuo della coda su Supabase
http://localhost:3000, registrati (/signup), conferma l'email se richiesto da Supabase.pnpm -r typecheck # type-check di tutti i package
pnpm --filter @clipforge/web build # build di produzione del frontend
pnpm --filter @clipforge/worker build # bundle di produzione del worker (esbuild → dist/index.js)
pnpm --filter @clipforge/worker exec tsx src/dev/smoke-test-render.ts <path-video>
# smoke test della sola pipeline di render (crop/zoom/captions/loudness), senza bisogno
# di credenziali Supabase/Anthropic/OpenAI — utile per verificare rapidamente ffmpeg.
apps/web): Vercel, root directory apps/web. Variabili d'ambiente da impostare nel progetto Vercel: NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET (solo se vuoi la pubblicazione YouTube), TWITCH_CLIENT_ID, TWITCH_CLIENT_SECRET (solo se vuoi i video long-form dai VOD Twitch). Ricorda di aggiungere il dominio Vercel definitivo sia alla CORS policy del bucket R2 sia agli URI di reindirizzamento autorizzati del client OAuth Google (vedi sopra).apps/worker): qualsiasi host capace di eseguire un processo Node long-running (Railway, Fly.io, un VPS con Docker/systemd, ecc.) — non Vercel, che non è pensato per processi persistenti né per rendering video pesante. Build: pnpm --filter @clipforge/worker build, avvio: pnpm --filter @clipforge/worker start (richiede ffmpeg e yt-dlp installati nell'immagine/host; apps/worker/models/ e node_modules devono essere presenti accanto a dist/ — onnxruntime-node ha un addon nativo per piattaforma che esbuild lascia esterno, vedi commento in scripts/build.mjs)..ttf nell'immagine del worker e puntarli esplicitamente.loudnorm a singolo passaggio (non i due passaggi raccomandati per la massima precisione) — scelta per semplicità/velocità.videos.insert ha un bucket dedicato da 100 upload/giorno (aggiornato da giugno 2026, prima erano ~6/giorno).yt-dlp, quindi eredita i suoi limiti — video privati, con restrizione età o soggetti a protezioni anti-bot possono fallire il download; nessun supporto per playlist (viene scaricato solo il video singolo).