Skip to content
Blog Programming

Bagaimana Saya Menyiapkan Aset Web Tanpa Watermark Milik Orang Lain

By Romi Fadli, S.Kom. 21 min read Tooling & Automation
On this page
One asset branching along two paths: the upper result carries a watermark, the lower one is clean

Aset di home page bukan sekadar file. Ia yang pertama dilihat pengunjung, dan ia sudah dinilai sebelum satu kalimat pun terbaca. Karena itulah logo kecil setengah tembus pandang di pojoknya — yang ditaruh entah situs mana yang tadi mengonversinya — bukan perkara kosmetik. Itu merek orang lain yang duduk di dalam merek saya, persis di bagian halaman yang membentuk kesan pertama.

Pendahuluan

A. Apa yang sebenarnya dilakukan watermark pada sebuah aset

Ketika mengonversi dokumen pribadi, saya menjauhkannya dari server orang lain karena satu alasan: kerahasiaan. KTP atau kontrak yang diunggah ke konverter gratisan meninggalkan salinan di mesin yang tak saya kendalikan, dan salinan itulah seluruh ongkosnya. Watermark nyaris tak berarti dalam urusan itu, sebab tak ada yang menilai tipografi ijazah hasil scan.

Keadaan sekarang berbeda dengan taruhan yang berbeda pula, dan pembedaannya layak dinyatakan terang-terangan. Hero image, foto produk, pratinjau bergerak di landing page — tak satu pun dari ketiganya rahasia. Mengunggahnya tak membocorkan apa-apa. Kerusakannya bukan karena ada salinan di tempat lain; kerusakannya adalah yang kembali sudah turun mutunya, dan penurunan itu mengenai bagian produk yang paling dulu dilihat orang.

Jadi konverter gratisan gagal di sini karena alasan yang sama sekali tak berhubungan dengan privasi. Mereka menandai keluarannya sebab menandai keluaran itulah cara tier gratis menjual yang berbayar. Watermark bukan efek samping. Ia memang produknya.

B. Apa arti "cukup layak dipajang"

Aset web hidup di bawah batasan yang tak dipunyai konversi dokumen: ia harus kecil, sebab halaman yang butuh empat detik untuk tampil sudah kalah duluan, dan ia harus tetap terlihat benar sesudah dikecilkan. Kedua tuntutan itu saling tarik, dan tiap keputusan di bawah berada di suatu titik pada garis tarik-menarik itu.

Kecil tak bisa ditawar, penampilan juga tidak, dan itu membuat pertanyaan yang menarik tak pernah "bagaimana mengonversinya" — konversinya satu perintah — melainkan "setelan mana yang membuatnya tetap terlihat benar pada ukuran yang sanggup ditanggung halaman". Jawaban pertanyaan itu berbeda untuk foto dan untuk screenshot, dan berbeda lagi untuk animasi.

C. Empat tool, tiga format, satu pekerjaan

Pekerjaannya tersebar di empat script kecil, dan pembagiannya tidak rapi. Dua di antaranya mengonversi satu gambar ke WebP atau JPEG. WebP adalah format gambar yang dirancang untuk web, biasanya jauh lebih kecil daripada JPEG atau PNG pada mutu tampilan yang sama. Satu mengonversi gambar atau seisi folder ke WebP lengkap dengan setelan kualitas. Satu lagi mengubah video jadi GIF bergerak.

Ketidakrapiannya sendiri memberi keterangan: dua di antaranya nyaris kembar, satu menggantikan yang lain, dan satu memecahkan kebutuhan yang cuma kelihatan mirip. Saya takkan merapikannya saat menceritakan, sebab bentuk kumpulan ini adalah hasil dari urutan kebutuhannya muncul, dan urutan itulah riwayat yang jujur.

D. Di mana sebenarnya letak kesulitannya

Tak satu pun dari ini melibatkan penulisan encoder. ffmpeg yang meng-encode: program command-line gratis yang mengonversi video, audio, dan gambar di antara hampir semua format, dan termasuk software paling mumpuni yang pernah ada. Kesulitannya justru ffmpeg mengerjakan persis yang disuruhkan, dan default-nya dipilih supaya aman untuk segala input yang terbayangkan — dan itu tidak sama dengan bagus untuk input yang satu ini.

