Kembali ke blog
13 Agustus 2026Sergei Solod12 mnt baca

Bagaimana Saya Memangkas Video Produksi dari ~280 MB menjadi ~50 MB dengan H.264

Satu video nyata dari sistem produksi turun dari sekitar 280 MB menjadi sekitar 50 MB setelah konfigurasi H.264 dibangun ulang dengan CRF 28, x264 veryslow, batas resolusi kelas 720p, laju bingkai yang benar-benar berguna, dan tuntutan dekoder yang wajar. Pada tahap sebelumnya, contoh yang sama sudah turun dari sekitar 350 menjadi 238 MB, dan pemeriksaan pustaka lama menunjukkan bahwa H.264 dengan laju beberapa megabit per detik memang umum.

H.264FFmpegx264Kompresi VideoKinerja SitusOptimasi Media

Angka yang akhirnya membuat optimasi ini konkret sangat sederhana: satu video produksi yang saya pantau turun dari sekitar 280 MB menjadi 50 MB setelah kebijakan H.264 baru diterapkan. Itu sekitar 5,6× lebih kecil, menghemat kurang lebih 230 MB atau sekitar 82% dari ukuran awal.

Saya tidak mendapatkan hasil itu dengan pindah ke AV1, HEVC, atau VP9. Keluaran produksi tetap H.264 di dalam MP4. Yang berubah adalah kebijakan di sekitar kodek: piksel yang tidak perlu lebih sedikit, sampel waktu yang tidak berguna lebih sedikit, sasaran mutu yang jauh kurang konservatif, lebih banyak CPU digunakan sekali pada tahap penyandian, serta kontrak dekoder yang sengaja dibatasi.

Ini kasus penggunaan yang sangat spesifik: materi ilustrasi dan animasi pendek, sekitar 80% lalu lintas dari perangkat seluler, lebar pita sebagai biaya berulang, dan penyandian luring, dengan waktu CPU yang murah dibanding mengirim berkas terlalu besar berulang kali.

Kebijakan lama dan baru kira-kira seperti ini:

konfigurasi lama
H.264 Main @ Level 4.0
CRF 19
prasetel slow
hingga 1920x1080 / 1080x1920
30 fps
refs = 3
bingkai B = 3
GOP ≈ 2 detik
VBV ≈ 10M / 20M

konfigurasi baru
H.264 Main @ Level 3.1
CRF 28
prasetel veryslow
batas kelas 720p, tanpa pembesaran
CFR yang berguna, biasanya <= 30 fps
refs = 4
bingkai B = 5
GOP ≈ 5 detik
VBV ≈ 4M / 8M
yuv420p / avc1 / faststart

Hasil terukur: dari ~280 MB menjadi ~50 MB

Saya punya beberapa pengukuran produksi nyata, tetapi semuanya bukan eksperimen yang sama. Memisahkan kategorinya lebih penting daripada memilih persentase yang terlihat paling spektakuler.

PengukuranSebelumSesudahPengurangan
Video konkret yang sama~280 MB~50 MB~5,6× lebih kecil / ~82% lebih sedikit
Tahap sebelumnya dari berkas yang sama~350 MB~238 MB~1,47× lebih kecil / 32% lebih sedikit

Baris pertama adalah bukti paling bersih untuk judul artikel. Satu video konkret sebelum dan sesudah kebijakan baru: kira-kira 280 MB menjadi kira-kira 50 MB. Saya tidak menemukan kembali baris laju bit/durasi untuk pasangan persis itu di catatan lama, jadi saya tidak akan mengarangnya. Perubahan ukuran saja sudah cukup: berkas tertentu ini menjadi sekitar 5,6 kali lebih kecil.

Kasus ~350→238 MB adalah tahap optimasi yang lebih awal untuk berkas yang sama. Keluaran saat itu sekitar 1264×720, 30 fps, durasi kira-kira 500 detik, tanpa suara, dan sekitar 3,8 Mbps. Hitungannya cocok dengan ukuran yang tercatat: 3,8 Mbps selama sekitar 500 detik menghasilkan kurang lebih 238 MB. Itu sudah menghemat 32% dari ~350 MB, tetapi masih terlalu besar untuk sasaran lebar pita saya.

