Proses video secara asinkron
Koordinasi job transcoding, pekerjaan duplikat, manifest keluaran, dan cara menangani transformasi yang gagal tanpa menerbitkan video setengah jadi.
Pertanyaan
Gimana memproses video yang butuh menit sampai jam tanpa menahan request, tanpa mengerjakan hal yang sama dua kali, dan tanpa menerbitkan hasil yang belum lengkap?
Setelah baca ini, kamu bisa merancang siklus job transcoding, menjaga hasil tetap idempoten, dan menentukan kapan video boleh dianggap siap.
Prasyarat dan contoh
Kamu sudah paham idempotensi (M03), durabilitas dan penyimpanan (M09), antrean job dengan lease dan retry (M10), serta alur unggah (M15.01).
Pengguna mengunggah video 10 menit, 1080p, sekitar 1,2 GB. Platform ingin menghasilkan tiga rendition (1080p, 720p, 480p) plus thumbnail. Transcoding satu rendition bisa memakan 0,5x sampai 2x durasi video di satu worker, tergantung codec dan perangkat keras. Misalkan total 25 menit kerja CPU untuk satu video. Kalau ini dikerjakan di request HTTP, timeout pasti datang lebih dulu.
Mekanisme
Pisahkan penerimaan dari pemrosesan. Setelah unggahan siap, aplikasi menulis satu catatan video berstatus diproses dan satu pesan ke antrean, lalu langsung membalas. Catatan dan pesan sebaiknya ditulis atomik (outbox, M10), supaya nggak ada video tanpa pesan atau pesan tanpa video.
unggahan siap → video: diproses → antrean → worker:
untuk tiap rendition: transcode → tulis ke key sementara
semua selesai → tulis manifest → video: siap
gagal permanen → video: gagal (dengan alasan)
Satu job per unit kerja. Pecah per rendition (atau per segmen untuk video panjang), bukan satu job raksasa. Job 25 menit yang gagal di menit ke-24 mengulang semuanya. Tiga job 8 menit yang satu gagal hanya mengulang 8 menit. Biayanya: koordinasi. Perlu catatan yang tahu "3 dari 3 rendition selesai".
Pekerjaan duplikat itu normal. Antrean at-least-once mengirim ulang pesan kalau worker mati atau lease habis. Dua worker bisa mengerjakan rendition yang sama. Rancang supaya itu aman:
- Key keluaran ditentukan oleh input, misalnya
video/<id>/<hash-input>/720p/dan bukan acak. Dua worker menulis isi yang sama ke key yang sama. - Worker menulis ke key sementara lalu menyatakan selesai lewat pembaruan kondisional di basis data (
UPDATE ... WHERE rendition=? AND status<>'selesai'). Penulis kedua melihat sudah selesai dan membuang hasilnya. - Sebelum mulai, worker memeriksa apakah rendition sudah
selesaidan melewatinya.
Manifest sebagai tanda terbit. Manifest adalah berkas kecil yang mendaftar rendition, durasi, ukuran, dan checksum. Pemutar hanya tahu video lewat manifest. Tulis manifest paling terakhir, setelah semua keluaran terverifikasi. Selama manifest belum ada, video nggak terlihat, jadi nggak mungkin ada pengguna melihat 720p yang separuh jadi.
Kegagalan yang berbeda. Bedakan sementara (worker mati, storage timeout) dari permanen (berkas rusak, codec tak didukung). Sementara: retry dengan backoff, batas 3 sampai 5 kali. Permanen: langsung ke gagal, kirim ke dead letter, dan beri pesan yang bisa dibaca pengguna. Retry untuk kegagalan permanen cuma membakar CPU.
Kemajuan dan batas waktu. Worker memperbarui heartbeat atau memperpanjang lease selama bekerja. Job tanpa kemajuan lebih dari, misalnya, 3x durasi yang diharapkan dianggap macet dan diambil worker lain.
Saat rancangan ini gagal
- Dua worker menimpa satu sama lain. Key acak untuk tiap percobaan meninggalkan dua set keluaran, dan manifest menunjuk yang mana saja. Key deterministik dan pembaruan kondisional mencegahnya.
- Terbit sebelum lengkap. Status
siapditulis ketika rendition pertama selesai. Pemutar mencari 480p yang belum ada. Tulissiaphanya setelah semua rendition wajib terverifikasi. - Job beracun. Satu berkas rusak membuat worker crash, pesan kembali, crash lagi. Batasi percobaan, lalu pindahkan ke dead letter.
- Antrean menumpuk. 500 unggahan masuk bersamaan x 25 menit CPU = 12.500 menit kerja. Dengan 50 worker, antrean butuh sekitar 250 menit. Beri tahu pengguna status
diprosesyang jujur, dan prioritaskan berdasarkan kebutuhan (misalnya rendition 480p lebih dulu supaya video cepat bisa diputar). - File sementara yatim. Percobaan yang mati meninggalkan keluaran sementara. Lifecycle storage dan job pembersih menghapus yang melewati batas umur.
Latihan
Worker transcoding mengerjakan tiga rendition untuk video v42. Rendition 1080p selesai, 720p dikerjakan worker A yang lalu kehilangan koneksi (lease habis), worker B mengambil ulang 720p dan selesai, lalu worker A pulih dan juga menulis hasil 720p. 480p gagal tiga kali karena storage timeout. Jelaskan apa yang harus terjadi pada status video dan keluaran, dan apa yang membuat skenario ini aman.
Lihat pembahasan
720p: worker A dan B menulis ke key yang sama (video/v42/<hash-input>/720p/), jadi isinya identik dan yang kedua menimpa dengan byte yang sama. Selain itu, pembaruan status rendition bersifat kondisional: B berhasil menandai selesai, A melihat sudah selesai dan membuang hasilnya tanpa mengubah catatan. Manifest nggak terpengaruh.
480p: tiga kali timeout storage adalah kegagalan sementara yang melewati batas percobaan. Jangan tandai video siap. Kirim job ke dead letter, tampilkan alert, dan biarkan operator atau retry terjadwal yang terpisah menjalankannya lagi setelah storage pulih. Rendition 1080p dan 720p tetap tersimpan, jadi pengulangan hanya mengerjakan 480p.
Status video: tetap diproses (atau sebagian kalau produk memang mengizinkan memutar tanpa 480p). Manifest belum ditulis, jadi video belum terlihat. Kalau kebijakan produk membolehkan terbit dengan 1080p dan 720p, itu keputusan eksplisit: manifest ditulis dengan dua rendition dan 480p ditambahkan lewat manifest versi baru nanti.
Yang membuat aman: key deterministik, pembaruan kondisional, manifest ditulis terakhir, dan batas percobaan dengan dead letter.
Terkait
- Sebelumnya: Unggah langsung ke penyimpanan (M15.01) menghasilkan unggahan yang sudah terverifikasi sebagai masukan job.
- Selanjutnya: Distribusikan video adaptif (M15.04) membahas bagaimana rendition dan manifest ini disajikan ke penonton.
- Antrean tahan lama, lease, dead letter, dan outbox ada di M10. Idempotensi ada di M03.
- Lab L15 dan proyek B11 belum tersedia.
Catatan
- Asumsi: antrean at-least-once dan satu catatan status di basis data. Angka waktu transcoding adalah perkiraan ilustratif, bukan benchmark codec.
- Yang nggak dibahas: pemilihan codec, transcoding pada GPU, DRM, dan pemindaian konten.
- Pemecahan per segmen mempercepat video panjang, tapi menambah penggabungan dan keharusan segmen konsisten antar worker.
- Terakhir ditinjau: 26 Oktober 2026.