Quelle est la bonne façon de corriger les images clés dans FFmpeg pour DASH?

39

Lors du conditionnement d'un flux pour la lecture DASH, les points d'accès aléatoires doivent être exactement à la même heure de flux source dans tous les flux. La façon habituelle de le faire est de forcer une fréquence d'images fixe et une longueur GOP fixe (c'est-à-dire une image clé toutes les N images).

Dans FFmpeg, la fréquence d'images fixe est facile (-r NUMBER).

Mais pour les emplacements d'images clés fixes (longueur du GOP), il existe trois méthodes ... laquelle est "correcte"? La documentation FFmpeg est frustrante et vague à ce sujet.

Méthode 1: jouer avec les arguments de libx264

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

Il semble y avoir un débat quant à savoir si la mise en scène doit être désactivée ou non, car il n'est pas clair si le "compteur" d'images clés est redémarré lorsqu'une scène est coupée.

Méthode 2: définition d'une taille GOP fixe:

-g GOP_LEN_IN_FRAMES

Ceci n'est malheureusement documenté qu'en passant dans la documentation FFMPEG, et donc l'effet de cet argument n'est pas très clair.

Méthode 3: insérez une image clé toutes les N secondes ( peut-être? ):

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

Ceci est explicitement documenté. Mais il n'est pas encore clair immédiatement si le "compteur de temps" redémarre après chaque image clé. Par exemple, dans un GOP attendu de 5 secondes, s'il y a une scenecutimage clé injectée 3 secondes par libx264, l'image clé suivante serait-elle 5 secondes plus tard ou 2 secondes plus tard?

En fait, la documentation FFmpeg fait la différence entre cela et l' -goption, mais elle ne dit pas vraiment comment ces deux options ci-dessus sont les moins différentes (évidemment, cela -gva nécessiter une fréquence d'images fixe).

Quelle est la bonne?

Il semblerait que le -force_key_framesserait supérieur , car il ne nécessiterait pas une fréquence d'images fixe. Cependant, cela nécessite que

  • il est conforme aux spécifications GOP en H.264 (le cas échéant )
  • il GARANTIT qu'il y aurait une image clé en cadence fixe, indépendamment des images scenecutclés libx264 .

Il semblerait également que -gcela ne pourrait pas fonctionner sans forcer une fréquence d'images fixe ( -r) , car il n'y a aucune garantie que plusieurs exécutions de ffmpegavec différents arguments de codec fourniraient la même fréquence d'images instantanée dans chaque résolution. Des fréquences d'images fixes peuvent réduire les performances de compression (IMPORTANT dans un scénario DASH!).

Enfin, la keyintméthode semble être un hack . J'espère contre espoir que ce n'est pas la bonne réponse.

Les références:

Un exemple utilisant la -force_key_framesméthode

Un exemple utilisant la keyintméthode

Section des options vidéo avancées de FFmpeg

Mark Gerolimatos
la source

Réponses:

28

TL; DR

Je recommanderais ce qui suit:

  • libx264: (et éventuellement ajouter )-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

Xest l'intervalle en images et Nest l'intervalle en secondes. Par exemple, pour un intervalle de 2 secondes avec une vidéo à 30 ips, X= 60 et N= 2.

Une note sur les différents types de cadres

Afin d'expliquer correctement ce sujet, nous devons d'abord définir les deux types d'images-images / images clés:

  • Trames de rafraîchissement instantané du décodeur (IDR): elles permettent un décodage indépendant des trames suivantes, sans accès aux trames antérieures à la trame IDR.
  • Trames non IDR: elles nécessitent une trame IDR précédente pour que le décodage fonctionne. Les images non IDR peuvent être utilisées pour des coupes de scène au milieu d'un GOP (groupe d'images).

Qu'est-ce qui est recommandé pour le streaming?

Pour le cas de streaming, vous souhaitez:

  • Assurez-vous que toutes les trames IDR sont à des positions régulières (par exemple à 2, 4, 6,… secondes) afin que la vidéo puisse être divisée en segments de longueur égale.
  • Activez la détection de coupure de scène, afin d'améliorer l'efficacité / la qualité du codage. Cela signifie permettre aux images I d'être placées entre les images IDR. Vous pouvez toujours travailler avec la détection de coupure de scène désactivée (et cela fait toujours partie de nombreux guides), mais ce n'est pas nécessaire.

Que font les paramètres?

