Quay lại blog
20 tháng 8, 2026Sergei Solod10 phút đọc

SSIMULACRA2 khi chuyển WebP sang AVIF: Vì sao tôi dùng 60 cho nguồn gốc và 65 cho bản dẫn xuất đã nén mất dữ liệu

Khi AVIF được tạo từ WebP đã nén lossy, SSIMULACRA2 chỉ đo thế hệ suy giảm thứ hai. Vì vậy tôi dùng 60/58 cho nguồn sạch và 65/63 cho các bản lossy derivative đã biết.

AVIFWebPSSIMULACRA2Nén hình ảnhHiệu năng web

Quy tắc nén ban đầu của tôi khá đơn giản: encode AVIF ở quality thấp nhất vẫn vượt target SSIMULACRA2 60. Với tập ảnh lớn, tôi cho phép một representative sample xuống tới 58, còn tất cả sample khác phải đạt ít nhất 60.

Với PNG và source image thông thường, quy tắc này ổn. Sau đó tôi bắt đầu nhận những file WebP đã được nén lossy từ original chất lượng cao hơn trước khi đến tay tôi.

original chất lượng cao hơn: ~2 MB
          ↓
      WebP lossy: ~100 KB
          ↓
          AVIF

Liệu lần chuyển đổi thứ hai vẫn nên được phép pass ở 60 so với WebP? Ban đầu tôi nghĩ là có. 60 vẫn là 60. Nhưng thứ thực sự thay đổi là reference image.

Metric không sai. Reference đã thay đổi.

SSIMULACRA2 so sánh một reference image với distorted image và chấm điểm perceptual difference giữa đúng hai input đó. Nó được thiết kế để phản ứng với hư hại do compression như blur, ringing và edge được tạo thêm; tài liệu đánh giá công khai cũng bao gồm distortion từ JPEG, WebP, AVIF và các codec khác. Tài](https://github.com/cloudinary/ssimulacra2/blob/main/README.md%22>Tài) liệu SSIMULACRA2 giải thích metric và các quality anchor xấp xỉ.

Nếu tôi encode AVIF trực tiếp từ source tốt, phép so sánh về cơ bản là source → AVIF. Score 60 khi đó mô tả degradation do chính lần chuyển đổi đó gây ra.

Với WebP đã lossy, lịch sử thực tế khác:

original
   ↓ first lossy encode
WebP
   ↓ second lossy encode
AVIF

Nhưng SSIMULACRA2 chỉ thấy WebP → AVIF. Nó không biết original từng tồn tại trước WebP. Các artifact đã có trong WebP trở thành một phần của reference.

Vì vậy score 60 có thể cho tôi biết AVIF không đi quá xa khỏi WebP hiện tại. Nó không cho biết final AVIF cách master đã mất bao xa.

Lossy transcoding tạo ra quality budget thứ hai

Giả sử original có gradient sạch. Encoder đầu tiên thêm một ít banding nhưng WebP vẫn trông chấp nhận được. Sau đó tôi encode WebP đó sang AVIF. SSIMULACRA2 có thể phạt degradation bổ sung do AVIF encoder tạo ra, nhưng không thể phạt damage đã tồn tại sẵn trong reference.

Đó là lý do encode từ ảnh đã lossy không tương đương với encode trực tiếp từ source tốt nhất. Một thảo luận trong dự](https://github.com/AOMediaCodec/libavif/discussions/2640%22>dự) án libavif nêu cùng nguyên tắc: compression artifact đã tồn tại có thể được mang sang AVIF mới khi input đã được nén trước đó.

Điều này không có nghĩa AVIF tự động làm mọi artifact của WebP tệ hơn, cũng không có nghĩa không bao giờ nên transcode. Nó chỉ có nghĩa encoder thứ hai bắt đầu làm việc sau khi một phần quality budget của original đã bị tiêu hao.

Policy cuối cùng tôi sử dụng

  • Canonical hoặc high-quality source: target 60, floor 58 cho một sample.
  • Lossless WebP: target 60, floor 58.
  • Known lossy derivative: target 65, floor 63.

Điểm phân biệt quan trọng không phải JPEG với WebP, mà là canonical source với known lossy derivative.

WebP có thể là lossless. Đặc](https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification%22>Đặc) tả WebP lossless mô tả mode phục hồi chính xác giá trị pixel, nên không có thế hệ lossy trước đó cần bù lại. Ngược lại, một JPEG mà tôi biết đã trải qua nhiều lossy transformation đáng được xử lý thận trọng như WebP đã từng bị nén.

