¿Cuál es la forma correcta de arreglar fotogramas clave en FFmpeg para DASH?

38

Al acondicionar una transmisión para la reproducción DASH, los puntos de acceso aleatorio deben estar exactamente al mismo tiempo de transmisión de la fuente en todas las transmisiones. La forma habitual de hacer esto es forzar una velocidad de cuadro fija y una longitud de GOP fija (es decir, un fotograma clave cada N cuadros).

En FFmpeg, la velocidad de fotogramas fija es fácil (-r NÚMERO).

Pero para ubicaciones de fotogramas clave fijos (longitud de GOP), hay tres métodos ... ¿cuál es "correcto"? La documentación de FFmpeg es frustrantemente vaga al respecto.

Método 1: jugar con los argumentos de libx264

-c:v libx264 -x264opts keyint=GOPSIZE:min-keyint=GOPSIZE:scenecut=-1

Parece haber cierto debate sobre si el corte de escena debe desactivarse o no, ya que no está claro si el "contador" de fotogramas clave se reinicia cuando ocurre un corte de escena.

Método 2: establecer un tamaño de GOP fijo:

-g GOP_LEN_IN_FRAMES

Desafortunadamente, esto solo se documenta al pasar la documentación de FFMPEG y, por lo tanto, el efecto de este argumento es muy poco claro.

Método 3: inserte un fotograma clave cada N segundos ( ¿Quizás? ):

-force_key_frames expr:gte(t,n_forced*GOP_LEN_IN_SECONDS)

Esto está explícitamente documentado. Pero aún no está claro de inmediato si el "contador de tiempo" se reinicia después de cada fotograma clave. Por ejemplo, en un GOP esperado de 5 segundos, si scenecutlibx264 inyecta un fotograma clave en 3 segundos, ¿sería el siguiente fotograma clave 5 segundos más tarde o 2 segundos más tarde?

De hecho, la documentación de FFmpeg diferencia entre esta y la -gopción, pero en realidad no dice cómo estas dos opciones anteriores son un poco diferentes (obviamente, -gva a requerir una velocidad de cuadro fija).

¿Lo cual está bien?

Parecería que -force_key_framessería superior , ya que no requeriría una velocidad de cuadro fija. Sin embargo, esto requiere que

  • cumple con las especificaciones de GOP en H.264 ( si corresponde )
  • GARANTIZA que habría un fotograma clave en cadencia fija, independientemente de los scenecutfotogramas clave libx264 .

También parece que -gno podría funcionar sin forzar una velocidad de cuadro fija ( -r) , ya que no hay garantía de que múltiples ejecuciones ffmpegcon diferentes argumentos de códec proporcionen la misma velocidad de cuadro instantánea en cada resolución. Las velocidades de cuadro fijas pueden reducir el rendimiento de compresión (¡IMPORTANTE en un escenario DASH!).

Finalmente, el keyintmétodo parece un truco . Espero contra esperanza que esta no sea la respuesta correcta.

Referencias

Un ejemplo usando el -force_key_framesmétodo

Un ejemplo usando el keyintmétodo

Sección de opciones de video avanzadas de FFmpeg

Mark Gerolimatos
fuente

Respuestas:

27

TL; DR

Yo recomendaría lo siguiente:

  • libx264: (y opcionalmente agregar )-g X -keyint_min X-force_key_frames "expr:gte(t,n_forced*N)"
  • libx265: -x265-params "keyint=X:min-keyint=X"
  • libvpx-vp9: -g X

donde Xes el intervalo en cuadros y Nes el intervalo en segundos. Por ejemplo, para un intervalo de 2 segundos con un video de 30 fps, X= 60 y N= 2.

Una nota sobre los diferentes tipos de cuadros.

Para explicar adecuadamente este tema, primero tenemos que definir los dos tipos de I-frames / keyframes:

  • Cuadros de actualización instantánea del decodificador (IDR): permiten la decodificación independiente de los siguientes cuadros, sin acceso a los cuadros anteriores al cuadro IDR.
  • Tramas no IDR: requieren una trama IDR previa para que la decodificación funcione. Los marcos que no son IDR se pueden usar para cortes de escena en medio de un GOP (grupo de imágenes).

