मेरी image-compression policy शुरू में काफी सरल थी: AVIF को उस सबसे कम quality पर encode करना जो अभी भी SSIMULACRA2 target 60 पास करे। बड़े image set में मैं एक representative sample को 58 तक गिरने देता था, जबकि बाकी samples को 60 या उससे ऊपर रहना होता था।
PNG और सामान्य source images के लिए यह rule मुझे ठीक लगा। फिर मुझे ऐसे WebP मिलने लगे जिन्हें मेरे पास आने से पहले higher-quality originals से lossy-compress किया जा चुका था।
higher-quality original: ~2 MB
↓
lossy WebP: ~100 KB
↓
AVIF
क्या इस दूसरी conversion को भी WebP के मुकाबले 60 पर पास होने देना चाहिए? शुरुआत में मुझे लगा, हाँ। 60 तो 60 ही है। लेकिन असली फर्क score में नहीं, reference image में था।
Metric गलत नहीं था; reference बदल गया था
SSIMULACRA2 एक reference image को distorted image से compare करता है और उन्हीं दो inputs के बीच perceptual difference को score करता है। इसे blur, ringing और artificial edges जैसी compression damage पर प्रतिक्रिया देने के लिए बनाया गया है, और इसके published evaluation material में JPEG, WebP, AVIF तथा अन्य codecs की distortions शामिल हैं। SSIMULACRA2](https://github.com/cloudinary/ssimulacra2/blob/main/README.md%22>SSIMULACRA2) documentation metric और उसके approximate quality anchors समझाती है।
जब मैं किसी अच्छे source से सीधे AVIF encode करता हूँ, comparison लगभग source → AVIF होता है। तब 60 का score उसी conversion से जुड़ी degradation बताता है।
लेकिन पहले से lossy WebP के साथ वास्तविक history अलग है:
original
↓ first lossy encode
WebP
↓ second lossy encode
AVIF
SSIMULACRA2 केवल WebP → AVIF देखता है। WebP से पहले मौजूद original के बारे में उसे कुछ पता नहीं होता। WebP में पहले से मौजूद artifacts reference का हिस्सा बन जाते हैं।
इसलिए score 60 मुझे बता सकता है कि AVIF WebP से बहुत दूर नहीं गया। यह नहीं बता सकता कि final AVIF खो चुके master से कितना दूर है।
Lossy transcoding दूसरा quality budget बनाता है
मान लीजिए original में साफ gradient है। पहला encoder थोड़ा banding जोड़ता है, लेकिन WebP अभी भी ठीक दिखता है। फिर मैं उसी WebP को AVIF में encode करता हूँ। SSIMULACRA2 AVIF encoder द्वारा जोड़ी गई अतिरिक्त degradation को penalize कर सकता है, लेकिन reference में पहले से मौजूद damage को नहीं।
यही कारण है कि already-lossy image से encoding करना best available source से direct encoding के बराबर नहीं है। libavif](https://github.com/AOMediaCodec/libavif/discussions/2640%22>libavif) project की discussion भी यही सामान्य बात बताती है: अगर input पहले से compressed है, तो मौजूदा compression artifacts नए AVIF में आगे जा सकते हैं।
इसका अर्थ यह नहीं कि AVIF हर WebP artifact को automatically बढ़ा देता है या transcoding कभी नहीं करनी चाहिए। इसका अर्थ केवल यह है कि second encoder काम तब शुरू करता है जब original quality budget का एक हिस्सा पहले ही खर्च हो चुका है।
आखिर में मैंने जो policy चुनी
- Canonical या high-quality source: target 60, single-sample floor 58.
- Lossless WebP: target 60, floor 58.
- Known lossy derivative: target 65, floor 63.
महत्वपूर्ण अंतर JPEG बनाम WebP नहीं है। असली अंतर canonical source बनाम known lossy derivative है।
WebP lossless भी हो सकता है। WebP](https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification%22>WebP) lossless specification ऐसे mode का वर्णन करती है जो pixel values को exact reconstruct करता है, इसलिए compensate करने के लिए कोई previous lossy generation नहीं होती। दूसरी ओर, अगर मुझे पता है कि कोई JPEG पहले ही कई lossy transformations से गुजर चुका है, तो उसे भी previously compressed WebP जितनी सावधानी चाहिए।
65 क्यों?
SSIMULACRA2 में ऐसा कोई rule नहीं है कि दूसरी lossy generation के लिए ठीक पाँच points बढ़ाना चाहिए। मुझे ऐसा कोई rule नहीं मिला क्योंकि वह मौजूद नहीं है। 65 एक engineering policy है, metric की property नहीं।
Published quality anchors useful context देते हैं। मोटे तौर पर 50 medium या fair quality के आसपास है, जबकि 70 high या good quality के आसपास। इसका मतलब 60 visually lossless zone में नहीं, बल्कि काफी aggressive web-compression range में है।
अच्छे source से direct conversion में smaller files के बदले मैं यह perceptual budget स्वीकार करता हूँ। दूसरी lossy generation में मैं additional distortion के लिए छोटा budget चाहता था।
मैंने 70 पर भी विचार किया, लेकिन इससे सभी transcoded images काफी stricter quality region में चले जाते। बहुत सारी images वाले pages पर, खासकर mobile connection में, extra bytes मायने रखते हैं। मेरे पास यह साबित करने वाला evidence नहीं था कि हर already-compressed image को 70 तक ले जाना cost justify करेगा। इसलिए conservative middle ground के रूप में 65 चुना।
65/62 की जगह 65/63 क्यों?
मेरी original policy 60/58 थी: एक representative outlier main target से दो points नीचे जा सकता था। Main target को 65 करने पर उसी policy को बनाए रखना स्वाभाविक रूप से 65/63 देता है।
60 - 58 = 2
65 - 63 = 2
62 इस्तेमाल करने पर exception तीन points का हो जाता। Normal samples stricter होते, जबकि सबसे खराब sample को अधिक छूट मिलती। Already lossy-compressed inputs के लिए इस exception को बड़ा करने का technical reason मुझे नहीं मिला।
63 और 65 में से कोई magic number नहीं है। महत्वपूर्ण बात policy की internal consistency है।
2 MB से 100 KB होना visual quality साबित नहीं करता
मैं compression ratio से SSIMULACRA2 threshold निकालने से जानबूझकर बचता हूँ। 2 MB से 100 KB होना dramatic लगता है, लेकिन file size अकेले perceptual degradation के बारे में बहुत कम बताता है।
Resolution, image entropy, noise, flat areas, line art, chroma subsampling और previous format सभी compression efficiency को प्रभावित करते हैं। Google](https://developers.google.com/speed/webp/docs/webp_study%22>Google) WebP compression study codecs की तुलना approximately matched quality पर करती है, न कि इस assumption पर कि equal file size का अर्थ equal visual quality है।
इसलिए मैं 20× smaller → target 65 जैसे rules नहीं बनाता। मेरी policy के लिए यह महत्वपूर्ण है कि current file known lossy derivative है या नहीं, न कि उसका size reduction कितना प्रभावशाली दिखता है।
Original हो तो WebP को transcode नहीं करता
अगर high-quality original और छोटा lossy WebP दोनों मौजूद हैं, तो मैं original से सीधे AVIF बनाता हूँ और normal 60/58 policy उपयोग करता हूँ।
preferred:
original → AVIF
avoid when possible:
original → lossy WebP → AVIF
Second-generation target को stricter करने से first encode में खोई जानकारी वापस नहीं आती। 65 केवल AVIF को WebP के अधिक पास रखता है; 70 और पास रखेगा। दोनों में से कोई lost original वापस नहीं बनाता।
62 बनाम 63 से अधिक महत्वपूर्ण implementation bug था
Policy review करते समय मुझे encoder logic में अधिक खतरनाक समस्या मिली। Code में format-specific target constants और WebP के लिए अलग target लौटाने वाला helper पहले से था। इसलिए WebP को 60 से 65 करना trivial लग रहा था।
लेकिन adaptive quality decision अभी भी global target और global worst-score threshold इस्तेमाल कर रहा था। Format-specific target बाद में individual result को pass या below-target label करने में काम आता था, लेकिन final AVIF quality चुनने वाले decision को जरूरी नहीं कि वही नियंत्रित करता हो।
इससे subtle failure संभव है: WebP sample को सही तरीके से उसके intended target 65 से नीचे बताया जा सकता है, जबकि adaptive search उसी quality को स्वीकार कर ले क्योंकि global pass condition अभी भी 60 है।
intended WebP target: 65
actual score: 61.2
format-aware label: below target
global search rule: pass if target is still 60
ऐसा threshold बेकार है जो encoded output चुनने वाले वास्तविक decision में भाग ही न ले।
Threshold को sample policy का हिस्सा बनाना ज्यादा सुरक्षित है
अब मैं thresholds को decorative format constants की जगह source properties के रूप में देखना पसंद करता हूँ। Simplified pseudocode:
if sample is a known lossy derivative:
target = 65
floor = 63
else:
target = 60
floor = 58
reject if any sample is below its floor
allow at most one sample below its target
महत्वपूर्ण बात यह है कि result को describe करने वाले thresholds ही acceptance decision को भी नियंत्रित करें।
Sampling policy भी मायने रखती है
हर candidate AVIF quality पर हर image को test करना जरूरी नहीं। Pipeline bytes-per-pixel distribution से अधिकतम दस representative JPEG, PNG या WebP samples चुनता है।
दस या उससे कम images वाले collection में हर sample को normal target पूरा करना होता है। बड़े collection में एक sample lower floor इस्तेमाल कर सकता है, लेकिन बाकी samples को main target pass करना ही होता है।
Sampling search को practical बनाती है, लेकिन इसी वजह से outlier rule को जरूरत से ज्यादा loose करना सही नहीं। चुने गए samples representative हैं, यह proof नहीं कि हर unsampled image उसी तरह behave करेगी।
वह experiment जो heuristic की जगह ले सकता है
सबसे मजबूत उत्तर पाने के लिए representative corpus के true originals बचाकर complete chains test करनी होंगी:
A: original → AVIF, target 60
B: original → lossy WebP → AVIF, target 60
C: original → lossy WebP → AVIF, target 63
D: original → lossy WebP → AVIF, target 65
E: original → lossy WebP → AVIF, target 70
हर variant के लिए final byte size, true original के against SSIMULACRA2, WebP intermediate के against SSIMULACRA2 और selected encoder quality record करता। Difficult images को manually inspect करना भी जरूरी होता।
मैंने sufficiently representative preserved-original set पर यह controlled experiment नहीं किया है, इसलिए मैं यह दावा नहीं कर सकता कि 65 globally optimal है। यह limitation महत्वपूर्ण है।
AVIF अपने-आप another encode justify नहीं करता
अगर केवल 100 KB WebP बचा है और 65/63 pass करने वाला AVIF 96 KB है, तो मैं conversion पर सवाल उठाऊँगा। सिर्फ 4 KB बचाने के लिए another lossy generation और additional processing complexity शायद उचित न हो।
लेकिन वही 100 KB WebP quality policy pass करते हुए 65 KB AVIF बन जाए, तो image-heavy pages पर trade-off काफी आकर्षक हो जाता है।
Codec conversion को दो अलग questions का उत्तर देना चाहिए: additional distortion acceptable है या नहीं, और size reduction वास्तव में पर्याप्त है या नहीं। पहला pass होना दूसरे को automatically साबित नहीं करता।
अब मैं जो rule इस्तेमाल करता हूँ
Best-quality original हो तो सीधे उसी से encode करता हूँ और इस web workload के लिए 60/58 रखता हूँ। WebP lossless हो तो भी 60/58। केवल remaining file known lossy derivative हो तो stricter second-generation budget, फिलहाल 65/63, लागू करता हूँ। AVIF अगर size बहुत कम नहीं करता तो existing WebP रखना भी उचित हो सकता है।
गहरी सीख यह नहीं कि WebP को कोई खास SSIMULACRA2 number चाहिए। Full-reference quality metric केवल उसी प्रश्न का उत्तर देता है जिसे उसकी reference image प्रस्तुत करती है।
अगर reference पहले ही information खो चुका है, तो high score का अर्थ “इस reference के करीब” है, “उस image के करीब जो इससे पहले मौजूद थी” नहीं। Image provenance को compression policy का हिस्सा मानने के बाद thresholds arbitrary codec settings नहीं लगे; वे अलग-अलग generations of loss के budgets बन गए।