Biasanya Safari yang paling rewel soal berkas media, dan peramban lain yang santai saja menerima apa pun. Kali ini kebalikannya. Dari lima peramban yang saya coba, cuma Safari yang mau memutar videonya.
Berkasnya datang dari animator pada 3 Mei 2026, untuk sebuah loop produk pendek. Satu MP4, 1080p, 60fps, ukurannya 7,6MB, dan masih membawa trek audio. Di Safari dia jalan. Di Chrome, Firefox, Brave, dan Edge dia rusak.
Baca kirimannya sebelum dipasang
Perintah yang saya jalankan tiap kali ada aset video masuk:
ffprobe -v error \
-show_entries stream=codec_name,codec_type,width,height,r_frame_rate,duration,bit_rate \
-show_entries format=duration,size,bit_rate \
-of default=noprint_wrappers=0 source.mp4Yang saya cari di keluarannya cuma beberapa baris: nama codec streamnya, frame rate-nya, dan ada atau tidaknya stream audio. Di berkas ini yang keluar adalah HEVC 1080p 60fps, plus trek audio yang untuk keperluan ini tidak pernah dipakai. Aturannya sejak itu saya pegang lurus, kiriman diperiksa dengan ffprobe sebelum dipasang, bukan setelah ada yang melapor.
Kenapa cuma Safari yang mau
HEVC, atau H.265, tidak punya dukungan web di luar Safari. Itu sudah menjelaskan seluruh gejalanya, dan tidak ada yang perlu didebug lebih jauh di sisi halaman.
Yang penting disadari, ini bukan kecelakaan satu animator. Keluaran animator umumnya memang HEVC/H.265, karena itu format yang keluar dari alat compositing dan grading yang lazim mereka pakai. Jadi kiriman semacam ini adalah keadaan default, bukan pengecualian yang perlu ditanyakan balik.
Ukurannya juga tidak menyalakan lampu apa pun. Batas yang saya pakai untuk aset video yang ikut dikirim bersama tema adalah 10MB ke bawah masih wajar, dan 7,6MB duduk nyaman di bawah itu. Tidak ada satu sinyal ukuran pun yang keliru di kiriman ini. Yang keliru codecnya.
Transcode pertama saya, dan yang menemukan salahnya bukan saya
Transcode pertama saya jalankan di 30fps, alasannya menghemat ukuran. Logika saya waktu itu sesederhana lebih kecil berarti lebih baik, dan setengah frame rate berarti setengah frame yang harus disimpan.
Yang menemukan kesalahannya bukan saya. Ada user yang melapor bahwa loopnya patah-patah, dan patah-patah di sini artinya motion judder yang terlihat pada loop produk yang berputar. Menurunkan 60fps ke 30fps pada loop berputar atau padat gerak memang menghasilkan judder yang kelihatan. Animator memilih 60fps bukan tanpa alasan.
Saya encode ulang di 60fps, dan hasilnya mulus.
Sejak itu flag -r 60 di perintah saya punya catatan sendiri: pertahankan 60fps sumbernya, jangan turunkan ke 30fps, karena juddernya terlihat terutama di loop produk yang berputar, dan user menyadarinya. Pelajarannya jangan pernah menurunkan frame rate pada loop berputar atau padat gerak.
Bagian yang paling menyebalkan dari kesalahan ini: penghematan yang saya kejar lewat frame rate itu tidak pernah dibutuhkan. Membuang audio ditambah codec modern sudah cukup mengecilkan berkasnya tanpa mengorbankan mutu gerak sama sekali.
Dua sumber, tetap 60fps, audio dibuang
Perbaikan akhirnya bukan satu berkas, tapi dua sumber sekaligus, dua-duanya 60fps dan dua-duanya tanpa audio.
ffmpeg -y -i source.mp4 \
-c:v libx264 -preset slower -crf 18 \
-r 60 -an -pix_fmt yuv420p -movflags +faststart \
loop-h264.mp4ffmpeg -y -i source.mp4 \
-c:v libvpx-vp9 -crf 30 -b:v 0 \
-row-mt 1 -tile-columns 4 -frame-parallel 1 \
-r 60 -an -pix_fmt yuv420p \
-deadline good -cpu-used 2 \
loop-vp9.webmFlag per flag, kenapa angkanya begitu:
-crf 18di H.264 adalah mutu visually lossless, titik yang dianggap transparan bagi mata manusia.-crf 30 -b:v 0di VP9 mengejar mutu yang setara. Skala CRF VP9 tidak sama dengan H.264, dan 30 di VP9 kira-kira sepadan dengan 18 di H.264.-anmembuang audio. Loop autoplay memang muted, dan audio menambah sekitar 5 sampai 15 persen ukuran tanpa guna.-pix_fmt yuv420padalah format piksel universal untuk semua peramban dan pemutar.-movflags +faststarthanya dipakai di H.264. Dia memindahkan moov atom ke depan berkas supaya pemutaran bisa mulai sebelum unduhannya selesai.-preset slowermemberi kompresi lebih baik pada mutu yang sama. Encodenya jadi lebih lama, tapi itu biaya yang dibayar sekali.
Hasilnya H.264 2,5MB dan VP9 2,5MB. Berkas aslinya saya simpan ke folder arsip aset, tidak ditimpa.
Dari 7,6MB ke 2,5MB itu turun 5,1MB, atau 5,1 dibagi 7,6, sekitar 67 persen. Yang tersisa 2,5 dibagi 7,6, sekitar 33 persen dari kiriman. Dua berkas itu memang menempati 5,0MB di repo, tapi tiap peramban cuma mengunduh salah satunya, jadi yang dibayar pengunjung tetap 2,5MB. Semuanya tanpa menyentuh frame rate sedikit pun.
Satu catatan supaya angkanya tidak dipakai buta. Patokan yang saya simpan menyebut VP9 WebM kira-kira 30 persen lebih kecil daripada H.264 pada mutu setara, tapi di klip ini dua-duanya mendarat di angka yang sama. Patokan begitu berguna untuk memperkirakan sebelum encode, dan yang saya pakai untuk memutuskan tetap ukuran yang benar-benar keluar dari berkasnya.
Urutan sumber menentukan siapa mengunduh apa
<video autoplay muted loop playsinline preload="auto"
poster="loop-poster.webp">
<source src="loop.webm" type="video/webm">
<source src="loop.mp4" type="video/mp4">
<img src="loop-fallback.webp">
</video>Urutannya menentukan. WebM ditaruh lebih dulu karena lebih kecil dan peramban modern akan mengambil yang pertama cocok. MP4 duduk di belakangnya sebagai fallback untuk Safari dan peramban lama. <img> jadi fallback terakhir kalau dua sumber video itu sama-sama gagal. Di template, elemen videonya juga saya tandai aria-hidden="true".
Soal preload, saya menolak preload="metadata" di sini. Dia cuma menarik metadata, videonya menyangga sambil jalan, dan hasilnya tersendat tepat saat autoplay mulai. preload="auto" menyangga penuh sehingga pemutarannya mulus, dan untuk loop dekoratif kecil berukuran 2 sampai 5MB biaya jaringannya bisa diabaikan. Berkas 2,5MB tadi jatuh persis di rentang itu.
Kapan berkasnya tidak boleh ikut tema lagi
Batas ukuran yang saya pakai ada tiga tingkat. 10MB ke bawah masih wajar sebagai aset tema. 10 sampai 20MB masih boleh, tapi pushnya jadi lambat. Di atas 20MB berkasnya tidak saya kirim sebagai aset tema lagi, melainkan diunggah lewat panel admin, lalu URL publiknya dirujuk dari setelan tema bertipe URL.
Yang saya bawa pulang
- Periksa kiriman dengan ffprobe sebelum dipasang. Satu perintah menghemat satu ronde laporan.
- HEVC/H.265 tidak punya dukungan web di luar Safari, dan format itu justru keluaran default dari alat yang dipakai animator.
- Selalu transcode ke dua sumber, H.264 MP4 dan VP9 WebM, supaya kompatibel di semua peramban.
- Pertahankan 60fps. Jangan pernah menurunkan frame rate pada loop berputar atau padat gerak, karena animator memilih 60fps bukan tanpa alasan.
- Buang audio untuk loop autoplay yang muted. Bersama codec modern, itu sudah cukup mengecilkan berkas tanpa mengorbankan mutu gerak.
- Aturan ini berlaku untuk semua aset video yang dipakai di tema: loop autoplay, video hero, dan gerak dekoratif.