Jadi pekerjaannya ada di flag-nya. Angka kualitas mana, preset mana, filter penskalaan mana, dan — untuk animasi — struktur dua tahap yang mana. Tiap satunya keputusan yang dengan senang hati dibiarkan ffmpeg saya buat keliru, dan ia takkan mengeluh saat itu terjadi. Keluarannya cuma akan lebih buruk dari semestinya, dengan cara yang baru kelihatan begitu asetnya sudah terpasang di halaman.

E. Delapan hambatan yang menghalangi

Jadi tujuannya gampang dirumuskan: menghasilkan gambar dan animasi yang cukup kecil untuk halaman web dan tetap terlihat benar di sana, tanpa satu pun membawa tanda milik orang lain. Bisa diulang, dari terminal, atas aset yang mungkin perlu saya bangun ulang belasan kali sebelum rancangannya mengendap.

Gampang dirumuskan, canggung dibangun. Delapan hambatan berdiri antara tujuan itu dan empat perintah yang saya percayai memegang bagian depan sebuah halaman.

Yang pertama, keluarannya dipajang, jadi cacatnya tak bisa ditutupi. Watermark pada dokumen yang dikirim cuma menjengkelkan; watermark pada hero image adalah cacat pada produknya. Konverter gratisan menambahkannya secara sengaja, membatasi jumlah konversi per hari, dan menjual penghapusannya — dan itu membuat tier gratisnya sebuah demo, bukan tool. Alternatif yang ditolak: berlangganan, yang berarti membayar untuk pekerjaan yang semestinya sebuah flag, dan memotong tandanya sesudahnya, yang mengorbankan komposisi demi menyembunyikan kerusakan ketimbang menghindarinya.

Yang kedua, default ffmpeg aman, bukan bagus. Dipanggil cuma dengan input dan output, ia memilih encoder dan setelan yang bekerja di mana-mana dan tak menonjol di mana pun. Untuk foto yang tujuannya sebuah halaman, hasilnya terasa lebih lembek dari semestinya pada ukuran yang lebih besar dari yang dibutuhkan — dua arah terburuk sekaligus.

Yang ketiga, aset aslinya tak bisa dibangun ulang. Render yang makan dua puluh menit, foto yang diambil satu kali, screenshot atas keadaan yang sudah tak ada lagi — ketiganya input, bukan file antara. Tool yang mengonversi di tempat cuma berjarak satu argumen salah ketik dari memusnahkan satu-satunya salinan benda yang sedang dikonversinya.

Yang keempat, GIF cuma punya 256 warna dan ada yang harus memilih 256 yang mana. Tiap format lain di sini menyimpan warna per pixel. GIF menyimpan indeks ke dalam palette, jadi meng-encode-nya berarti memecahkan soal pemilihan lebih dulu. Diserahkan ke satu tahap, encoder-nya memungut palette generik dan hasilnya berbintik kelihatan — tampilan berbutir yang berkata "salah konversi" kepada siapa pun yang pernah melihat GIF yang bagus.

Yang kelima, palette harus dihitung dari frame yang persis akan memakainya. Memecahkan soal palette melahirkan soal yang lebih halus: tahap analisis dan tahap encoding adalah dua pemanggilan terpisah, dan bila keduanya berselisih soal frame rate atau ukuran, palette-nya menggambarkan kumpulan gambar yang sedikit berbeda dari yang sedang di-encode. Kegagalannya senyap dan keluarannya cuma terlihat agak keliru.

Yang keenam, frame rate yang diminta bisa melebihi yang sungguh dimiliki sumbernya. Frame rate itu argumen, dan argumen bisa diisi apa saja. Meminta enam puluh frame per detik dari sumber tiga puluh frame tak menghasilkan gerakan yang lebih mulus; ia menghasilkan frame duplikat, file yang lebih besar, dan nol tambahan keterangan.

Yang ketujuh, penskalaan butuh pagar sekaligus rasio yang terjaga. Faktor skala adalah angka yang diberikan pemanggilnya, dan angka di luar rentang yang masuk akal menghasilkan entah thumbnail tak terpakai atau pembesaran yang mengarang detail. Menyebutkan kedua dimensi sendiri-sendiri lebih buruk lagi — rasionya melenceng, dan foto produk yang melar terbaca sebagai fotografi yang buruk, bukan sebagai kekeliruan langkah konversi.

