Volver al blog
20 de agosto de 2026Sergei Solod10 min de lectura

SSIMULACRA2 al convertir WebP a AVIF: por qué uso 60 para fuentes y 65 para derivados con pérdida

Cuando genero AVIF a partir de un WebP que ya fue comprimido con pérdida, SSIMULACRA2 solo mide la segunda generación de degradación. Por eso uso 60/58 para fuentes limpias y 65/63 para derivados con pérdida conocidos.

AVIFWebPSSIMULACRA2Compresión de imágenesRendimiento web

Mi regla de compresión parecía muy sencilla: generar AVIF con la calidad más baja que todavía superara un objetivo SSIMULACRA2 de 60. En colecciones grandes permitía que una sola muestra representativa bajara hasta 58, mientras que el resto debía mantenerse en 60 o más.

Con PNG y fuentes normales esa regla me parecía adecuada. El problema apareció cuando empecé a recibir archivos WebP que ya habían sido comprimidos con pérdida desde originales de mayor calidad.

original de mayor calidad: ~2 MB
          ↓
      WebP con pérdida: ~100 KB
          ↓
          AVIF

¿Debía permitirse que esa segunda conversión siguiera pasando con 60 frente al WebP? Al principio pensé que sí. Un 60 sigue siendo 60. Lo que había cambiado, sin embargo, era la referencia.

La métrica no estaba equivocada. La referencia había cambiado.

SSIMULACRA2 compara una imagen de referencia con una imagen distorsionada y puntúa la diferencia perceptual entre esas dos entradas concretas. Está diseñada para reaccionar ante degradaciones de compresión como desenfoque, ringing y bordes introducidos artificialmente, y el material de evaluación publicado incluye distorsiones de JPEG, WebP, AVIF y otros códecs. La documentación](https://github.com/cloudinary/ssimulacra2/blob/main/README.md%22>documentación) de SSIMULACRA2 explica la métrica y sus referencias aproximadas de calidad.

Si genero AVIF directamente desde una buena fuente, la comparación es esencialmente source → AVIF. Un valor de 60 describe el daño introducido por esa conversión.

Con un WebP que ya es lossy, el historial real es distinto:

original
   ↓ primera codificación con pérdida
WebP
   ↓ segunda codificación con pérdida
AVIF

Pero SSIMULACRA2 solo ve WebP → AVIF. No sabe nada del original que existía antes del WebP. Los artefactos ya presentes en el WebP pasan a formar parte de la referencia.

Por tanto, un 60 puede decirme que el AVIF no se ha alejado demasiado del WebP. No puede decirme cuánto se ha alejado el AVIF final del máster perdido.

El transcoding con pérdida crea un segundo presupuesto de calidad

Supongamos que el original contiene un degradado limpio. El primer codificador introduce algo de banding, pero el WebP sigue viéndose aceptable. Después convierto ese WebP a AVIF. SSIMULACRA2 puede penalizar la degradación adicional introducida por AVIF, pero no puede penalizar el daño que ya forma parte de la referencia.

Por eso codificar desde una imagen que ya ha pasado por pérdida no equivale a codificar directamente desde la mejor fuente disponible. Una discusión del proyecto](https://github.com/AOMediaCodec/libavif/discussions/2640%22>proyecto) libavif expone la misma idea general: los artefactos de compresión existentes pueden trasladarse al nuevo AVIF cuando la entrada ya está comprimida.

Eso no significa que AVIF amplifique automáticamente todos los artefactos de WebP ni que nunca deba hacerse transcoding. Significa que el segundo codificador empieza a trabajar después de que ya se haya gastado una parte del presupuesto de calidad original.

La política que terminé usando

  • Fuente canónica o de alta calidad: objetivo 60, suelo 58 para una única muestra.
  • WebP lossless: objetivo 60, suelo 58.
  • Derivado conocido con pérdida: objetivo 65, suelo 63.

La distinción importante no es JPEG frente a WebP. Es fuente canónica frente a derivado conocido con pérdida.

WebP también puede ser lossless. La especificación](https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification%22>especificación) de WebP lossless describe un modo que reconstruye los valores de los píxeles exactamente, por lo que no existe una generación previa de pérdida que compensar. Del mismo modo, un JPEG que sé que ya ha pasado por varias transformaciones con pérdida merece la misma cautela que un WebP previamente comprimido.

¿Por qué 65?

No existe una regla de SSIMULACRA2 que diga que una segunda generación con pérdida necesita exactamente cinco puntos adicionales. No encontré esa regla porque no existe. El 65 es una política de ingeniería, no una propiedad de la métrica.

Las referencias de calidad publicadas ayudan a situarlo. Aproximadamente, 50 corresponde a calidad media o aceptable y 70 a calidad alta o buena. Eso coloca 60 en una zona de compresión web bastante agresiva, no en la zona visualmente lossless.

En una conversión directa desde una buena fuente, acepto gastar ese presupuesto perceptual a cambio de archivos más pequeños. Para una segunda generación con pérdida quería permitir menos distorsión adicional.

Consideré 70, pero eso llevaría todos los archivos transcodificados a una región de calidad considerablemente más estricta. En páginas que cargan muchas imágenes, especialmente en conexiones móviles, los bytes adicionales importan. No tenía evidencia de que obligar a todas las imágenes ya comprimidas a llegar a 70 justificara ese coste. Por eso elegí 65 como punto intermedio conservador.

¿Por qué 65/63 y no 65/62?

Mi política original era 60/58: una muestra representativa podía quedar dos puntos por debajo del objetivo principal. Al subir el objetivo a 65, conservar la misma política conduce naturalmente a 65/63.

60 - 58 = 2
65 - 63 = 2

