v-pipeline: Menyewa GPU per Job, Bukan per Jam
Pipeline generate video untuk dipakai sendiri — aplikasi dan berkasnya tinggal di homelab, GPU disewa di RunPod Serverless dan mati begitu job selesai. Catatan tentang idempotensi, dry run, dan kenapa restart worker bisa membuat kita membayar dua kali.
Proyek pribadi, repositorinya tertutup — ditulis di sini karena keputusan arsitekturnya menarik, bukan hasilnya.
Idenya: menghasilkan video di mana foto menyuplai identitas dan video referensi menyuplai gerakan. Aplikasi, database, dan seluruh berkasnya tinggal di homelab; yang disewa hanya GPU-nya, di RunPod Serverless, dan GPU itu mati begitu job selesai.
Kenapa serverless
GPU sewaan per jam berarti membayar untuk waktu menganggur, dan pemakaian saya berbentuk letupan — beberapa job dalam satu sore, lalu tidak sama sekali selama seminggu. Serverless membalik hubungannya: satu job satu tagihan, dan tidak ada yang menyala di antaranya.
Konsekuensinya bagian yang tersisa di homelab harus tahan menunggu, tahan mati listrik, dan tahan di-restart di tengah jalan.
Job yang dibuat dua kali berarti bayar dua kali
Ini kendala yang paling banyak menentukan bentuk kodenya.
Kalau worker mati di tengah job — deploy, kehabisan memori, listrik mati — lalu hidup lagi, dia harus menyambung kembali ke job yang sama di penyedia, bukan membuat job baru. Kalau provider_job_id-nya berubah setelah restart, artinya ada satu generate yang sudah dibayar dan ditinggalkan, ditambah satu lagi yang baru dimulai.
Karena itu smoke test-nya bukan cuma menguji jalur sukses. Dia membunuh worker di tengah job, menjalankannya lagi, dan memastikan provider_job_id-nya sama persis. Kalau berbeda, tesnya gagal — walaupun videonya jadi.
Dry run yang bisa dipercaya
Mengembangkan sesuatu yang tiap percobaannya menghabiskan biaya nyata itu tidak nyaman. Jadi ada penyedia tiruan, dan pemilih DRY/LIVE ada di header antarmuka, membalik penyedia tanpa perlu me-restart container. Pilihan itu disimpan sebagai cookie per browser, jadi ponsel bisa jalan live sementara laptop tetap dry run.
Bagian yang penting: flag penyedia dicap saat job dibuat, bukan dibaca saat job dijalankan. Job yang lahir dalam sesi dry run tetap mock walaupun tombolnya dibalik semenit kemudian. Tanpa itu, satu klik di waktu yang salah akan mengirim antrean uji coba ke GPU sungguhan.
Jalur gagalnya juga bisa dipanggil dengan sengaja. Di mode dry run, menulis token tertentu di kolom catatan memicu kegagalan tertentu — normalisasi ffmpeg gagal sebelum ada biaya, model menolak karena alasan keamanan (dan ini ditandai tidak bisa diulang, jadi tombol coba lagi tidak muncul), job melewati batas waktu eksekusi, tidak ada kapasitas GPU, atau generate berhasil tapi unduhannya gagal. Kelimanya diuji di smoke test.
Tiga mode, dan satu hal yang tidak bisa dilakukan model
| Mode | Latar datang dari | Prompt dipakai | Keluaran |
|---|---|---|---|
animate | foto | tidak | video |
replace | video referensi | tidak | video |
edit | prompt | ya | foto |
Model animasinya tidak membaca teks sama sekali. Jadi kalau latar belakang ingin ditentukan lewat kata-kata, jalurnya dua langkah — edit dulu untuk menghasilkan foto, baru animate — bukan satu job dengan prompt. Ini pembatas yang jauh lebih baik disadari di awal daripada ditemukan setelah dua puluh percobaan yang mengabaikan prompt.
Status
Masih berjalan. Yang sudah mantap: mesin job, idempotensi lintas restart, dan seluruh lapisan dry run. Aplikasinya sendiri Python dengan penyimpanan berkas di homelab, dan ffmpeg dipakai untuk normalisasi masukan sebelum apa pun dikirim ke GPU — karena menolak masukan yang tidak layak itu gratis, sementara menolaknya di sisi GPU tidak.