Yang kedelapan, tool yang nyaris kembar menumpuk, dan penumpukan itu sebuah keputusan. Dua dari empat ini beda satu baris. Satu menggantikan yang lain dan tetap hidup berdampingan dengannya. Tiap penggandaan itu, pada saat ia terjadi, lebih murah ketimbang menggeneralkan — dan apakah itu keputusan yang benar baru bisa dijawab dengan menengok ke belakang.

Masing-masing punya seksi di bawah. Tiga yang pertama menentukan apakah tool ini layak dimiliki sama sekali; empat berikutnya adalah keputusan spesifik yang memisahkan aset yang terlihat benar dari yang terlihat hasil konversi; yang terakhir soal bentuk yang akhirnya ditempati kumpulan ini.

Metode

A. Menjauhkan tanda itu dari keluarannya

Inilah jawaban atas hambatan pertama, dan inilah keputusan yang menopang sisa artikel: konversinya terjadi lewat ffmpeg di mesin ini, jadi tak ada tier gratis dan karena itu tak ada yang perlu ditandai.

Itu terdengar seperti argumen privasi padahal bukan. Aset ini memang akan dipublikasikan; tak ada yang perlu dilindungi. Yang dibeli oleh eksekusi lokal di sini adalah keluarannya persis seperti yang dihasilkan encoder — tanpa tambahan, tanpa penghitung harian, dan tanpa versi tool yang sengaja dibuat lebih buruk demi menjual yang lebih baik.

bash
# a converter with no business model attached to its output
ffmpeg -y -loglevel error -i "$src" \
  -c:v libwebp -quality 80 -preset photo \
  "$dst"

Keuntungan keduanya soal pengulangan. Aset tak dikonversi sekali saja — rancangan berubah, render diulang, screenshot diambil lagi — dan batas konversi harian paling menghalangi persis pada jam-jam sebuah halaman sedang diutak-atik.

B. Memilih angka yang takkan dipilih ffmpeg

Inilah jawaban atas hambatan kedua, dan inilah beda antara kedua tool WebP yang saya punya.

Yang lebih lama tak menyerahkan apa-apa: sebuah input, sebuah output, dan apa pun yang diputuskan ffmpeg. Yang lebih baru menyebut encoder-nya secara eksplisit, menetapkan kualitas di 80, dan memilih preset photo. Keduanya masih ada di mesin ini, dan yang kedua ada justru karena yang pertama belum cukup bagus.

bash
# earlier: every quality decision left to ffmpeg
ffmpeg -i "$SOURCE" "$OUTPUT"

# later: the encoder, the quality, and the tuning are all stated
ffmpeg -y -loglevel error -i "$src" -c:v libwebp -quality 80 -preset photo "$dst"

Angka 80 bukan dari rujukan. Ia datang dari mengonversi segelintir gambar yang sama pada beberapa nilai lalu melihat hasilnya bersebelahan dengan aslinya: di bawahnya, gradasi pada foto mulai berpita kelihatan; di atasnya, ukuran file tumbuh tanpa beda yang bisa saya lihat di sebuah halaman. Itulah titik di mana membayar lebih banyak byte berhenti membeli apa pun, untuk jenis input ini, pada jenis layar ini.

Preset photo penting karena alasan yang bersebelahan. Ia menyetel pertukaran internal encoder untuk gambar bernada kontinu ketimbang grafis bidang datar, dan itulah andaian yang benar untuk foto produk dan render — sekaligus andaian yang keliru untuk screenshot antarmuka, di mana tepi tajam tulisan akan lebih terlayani preset lain. Bahwa default-nya disetel untuk foto adalah sebuah pilihan, dan pilihan itu benar cuma karena foto memang yang paling sering saya konversi.

C. Tak pernah menulis di atas input

Inilah jawaban atas hambatan ketiga, dan ia satu baris penyusunan path.

bash
SRC_DIR="${INPUT%/}"
DST_DIR="${SRC_DIR}_webp"     # a new folder beside it, never the folder itself
mkdir -p "$DST_DIR"

Ketika input-nya satu folder, keluarannya folder bersebelahan dengan imbuhan _webp, dibuat baru. Aslinya tak disentuh, tak dipindahkan, tak ditimpa. Mengonversi satu folder dua kali menghasilkan hasil yang sama dua kali ketimbang menurunkan mutu input-nya bertahap — dan penurunan bertahap itulah yang akan dilakukan konversi di tempat kepada apa pun yang dijalankan berulang padanya.