Pemeriksaan pustaka lama juga menunjukkan bahwa H.264 berukuran besar bukan satu pencilan aneh. Dalam satu pemeriksaan saya memiliki 238 video produksi dengan total 6,37 GB: 117 H.264 dan 121 AV1. Sebanyak 101 berkas berukuran setidaknya 20 MB dan 34 berkas setidaknya 50 MB. Beberapa H.264 besar terlihat seperti ini:

UkuranDurasiLaju bit rata-rata
121,0 MB4:253,83 Mbps
101,2 MB5:192,659 Mbps
92,78 MB4:442,735 Mbps
90,10 MB3:553,206 Mbps
89,74 MB4:412,676 Mbps

Berkas-berkas itu berisi materi yang berbeda, jadi tabel tersebut memberi konteks, bukan pengujian A/B. Namun tabel itu menunjukkan bahwa contoh lama 3,8 Mbps bukan kejadian tunggal: beberapa H.264 besar dalam pustaka lama memang berada di kisaran sekitar 2,6–3,8 Mbps.

Optimasi terpenting bukan sebuah opsi FFmpeg

Perubahan terbesar adalah cara saya memandang biaya.

Pengodean dilakukan sekali. Pengiriman berkas terjadi setiap kali seseorang memintanya.

Untuk video waktu nyata, menghabiskan jauh lebih banyak CPU demi sedikit menghemat laju bit bisa menjadi pertukaran yang buruk. Berkas saya dikodekan sebelumnya lalu disajikan berulang kali. Dalam model ini, menghemat sepuluh menit saat pengodean hampir tidak bernilai secara ekonomi jika pengodean yang lebih cepat membuat setiap permintaan di masa depan lebih besar.

Itulah mengapa -preset veryslow masuk akal bagi saya. Saya bersedia membayar biaya CPU sekali jika x264 dapat memakainya untuk menemukan representasi yang lebih efisien. Peramban tidak mengulangi pencarian pengode; peramban hanya mendekode aliran bit yang sudah jadi.

Aturannya menjadi sederhana: gunakan komputasi pada langkah yang hanya dilakukan sekali, dan hemat setiap byte pada langkah yang terus berulang.

Mengapa saya tetap memakai H.264 alih-alih mengejar kodek terbaru

Saya tidak mengatakan H.264 adalah kodek dengan efisiensi kompresi terbaik yang tersedia. Bukan. Kodek yang lebih baru bisa sangat menarik jika sistem distribusi dapat menyimpan beberapa versi dan memilih yang paling sesuai untuk setiap klien.

Kendala saya berbeda: satu URL, satu berkas, satu kodek, dan sesedikit mungkin masalah pemutaran untuk audiens yang sebagian besar menggunakan perangkat seluler.

Untuk kebutuhan itu, H.264 di dalam MP4 masih merupakan dasar yang sangat aman. Apple saat ini menyarankan pengembang situs menggunakan berkas MP4 yang dikodekan H.264 untuk video statis di Safari. Dokumentasi Android saat ini mencantumkan H.264 di MP4 dan mewajibkan dekoder Profil Main pada Android 6.0 dan versi setelahnya; rekomendasi pemutaran H.264 juga mencantumkan 1280×720 pada 30 fps untuk HD, sambil mencatat bahwa HD tidak tersedia di semua perangkat. Lihat format media yang didukung Android.

Itu tidak berarti perangkat modern dibatasi pada Profil Main atau Tingkat 3.1. Misalnya, panduan HLS Apple umumnya lebih memilih Profil High daripada Main atau Profil Baseline. Saya memilih Main@3.1 karena ingin persyaratan dekoder yang sengaja cukup ringan untuk satu berkas MP4 statis, bukan karena Apple mewajibkannya.

Saya berhenti mengodekan piksel yang tidak perlu ada

Resolusi adalah salah satu pengungkit terbesar. Batas saya menjadi kira-kira 1280×720 untuk lanskap, 720×1280 untuk potret, dan sekitar 960×960 untuk materi persegi atau campuran orientasi.

