ffmpeg-supprimer les cadres sequentiellement dupliqués
y a-t-il un moyen de détecter les images dupliquées dans la vidéo en utilisant ffmpeg
.
j'ai essayé -vf
drapeau avec select=gt(scene,0.xxx)
pour changement de scène. Mais, il ne fonctionne pas pour mon cas.
2 réponses
mpdecimate filtre, dont le but est de "supprimer les cadres qui ne diffèrent pas beaucoup du cadre précédent afin de réduire la cadence."
ceci générera une lecture de la console montrant les cadres que le filtre pense être des doublons.
ffmpeg -i input.mp4 -vf mpdecimate -loglevel debug -f null -
Pour générer une vidéo avec les doublons supprimés
ffmpeg -i input.mp4 -vf mpdecimate,setpts=N/FRAME_RATE/TB out.mp4
Th setpts l'expression filter génère des horodateurs lisses pour une vidéo à FRAME_RATE fps. Voir une explication pour les horodateurs à qu'est-Ce que la vidéo de l'échelle de temps, la base de temps, ou d'horodatage dans ffmpeg?
j'ai aussi eu ce problème et L'excellente réponse de Gyan ci-dessus m'a permis de commencer mais le résultat était un audio désynchronisé donc j'ai dû Explorer plus d'options:
mpdecimate et décimer filtres
mpdecimate
est la recommandation standard que j'ai trouvé partout ainsi et l'internet, mais je ne pense pas que ce devrait être le premier choix- il utilise des heuristiques de sorte qu'il peut et va sauter certaines en double les frames
- vous pouvez modifier la détection
frac
paramètre, mais c'est un travail supplémentaire, vous voudrez peut-être éviter si vous pouvez - il n'est pas vraiment censé fonctionner
mp4
container ( source), mais j'utilisaismkv
donc cette limitation ne s'applique pas à mon cas, mais bon d'être conscient de cela
decimate
supprime les cadres avec précision, mais il n'est utile que pour des situations périodiques les doublons
détectée vs cadence réelle
- vous avez donc un fichier multimédia avec des images dupliquées, c'est une bonne idée de s'assurer que la fréquence d'images détectée corresponde à la fréquence réelle
ffprobe in.mkv
produira les FPS détectés; il peut ressembler à ceciStream #0:0: Video: h264 (Main), yuvj420p(pc, bt709, progressive), 1920x1080, SAR 1:1 DAR 16:9, 25 fps, 25 tbr, 1k tbn, 50 tbc (default)
la cadence réelle peut être trouvée si vous ouvrez les médias
in.mkv
dans un lecteur multimédia qui vous permet de passer à l'image à l'époque; puis compter les étapes nécessaires pour avancer le temps de lecture pendant 1 seconde, dans mon cas il était 30 fps- ce n'est pas une grande surprise pour moi, parce que chaque 6ème image était dupliquée (5 bonnes images et 1 duplicata), donc après 25 bonnes images il y avait aussi 5 duplicata
qu'est-ce que N/FRAME_RATE/TB
sauf l'utilisation de
FRAME_RATE
variable laN/FRAME_RATE/TB
est égal à l'exemple ci-dessous de ffmpeg documentation ( source)Définir le taux fixe de 25 images par seconde:
setpts=N/(25*TB)
les mathématiques derrière elle parfaitement expliqué dans Qu'est-ce que le timescale, timebase ou timestamp vidéo dans ffmpeg?
- il calcule essentiellement timestamp pour chaque image et le multiplie avec timebase
TB
pour améliorer précision
- il calcule essentiellement timestamp pour chaque image et le multiplie avec timebase
FRAME_RATE
variable vs valeur fps littérale (e.g. 25)
- c'est pourquoi il est important de connaître vos FPS détectés et réels
- si les FPS détectés correspondent à vos FPS réels (par exemple, les deux sont 30 fps) vous pouvez heureusement utilisation
FRAME_RATE
variableN/FRAME_RATE/TB
- mais si le FPS détecté diffère de celui que vous devez calculer le
FRAME_RATE
sur votre propre- dans mon cas mon FPS actuel 30 images par seconde et j'ai enlevé tous les 6 cadre, de sorte que la cible FPS 25 ce qui mène à
N/25/TB
- si j'ai utilisé
FRAME_RATE
(et j'ai effectivement essayé), il allait prendre le mauvais détecté fps 25 images c'est à direFRAME_RATE=25
, le lancer à traversmpdecimate
filtre qui supprimerait toutes les 6 images et mettrait à jour versFRAME_RATE=20.833
N/FRAME_RATE/TB
seraitN/20.833/TB
qui est complètement mal
- si j'ai utilisé
- dans mon cas mon FPS actuel 30 images par seconde et j'ai enlevé tous les 6 cadre, de sorte que la cible FPS 25 ce qui mène à
utiliser ou ne pas utiliser setpts
- setpts le filtre est déjà assez compliqué surtout à cause du désordre FPS que les cadres dupliqués peuvent créer
- la bonne nouvelle est que vous n'avez peut-être pas besoin du setpts filtrer du tout
voici ce que j'ai utilisé avec bonne résultats
ffmpeg -i in.mkv -vf mpdecimate out.mkv
ffmpeg -i in.mkv -vf decimate=cycle=6,setpts=N/25/TB out.mkv
mais ce qui suit m'a donné audio désynchronisé
ffmpeg -i in.mkv -vf mpdecimate,setpts=N/FRAME_RATE/TB out.mkv
ffmpeg -i in.mkv -vf mpdecimate,setpts=N/25/TB out.mkv
comme vous le voyez
- mpdecimate et décimer ne fonctionne pas de la même façon
- mpdecimate a fonctionné mieux pour moi sans setpts filtre
- décimer nécessaire setpts filtre et de plus je dois éviter
FRAME_RATE
variable et utiliserN/25/TB
au lieu de cela parce que le FPS réel n'a pas été détecté correctement
remarque: asetpts
- il fait le même travail que setpts mais pour l'audio
- il n'a pas vraiment fixer désynchronisation audio pour moi, mais vous voulez utiliser quelque chose comme ceci
-af asetpts=N/SAMPLE_RATE/TB
- peut-être que vous êtes censé régler le
SAMPLE_RATE
selon le rapport des cadres dupliqués supprimés, mais il me semble qu'il y a un travail superflu surtout quand ma vidéo a l'audio synchronisé au début, donc il est préférable d'utiliser des commandes qui le maintiendront ainsi au lieu de le corriger plus tard
tl;dr
si la commande habituellement recommandée ffmpeg -i in.mkv -vf mpdecimate,setpts=N/FRAME_RATE/TB out.mkv
ne fonctionne pas pour vous, essayez ceci:
ffmpeg -i in.mkv -vf mpdecimate out.mkv
ou
ffmpeg -i in.mkv -vf decimate=cycle=6,setpts=N/25/TB out.mkv
(cycle=6
parce que toutes les 6 images sont dupliquées et N/25/TB
parce qu'après avoir supprimé les doublons, la vidéo aura 25 fps (évitez les FRAME_RATE
variable); adapter à votre cas d'utilisation)