FFmpeg no conserva los colores después de cambiar el tamaño

Me gustaría cambiar el tamaño de un video mkv de 4K a 1920 × 1080 con ffmpeg version 3.4.6-0ubuntu0.18.04.1Ubuntu 18.04. El archivo original tiene las siguientes características:

Input #0, matroska,webm
encoder         : libebml v1.3.9 + libmatroska v1.5.2
Stream #0:0(eng): Video: hevc (Main 10), yuv420p10le(tv, bt2020nc/bt2020/smpte2084), 3840x2160 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 23.98 tbc (default)

Es posible que esta versión de FFmpegno admita x265. Compilé una nueva versión del repositorio actual de Git , habilitandox265 explícitamente . Ahora, ffmpeg -hide_banner -pix_fmtstiene, en su salida:

FLAGS NAME            NB_COMPONENTS BITS_PER_PIXEL
-----
IO... yuv420p10le            3            15

Este formato ahora debería ser compatible tanto para la codificación como para la decodificación. Lo intenté:

ffmpeg -i original_file.mkv -c:v libx265 -pix_fmt + -vf scale=1920:1080 -colorspace bt709 -c:a copy test_output.mkv

Esto produce:

Input #0, matroska,webm, from 'test_output.mkv':
  Metadata:
    ENCODER         : Lavf58.35.100
    Stream #0:0(eng): Video: hevc (Main 10), yuv420p10le(tv, bt709/unknown/unknown), 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 23.98 tbc (default)

Entonces, aparentemente está bien. Sin embargo, test_output.mkvlos colores todavía parecen tener la mitad de la intensidad del original, como si una capa gris se superpusiera al video 4K. Abrí el archivo con ambos vlcy mpv, sin diferencia.

  1. ¿Cómo conservar los colores originales tanto como sea posible?

  2. Si es posible, también me gustaría bajar la tasa de bits, pero mi intento

    ffmpeg -i original_file.mkv -s 1920x1080 -b 1700 output.mkv
    

    produjo un video solo en gris sólido con algunos cuadrados en movimiento.


Siempre recibo este mensaje:

[matroska,webm @ 0x55a5507ad100] Could not find codec parameters for stream 1 (Subtitle: hdmv_pgs_subtitle (pgssub)): unspecified size
Consider increasing the value for the 'analyzeduration' and 'probesize' options

FFmpegconstruido desde la fuente tiene la siguiente configuración:

ffmpeg version N-95768-gd831edc387 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 7 (Ubuntu 7.4.0-1ubuntu1~18.04.1)
configuration: --enable-gpl --enable-libx264 --enable-libx265
libavutil      56. 36.100 / 56. 36.100
libavcodec     58. 62.100 / 58. 62.100
libavformat    58. 35.100 / 58. 35.100
libavdevice    58.  9.101 / 58.  9.101
libavfilter     7. 66.100 /  7. 66.100
libswscale      5.  6.100 /  5.  6.100
libswresample   3.  6.100 /  3.  6.100
libpostproc    55.  6.100 / 55.  6.100

Respuestas (2)

Anuncio 1:

Intente agregar la -pix_fmt yuv420p10leopción (por ejemplo, antes de -vf). O solo -pix_fmt +para usar el mismo formato de píxel que tiene el video de entrada.

Si no ayuda, obviamente tiene una versión FFmpeg inapropiada, aunque más común, solo para colores de 8 bits. (Tu video original usa colores de 10 bits y FFmpeg intentará usar el mejor formato de píxeles de 8 bits en este caso, con la degradación de los colores, por supuesto).

FFmpeg puede construirse para colores de 8 bits o para colores de 10 bits o, recientemente, para ambos (para su video codificado en HEVC).

Por lo tanto, debe crear (u obtener de otra manera) una versión para una profundidad de color de 8/10 o 10 bits.

Anuncio 2:

La tasa de bits 1700es muy baja: solo 1700 bits por segundo, es decir, alrededor de 212 bytes por segundo.

Para alcanzar una tasa de bits tan baja y al mismo tiempo alcanzar sus 23.98fotogramas por segundo, el codificador está limitado con un tamaño promedio para 1 fotograma de aproximadamente 212/24 = ¡solo 9 bytes!

