¿Subir el framesize de Opus de 20 a 60 ms al recodificar audio de alta calidad?

Opus es la nueva generación de algoritmos de codificación de audio. En un único estándar (RFC 6716) se combinan algoritmos que permiten cubrir todo el espectro de audio moderno: desde voz monofónica de baja calidad y muy bajo bitrate hasta sonido multicanal de calidad transparente.

Otra ventaja de Opus respecto a sistemas como Vorbis es que se trata de un verdadero estándar abierto mundial con el soporte de la industria y desplegado, por ejemplo, en los navegadores web modernos que soportan WebRTC (se trata de un algoritmo exigido para todas las implementaciones WebRTC). Si a esto sumamos que su calidad es superior a la de la competencia y que su empleo (también para los creadores de software) es gratuito, la decisión está tomada.

Empecé a recodificar el audio de mis películas en Opus a partir del 10 de abril de 2015.

La conversión de un fichero WAV a Opus es bien sencilla, siempre que tengamos el software instalado:

$ opusenc fuente.wav destino.opus

Opus se configura automáticamente en función del audio de entrada (de hecho esta configuración puede variar frame a frame, lo que es impresionante). Para música normal y corriente, Opus se configura solo de esta forma:

 Input: 44.1kHz 2 channels
Output: 2 channels (2 coupled)
        20ms packets, 96kbit/sec VBR

La señal es estéreo y la frecuencia de muestreo es 44.1 Khz, algo típico para audio de un Compact Disc.

La decisión de usar 96 Kbps la toma Opus por su cuenta. En cuanto al tamaño de trama, Opus permite tamaños entre 2.5 ms y 60 ms, pero su impacto en la calidad y el bitrate final no está bien documentado. Por defecto siempre utiliza 20 ms.

Intuitivamente parecería que emplear tramas de 60 ms debería reducir la sobrecarga del contenedor (porque hay menos tramas más grandes) y, dado que cada trama se comprime de forma independiente, es intuitivo pensar que ofrecer al compresor tramas más grandes le proporciona más oportunidades para mejorar la compresión.

Pero en la práctica no es así:

  Tamaño de trama
Tipo de Sonido 60 ms 40 ms 10 ms 5 ms 2.5 ms
Canción estéreo 1, 44.1 Khz 100.15% 100.00% 98.32% 101.74% 109.52%
Canción estéreo 2, 44.1 Khz 100.15% 99.99% 98.74% 103.16% 109.15%
Canción estéreo 3, 44.1 Khz 100.15% 99.99% 99.96% 101.51% 109.67%
Canción estéreo 4, 44.1 Khz 100.15% 99.99% 99.66% 100.82% 109.19%
 
Sonido película 1, 48 Khz 100.15% 99.99% 98.33% 106.95% 119.99%
Sonido película 2, 48 Khz 100.16% 99.99% 100.21% 108.08% 117.26%
Sonido película 3, 160 Kbps 100.11% 99.98% 102.50% 119.51% 142.19%

Estas pruebas han sido realizadas con la versión 1.1 de la biblioteca Opus de referencia oficial. La referencia de tamaño (100%) es la codificación de la fuente con un tamaño de trama de 20 ms, el valor por defecto. El tamaño de trama se modifica con el parámetro --framerate.

En todos los casos Opus analiza el sonido de entrada, lo reconoce como una fuente estéreo de alta calidad y decide emplear un bitrate de 96 Kbps. En el caso de la película con audio MP3 de 160 Kbps, Opus decide usar un objetivo de 96 Kbps también, pero al final ve que la calidad es mediocre y le basta con utilizar 74 Kbps [1].

[1]

Es interesante señalar que en todos los casos la fuente de entrada que le doy a Opus son ficheros WAV con parámetros idénticos. Esta versión MP3 a 160 Kbps se ha traducido primero a WAV. Lo que Opus ve es un fichero de entrada con sonido estéreo a 48 Khz y a eso le corresponde automáticamente un bitrate objetivo de 96 Kbps.

Opus, no obstante, es un algoritmo VBR en el que el bitrate objetivo es orientativo. Si ve que se queda corto de calidad, subirá el bitrate automáticamente. De hecho en un fichero codificado a 96 Kbps no es raro tener tramas ocasionales a más de 195 Kbps, más del doble [2]. Pero este proceso funciona en los dos sentidos y, si ve que 96 Kbps son excesivos para la calidad de sonido que realmente está viendo, reducirá el bitrate automáticamente. Todo esto trama a trama. Incluso se puede modificar trama a trama el número de canales de sonido, se puede pasar de mono a estéreo 50 veces por segundo en la misma transmisión.

¿He dicho ya que Opus es impresionante? :-)

[2] Ese mismo fichero a 96 Kbps de media y con picos de 195 Kbps tiene tramas codificadas a... 1.2 Kbps. Es decir, tres bytes por trama. Todo en el mismo fichero. Opus utiliza solo lo que necesita y lo que necesita lo decide trama a trama.

Si exceptuamos las tramas de 2.5 ms, todas las demás juegan en la misma liga en cuanto a la longitud del fichero generado. La diferencia de tamaño es, en general, despreciable. Por tanto, no parece que valga la pena cambiar mis scripts de recodificación de sonido para modificar el tamaño de trama.

A nivel de calidad percibo deficiencias en la versión de 2.5 ms. El aumento de tamaño y la pérdida de calidad descarta las versiones de 2.5 ms y 5 ms.

Conclusión final: para sonido estéreo de alta calidad (sonido con una tasa de muestreo de 44.1 Khz o superior y un ancho de banda de 16 Khz o más), el uso de tamaños de trama mayores que los 20 ms usados por defecto no es efectivo para reducir el bitrate final.

¿Por qué se permiten diferentes tamaños de trama para este tipo de sonidos? Cuando estamos enviando las tramas por Internet, perder una trama grande supone perder mucha información, pero, al mismo tiempo, si la sobrecarga por trama es constante (por ejemplo, cada trama se envía en un datagrama separado), mandar menos tramas ahorra tráfico. Opus permite modificar la mayoría de sus parámetros trama a trama, así que esta flexibilidad permite que la implementación modifique el tamaño de trama y el bitrate instantáneo en función del ancho de banda disponible y de la tasa de pérdida de paquetes en la red. Esta característica es impresionante.

Se explica algo al respecto en el hilo [opus] recommended opus bitrate / opusenc setting for general? de la lista de correo de Opus. En concreto, podéis leer mi respuesta.

La cosa cambia para fuentes de sonido de menor calidad, pero es tema de otro artículo.