Alasannya: input di sini tak tergantikan dengan cara yang tak berlaku bagi file antara. WebP bisa dibangun ulang dari PNG dalam sedetik. PNG-nya mungkin render yang menghabiskan dua puluh menit komputasi, atau foto benda fisik di bawah pencahayaan yang sudah dibongkar. Memperlakukan sumber sebagai read-only berongkos beberapa ratus kilobyte penggandaan dan melenyapkan satu kategori kekeliruan seluruhnya.

Jalur file tunggal mengikuti aturan yang sama dengan cara berbeda: ia menulis bersebelahan dengan input-nya dengan ekstensi yang ditukar, dan itu mustahil bertabrakan dengan sumbernya sebab ekstensinya niscaya berbeda.

D. Menghitung 256 warna yang mana

Inilah jawaban atas hambatan keempat, dan inilah kenapa mengubah video jadi GIF butuh dua perintah dan bukan satu.

bash
# pass 1: look at the whole video, decide on 256 colours
ffmpeg -an -i "$SOURCE" -vf "fps=${FPS},${SCALE_FILTER},palettegen" "$PALETTE"

# pass 2: encode using that palette
ffmpeg -i "$SOURCE" -i "$PALETTE" -an \
  -lavfi "fps=${FPS},${SCALE_FILTER} [x]; [x][1:v] paletteuse" "$OUTPUT"

GIF tak sanggup menyimpan warna sembarang per pixel. Ia menyimpan palette berisi paling banyak 256 entri beserta satu indeks per pixel, jadi encoder-nya harus memutuskan 256 warna mana yang mewakili seluruh animasi sebelum ia bisa meng-encode satu frame pun. Satu tahap memaksa keputusan itu diambil tanpa pernah melihat bahannya, dan hasilnya tampilan berbintik dan berbutir yang seketika dikenali — saya menghasilkan persis itu sebelum menambahkan tahap pertamanya, dan cukup kentara di halaman sampai versi dua tahapnya langsung menyusul.

Menjalankan palettegen lebih dulu membuat keputusannya diambil dengan seluruh video tersedia. Palette-nya ditulis ke file sementara, dipakai, lalu dihapus — dan itu menjaga potongan keadaan antara supaya tak menumpuk di folder tempat asetnya tinggal.

E. Membuat kedua tahap melihat frame yang sama

Inilah jawaban atas hambatan kelima, dan ia batasan yang ada justru karena jawaban atas hambatan sebelumnya.

Lihat rangkaian filter di kedua perintah di atas: fps=${FPS} dan filter skala yang sama muncul di keduanya, disusun dari variabel yang sama. Itu bukan pengulangan demi pengulangan. Palette wajib dihitung dari frame yang persis akan di-encode dengannya.

bash
# one definition, used by both passes — they must not disagree
SCALE_FILTER="scale=iw*${SCALE}:-1:flags=lanczos"

Bila tahap analisis melihat video pada ukuran penuh dan tiga puluh frame per detik sementara tahap encoding melihatnya pada separuh ukuran dan dua belas, palette-nya dipilih untuk kumpulan gambar yang berkerabat dengan — tapi bukan sama dengan — kumpulan yang sedang di-encode. Penskalaan mengubah nilai pixel lewat interpolasi; membuang frame mengubah momen mana saja yang terwakili. Palette-nya berakhir keliru secara halus bagi bahannya sendiri.

Tak ada yang error. Keluarannya GIF yang sah dan cuma terlihat agak meleset, dan itulah jenis keliru yang paling mahal — ia lolos pemeriksaan lalu ketahuan belakangan, oleh orang lain, di halaman yang sudah terbit.

F. Membiarkan sumbernya yang menetapkan plafon

Inilah jawaban atas hambatan keenam. Frame rate boleh disebutkan, tapi tak boleh melampaui yang sungguh dimuat file-nya.

bash
RAW_FPS=$(ffprobe -v error -select_streams v:0 \
  -show_entries stream=r_frame_rate -of csv=p=0 "$SOURCE")