Vì sao là 65?

Không có rule nào của SSIMULACRA2 nói rằng thế hệ lossy thứ hai cần chính xác thêm năm điểm. Tôi không tìm thấy rule đó vì nó không tồn tại. 65 là engineering policy, không phải thuộc tính của metric.

Các quality anchor công khai cho một số context. Xấp xỉ, 50 tương ứng với medium hoặc fair quality, còn 70 tương ứng với high hoặc good quality. Vì thế 60 vẫn nằm trong vùng web compression khá aggressive, chứ không phải visually lossless.

Với chuyển đổi trực tiếp từ source tốt, tôi chấp nhận dùng perceptual budget đó để đổi lấy file nhỏ hơn. Với thế hệ lossy thứ hai, tôi muốn budget cho distortion bổ sung nhỏ hơn.

Tôi đã cân nhắc 70, nhưng như vậy mọi ảnh transcoded sẽ bị đẩy lên vùng quality nghiêm ngặt hơn đáng kể. Trên các trang tải nhiều ảnh, đặc biệt qua mobile connection, byte bổ sung có ý nghĩa. Tôi không có evidence rằng ép mọi ảnh đã được nén lên 70 xứng đáng với chi phí. Vì vậy tôi chọn 65 làm điểm trung gian tương đối bảo thủ.

Vì sao 65/63 chứ không phải 65/62?

Policy cũ của tôi là 60/58: một representative outlier có thể thấp hơn main target hai điểm. Khi tăng target lên 65 mà giữ nguyên policy, kết quả tự nhiên là 65/63.

60 - 58 = 2
65 - 63 = 2

Dùng 62 sẽ tạo ngoại lệ ba điểm. Các sample bình thường nghiêm ngặt hơn, trong khi sample tệ nhất lại được nới rộng hơn. Tôi không tìm thấy lý do kỹ thuật để tăng ngoại lệ riêng cho input đã trải qua lossy compression.

Cả 63 lẫn 65 đều không phải magic number. Điều hữu ích là policy giữ được tính nhất quán nội bộ.

Từ 2 MB xuống 100 KB không cho biết visual quality

Tôi cố ý không suy ra SSIMULACRA2 threshold từ compression ratio. Giảm từ 2 MB xuống 100 KB nghe rất mạnh, nhưng file size đơn lẻ cho biết rất ít về perceptual degradation.

