D
P
0

Shopify & Liquid

Background Video Kelihatan Kotak Beda Warna dari Section? Chroma-Key `ffmpeg` dan Berhenti Hardcode `#ffffff`

21 Juli 2026·4 menit baca
Background Video Kelihatan Kotak Beda Warna dari Section? Chroma-Key `ffmpeg` dan Berhenti Hardcode `#ffffff`

Sebuah section hero di situs klien berbasis Shopify pakai background video: satu loop animasi produk yang dirender tim animator klien, dipasang mengisi lebar section, dengan teks di atasnya. Di preview desktop saya sendiri kelihatan mulus. Lalu klien balik dengan satu keluhan yang terus berulang selama enam ronde revisi: "warna putihnya beda", "background videonya masih kelihatan kotak". Videonya memang punya latar terang, tapi latar itu tidak menyatu dengan section di belakangnya. Yang muncul justru sebuah persegi panjang samar dengan warna sedikit berbeda, seolah videonya ditempel sebagai stiker di atas halaman.

Yang bikin menyebalkan: di monitor tertentu selisihnya nyaris tak terlihat, di monitor lain jelas banget. Jadi setiap kali saya kira sudah beres, klien lihat di layar dia dan kotaknya masih ada.

Dead end yang saya coba dulu

Tebakan pertama: tinggal samarkan videonya pakai blend mode. Saya pasang mix-blend-mode: multiply ke elemen video, harapannya piksel putih video lebur ke background putih section. Hasilnya cuma setengah jalan. multiply memang menggelapkan area terang video terhadap background, tapi kalau warna latar video dan warna section tidak identik, dia malah menonjolkan selisihnya di area subjek. Kotaknya berkurang, tidak hilang, dan di bagian produk yang lebih terang muncul artefak warna.

Tebakan kedua: mungkin ini soal kompresi. Saya naikkan bitrate, ganti codec, re-render dari sumber. Tetap ada. Di titik ini saya berhenti menebak dan mulai mengukur.

Saya ambil satu frame video dan satu screenshot section, lalu sampel warnanya piksel demi piksel pakai Python PIL:

from PIL import Image
 
frame = Image.open("frame.png").convert("RGB")
print(frame.getpixel((10, 10)))   # sudut latar video

Angkanya langsung membuka semuanya. Latar video terbaca #ECEBEE, sementara background section yang saya kira putih murni #ffffff. Selisih kecil, tapi mata manusia menangkapnya sebagai kotak. Lebih parah, di versi sumber berikutnya latar videonya ternyata tidak rata: sudut-sudutnya #DFDFDF tapi pojok kiri bawah #E5E3E4. Ada gradien halus yang, setelah upscale lanczos dan kuantisasi codec, malah ikut terawetkan.

Akar masalahnya

Ada tiga hal yang menumpuk jadi satu gejala.

Pertama, latar bawaan (baked-in) di dalam video tidak pernah persis sama dengan background section. Apa pun warna yang dirender animator, dia jadi piksel tetap di dalam file, dan piksel itu tidak akan menyesuaikan warna section di belakangnya.

Kedua, mix-blend-mode: multiply cuma menyembunyikan setengah masalah. Dia tidak menghapus latar video, dia hanya mencampurnya, jadi selisih warna sekecil apa pun tetap bocor.

Ketiga, dan ini yang paling menyesatkan: background section-nya saya hardcode #ffffff, padahal theme color variable sebenarnya resolve ke #FAFAFA. Putih murni terbaca lebih terang dari section tetangganya, jadi walaupun video dan section "sama-sama putih", keduanya sebenarnya tiga warna berbeda: latar video, #ffffff yang saya tulis, dan #FAFAFA bawaan theme.

Perbaikannya

Kuncinya: berhenti berharap warna kebetulan cocok, dan buat cocok secara sengaja.

Langkah pertama, ukur dulu warna asli pakai PIL sebelum memutuskan apa pun. Angka mengalahkan tebakan mata.

Langkah kedua, chroma-key latar video pakai ffmpeg, dengan threshold ketat yang disetel di antara variasi warna latar dan jarak ke tepi subjek. Untuk MP4 (tanpa alpha), saya key latarnya lalu tumpuk di atas warna solid yang sama persis dengan section:

ffmpeg -i in.mp4 -filter_complex \
  "color=c=0xFAFAFA:s=1920x1080[bg]; \
   [0:v]colorkey=0xDFDFDF:0.02:0.05[fg]; \
   [bg][fg]overlay=format=auto" \
  -c:v libx264 -pix_fmt yuv420p out.mp4

Angka di colorkey=0xDFDFDF:0.02:0.05 itu penting. Similarity 0.02 bikin band threshold sekitar 8 sampai 13 RGB: cukup lebar untuk menangkap variasi latar yang cuma sekitar 4 RGB, tapi cukup sempit supaya tepi produk yang duduk 10+ RGB dari latar tidak ikut termakan. Kalau saya buka terlalu lebar, tepi subjek ikut transparan dan produknya "makan" pinggirnya.

Kalau butuh alpha sungguhan buat WebM, saya key lalu paksa format beralpha:

ffmpeg -i in.mp4 -vf \
  "colorkey=0xEDECEF:0.08:0.05,format=yuva420p" \
  -c:v libvpx-vp9 -pix_fmt yuva420p out.webm

Verifikasi alpha-nya benar-benar ada, jangan asal percaya:

ffprobe -show_streams out.webm | grep alpha_mode
# TAG:alpha_mode=1

Satu jebakan penting: jangan chroma-key kalau warna subjek terlalu dekat ke latar. Di salah satu revisi, badan produk #DDDDDD cuma 3 sampai 4 RGB dari latar #DFDFDF. Key apa pun yang cukup lebar untuk menghapus latar juga akan melubangi produknya. Untuk kasus itu, lebih aman skip chroma-key sepenuhnya dan cukup samakan warna section ke latar video.

Terakhir, di sisi CSS, berhenti hardcode #ffffff. Section harus pakai variabel theme, dan warna overlay video harus cocok dengan hasil resolve variabel itu:

.hero-video-section {
  background: var(--color-background); /* resolve ke #FAFAFA, jangan tulis #ffffff */
}

Kalau setting warna theme berubah, re-encode videonya ke warna baru. Warna latar video itu piksel tetap; dia tidak ikut berubah saat kamu ganti variabel theme.

Pelajaran

  • Ukur warna dengan PIL sebelum menyimpulkan; selisih 3 sampai 4 RGB pun terbaca sebagai kotak oleh mata.
  • mix-blend-mode: multiply menyembunyikan, bukan menghapus. Selisih warna tetap bocor.
  • Setel threshold colorkey di antara variasi latar dan jarak ke tepi subjek, jangan asal lebar.
  • Skip chroma-key kalau warna subjek dalam 3 sampai 4 RGB dari latar; key-nya bakal melubangi subjek.
  • Jangan pernah hardcode #ffffff di section. Pakai var(--color-background) dan samakan warna overlay video ke hasil resolve-nya.
  • Kalau warna theme berubah, re-encode. Latar video itu baked-in, bukan variabel.