Aturan yang lebih penting adalah: jangan melakukan pembesaran hanya untuk mencapai batas.

Jika sumber berukuran 900×600, mengubahnya menjadi 1280×720 tidak mengembalikan detail. Itu hanya membuat lebih banyak sampel yang harus dijelaskan pengode. Sumber 1920×1080 dapat diturunkan ke kelas 720p, sedangkan sumber 900×600 dapat tetap sekitar 900×600. Batas adalah maksimum, bukan sasaran.

Kedengarannya sederhana, tetapi membuang piksel yang tidak perlu dapat memberi dampak lebih besar daripada banyak penyetelan pengode yang rumit.

Batas itu bukan dipilih sekadar karena angkanya bulat. Satu bingkai 1920×1080 memiliki 2.073.600 piksel, sedangkan 1280×720 memiliki 921.600. Jadi, turun dari 1080p ke 720p membuang sekitar 55,6% sampel spasial bahkan sebelum penyandi mulai mengambil keputusan kompresi.

Saya juga mempertimbangkan 540p sebagai pilihan umum. Namun 960×540 hanya memiliki 518.400 piksel: 43,75% lebih sedikit daripada 1280×720, sehingga tersisa 56,25% sampel 720p. Pada materi ilustrasi, sampel itu menggambarkan garis tipis, mata, rambut, jari, wajah, dan tepi yang tajam. Jika masih perlu menghemat bita, saya lebih memilih menguji CRF sedikit lebih tinggi sebelum membuang lagi 43,75% informasi spasial tanpa pengukuran. Kuantisasi dapat diubah pada penyandian berikutnya; detail yang sudah hilang akibat penurunan resolusi tidak dapat dikembalikan.

Karena itu kelas 720p menjadi batas umum saya yang berhati-hati, bukan pernyataan bahwa 540p buruk. Untuk satu berkas tertentu, versi 540p yang diukur bisa saja lebih baik. Saya hanya tidak menjadikan pengurangan spasial yang tidak dapat dibalik itu sebagai aturan seluruh pustaka tanpa data.

Saya berhenti membayar untuk bingkai yang sebenarnya tidak dimiliki sumber

Laju bingkai adalah pengali lain. Jika sebuah animasi memiliki kira-kira 16 keadaan visual yang benar-benar berguna per detik, menyimpannya pada 30 atau 60 fps tidak otomatis membuat gerakan lebih baik. Sering kali itu hanya menambah sampel waktu yang diulang atau disintesis dan tetap harus dikodekan.

Kebijakan saya adalah mempertahankan ritme berguna dari sumber dan biasanya tetap di 30 fps atau lebih rendah. Untuk materi seperti ini, 12, 15, 16, 18, 20, 24, 25, atau 30 fps semuanya bisa masuk akal jika memang menggambarkan sumber.

Saya juga lebih suka keluaran dengan laju bingkai konstan yang bersih. VFR pada dasarnya tidak rusak; CFR hanya membuat stempel waktu, jumlah bingkai, pemeriksaan durasi, pencarian posisi, dan validasi berikutnya lebih mudah dalam alur pemrosesan saya.

Prinsip umumnya lebih berguna daripada satu angka FPS tertentu: jangan membayar lebar pita untuk informasi waktu yang tidak ada di sumber.

CRF 28 adalah pilihan untuk beban kerja saya, bukan angka ajaib

Saya tidak ingin memaksa setiap cuplikan menuju laju bit sasaran yang sama. Ilustrasi yang hampir statis dan adegan dengan gerakan kompleks tidak membutuhkan jumlah bit yang sama agar terlihat layak.

Karena itu saya memakai mode CRF x264 dan, untuk beban kerja ilustrasi yang mengutamakan lebar pita ini, saya memilih sekitar -crf 28. FFmpeg mendokumentasikan CRF di libx264 sebagai kontrol laju dengan kualitas konstan; lihat dokumentasi kodek FFmpeg.

CRF 28 sengaja agresif. Saya tidak akan menyalinnya begitu saja ke butiran film, rekaman kamera yang berisik, teks layar yang sangat kecil, atau penggunaan yang lebih mementingkan fidelitas daripada lebar pita.