Pour configurer l'encodeur, nous devons comprendre ce que font les paramètres des images clés. Je l' ai fait quelques tests et a découvert ce qui suit, pour les trois codeurs libx264, libx265et libvpx-vp9dans FFmpeg:

  • libx264:

    • -g définit l'intervalle d'images clés.
    • -keyint_min définit l'intervalle d'image clé minimum.
    • -x264-params "keyint=x:min-keyint=y"est le même que -g x -keyint_min y.
    • Remarque: Lorsque vous définissez les deux sur la même valeur, le minimum est défini en interne à la moitié de l'intervalle maximum plus un, comme indiqué dans le x264code:

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

    • -g n'est pas implémenté.
    • -x265-params "keyint=x:min-keyint=y" travaux.
  • libvpx-vp9:

    • -g définit l'intervalle d'images clés.
    • -keyint_min définit l'intervalle d'image clé minimum
    • Remarque: En raison du fonctionnement de FFmpeg, il -keyint_minn'est transmis à l'encodeur que lorsqu'il est identique à -g. Dans le code de libvpxenc.cFFmpeg, nous pouvons trouver:

      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;
      

      Cela peut être un bug (ou un manque de fonctionnalité?), libvpxCar il prend définitivement en charge la définition d'une valeur différente pour kf_min_dist.

Devriez-vous utiliser -force_key_frames?

L' -force_key_framesoption insère de force les images clés à l'intervalle (expression) donné. Cela fonctionne pour tous les encodeurs, mais cela pourrait perturber le mécanisme de contrôle du débit. Surtout pour VP9, ​​j'ai remarqué de graves fluctuations de qualité, donc je ne peux pas recommander de l'utiliser dans ce cas.

slhck
la source
Merci! Ce sont d'excellents commentaires. Une question que j'ai est de savoir comment vous avez généré ce tableau génial. Je pourrais totalement utiliser quelque chose comme ça.
Mark Gerolimatos
(Il semble qu'il n'y ait aucun moyen de vous écrire directement) Pouvez-vous s'il vous plaît me diriger vers des liens vers des fils de discussion de l'UIT-T? Merci!
Mark Gerolimatos
2
Je viens de le faire dans Excel, en collant la sortie que j'ai obtenue à partir de trois séries de ffprobe -i input.mp4 -select_streams v -show_frames -of csv -show_entries frame=pict_type, puis en coloriant les cellules. Je crains qu'il n'y ait pas de discussions publiques, mais je vais voir si je peux trouver certains des liens que j'ai trouvés à l'époque.
slhck
Pourriez-vous réessayer votre expérience avec le -force_key_frames expr:gte(t,n_forced*GOP_LEN_IN_SECONDS)formulaire? Je viens de l'essayer et j'ai constaté que, même s'il y avait des images I supplémentaires dans le flux, cela semblait respecter ma règle. Un programme PERL suivra comme une "réponse", car vous ne pouvez apparemment pas utiliser de balisage dans les commentaires.
Mark Gerolimatos
Intéressant. Je crois que cela vaut une "vraie" réponse séparée si vous découvrez que cela fonctionne. (Les sites Stack Exchange ne sont pas vraiment bons pour cette réponse de type discussion.) La dernière fois que j'ai vérifié, cela -force_key_framesn'a pas fonctionné pour moi, et je ne l'ai donc jamais réessayé. C'était il y a plus d'un an. C'était peut-être un bug. Je réessayerai bientôt.
slhck
12

Voici mes cinquante cents pour l'affaire.

Méthode 1:

jouer avec les arguments de libx264

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

Générez des iframes uniquement aux intervalles souhaités.

Exemple 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

Générez des iframes comme prévu comme ceci:

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

La méthode 2 est dépréciée. Ommit.

Méthode 3:

insérer une image clé toutes les N secondes (PEUT-ÊTRE):

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

Exemple 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

Générez un iframes d'une manière légèrement différente:

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

Comme vous pouvez le voir, il place des iframes toutes les 2 secondes ET sur des scènes (secondes avec partie flottante), ce qui est important pour la complexité du flux vidéo à mon avis.

Les tailles de fichier générées sont à peu près les mêmes. Très étrange que même avec plus d'images clés dans la méthode 3, il génère parfois moins de fichiers que l'algorithme de bibliothèque x264 standard.