# r_frame_rate arrives as a fraction: 30000/1001, not 29.97
SOURCE_FPS=$(echo "$RAW_FPS" | awk -F'/' \
  '{ if (NF==2 && $2 != 0) printf "%.4f", $1/$2; else printf "%.4f", $1 }')

Ada dua urusan yang sedang berjalan. Pertama, ffprobe melaporkan frame rate sebagai bilangan rasional yang eksak — 30000/1001 dan bukan 29.97 — sebab frame rate siaran memang bukan angka bulat dan membulatkannya terlalu dini menumpuk error. Mendapatkan angka yang terpakai berarti membaginya, dan untuk itulah awk di situ.

Kedua, pemeriksaan yang menyusulnya: frame rate dari pemakainya diterima cuma bila positif dan tak melebihi milik sumbernya. Meminta lebih banyak frame ketimbang yang ada tak sanggup menambah gerakan; encoder-nya menggandakan frame untuk menutup selisihnya, menghasilkan file lebih besar yang tampak identik. Menolaknya dengan pesan yang menyebut angka maksimum sebenarnya lebih berguna ketimbang diam-diam menghasilkan file itu.

Ini plafon yang datang dari bahannya, bukan dari konstanta yang saya pilih — dan cuma batas semacam itulah yang tetap benar melintasi input yang belum pernah saya lihat.

G. Menskalakan tanpa membuatnya melar

Inilah jawaban atas hambatan ketujuh, dan ia tiga keputusan di dalam satu ungkapan filter.

bash
scale=iw*${SCALE}:-1:flags=lanczos

Lebarnya adalah lebar input dikali sebuah faktor. Tingginya -1, yang menyuruh ffmpeg menurunkannya dari lebar sambil menjaga rasionya — sedangkan alternatifnya, menyebut keduanya, berarti tiap keseleo aritmetika menarik gambarnya melar, dan foto produk yang melar terbaca sebagai fotografi buruk, bukan sebagai kekeliruan konversi.

lanczos adalah filter resampling-nya. Mengecilkan berarti membuang pixel dan ada yang harus memutuskan seperti apa rupa yang tersisa; filter yang lebih murah menghasilkan kelembekan dan tepi bertangga, dan itu paling kelihatan persis pada isi yang berakhir di animasi web — elemen antarmuka, tulisan, batas tegas antar bidang datar.

Faktornya sendiri divalidasi sebelum dipakai: ia wajib terbaca sebagai angka antara 0.1 dan 1.0. Batas bawahnya mencoret thumbnail yang terlalu kecil untuk jadi benda yang sebenarnya diinginkan siapa pun, dan batas atasnya mencoret pembesaran, yang tak menambah detail dan cuma membuat encoder-nya mengarang pixel.

H. Empat tool yang tak pernah menyatu

Inilah jawaban atas hambatan kedelapan, dan ia lebih berupa pembukuan atas bentuk yang akhirnya ditempati kumpulan ini ketimbang sebuah teknik.

bash
# the entire difference between two of these four scripts
OUTPUT="$DIR/${BASENAME}.webp"
OUTPUT="$DIR/${BASENAME}.jpeg"

Dua dari keempatnya berbeda cuma pada satu baris yang bermakna — yang satu menulis .webp, yang lain menulis .jpeg, dan sisanya identik. Yang ketiga menggantikan salah satunya dan tetap hidup berdampingan dengannya. Tiap penggandaan itu, pada saat ia terjadi, lebih murah ketimbang alternatifnya: menyalin script dua puluh tujuh baris makan waktu beberapa detik, sementara menggeneralkannya berarti merancang antarmuka untuk argumen format, dan antarmuka itu harus diingat tiap kali tool-nya dipakai sesudahnya.

Ada juga alasan kenapa yang JPEG belum dilebur ke dalam yang WebP walau kodenya nyaris sama. Ia melayani kebutuhan yang lain. WebP untuk halaman; JPEG untuk kolom unggah pada form yang tak menerima format lain — kebutuhan urusan dokumen yang kebetulan tinggal di kotak tool untuk aset web. Perintah sama, ffmpeg sama, alasan keberadaan berbeda, dan perbedaan itulah yang membuat tak satu pun menyerap yang lain.

Hasil dan Pembahasan

A. Berapa sebenarnya nilai setelan itu