Saya juga tidak memiliki skor perseptual universal yang membuktikan CRF 28 transparan. Yang dapat saya katakan dari materi saya sendiri lebih terbatas: berkas menjadi jauh lebih kecil dan masih terlihat normal bagi saya saat diputar biasa. Ini pengamatan praktis, bukan klaim bahwa CRF 28 tidak memiliki kehilangan visual.

veryslow mahal bagi pengode, bukan otomatis bagi dekoder

Prasetel saya adalah -preset veryslow. Prasetel yang lebih lambat memberi x264 lebih banyak kesempatan mencari keputusan prediksi dan pengodean yang efisien. Harganya adalah CPU dan waktu pengodean.

Perbedaan pentingnya adalah: usaha pengode dan kompleksitas dekoder bukan hal yang sama.

Saya dapat membiarkan x264 bekerja sangat keras sambil membatasi aliran bit akhir secara terpisah. Kontrak keluaran konservatif saya adalah:

H.264, profil Main
Level 3.1
yuv420p 8 bit
avc1
refs = 4
bingkai B = 5
B-pyramid = normal
GOP terbuka = dinonaktifkan

FFmpeg mengekspos CRF, prasetel, penyetelan, batas profil, bingkai referensi, dan B-bingkai secara terpisah. Saya memandangnya dengan cara yang sama: biarkan pengode mencari sekeras mungkin, tetapi jaga sisi pemutaran tetap biasa dan mudah diprediksi.

GOP dan VBV adalah pagar pengaman, bukan kendali kualitas utama

Untuk cuplikan progresif pendek ini saya menggunakan GOP maksimum sekitar lima detik: kira-kira -g 150 pada 30 fps, -g 120 pada 24 fps, atau -g 80 pada 16 fps.

Ini pilihan untuk beban kerja saya, bukan aturan universal. pengiriman adaptif memiliki kendala berbeda; misalnya, panduan penyusunan HLS Apple merekomendasikan IDR setiap dua detik. Saya tidak menyalin aturan HLS itu begitu saja ke berkas MP4 statis progresif yang pendek.

Saya juga memakai kira-kira:

-maxrate:v 4M
-bufsize:v 8M

Nilai-nilai itu adalah batas terhadap lonjakan laju bit yang tidak biasa. Nilai tersebut tidak berarti “kodekan semuanya pada 4 Mbps”. CRF tetap mengatur alokasi bit normal, sehingga cuplikan yang mudah dikompresi masih bisa menjadi sangat kecil.

Saya juga membuat kontainer MP4 sesederhana mungkin

Saya secara eksplisit menggunakan avc1. Dokumentasi HLS Apple saat ini merekomendasikan format sampel seperti avc1 alih-alih avc3. Itu bukan penyebab berkas saya menjadi lebih kecil, tetapi sesuai dengan tujuan membuat keluaran H.264 di dalam MP4 yang konvensional.

Saya juga memakai -movflags +faststart. Dokumentasi format FFmpeg mengatakan faststart memindahkan indeks moov MP4 ke awal berkas. Persyaratan transmisi melalui HTTP Android juga menyatakan bahwa untuk MPEG-4, moov harus berada setelah ftyp dan sebelum mdat.

ftyp
moov
mdat

Faststart tidak meningkatkan kompresi. Ia hanya membuat pemutaran progresif melalui HTTP lebih mulus.

Untuk keluaran SDR biasa saya memakai yuv420p 8 bit dan menandai BT.709 dengan rentang video terbatas. Jika cuplikan tidak punya suara, saya tidak membuat jalur suara. Untuk konten ilustrasi ini saya juga memakai -tune animation; saya menganggapnya sebagai pilihan khusus jenis konten, bukan bagian dari kontrak kompatibilitas universal.

Profil FFmpeg inti

Untuk sumber ilustrasi 30 fps, bagian inti perintahnya kira-kira seperti ini:

ffmpeg -i input \
  -c:v libx264 \
  -preset veryslow \
  -tune animation \
  -crf 28 \
  -profile:v main \
  -level:v 3.1 \
  -pix_fmt yuv420p \
  -tag:v avc1 \
  -refs 4 \
  -bf 5 \
  -g 150 \
  -maxrate:v 4M \
  -bufsize:v 8M \
  -x264-params "open-gop=0:b-pyramid=normal:nal-hrd=none" \
  -color_range tv \
  -color_primaries bt709 \
  -color_trc bt709 \
  -colorspace bt709 \
  -an \
  -movflags +faststart \
  output.mp4

Tahap penskalaan dan laju bingkai sengaja tidak ditulis tetap di sini. Sumber 900×600 tidak seharusnya diperbesar hanya karena batasnya 1280×720, dan animasi dengan laju bingkai alami yang rendah tidak seharusnya dipaksa menjadi 30 fps hanya karena contoh memakai -g 150.

Perintah adalah implementasi kebijakan, bukan kebijakan itu sendiri.

Mengapa berkas menjadi beberapa kali lebih kecil

Tidak ada opsi ajaib.

Pengurangan ukuran berasal dari gabungan beberapa keputusan yang masing-masing menghilangkan pemborosan berbeda: piksel yang tidak perlu, bingkai yang tidak perlu, sasaran mutu yang terlalu konservatif, pengaturan penyandi yang lebih mengutamakan kecepatan daripada efisiensi, bingkai kunci yang terlalu sering, dan aliran data yang tidak saya butuhkan.

Itulah mengapa pernyataan “berkas ini H.264” ternyata memberi sangat sedikit informasi tentang ukurannya. Dua hasil pengodean H.264 dari sumber yang sama bisa sangat berbeda karena nama kodek tidak menjelaskan resolusi, laju bingkai, kontrol laju, prasetel, struktur GOP, profil, atau persiapan sumber.

Dalam kasus saya, mengubah keputusan di sekitar kodek lebih penting daripada mengganti kodek.

Apa yang tidak dibuktikan oleh hasil ini

Saya tidak mengisolasi setiap pengaturan dalam eksperimen terkontrol, jadi saya tidak dapat secara jujur menentukan persentase tepat penghematan yang berasal masing-masing dari veryslow, CRF 28, pengurangan resolusi, atau pengurangan laju bingkai.

Saya juga tidak dapat mengklaim setiap keluaran CRF 28 transparan secara perseptual. “Tidak ada penurunan kualitas yang jelas” adalah pengamatan saya untuk materi ilustrasi ini pada ukuran tontonan normal, bukan jaminan ilmiah untuk video apa pun.

Saya juga tidak berargumen bahwa satu berkas H.264 adalah arsitektur yang tepat untuk setiap situs. Beberapa versi, pengiriman adaptif, HDR, 4K, dan negosiasi kodek mengubah komprominya.

Yang benar-benar dapat saya klaim lebih sempit: untuk pustaka cuplikan ilustrasi dan animasi pendek yang mengutamakan lebar pita, mayoritas penontonnya memakai perangkat seluler, waktu pengodean murah, dan pemutaran yang dapat diprediksi penting, profil ini membuat berkas saya beberapa kali lebih kecil sambil tetap terlihat normal saat diputar biasa.

Bagaimana hasil ini mengubah strategi optimasi saya

Dulu saya memandang optimasi video terutama sebagai masalah pengaturan pengode. Sekarang saya memandangnya sebagai masalah biaya sepanjang umur berkas.

Pengode mungkin berjalan sekali. Byte dapat melewati jaringan ribuan atau jutaan kali.

Itu mengubah arti kata “mahal”.

Saya senang membayar CPU sekali. Saya jauh lebih enggan mengirim piksel yang dibuat oleh pembesaran, bingkai yang tidak menambah gerakan berguna, atau laju bit yang tidak dibutuhkan konten pada setiap permintaan di masa depan.

Kodeknya tetap membosankan: H.264 di dalam MP4. Optimasi terjadi di sekelilingnya.

Untuk beban kerja ini, pelajarannya lebih jelas daripada opsi FFmpeg mana pun: optimalkan biaya yang Anda bayar berulang kali, bukan biaya yang hanya Anda bayar sekali.