Resolution, image entropy, noise, vùng màu phẳng, line art, chroma subsampling và format trước đó đều ảnh hưởng mạnh đến compression efficiency. Nghiên](https://developers.google.com/speed/webp/docs/webp_study%22>Nghiên) cứu WebP compression của Google so sánh codec ở quality gần tương đương, thay vì giả định file size bằng nhau nghĩa là visual quality bằng nhau.

Do đó tôi không dùng rule như nhỏ hơn 20× → target 65. Với policy của tôi, điều quan trọng là file hiện tại có phải known lossy derivative hay không, chứ không phải tỷ lệ giảm size trông ấn tượng đến mức nào.

Nếu còn original, tôi không transcode WebP

Nếu cả high-quality original và WebP lossy nhỏ vẫn tồn tại, tôi encode AVIF trực tiếp từ original và dùng policy bình thường 60/58.

preferred:
original → AVIF

avoid when possible:
original → lossy WebP → AVIF

Target nghiêm hơn ở thế hệ thứ hai không thể phục hồi thông tin đã mất ở encode đầu tiên. 65 chỉ giữ AVIF gần WebP hơn; 70 sẽ giữ gần hơn nữa. Không giá trị nào tái tạo được original đã mất.

Implementation bug quan trọng hơn tranh luận 62 với 63

Trong lúc xem lại policy, tôi phát hiện vấn đề nguy hiểm hơn trong encoder logic. Code đã có format-specific target constants và helper có thể trả target khác cho WebP, nên đổi WebP từ 60 thành 65 trông rất đơn giản.

Nhưng không phải vậy. Adaptive quality decision vẫn sử dụng global target và global worst-score threshold. Format-specific target chỉ được dùng sau đó để label từng result là pass hoặc below-target, nhưng không nhất thiết điều khiển quyết định chọn final AVIF quality.

Điều này tạo ra failure tinh vi: WebP sample có thể được đánh dấu đúng là dưới target 65, trong khi adaptive search vẫn accept quality đó vì global pass condition còn là 60.

intended WebP target: 65
actual score:         61.2

format-aware label:  below target
global search rule:  pass if target is still 60

Một threshold không có ý nghĩa nếu nó không tham gia vào quyết định chọn encoded output thực tế.

An toàn hơn là đưa threshold vào sample policy

Giờ tôi thích coi threshold là property của source thay vì format constant mang tính hình thức. Pseudocode đơn giản:

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

Điểm quan trọng là cùng threshold dùng để mô tả result cũng phải điều khiển việc result đó có được accept hay không.

Sampling policy cũng quan trọng

Tôi không cần test mọi ảnh ở mọi candidate AVIF quality. Pipeline chọn tối đa mười representative JPEG, PNG hoặc WebP sample trên phân bố bytes-per-pixel.

Với collection có mười ảnh trở xuống, mọi sample phải đạt normal target. Với collection lớn hơn, một sample được dùng lower floor, nhưng các sample còn lại vẫn phải đạt main target.

Sampling giúp search khả thi, nhưng cũng là lý do không nên làm outlier rule quá lỏng. Các sample được chọn có tính đại diện, không phải bằng chứng rằng mọi ảnh không được sample đều cư xử giống nhau.

Experiment có thể thay thế heuristic

Câu trả lời mạnh nhất là giữ true original cho một corpus đại diện rồi test full chain:

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

Với mỗi variant, tôi sẽ ghi final byte size, SSIMULACRA2 so với true original, SSIMULACRA2 so với WebP intermediate và encoder quality được chọn. Những ảnh khó cũng cần được kiểm tra thủ công.

Tôi chưa chạy controlled experiment này trên một tập preserved originals đủ đại diện, vì thế không thể khẳng định 65 là global optimum. Hạn chế này rất quan trọng.

AVIF không tự động xứng đáng với thêm một lần encode

Nếu source duy nhất còn lại là WebP 100 KB và AVIF vượt 65/63 có kích thước 96 KB, tôi sẽ đặt câu hỏi về conversion. Tiết kiệm 4 KB có thể không đáng cho thêm một lossy generation và processing complexity.

Nếu cùng WebP 100 KB đó thành AVIF 65 KB mà vẫn đạt quality policy, trade-off trở nên hấp dẫn hơn nhiều trên các trang có nhiều hình ảnh.

Codec conversion phải trả lời hai câu hỏi riêng: additional distortion có chấp nhận được không, và size reduction có đủ lớn để đáng kể không? Vượt câu hỏi đầu tiên không tự động đáp ứng câu hỏi thứ hai.

Rule tôi dùng hiện nay

Nếu có original tốt nhất, tôi encode trực tiếp từ đó và dùng 60/58 cho web workload này. Nếu WebP là lossless, cũng dùng 60/58. Nếu file duy nhất còn lại là known lossy derivative, tôi áp dụng second-generation budget nghiêm ngặt hơn, hiện là 65/63. Nếu AVIF gần như không giảm size, tôi cân nhắc giữ WebP hiện tại.

Bài học sâu hơn không phải WebP cần một con số SSIMULACRA2 đặc biệt. Full-reference quality metric chỉ trả lời câu hỏi mà reference image của nó đại diện.

Nếu reference đã mất thông tin, high score có nghĩa “gần với reference này”, không phải “gần với image từng tồn tại trước đó”. Khi tôi bắt đầu xem image provenance là một phần của compression policy, threshold không còn giống các codec setting tùy ý; chúng trở thành budget cho những generation of loss khác nhau.