¿Qué se recomienda para la transmisión?

Para el caso de transmisión, desea:

  • Asegúrese de que todos los cuadros IDR estén en posiciones regulares (por ejemplo, a 2, 4, 6,… segundos) para que el video se pueda dividir en segmentos de igual longitud.
  • Habilite la detección de corte de escena, para mejorar la eficiencia / calidad de codificación. Esto significa permitir que los cuadros I se coloquen entre cuadros IDR. Todavía puede trabajar con la detección de corte de escena desactivada (y esto es parte de muchas guías, aún), pero no es necesario.

¿Qué hacen los parámetros?

Para configurar el codificador, tenemos que entender qué hacen los parámetros del fotograma clave. Hice algunas pruebas y descubrí lo siguiente, para los tres codificadores libx264, libx265y libvpx-vp9en FFmpeg:

  • libx264:

    • -g establece el intervalo de fotogramas clave.
    • -keyint_min establece el intervalo mínimo de fotogramas clave.
    • -x264-params "keyint=x:min-keyint=y"es el mismo que -g x -keyint_min y.
    • Nota: Al configurar ambos en el mismo valor, el mínimo se establece internamente en la mitad del intervalo máximo más uno, como se ve en el x264código:

      h->param.i_keyint_min = x264_clip3( h->param.i_keyint_min, 1, h->param.i_keyint_max/2+1 );
      
  • libx265:

    • -g No está implementado.
    • -x265-params "keyint=x:min-keyint=y" trabajos.
  • libvpx-vp9:

    • -g establece el intervalo de fotogramas clave.
    • -keyint_min establece el intervalo mínimo de fotogramas clave
    • Nota: Debido a cómo funciona FFmpeg, -keyint_minsolo se reenvía al codificador cuando es igual que -g. En el código de libvpxenc.cFFmpeg podemos encontrar:

      if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size)
          enccfg.kf_min_dist = avctx->keyint_min;
      if (avctx->gop_size >= 0)
          enccfg.kf_max_dist = avctx->gop_size;
      

      Esto podría ser un error (¿o falta de función?), Ya que libvpxdefinitivamente admite establecer un valor diferente para kf_min_dist.

Deberías usar -force_key_frames?

La -force_key_framesopción inserta por la fuerza los fotogramas clave en el intervalo dado (expresión). Esto funciona para todos los codificadores, pero podría interferir con el mecanismo de control de velocidad. Especialmente para VP9, ​​he notado fuertes fluctuaciones de calidad, por lo que no puedo recomendar su uso en este caso.

slhck
fuente
¡Gracias! Esta es una excelente respuesta. Una pregunta que tengo es cómo generó esa increíble tabla. Podría usar algo así por completo.
Mark Gerolimatos
(Parece que no hay forma de escribirle directamente) ¿Puede señalarme enlaces a algún hilo en esta discusión del UIT-T? ¡Gracias!
Mark Gerolimatos
2
Acabo de hacer eso en Excel, pegando el resultado que obtuve de tres ejecuciones ffprobe -i input.mp4 -select_streams v -show_frames -of csv -show_entries frame=pict_typey luego coloreando las celdas. Me temo que no hay discusiones públicas, pero veré si puedo desenterrar algunos de los enlaces que encontré en ese momento.
slhck
¿Podría volver a intentar su experimento con el -force_key_frames expr:gte(t,n_forced*GOP_LEN_IN_SECONDS)formulario? Acabo de probarlo y descubrí que si bien había marcos I adicionales en la transmisión, parecía acatar mi regla. Un programa PERL seguirá como una "respuesta", ya que aparentemente no puede usar el marcado en los comentarios.
Mark Gerolimatos
Interesante. Creo que vale la pena una respuesta "real" por separado si descubres que funciona. (Los sitios de Stack Exchange no son realmente buenos para esta respuesta de estilo de discusión). La última vez que lo revisé -force_key_framesno funcionó para mí, por lo que nunca lo volví a intentar. Eso fue hace mas de un año. Quizás fue un error. Lo intentaré de nuevo pronto.
slhck
12

Aquí están mis cincuenta centavos para el caso.

Método 1:

jugando con los argumentos de libx264