Usar 62 crearía una excepción de tres puntos. Las muestras normales serían más estrictas, mientras que la peor muestra recibiría más margen. No encontré una razón técnica para ampliar precisamente esa excepción en entradas que ya habían sufrido compresión con pérdida.

Ni 63 ni 65 son números mágicos. Lo importante es mantener la política internamente coherente.

Que un archivo pase de 2 MB a 100 KB no revela su calidad visual

No deduzco los umbrales de SSIMULACRA2 a partir de la relación de compresión. Pasar de 2 MB a 100 KB parece espectacular, pero el tamaño por sí solo dice sorprendentemente poco sobre la degradación perceptual.

La resolución, la entropía de la imagen, el ruido, las zonas uniformes, el line art, el chroma subsampling y el formato anterior cambian mucho la eficiencia de compresión. El estudio](https://developers.google.com/speed/webp/docs/webp_study%22>estudio) de compresión WebP de Google compara códecs con calidades aproximadamente equivalentes, en vez de asumir que tamaños iguales implican calidad visual igual.

Por eso no uso reglas como 20× más pequeño → objetivo 65. Lo relevante para mi política es saber si el archivo actual es un derivado con pérdida, no lo impresionante que parezca su reducción de tamaño.

Si todavía tengo el original, no transcodifico el WebP

Si conservo tanto el original de alta calidad como el pequeño WebP con pérdida, genero AVIF directamente desde el original y uso la política normal 60/58.

preferido:
original → AVIF

evitar cuando sea posible:
original → WebP con pérdida → AVIF

Un objetivo más estricto en la segunda generación no puede recuperar información perdida en la primera. 65 solo obliga al AVIF a permanecer más cerca del WebP. 70 lo mantendría todavía más cerca. Ninguno reconstruye el original perdido.

El error de implementación importaba más que 62 frente a 63

Mientras revisaba la política encontré un problema más peligroso en la lógica del codificador. El código ya tenía objetivos específicos por formato y una función capaz de devolver un objetivo distinto para WebP, de modo que cambiar WebP de 60 a 65 parecía trivial.

No lo era. La decisión adaptativa de calidad seguía usando el objetivo global y el umbral global para el peor resultado. El objetivo específico del formato se utilizaba después para etiquetar cada muestra como válida o por debajo del objetivo, pero no necesariamente controlaba la decisión que seleccionaba la calidad AVIF final.

Eso genera un fallo sutil: una muestra WebP puede estar correctamente marcada como inferior a su objetivo de 65 y, aun así, la búsqueda adaptativa aceptar la calidad porque la condición global de aprobación sigue siendo 60.

intended WebP target: 65
actual score:         61.2

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

Un umbral carece de valor si no participa en la decisión que elige el archivo codificado.

Es más seguro hacer que los umbrales formen parte de la política de cada muestra

Ahora prefiero tratar los umbrales como propiedades de la fuente y no como constantes decorativas por formato. En pseudocódigo simplificado:

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

La propiedad importante es que los mismos límites usados para describir el resultado también controlen si se acepta.

La política de muestreo también importa

No necesito probar todas las imágenes con cada calidad candidata de AVIF. El pipeline selecciona hasta diez muestras representativas JPEG, PNG o WebP a lo largo de la distribución de bytes por píxel.

En colecciones de diez imágenes o menos, todas las muestras deben alcanzar el objetivo normal. En colecciones mayores, una muestra puede usar el suelo inferior, mientras que las demás deben cumplir el objetivo principal.

El muestreo hace viable la búsqueda, pero también es un motivo para no hacer demasiado permisiva la regla del outlier. Las muestras seleccionadas son representativas; no prueban que todas las imágenes no muestreadas se comporten de forma idéntica.

El experimento que podría sustituir esta heurística

La respuesta más sólida exigiría conservar los originales reales de un corpus representativo y probar cadenas completas:

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

Para cada variante registraría el tamaño final, SSIMULACRA2 frente al original real, SSIMULACRA2 frente al WebP intermedio y la calidad elegida por el codificador. También inspeccionaría manualmente las imágenes difíciles.

No he ejecutado ese experimento controlado sobre un conjunto suficientemente representativo de originales conservados, así que no puedo afirmar que 65 sea óptimo de forma universal. Esa limitación importa.

AVIF no justifica automáticamente otra codificación

Si la única fuente disponible es un WebP de 100 KB y el AVIF que supera 65/63 pesa 96 KB, cuestionaría la conversión. Ahorrar 4 KB quizá no compense otra generación con pérdida y más complejidad de procesamiento.

Si ese mismo WebP de 100 KB se convierte en un AVIF de 65 KB sin dejar de cumplir la política de calidad, el intercambio resulta mucho más interesante en páginas con muchas imágenes.

Una conversión de códec debe responder dos preguntas distintas: ¿es aceptable la distorsión adicional? y ¿la reducción de tamaño es lo bastante grande como para importar? Superar la primera no garantiza la segunda.

La regla que uso ahora

Si tengo el original de mejor calidad, codifico directamente desde él y uso 60/58 para este tipo de carga web. Si el WebP es lossless, también uso 60/58. Si el único archivo disponible es un derivado conocido con pérdida, aplico un presupuesto más estricto para la segunda generación, actualmente 65/63. Si AVIF apenas reduce el tamaño, considero conservar el WebP existente.

La lección profunda no es que WebP necesite un número especial de SSIMULACRA2. Una métrica full-reference solo responde a la pregunta representada por su imagen de referencia.

Si la referencia ya ha perdido información, una puntuación alta significa «cerca de esta referencia», no «cerca de la imagen que existía antes». Cuando empecé a tratar la procedencia de la imagen como parte de la política de compresión, los umbrales dejaron de parecer ajustes arbitrarios del códec y pasaron a ser presupuestos para distintas generaciones de pérdida.