Pour générer plusieurs fichiers de débit binaire pour le flux HLS, nous choisissons la méthode trois. Il est parfaitement aligné avec 2 secondes entre les morceaux, ils ont un iframe au début de chaque morceau et ils ont des iframes supplémentaires sur des scènes complexes qui offrent une meilleure expérience pour les utilisateurs qui ont des appareils obsolètes et ne peuvent pas lire les profils élevés x264.

J'espère que cela aide quelqu'un.

Ara Saahov
la source
Fantastique, merci pour vos 50 cents!
BrunoFenzl
7

La réponse semble donc être:

  • La méthode 1 est vérifiée pour fonctionner, mais elle est libx264spécifique et se fait au prix de l'élimination de l' scenecutoption très utile dans libx264.
  • La méthode 3 fonctionne à partir de la version FFMPEG d'avril 2015, mais vous devez vérifier vos résultats avec le script inclus au bas de cet article, car la documentation FFMPEG n'est pas claire quant à l'effet de l'option. Si cela fonctionne, c'est le supérieur des deux options.
  • NE PAS UTILISER la méthode 2, -gsemble obsolète. Il ne semble ni fonctionner, ni défini explicitement dans la documentation, ni trouvé dans l'aide, ni être utilisé dans le code. L'inspection du code montre que l' -goption est probablement destinée aux flux MPEG-2 (il existe même des strophes de code faisant référence à PAL et NTSC!).

Également:

  • Les fichiers générés avec la méthode 3 peuvent être légèrement plus volumineux que la méthode 1, car les images I interstitielles (images clés) sont autorisées.
  • Vous devez définir explicitement le drapeau « -r » dans les deux cas, même si la méthode 3 places un cadre I à la prochaine frameslot ou après l'heure indiquée. Le fait de ne pas définir l'indicateur "-r" vous place à la merci du fichier source, éventuellement avec une fréquence d'images variable. Des transitions DASH incompatibles peuvent en résulter.
  • Malgré les avertissements de la documentation FFMPEG, la méthode 3 n'est PAS moins efficace que les autres. En fait, les tests montrent qu'elle pourrait être légèrement PLUS efficace que la méthode 1.

Script pour l' -force_key_framesoption

Voici un court programme PERL que j'ai utilisé pour vérifier la cadence de l'image I en fonction de la sortie de la suggestion ffprobe de slhck. Il semble vérifier que la -force_key_framesméthode fonctionnera également et présente l'avantage supplémentaire de permettre les scenecuttrames. Je n'ai absolument aucune idée de la façon dont FFMPEG fait fonctionner cela, ou si j'ai juste eu de la chance parce que mes streams sont bien conditionnés.

Dans mon cas, j'ai encodé à 30 images par seconde avec une taille GOP attendue de 6 secondes, ou 180 images. J'ai utilisé 180 comme argument Gopsize de ce programme qui a vérifié une trame I à chaque multiple de 180, mais le définir sur 181 (ou tout autre nombre différent de 180) l'a fait se plaindre.

#!/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
la source
Juste une note: comme il s'agit d'un site de questions / réponses et pas vraiment d'un forum de discussion où les articles sont classés par ordre chronologique, il est préférable de mettre toutes les informations dans une seule réponse, afin que les personnes à la recherche d'une solution n'aient qu'à lire un article et à ne pas regarder à qui a posté quoi, quand :) J'ai fusionné vos réponses et vous ai également donné un +1 à ce sujet. Étant donné que la publication croisée n'est pas autorisée , je vous suggère de supprimer votre question sur le site vidéo. Les gens trouveront la ou les réponses ici.
slhck
1
J'ai juste eu une autre pensée (en fait, elle a été soulevée sur la liste de diffusion FFmpeg). Lorsque vous utilisez force_key_frames, cela gâche en quelque sorte l'algorithme d'allocation x264 bits, de sorte qu'il peut vous donner une qualité pire que de simplement définir un intervalle d'images clés fixe.
slhck
Merde. Pourtant, une raison de plus pour que FFMPEG fournisse un moyen non spécifique pour le faire, un argument qui "ferait la meilleure chose pour le codec en question". J'ai essayé de déposer un ticket pour cela avec le trac de FFMPEG, mais le rebondi :-(
Mark Gerolimatos
@slhck: Pourriez-vous donner plus de détails s'il vous plaît? J'ai regardé dans les archives de la liste de diffusion en mai 2015 mais je n'ai rien trouvé. L'essentiel serait d'oublier la "Méthode 3" et de s'en tenir à la "Méthode 1".
schieferstapel
3
@MarkGerolimatos: à propos -g, vous dites: "Cela ne semble pas fonctionner, ... ni ne semble être utilisé dans le code.". J'ai vérifié et l'entrée gest stockée dans avctx->gop_sizeet qui fait de libx264 utilise de celui - ci: x4->params.i_keyint_max = avctx->gop_size;. Lorsque je sonde ce fichier de test généré ffmpeg -i a-test-file.mp4 -g 37 -t 15 gtest.mp4:, j'obtiens des images clés exactement 0,37,74,111,148,185,222,259,296,333,370. Un GOP pourrait être écourté si un changement de scène est déclenché, et pour cela, il -sc_thresholdpourrait être défini, qui est également capté par x264.
Gyan
4