-c: v libx264 -x264opts keyint = GOPSIZE: min-keyint = GOPSIZE: scenecut = -1

Genere iframes solo en los intervalos deseados.

Ejemplo 1:

ffmpeg -i test.mp4 -codec:v libx264 \
-r 23.976 \
-x264opts "keyint=48:min-keyint=48:no-scenecut" \
-c:a copy \
-y test_keyint_48.mp4

Genere iframes como se espera así:

Iframes     Seconds
1           0
49          2
97          4
145         6
193         8
241         10
289         12
337         14
385         16
433         18
481         20
529         22
577         24
625         26
673         28
721         30
769         32
817         34
865         36
913         38
961         40
1009        42
1057        44
1105        46
1153        48
1201        50
1249        52
1297        54
1345        56
1393        58

El método 2 se deprecia. Omitido

Método 3:

inserte un fotograma clave cada N segundos (QUIZÁS):

-force_key_frames expr: gte (t, n_forced * GOP_LEN_IN_SECONDS)

Ejemplo 2

ffmpeg -i test.mp4 -codec:v libx264 \
-r 23.976 \
-force_key_frames "expr:gte(t,n_forced*2)"
-c:a copy \
-y test_fkf_2.mp4

Genere un iframes de una manera ligeramente diferente:

Iframes     Seconds
1           0
49          2
97          4
145         6
193         8
241         10
289         12
337         14
385         16
433         18
481         20
519         21.58333333
529         22
577         24
625         26
673         28
721         30
769         32
817         34
865         36
913         38
931         38.75
941         39.16666667
961         40
1008        42
1056        44
1104        46
1152        48
1200        50
1248        52
1296        54
1305        54.375
1344        56
1367        56.95833333
1392        58
1430        59.58333333
1440        60
1475        61.45833333
1488        62
1536        64
1544        64.33333333
1584        66
1591        66.29166667
1632        68
1680        70
1728        72
1765        73.54166667
1776        74
1811        75.45833333
1824        75.95833333
1853        77.16666667
1872        77.95833333
1896        78.95833333
1920        79.95833333
1939        80.75
1968        81.95833333

Como puede ver, coloca iframes cada 2 segundos Y en el corte de escena (segundos con parte flotante), lo cual es importante para la complejidad de la transmisión de video en mi opinión.

Los tamaños de archivo geneada son bastante iguales. Muy extraño que incluso con más fotogramas clave en el Método 3 , a veces genera menos archivos que el algoritmo de biblioteca estándar x264.

Para generar múltiples archivos de bitrate para HLS, elegimos el método tres. Se alineó perfectamente con 2 segundos entre fragmentos, tienen un iframe al comienzo de cada fragmento y tienen iframes adicionales en escenas complejas que brindan una mejor experiencia para los usuarios que tienen dispositivos obsoletos y no pueden reproducir perfiles de alto x264.

Espero que ayude a alguien.

Ara Saahov
fuente
Fantástico, gracias por tus 50 centavos!
BrunoFenzl
7

La respuesta, por lo tanto, parece ser:

  • Se verifica que el Método 1 funciona, pero es libx264específico y tiene el costo de eliminar la scenecutopción muy útil en libx264.
  • El método 3 funciona a partir de la versión FFMPEG de abril de 2015, pero debe verificar sus resultados con el script incluido al final de esta publicación, ya que la documentación de FFMPEG no es clara en cuanto al efecto de la opción. Si funciona, es la superior de las dos opciones.
  • NO USE el método 2, -gparece estar en desuso. Parece que no funciona, ni está explícitamente definido en la documentación, ni se encuentra en la ayuda, ni parece estar usado en el código. La inspección de código muestra que la -gopción probablemente esté destinada a transmisiones MPEG-2 (¡incluso hay estrofas de código que se refieren a PAL y NTSC!).

También:

  • Los archivos generados con el Método 3 pueden ser un poco más grandes que el Método 1, ya que se permiten los fotogramas intersticiales I (fotogramas clave).
  • Debe establecer explícitamente el indicador "-r" en ambos casos, aunque el Método 3 coloca un cuadro I en el siguiente intervalo de cuadros en o después del tiempo especificado. Si no establece el indicador "-r", estará a merced del archivo de origen, posiblemente con una velocidad de fotogramas variable. Pueden producirse transiciones DASH incompatibles.
  • A pesar de las advertencias en la documentación de FFMPEG, el método 3 NO es menos eficiente que otros. De hecho, las pruebas muestran que podría ser ligeramente MÁS eficiente que el método 1.