¿Viste una foto de tan poca memoria? Casi no tiene información, por lo que la imagen gris.

Probablemente quería 1700k (Kilobits por segundo) o, más probablemente, 170k:

-b:v 170k

así que corrija su comando de esta manera.


Anexo al Anuncio 1:

Utiliza el submuestreo de croma 4:2:0 (predeterminado) (con degradación inevitable del color y el contraste).
Pruebe la máxima calidad, es decir, 4:4:4 (sin submuestreo) o, si le resulta suficiente, 4:2:2.

Para llegar a esto, use -pix_fmt yuv444p10ley cambie el perfil de video a main444-10 (con la opción -profile:v main444-10).

Gracias por todas las explicaciones muy útiles. Probé con una versión compilada desde la fuente (con x265 habilitado) FFmpegy también con una versión empaquetada más nueva. Incluso usando (en ambos casos) -pix_fmt yuv420p10le, el problema es el mismo. Consulte el mensaje de error que agregué en la pregunta, si es útil. Además, FFmpegcrea una x264salida por defecto; ¿Cómo preservar el original HEVCen su lugar?
Úselo ffmpeg -hide_banner -pix_fmtspara ver si tiene un formato de píxel yuv420p10le en su compilación. De lo contrario, su compilación no admite una profundidad de color de 10 bits. Agregue -c:v libx265a sus comandos para obtener salida HEVC. El mensaje de error adjunto a su pregunta no tiene nada que ver con sus problemas.
Soy consciente de que esto es muy complicado. De todos modos, encontrará todo el procedimiento que seguí (y sus resultados) en mi pregunta actualizada. El problema sigue ahí, independientemente del archivo de salida que utilice yuv420p10leel formato.
Intente agregar la opción -color_range pc(para un rango de color completo de 0 a 255 en lugar de 16 a 235 para TV).
Su entrada tiene un conjunto de parámetros de color no estándar ( bt2020nc/bt2020/smpte2084). Utilice el filtro de espacio de color para convertir a bt709 estándar. El rango de color no es relevante aquí, y las tasas de bits bajas degradarán el color de la imagen, pero no es el factor principal en este caso.
@MarianD Desafortunadamente -color_range pcno cambia el resultado.
@Gyan Edité la pregunta con este nuevo intento. El video sigue con los colores "incorrectos". Sin embargo, tenga en cuenta tv, bt709/unknown/unknownen la salida. ¿ Quizás también colormatrixy algo más se debe modificar? Intenté agregar la opción -colormatrix bt709, pero esto genera un error: Unrecognized option 'colormatrix'..
El filtro de espacio de color, no la opción.
@Gyan Está bien. Espero que la sintaxis sea correcta: usando -vf "scale=1920:1080, colorspace=bt709"produce un error: [Parsed_colorspace_1 @ 0x560001239540] Unsupported input transfer characteristics 16 (smpte2084) Error while filtering: Invalid argument Failed to inject frame into filter network: Invalid argument Error while processing the decoded data for stream #0:0. Lo mismo incluso si uso solo -vf colorspace=bt709.
Me ocuparé de esto mañana.
Ver la actualización de mi respuesta ( Anexo al anuncio 1 ).

Ya hay una solución aquí . Pero intentaré resumirlo brevemente.

Debe especificar los indicadores correctos para las propiedades de color del archivo original. Su archivo original (como probablemente muchos otros archivos) tiene estas propiedades: yuv420p10le(tv, bt2020nc/bt2020/smpte2084). Por lo tanto, debe agregar los siguientes argumentos respectivamente: -pix_fmt, -color_range, -colorspace, -color_primariesy -color_trc. Los últimos cuatro son solo banderas (las que están entre paréntesis), por lo que si ya codificó el archivo, no necesita volver a hacerlo, solo agregue las banderas correctas. Sus argumentos entonces deberían verse así:

-c:v libx265
-pix_fmt +
-color_range tv 
-colorspace bt2020nc
-color_primaries bt2020 
-color_trc smpte2084  
-vf scale=1920:1080

Como se mencionó en otra parte, la propiedad de formato de color -pix_fmtcon valor +significa "usar el mismo formato de píxel", pero puede especificarlo manualmente: -pix_fmt yuv420p10le.