Keempat tool menerapkan kadar pertimbangan yang berbeda, dan kadarnya mengikuti seberapa parah default-nya gagal untuk format itu.

ToolKeputusan yang ia ambilOngkos kalau diserahkan ke default
WebP atau JPEG file tunggalNol — format sajaLebih lembek dan lebih besar dari perlunya
Gambar atau folder ke WebPEncoder, quality 80, preset photoSama, pada tiap file dalam satu batch
Video ke GIFPalette dua tahap, plafon fps, pagar skala, lanczosAnimasi berbintik kelihatan

Baris terakhir tempat default paling parah gagal, sekaligus tempat tool-nya paling banyak bekerja. Itu bukan kebetulan: format GIF memaksa satu keputusan yang tak bisa ditunda, jadi konverter yang tak mengambilnya dengan sengaja pasti mengambilnya dengan buruk. Encoder WebP sebaliknya punya default yang masuk akal dan cuma belum disetel — jarak antara default dan yang dipertimbangkan memang nyata, tapi sempit.

Baris pertama juga layak tetap terlihat. Tool di situ tak mengambil keputusan kualitas apa pun dan tetap berguna, sebab sebagian besar nilainya justru pada tak perlunya mengingat satu pemanggilan. Sebuah tool bisa sepadan ditulis semata-mata demi namanya.

B. Untuk apa flag di sekeliling konversinya

Beberapa flag di perintah-perintah ini tak ada hubungannya dengan mutu gambar dan sepenuhnya soal bisa dipanggil tanpa ditunggui.

bash
ffmpeg -y -loglevel error -i "$src" ...   # -y: no prompt mid-batch
                                          # -loglevel error: only real failures
ffmpeg -an -i "$SOURCE" ...               # -an: audio GIF cannot carry anyway

-y menimpa keluaran tanpa bertanya, dan itu penting sebab alternatifnya script yang menggantung menunggu jawaban di tengah batch. -loglevel error membungkam banner dan keluaran kemajuannya, menyisakan kegagalan yang sungguhan saja — konverter yang bercerita soal tiap file membuat satu error sungguhan lewat begitu saja tanpa terlihat. -an pada perintah GIF membuang audio, yang toh tak sanggup dibawa GIF, tapi yang tanpa itu akan di-decode dulu sebelum dibuang.

Tak satu pun dari ketiganya mengubah satu pixel. Ketiganya mengubah apakah tool-nya bisa dijalankan menyisir folder tanpa ditunggui, dan itulah beda antara sebuah perintah dengan sebuah peragaan.

C. Di mana pendekatan ini berhenti jadi tepat

Ketiga tool ini memuat andaian satu orang tentang satu jenis aset, dan andaiannya kelihatan di default-nya.

Preset photo dan quality 80 disetel untuk gambar bernada kontinu; screenshot antarmuka yang penuh tulisan dan bidang datar akan lebih terlayani setelan lain dan akan keluar lebih lembek dari semestinya. GIF sendiri format yang keliru untuk apa pun yang panjang atau berdetail — loop pendek itulah tujuannya, dan lewat beberapa detik format video lebih kecil sekaligus lebih baik di segala sisi. Lalu tak satu pun tool ini membuang metadata, jadi foto yang dikonversi untuk sebuah halaman membawa apa pun yang ditulis kameranya, termasuk lokasi, langsung ke web server.

Simpulan

Watermark-lah alasan saya mulai menulis ketiganya, dan ia ternyata bagian paling tak menarik dari semuanya. Tak ada di sini yang sulit dikerjakan sekali; seluruh nilainya ada pada segelintir keputusan yang dengan rela dibiarkan ffmpeg saya buat dengan buruk — angka kualitas mana, preset mana, apakah palette-nya dihitung sama sekali, dan apakah kedua tahapnya menatap frame yang sama.

Yang akan saya bawa: default itu tidak netral. Tiap default pada tool serbaguna adalah tebakan atas input yang tak dikenalnya, dan input saya bukan hal asing bagi saya. Pekerjaannya tak pernah ada pada konversinya. Pekerjaannya adalah memutuskan, sekali, apa jawaban yang benar untuk jenis aset yang memang saya buat — lalu menjadikan jawaban itu otomatis, supaya keputusannya tak perlu diingat dengan benar pada saat sebuah halaman sedang menunggunya.