Je voulais ajouter des informations ici, car ma recherche sur Google a entraîné cette discussion un peu dans ma quête pour trouver des informations sur la façon de trouver un moyen de segmenter mon encodage DASH comme je le souhaitais, et aucune des informations que j'ai trouvées n'était totalement correcte.

Plusieurs idées fausses dont il faut se débarrasser:

  1. Tous les cadres I ne sont pas identiques. Il y a de grands cadres en "I" et de petits cadres en "i". Ou pour utiliser la terminologie correcte, les cadres I IDR et les cadres I non IDR. Les images I IDR (parfois appelées "images clés") créeront un nouveau GOP. Les trames non IDR ne le seront pas. Ils sont pratiques pour avoir à l'intérieur d'un GOP où il y a un changement de scène.

  2. -x264opts keyint=GOPSIZE:min-keyint=GOPSIZE← Cela ne fait pas ce que vous pensez. Cela m'a pris un peu de temps pour comprendre. Il s'avère que le min-keyintest limité dans le code. Il ne doit pas être supérieur à (keyint / 2) + 1. Ainsi, l'attribution de la même valeur à ces deux variables entraîne une min-keyintréduction de moitié de la valeur lors de l'encodage.

Voici le truc: la coupe de scène est vraiment géniale, surtout dans les vidéos qui ont des coupes rapides et dures. Il le garde agréable et net, donc je ne veux pas le désactiver, mais en même temps, je ne pouvais pas obtenir une taille GOP fixe tant qu'il était activé. Je voulais activer le découpage de scène, mais le faire uniquement utiliser des images I non IDR. Mais cela ne fonctionnait pas. Jusqu'à ce que je comprenne (à partir de nombreuses lectures) une idée fausse n ° 2.

Il s'avère que je devais régler keyintle double de la taille GOP souhaitée. Cela signifie que vous min-keyintpouvez définir la taille GOP souhaitée (sans que le code interne ne le coupe en deux), ce qui empêche la détection de coupure de scène d'utiliser des images I IDR à l'intérieur de la taille GOP car le nombre d'images depuis la dernière image I IDR est toujours moins que min-keyinit.

Enfin, la définition de l' force_key_frameoption remplace la double taille keyint. Voici donc ce qui fonctionne:

Je préfère les segments en morceaux de 2 secondes, donc ma 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>

Vous pouvez vérifier en utilisant ffprobe:

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

Dans le fichier CSV généré, chaque ligne vous indiquera: 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

Le résultat est que vous ne devriez voir les images I IDR qu'à GOPSIZEintervalles fixes , tandis que toutes les autres images I sont des images I non IDR insérées selon les besoins par la détection de coupure de scène.

