Comment diviser des fichiers vidéo en cas de changement de résolution détecté? (c'est-à-dire des flux enregistrés contenant plusieurs largeurs)

2

J'ai beaucoup de fichiers vidéo (flv / mp4) qui changent de résolution en cours de flux (720p / 1080p / 640).

J'aimerais utiliser quelque chose comme ffmpeg pour détecter automatiquement le changement de résolution et scinder les vidéos en scènes individuelles, en conservant la qualité d'encodage existante: segment sans réencodage (Video1-scene1.flv, Video1-scene2.flv, etc.) .

J'ai trouvé diverses méthodes pour diviser sur le silence, sur le changement de scène, sur les scènes noires, mais rien d'aussi simple qu'un changement de largeur de résolution.

Ces fichiers entraînent souvent le blocage des éditeurs / trimmers vidéo. Identifier et supprimer manuellement les scènes basse résolution prend beaucoup de temps si je convertis simplement la vidéo entière en 1080p.

L'algorithme est probablement aussi simple que de comparer l'image actuelle à l'image précédente. S'il s'agit de résolutions différentes, divisez la vidéo et démarrez un nouveau segment.

Quelqu'un peut-il aider s'il vous plaît?

EXEMPLE DE FICHIER (temporarily available): Example.flv

Voici quelques réponses connexes:

Couper une partie du fichier vidéo de la position de départ à la position de fin avec FFmpeg

https://stackoverflow.com/questions/36074224/how-to-split-video-or-audio-by-silent-parts

Scinder automatiquement les gros fichiers vidéo .mov en fichiers plus petits avec des cadres noirs (changements de scène)?

Scinder une vidéo à l'aide de FFMPEG via la détection de scène

Ressources supplémentaires:
En utilisant la solution de Lord Neckbeard, je joins le processus (malheureusement très manuel) que je me suis finalement mis à travailler sur Windows 10. Peut-être que cela pourrait engendrer d'autres idées autour de ffmpeg.
(J'ai posté une question distincte destinée à quiconque ayant suffisamment de ressources GURU pour: automatiser ce processus ... )

faites glisser la vidéo sur un fichier de commandes contenant:

ffprobe -v erreur -show_entries frame = pkt_pts_time, largeur, hauteur -select_streams v -of csv = p = 0% 1> allkeyframes.txt

(exemple allkeyframes.txt ...)

13.652000,640,480
13.755000,640,480
13.597000,480,360
13.652000,480,360

collez ce texte dans POWERSHELL:

$o=""
$n=0
foreach($line in (Get-Content allkeyframes.txt)){
  $nline = $line.Split(",")
  $nline2=($nline[1]+$nline[2])
  if ($nline2 -ne $preventry) {
    $n0=$nline[0]
    $o="$o,$n0"
    $n=$n0
}
  $preventry = $nline2
}
if ($o.length -gt 1){
echo $o.Remove(0,1) > resolutionchanges.txt
} else {
Write-Host "No resolution changes found" -ForegroundColor Red
}

(resolutionchanges.txt :)

13.597000,25.618000,33.628000,45.598000

Entrez ce qui suit dans la fenêtre de commande, après avoir collé le contenu de resolutionchanges.txt et remplacé "input.flv" par le nom de la vidéo (Win10 a refusé mes tentatives de traitement par lot):

ffmpeg -i input.flv -map 0 -c copy -segment_times 13.597000,25.618000,33.628000,45.598000 -reset_timestamps 1 -f segment de sortie_% 03d.flv

EverT
la source

Réponses:

0

La solution Lazyman consiste à utiliser le filtre d'échelle pour adapter chaque entrée à une largeur x hauteur souhaitée .

Pour votre solution proposée, vous pouvez utiliser ffprobepour déterminer quand les changements de taille se produisent.

ffprobe -v error -show_entries frame=pkt_pts_time,width,height -select_streams v -of csv=p=0 input.flv

Exemple d’extrait de sortie lors du changement de largeur et de hauteur (key_frame, pkt_pts_time, width, height):

0,89.081000,480,640
0,89.281000,480,640
0,89.481000,480,640
1,89.568000,640,480
0,89.592000,640,480
0,89.632000,640,480
1,97.749000,480,640

Les changements de taille se produiront probablement sur les images clés, c’est à cet endroit que vous pouvez effectuer les coupes si la copie de flux est une nécessité. Si vous voulez seulement les images clés, ajoutez l' -skip_frame nokeyoption.

Ensuite, utilisez le segment muxer :

ffmpeg -i input.flv -map 0 -c copy -segment_times 89.568,97.749 -reset_timestamps 1 -f segment output_%03d.flv
llogan
la source
1
MERCI! Cela seul me sauve des semaines d'effort! J'espère toujours quelque chose d'un peu plus efficace (idéalement dans ffmpeg seul), mais à l'exception de 5 secondes de noir sur le premier segment vidéo, il semble que cela fonctionne. Je n'ai eu aucun succès dans la tuyauterie dans Windows10 ni avec les fichiers Batch (variables ignorées de manière incohérente), donc tout conseil serait également apprécié. (J'ajouterai le script Powershell que je devais utiliser manuellement au cas où cela aiderait quelqu'un d'autre).
EverT
@EverT Je ne suis pas un grand utilisateur Windows. Je n'ai donc aucune suggestion à propos de Powershell, etc., mais vous pouvez poser une nouvelle question pour traiter le (s) problème (s) spécifique (s) de Windows et laisser ce Q & R spécifique ffmpegpartie. Cela évitera que les questions soient trop larges et trop larges et vous aurez plus de chances d'obtenir des réponses.
llogan
@ LordNeckbeard - Excellent conseil. J'ai éclaté la pipequestion séparément. J'ai laissé la solution «en quelque sorte» efficace aux autres, juste au cas où une approche plus directe ne serait pas trouvée. Je souhaiterais avoir les connaissances nécessaires pour compléter votre réponse grep pour ces utilisateurs de Google qui en auraient besoin un jour.
EverT
@EverT Essayez d'ajouter -skip_frame nokey. J'ai oublié ça quand j'ai écrit la réponse. Doit avoir une optionite: commence à les oublier. Ensuite, vous pouvez passer de la tuyauterie à un autre processus.
llogan
@ LordNeckbeard- Est-ce qu'il importe où? Dans un clip de 30 secondes avec 5 changements de résolution, -skip_frame nokeyréduit le texte ffprobe de 848 lignes à 21, mais cela déclencherait quand même 21 segments au lieu de 5. Le traitement est nettement plus rapide! (merci!)
EverT