Script para la -force_key_framesopción

Aquí hay un breve programa PERL que utilicé para verificar la cadencia de trama I basada en el resultado de la sugerencia ffprobe de slhck. Parece verificar que el -force_key_framesmétodo también funcionará y tiene el beneficio adicional de permitir scenecutmarcos. No tengo ni idea de cómo FFMPEG hace que esto funcione, o si tuve suerte de alguna manera porque mis transmisiones están bien condicionadas.

En mi caso, codifiqué a 30 fps con un tamaño GOP esperado de 6 segundos, o 180 fotogramas. Usé 180 como el argumento gopsize para este programa verificó un marco I en cada múltiplo de 180, pero establecerlo en 181 (o cualquier otro número que no sea un múltiplo de 180) hizo que se quejara.

#!/usr/bin/perl
use strict;
my $gopsize = shift(@ARGV);
my $file = shift(@ARGV);
print "GOPSIZE = $gopsize\n";
my $linenum = 0;
my $expected = 0;
open my $pipe, "ffprobe -i $file -select_streams v -show_frames -of csv -show_entries frame=pict_type |"
        or die "Blah";
while (<$pipe>) {
  if ($linenum > $expected) {
    # Won't catch all the misses. But even one is good enough to fail.
    print "Missed IFrame at $expected\n";
    $expected = (int($linenum/$gopsize) + 1)*$gopsize;
  }
  if (m/,I\s*$/) {
    if ($linenum < $expected) {
      # Don't care term, just an extra I frame. Snore.
      #print "Free IFrame at $linenum\n";
    } else {
      #print "IFrame HIT at $expected\n";
      $expected += $gopsize;
    }
  }
  $linenum += 1;
}
Mark Gerolimatos
fuente
Solo una nota: dado que este es un sitio de preguntas y respuestas y no realmente un foro de discusión donde las publicaciones se ordenan cronológicamente, es mejor poner toda la información en una respuesta, para que las personas que buscan una solución solo tengan que leer una publicación y no mirar en quién publicó qué, cuándo :) Combiné tus respuestas y también te di un +1 en esto. Como la publicación cruzada no está permitida , le sugiero que elimine su pregunta en el sitio de videos. La gente encontrará las respuestas aquí.
slhck
1
Solo tuve un pensamiento más (en realidad fue planteado en la lista de correo FFmpeg). Cuando lo usa force_key_frames, confunde el algoritmo de asignación de bits x264, por lo que puede darle una peor calidad que simplemente establecer un intervalo fijo de fotogramas clave.
slhck
Santo cielo. Sin embargo, una razón más para que FFMPEG proporcione una forma de códec no específica para hacer esto, un argumento que "haría lo mejor para el códec en cuestión". Traté de presentar un boleto para esto con el seguimiento de FFMPEG, pero rebotó :-(
Mark Gerolimatos
@slhck: ¿Podría dar más detalles por favor? Busqué en los archivos de la lista de correo en mayo de 2015, pero no pude encontrar nada. La conclusión sería olvidarse del "Método 3" y apegarse al "Método 1".
schieferstapel
3
@MarkGerolimatos: sobre -g, usted dice, "Parece que no funciona, ... ni parece estar usado en el código". Lo comprobé y la entrada de la gse almacena en avctx->gop_sizey eso hace que libx264 uso de ella: x4->params.i_keyint_max = avctx->gop_size;. Cuando sondeo este archivo de prueba generado: ffmpeg -i a-test-file.mp4 -g 37 -t 15 gtest.mp4obtengo fotogramas clave exactamente 0,37,74,111,148,185,222,259,296,333,370. Un GOP podría interrumpirse si se activa el cambio de escena, y para eso -sc_thresholdpodría establecerse, lo que también es recogido por x264.
Gyan
4

Quería agregar información aquí, ya que mi búsqueda en Google sacó bastante de esta discusión en mi búsqueda para encontrar información sobre cómo tratar de encontrar una forma de segmentar mi codificación DASH de la manera que quería, y ninguna de la información que encontré era totalmente correcta.

Primero varios conceptos erróneos para deshacerse de:

  1. No todos los cuadros I son iguales. Hay grandes cuadros "I" y pequeños cuadros "i". O para utilizar la terminología correcta, IDR I-Frames y no IDR I-Frames. IDR I-frames (a veces llamados "fotogramas clave") creará un nuevo GOP. Las tramas no IDR no lo harán. Son útiles para tener dentro de un Partido Republicano donde hay un cambio de escena.

  2. -x264opts keyint=GOPSIZE:min-keyint=GOPSIZE← Esto no hace lo que crees que hace. Esto me llevó un tiempo darme cuenta. Resulta que min-keyintestá limitado en el código. No está permitido ser mayor que (keyint / 2) + 1. Por lo tanto, asignar el mismo valor a estas dos variables da como resultado el valor de min-keyintser derribado a la mitad al codificar.

Aquí está la cosa: el corte de escena es realmente genial, especialmente en videos que tienen cortes duros rápidos. Lo mantiene agradable y nítido, por lo que no quiero deshabilitarlo, pero al mismo tiempo no pude obtener un tamaño de GOP fijo mientras estaba habilitado. Quería habilitar el corte de escena, pero solo para que use marcos I que no sean IDR. Pero no estaba funcionando. Hasta que descubrí (de muchas lecturas) sobre el concepto erróneo # 2.

Resulta que necesitaba configurar el keyintdoble del tamaño deseado de GOP. Esto significa que min-keyintse puede establecer en mi tamaño de GOP deseado (sin que el código interno lo corte por la mitad), lo que evita que la detección de corte de escena use fotogramas IDR I dentro del tamaño de GOP porque el recuento de fotogramas desde el último fotograma I de IDR es siempre menos que min-keyinit.

Y finalmente, configurar la force_key_frameopción anula el tamaño doble keyint. Entonces, esto es lo que funciona:

Prefiero segmentos en fragmentos de 2 segundos, por lo que mi GOPSIZE = Framerate * 2

ffmpeg <other_options> -force_key_frames "expr:eq(mod(n,<GOPSIZE>),0)" -x264opts rc-lookahead=<GOPSIZE>:keyint=<GOPSIZE * 2>:min-keyint=<GOPSIZE> <other_options>

Puede verificar usando ffprobe:

ffprobe <SRC_FLE> -select_streams v -show_frames -of csv -show_entries frame=coded_picture_number,key_frame,pict_type > frames.csv

En el archivo CSV generado, cada línea le dirá frame, [is_an_IDR_?], [frame_type], [frame_number]:

frame,1,I,60  <-- frame 60, is I frame, 1 means is an IDR I-frame (aka KeyFrame)
frame,0,I,71  <-- frame 71, is I frame, 0 means not an IDR I_frame

El resultado es que solo debería ver marcos I IDR a GOPSIZEintervalos fijos , mientras que todos los demás cuadros I son cuadros I sin IDR insertados según sea necesario para la detección de corte de escena.

Rubén
fuente
¡eso fue fantastico! También fue muy contradictorio, gracias por hacer el esfuerzo. Y para resumir, supongo que su definición de "I-frames" e "i-frames" es conceptual (es decir, no explícitamente configurable en libx264), y que "max * 2" fue la forma en que lo hizo cumplir.
Mark Gerolimatos
Sí, eso fue conceptual, aunque he visto a personas usar "I" frente a "i" para distinguir entre marcos I IDR y no IDR. Y sí, establecer keyinit en el tamaño de gop deseado * 2 es una forma de forzar que todos los cuadros I dentro del gop sean cuadros I sin IDR. Luego, ffmpeg -force-key-frames anula key-init en x264opts. Básicamente es una forma realmente inversa de obtener el resultado deseado que sería posible si el código x264 le permitiera establecer min-keyinit y keyinit en el mismo valor.
Rubén
... a la vez que puede mantener activada la detección de corte de escena y obtener un tamaño GOP fijo.
Rubén
¡Gracias de nuevo por tu increíble trabajo! Parece que necesitamos una forma menos "hacia atrás" de efectuarlo
Mark Gerolimatos
¿Es necesario mirar hacia adelante? Afecta a mbtree y VBV, pero ¿afecta a la generación de i-frame?
Alexander Svetkin
0

Parece que esta sintaxis no funciona siempre. He probado bastante en nuestro contenido de VOD, así como en el contenido en vivo (volcados de archivos) y, a veces, el corte de escena no funciona y desencadena un iframe intermedio:

Sintaxis para una conversión ascendente i50-> p50, gop / segmento de 2 segundos, IDR al inicio, marcos intermedios si es necesario

ffmpeg.exe -loglevel verbose -i avc_50i.ts -pix_fmt yuv420p -filter_complex yadif=1,scale=1920:1080 -vcodec libx264 -preset fast -x264-params "rc-lookahead=100:keyint=200:min-keyint=100:hrd=1:vbv_maxrate=12000:vbv_bufsize=12000:no-open-gop=1" -r 50 -crf 22 -force_key_frames "expr:eq(mod(n,100),0)" -codec:a aac -b:a 128k -y target.ts
TEB
fuente
0

Twitch tiene una publicación sobre esto. Explican que decidieron usar su propio programa por varias razones; Una de ellas fue que ffmpeg no le permite ejecutar diferentes instancias x264 en diferentes subprocesos, sino que dedica todos los subprocesos especificados a un cuadro en una salida antes de pasar a la siguiente salida.

Si no estás haciendo streaming en tiempo real, tienes más lujo. La forma 'correcta' es probablemente codificar en una resolución con solo el tamaño de GOP especificado con -g, y luego codificar las otras resoluciones forzando fotogramas clave en los mismos lugares.

Si desea hacer eso, puede usar ffprobe para obtener los tiempos de fotogramas clave y luego usar un script de shell o un lenguaje de programación real para convertirlo en un comando ffmpeg.

Pero para la mayoría del contenido, hay muy poca diferencia entre tener un fotograma clave cada 5 segundos y dos fotogramas clave cada 5 segundos (uno forzado y otro de corte de escena). Esto es aproximadamente el tamaño promedio de I-frame versus el tamaño de P-frames y B-frames. Si usa x264 con configuraciones típicas (la única razón por la que creo que debería hacer algo para afectarlas es si configura -qmin, como una forma pobre de evitar que x264 use bitrate en contenido fácil; esto limita todos los tipos de cuadros al mismo valor , Creo) y obtener un resultado como el tamaño promedio del cuadro I de 46 kB, cuadro P 24 kB, cuadro B 17 kB (la mitad de frecuente que los cuadros P), luego un cuadro I adicional cada segundo a 30 fps es solo un aumento del 3% en el tamaño del archivo La diferencia entre h264 y h263 podría estar compuesta por un montón de disminuciones del 3%, pero una sola no es muy importante.

En otros tipos de contenido, los tamaños de los cuadros serán diferentes. Para ser justos, se trata de la complejidad temporal y no de la complejidad espacial, por lo que no se trata solo de contenido fácil frente a contenido duro. Pero en general, los sitios de transmisión de video tienen un límite de velocidad de bits, y el contenido con fotogramas I relativamente grandes es un contenido fácil que se codificará en alta calidad sin importar cuántos fotogramas clave adicionales se agreguen. Es un desperdicio, pero este desperdicio generalmente no se notará. El caso más derrochador es probablemente un video que es solo una imagen estática que acompaña a una canción, donde cada fotograma clave es exactamente el mismo.

Una cosa de la que no estoy seguro es de cómo los fotogramas clave forzados interactúan con el limitador de velocidad establecido con -maxrate y -bufsize. Creo que incluso YouTube ha tenido problemas recientes al configurar correctamente los ajustes del búfer para brindar una calidad constante. Si solo está utilizando la configuración de velocidad de bits promedio como puede verse en algunos sitios (ya que puede inspeccionar las opciones de x264 en el encabezado / mov atom? Con un editor hexadecimal), entonces el modelo de búfer no es un problema, pero si Al ofrecer contenido generado por el usuario, la tasa de bits promedio alienta a los usuarios a agregar una pantalla en negro al final de su video.

La opción -g de Ffmpeg, o cualquier otra opción de codificador que utilice, se asigna a la opción específica del codificador. Entonces '-x264-params keyint = GOPSIZE' es equivalente a '-g GOPSIZE'.

Un problema con el uso de la detección de escenas es si prefiere fotogramas clave cerca de números específicos por cualquier razón. Si especifica fotogramas clave cada 5 segundos y utiliza la detección de escena, y hay un cambio de escena en 4.5, entonces debería detectarse, pero el siguiente fotograma clave será en 9.5. Si el tiempo se acelera de esta manera, podría terminar con fotogramas clave en 42.5, 47.5, 52.5, etc., en lugar de 40, 45, 50, 55. Por el contrario, si hay un cambio de escena en 5.5, habrá un fotograma clave en 5 y 5.5 será demasiado temprano para otro. Ffmpeg no le permite especificar "hacer un fotograma clave aquí si no hay cambio de escena en los próximos 30 fotogramas". Sin embargo, alguien que entienda C podría agregar esa opción.

Para el video de velocidad de cuadro variable, cuando no está transmitiendo en vivo como Twitch, debería poder usar los cambios de escena sin convertir permanentemente a una velocidad de cuadro constante. Si usa el filtro 'select' en ffmpeg y usa la constante 'escena' en la expresión, entonces la salida de depuración (-v debug o presione '+' varias veces mientras codifica) muestra el número de cambio de escena. Esto es probablemente diferente y no tan útil como el número utilizado por x264, pero aún podría ser útil.

El procedimiento, entonces, probablemente sería hacer un video de prueba que sea solo para cambios de fotogramas clave, pero tal vez podría usarse para datos de control de velocidad si se usa 2 pasos. (No estoy seguro de si los datos generados son útiles para diferentes resoluciones y configuraciones; los datos del árbol de macrobloques no lo serán). Conviértalo a video de velocidad de fotogramas constante, pero vea este error sobre la tartamudez de salida al reducir a la mitad la velocidad de fotogramas si alguna vez decide usar el filtro fps para otros fines. Ejecútelo a través de x264 con el fotograma clave deseado y la configuración de GOP.

Luego, solo use estos tiempos de fotogramas clave con el video original de velocidad de cuadro variable.

Si permite contenido generado por el usuario completamente loco con un espacio de 20 segundos entre fotogramas, entonces para la codificación de velocidad de fotogramas variable, podría dividir la salida, usar el filtro fps, de alguna manera usar el filtro select (tal vez construir una expresión realmente larga que tenga cada tiempo de fotograma clave) ... o tal vez podría usar el video de prueba como entrada y decodificar solo fotogramas clave, si esa opción ffmpeg funciona, o usar el filtro de selección para seleccionar fotogramas clave. Luego escale al tamaño correcto (incluso hay un filtro scale2ref para esto) y superponga el video original en él. Luego use el filtro de intercalación para combinar estos fotogramas clave destinados a ser forzados con el video original. Si esto resulta en dos cuadros separados por 0.001 segundos que el filtro de intercalación no previene, entonces resuelva este problema usted mismo con otro filtro de selección. Tratar con los límites de la memoria intermedia de trama para el filtro intercalado podría ser el principal problema aquí. Todo esto podría funcionar: use algún tipo de filtro para amortiguar el flujo más denso (¿filtro de quince?); consulte el archivo de entrada varias veces para que se decodifique más de una vez y los marcos no tengan que almacenarse; use el filtro 'streamselect', que nunca he hecho, exactamente en el momento de los fotogramas clave; mejorar el filtro de intercalación cambiando su comportamiento predeterminado o agregando una opción para generar el marco más antiguo en un búfer en lugar de soltar un marco. que nunca he hecho, exactamente en los tiempos de los fotogramas clave; mejorar el filtro de intercalación cambiando su comportamiento predeterminado o agregando una opción para generar el marco más antiguo en un búfer en lugar de soltar un marco. que nunca he hecho, exactamente en los tiempos de los fotogramas clave; mejore el filtro de intercalación cambiando su comportamiento predeterminado o agregando una opción para generar el fotograma más antiguo en un búfer en lugar de soltar un fotograma.

Misaki
fuente