Reuben
la source
c'était fantastique! C'était aussi très contre-intuitif, merci d'avoir fait l'effort. Et pour résumer, je suppose que votre définition des "I-frames" et des "i-frames" est conceptuelle (c'est-à-dire, non explicitement configurable dans libx264), et que le "max * 2" était la façon dont vous l'avez appliqué?
Mark Gerolimatos
Oui, c'était conceptuel, même si j'ai vu des gens utiliser "I" contre "i" pour faire la distinction entre les cadres I IDR et non IDR. Et oui, définir keyinit à la taille de gop souhaitée * 2 est un moyen de forcer toutes les images I à l'intérieur du gop à être des images I non IDR. Ensuite, ffmpeg -force-key-frames remplace le key-init dans les x264opts. Fondamentalement, c'est un moyen vraiment inversé d'obtenir le résultat souhaité qui serait possible si le code x264 vous permettait de définir min-keyinit et keyinit à la même valeur.
Ruben
... tout en pouvant à la fois garder la détection de coupure de scène activée et obtenir une taille GOP fixe.
Ruben
merci encore pour votre travail génial! On dirait que nous avons besoin d'une façon moins "en arrière" de le faire
Mark Gerolimatos
Le rc-lookahead est-il nécessaire ici? Cela affecte mbtree et VBV, mais affecte-t-il la génération d'i-frame?
Alexander Svetkin
0

Il semble que cette syntaxe ne fonctionne pas toujours .. J'ai testé beaucoup sur notre contenu VOD ainsi que le contenu en direct (vidage de fichiers) et parfois Scenecut ne fonctionne pas et déclenche un iframe intermédiaire:

Syntaxe pour une conversion ascendante i50-> p50, gop / segment de 2 secondes, IDR au début, iframes intermédiaires si nécessaire

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
la source
0

Twitch a un post à ce sujet. Ils expliquent qu'ils ont décidé d'utiliser leur propre programme pour plusieurs raisons; L'un d'eux était que ffmpeg ne vous permet pas d'exécuter différentes instances x264 dans différents threads, mais consacre plutôt tous les threads spécifiés à une image dans une sortie avant de passer à la sortie suivante.

Si vous ne faites pas de streaming en temps réel, vous avez plus de luxe. La méthode «correcte» consiste probablement à coder à une résolution avec uniquement la taille GOP spécifiée avec -g, puis à coder les autres résolutions en forçant les images clés aux mêmes endroits.

Si vous le souhaitez, vous pouvez utiliser ffprobe pour obtenir les heures des images clés, puis utiliser un script shell ou un véritable langage de programmation pour le convertir en une commande ffmpeg.

Mais pour la plupart des contenus, il y a très peu de différence entre avoir une image clé toutes les 5 secondes et deux images clés toutes les 5 secondes (une forcée et une de scenecut). Il s'agit de la taille moyenne des images I par rapport à la taille des images P et des images B. Si vous utilisez x264 avec des paramètres typiques (la seule raison pour laquelle je pense que vous devriez faire quoi que ce soit pour les modifier est si vous définissez -qmin, comme un moyen médiocre d'empêcher x264 d'utiliser le débit binaire sur un contenu facile; cela limite tous les types de trames à la même valeur , Je pense) et obtenez un résultat comme une taille moyenne de trame I de 46 Ko, une trame P de 24 Ko, une trame B de 17 Ko (moitié moins fréquente que des trames P), puis une trame I supplémentaire chaque seconde à 30 ips est seulement une augmentation de 3% de la taille du fichier. La différence entre h264 et h263 pourrait être constituée d'un tas de diminutions de 3%, mais une seule n'est pas très importante.

Sur d'autres types de contenu, les tailles de trame seront différentes. Pour être honnête, il s'agit de complexité temporelle et non de complexité spatiale, donc ce n'est pas seulement un contenu facile vs un contenu dur. Mais en général, les sites de streaming vidéo ont une limite de débit binaire, et le contenu avec des images I relativement grandes est un contenu facile qui sera encodé à haute qualité quel que soit le nombre d'images clés supplémentaires ajoutées. C'est du gaspillage, mais ces déchets ne seront généralement pas remarqués. Le cas le plus inutile est probablement une vidéo qui n'est qu'une image statique accompagnant une chanson, où chaque image clé est exactement la même.

Une chose dont je ne suis pas sûr est de savoir comment les images clés forcées interagissent avec le limiteur de débit défini avec -maxrate et -bufsize. Je pense que même YouTube a récemment rencontré des problèmes de configuration correcte des paramètres de tampon pour donner une qualité constante. Si vous utilisez simplement des paramètres de débit binaire moyens comme certains sites peuvent le voir (puisque vous pouvez inspecter les options de x264 dans l'atome header / mov? Avec un éditeur hexadécimal), le modèle de tampon n'est pas un problème, mais si vous êtes diffusant du contenu généré par l'utilisateur, le débit binaire moyen encourage les utilisateurs à ajouter un écran noir à la fin de leur vidéo.

L'option -g de Ffmpeg, ou toute autre option d'encodeur que vous utilisez, est mappée à l'option spécifique à l'encodeur. Donc '-x264-params keyint = GOPSIZE' est équivalent à '-g GOPSIZE'.

Un problème avec l'utilisation de la détection de scène est que vous préférez des images clés à proximité de nombres spécifiques pour une raison quelconque. Si vous spécifiez des images clés toutes les 5 secondes et utilisez la détection de scène, et qu'il y a un changement de scène à 4,5, il doit être détecté, mais l'image clé suivante sera à 9,5. Si le temps continue à augmenter comme ça, vous pourriez vous retrouver avec des images clés à 42,5, 47,5, 52,5, etc., au lieu de 40, 45, 50, 55. Inversement, s'il y a un changement de scène à 5,5, alors il y aura une image clé à 5 et 5,5 sera trop tôt pour une autre. Ffmpeg ne vous permet pas de spécifier "créer une image clé ici s'il n'y a pas de changement de scène dans les 30 images suivantes". Cependant, quelqu'un qui comprend C pourrait ajouter cette option.

Pour la vidéo à fréquence d'images variable, lorsque vous ne diffusez pas en direct comme Twitch, vous devriez pouvoir utiliser les changements de scène sans convertir de manière permanente en fréquence d'images constante. Si vous utilisez le filtre 'select' dans ffmpeg et utilisez la constante 'scene' dans l'expression, la sortie de débogage (-v debug ou appuyez plusieurs fois sur '+' lors de l'encodage) affiche le numéro de changement de scène. Ceci est probablement différent et pas aussi utile que le nombre utilisé par x264, mais il pourrait quand même être utile.

La procédure serait alors probablement de faire une vidéo de test uniquement pour les changements d'images clés, mais pourrait peut-être être utilisée pour les données de contrôle de débit si vous utilisez 2 passes. (Je ne sais pas si les données générées sont utiles pour différentes résolutions et paramètres; les données de l'arborescence des macroblocs ne le seront pas.) Convertissez-les en vidéo à fréquence d'images constante, mais voyez ce bogue sur la sortie du bégaiement lors de la réduction de moitié du framerate si jamais vous décidez pour utiliser le filtre fps à d'autres fins. Exécutez-le via x264 avec les images clés et les paramètres GOP souhaités.