Istilah

ffmpeg
Program command-line gratis untuk mengonversi dan mengolah video, audio, dan gambar. Tool-tool di artikel ini menyerahkan seluruh encoding kepadanya.
WebP
Format gambar untuk halaman web, mendukung kompresi lossy maupun lossless, dan biasanya lebih kecil daripada JPEG atau PNG pada mutu tampilan yang sama.
Palette
Tabel berisi paling banyak 256 warna yang disimpan GIF satu kali; tiap pixel berupa indeks ke dalamnya, bukan nilai warna. Memilih isinya dengan baik adalah soal terpisah dari meng-encode.
Encoding dua tahap
Menganalisis bahannya lebih dulu lalu meng-encode belakangan, supaya keputusan encoder diambil berdasarkan seluruh input dan bukan berdasarkan yang baru sempat ia lihat.
Preset
Seikat penyetelan encoder bernama yang menyasar satu kelas isi, misalnya gambar fotografis lawan grafis bidang datar. Mengubah pertukaran internalnya, bukan sasaran kualitasnya.
Filter resampling
Algoritma yang menentukan nilai pixel saat ukuran gambar berubah. Lanczos menjaga tepi lebih baik ketimbang alternatif yang lebih murah, dengan ongkos komputasi lebih tinggi.
Rasio aspek
Perbandingan antara lebar dan tinggi. Menurunkan satu dimensi dari yang lain menjaganya; menyebut keduanya sendiri-sendiri berisiko membuatnya melar.
r_frame_rate
Frame rate sebagaimana dilaporkan ffprobe, dinyatakan sebagai pecahan eksak seperti 30000/1001 dan bukan desimal yang sudah dibulatkan.

Technologies covered

  • Bash
  • FFmpeg

About the author

Photo of Romi Fadli

Romi Fadli, S.Kom.

Solution Architect · Backend Engineer · Embedded Systems

In my day job I work as a solution architect. I design the system, lead the team that builds it — quality assurance, backend developers, a UI developer, DevOps and DevSecOps — and write the most critical modules myself, such as a certificate authority, a long-term PDF signer, and the core API of a personnel system.

I work across the whole stack that a running system actually needs. On the hardware side that means PCB design, microcontrollers, and embedded firmware — including RISC-V boards running FreeRTOS and Embassy, speaking MQTT over mutually authenticated TLS on a microcontroller with 64 KB of SRAM.

Most of my day-to-day work is software: Rust backends and API modules built on Clean Architecture, an OAuth2/OpenID Connect authorization server written from scratch, PAdES document signing, and certificate authorities — root CAs, timestamping authorities, and OCSP responders. I also build the frontends that sit on top of them.

Running all of that means infrastructure: Docker Compose stacks, networking, Mikrotik and RADIUS, observability with OpenTelemetry, and a steady habit of writing command-line tools and utilities for Linux when the existing ones do not fit.

Share

Enjoyed this?

Get an email when a new article is published.

Related Articles

A stack of Markdown documents and an orange arrow leading to a browser page with a side menu, a heading, paragraphs, a dark code panel, and a table of contents with its active entry highlighted

Satu script yang mengubah dokumentasi Markdown satu project menjadi situs statis yang terbuka dari folder tanpa server maupun internet: menu, daftar isi yang mengikuti pembaca, tabel yang tak pernah terpotong, kode dengan tombol salin, dan tautan yang tetap berfungsi.

7 min read Read more →
An old layout with a grey banner and a new structure with a green banner, each holding a blue database, a purple document store, and an orange telemetry store; three coloured paths pass through one export package marked with a green check

Empat perintah yang memindahkan stack dari layout lama ke struktur baru melintasi versi mayor: export tanpa mengubah data sumber, import tiap store sesuai cara yang diizinkan versinya, verifikasi apa yang benar-benar tiba, dan rename modul sambil memindahkan datanya.

11 min read Read more →
Three image layer stacks, each with a version tag of its own colour, blue, orange, and green, each leading to an archive file banded in the same colour

Perintah yang memberi versi tersendiri pada tiap modul stack, mem-build image-nya di bawah tag yang berarti tepat satu build, menolak memakai ulang versi atau menelan compile yang gagal, dan mengarsipkan image menurut nama dan tag supaya versi tak saling menimpa.

7 min read Read more →