D
P
0
← Semua artikel Read in English

Layout, Overflow & Cascade CSS

Video Kiriman Animator Cuma Jalan di Safari? Itu HEVC, dan Menurunkannya ke 30fps Bikin Masalah Kedua

· · 5 menit baca
Video Kiriman Animator Cuma Jalan di Safari? Itu HEVC, dan Menurunkannya ke 30fps Bikin Masalah Kedua

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.mp4

Yang 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.mp4
ffmpeg -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.webm

Flag per flag, kenapa angkanya begitu:

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