Utilisez ensuite ces temps d'images clés avec la vidéo à fréquence d'images variable d'origine.

Si vous autorisez un contenu généré par l'utilisateur complètement fou avec un intervalle de 20 secondes entre les images, alors pour l'encodage à fréquence d'images variable, vous pouvez diviser la sortie, utiliser le filtre fps, utiliser en quelque sorte le filtre de sélection (peut-être créer une expression très longue qui a chaque image clé) ... ou vous pouvez peut-être utiliser la vidéo de test comme entrée et décoder uniquement les images clés, si cette option ffmpeg fonctionne, ou utiliser le filtre de sélection pour sélectionner les images clés. Ensuite, redimensionnez-le à la bonne taille (il y a même un filtre scale2ref pour cela) et superposez la vidéo originale dessus. Utilisez ensuite le filtre d'entrelacement pour combiner ces images clés forcées destinées à être utilisées avec la vidéo d'origine. Si cela se traduit par deux images distantes de 0,001 seconde que le filtre d'entrelacement n'empêche pas, résolvez vous-même ce problème avec un autre filtre de sélection. Le traitement des limites de tampon de trame pour le filtre d'entrelacement pourrait être le problème principal ici. Ceux-ci pourraient tous fonctionner: utiliser une sorte de filtre pour tamponner le flux plus dense (filtre fifo?); se référer au fichier d'entrée plusieurs fois pour qu'il soit décodé plus d'une fois et les images n'ont pas besoin d'être stockées; utiliser le filtre 'streamselect', ce que je n'ai jamais fait, exactement au moment des images clés; améliorer le filtre d'entrelacement en modifiant son comportement par défaut ou en ajoutant une option pour sortir la plus ancienne trame dans un tampon au lieu de supprimer une trame. ce que je n'ai jamais fait, exactement au moment des images clés; améliorer le filtre d'entrelacement en modifiant son comportement par défaut ou en ajoutant une option pour sortir la plus ancienne trame dans un tampon au lieu de supprimer une trame. ce que je n'ai jamais fait, exactement au moment des images clés; améliorer le filtre d'entrelacement en modifiant son comportement par défaut ou en ajoutant une option pour sortir la plus ancienne trame dans un tampon au lieu de supprimer une trame.

Misaki
la source