Redimensionner des vidéos avec ffmpeg / avconv pour les adapter à un lecteur de taille statique

65

J'ai un lecteur vidéo html 5 de 700 pixels de large et 400 pixels de haut. J'essaie d'utiliser avconvffmpeg pour redimensionner (tout en conservant le rapport de format) et pour m'assurer qu'il s'intègre bien dans mon lecteur.

L'entrée peut être un fichier de n'importe quelle taille, je dois donc redimensionner les plus gros mais centrer les plus petits avec des barres noires. Jusqu'ici, j'ai essayé: -set -aspect, j'ai déjà vu padêtre utilisé avec l' -vfinterrupteur mais je ne comprends pas comment cela fonctionne assez pour obtenir ce dont j'ai besoin.

Images

Ceci est une idée approximative de ce dont j'ai besoin. Je ne sais pas si c'est même possible. C'est presque comme la largeur maximale / maximale de CSS. Je réalise que ce n'est peut-être qu'un mélange de mots, mais si quelqu'un comprenait de quoi je parle, j'apprécierais de l'aide, merci.

commande avconv:

avconv -y -i control.avi -vcodec libx264 -b 2000k -bufsize 20M -acodec aac -strict experimental -ar 44100 -ab 256k bigbuck_out.mp4

Jamie Taylor
la source
4
J'écrirai une réponse plus tard, mais je pensais mentionner ceci: Ré-encoder une vidéo simplement pour ajouter des colonnes fixes ou des boîtes aux lettres est une idée terrible. Non seulement vous perdrez de la qualité dans ce processus (ou vous augmenterez inutilement la taille du fichier), mais vous empêcherez également de vous débarrasser des barres plus tard. Idéalement, votre lecteur devrait simplement s’occuper de cela et redimensionner la vidéo tout en l’affichant. Quel est votre cas d'utilisation si je peux demander?
Slhck
Nous stockons le fichier d'origine dans un compartiment S3, donc ce n'est pas un problème, et nous le réencodons quand même, car nous acceptons une grande variété de types de vidéos. Tous ces fichiers doivent aboutir à des fichiers h.264 mp4 appropriés pour la lecture en continu. un navigateur. Vous suggéreriez donc de redimensionner la vidéo, puis de créer des colonnes / boîtes aux lettres html / css? Merci
Jamie Taylor
1
En tant que propriétaire de la réponse acceptée, je vous suggérerais de ne pas accepter mon message et d’accepter plutôt la réponse de LordNeckbeard, car c’est la plus récente et la plus simple.
Slhck
@slhck, j'y pensais, avec votre bénédiction, je vais le faire.
Jamie Taylor

Réponses:

52

Une méthode simple consiste à utiliser l' force_original_aspect_ratiooption du filtre d'échelle .

image originale
Image originale. Représente une vidéo au format 640x480, 4: 3.

Dans ces exemples, l'image d'origine sera mise à l'échelle pour tenir dans une sortie au format 16: 9 tout en préservant le rapport d'origine. Pour ce faire, vous pouvez soit:

Pilier ou boîte aux lettres

image de pilier
Image pilarbox. Insertion d’une entrée 640x480 (4: 3) dans une sortie 1280x720 (16: 9).

ffmpeg -i input -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output
  • Cela va redimensionner l'image. Si vous voulez éviter la montée en gamme, voir l'exemple ci-dessous.

  • Le Letterboxing se produirait à la place si le format d'image en entrée est plus large que le format d'image en sortie. Par exemple, une entrée dont le format d'image correspond à 2,35: 1 dans une sortie 16: 9 entraîne un Letterboxing.

Comme ci-dessus mais sans upscaling

pas d'upscaling
640x480 (4: 3) entrée en sortie 1280x720 (16: 9) sans conversion ascendante.

ffmpeg -i input -vf "scale='min(1280,iw)':min'(720,ih)':force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output

Surgir

entrez la description de l'image ici
Image recadrée. Rapport d'aspect d'entrée 4: 3, rapport d'aspect de sortie 16: 9.

ffmpeg -i input -vf "scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720" output
llogan
la source
Et pour moi d'ajouter un remplissage vierge?
Tiago Ferezin le
@TiagoFerezin Qu'est-ce qu'un "remplissage vide"?
llogan
oh désolé, remplissez avec une autre couleur au lieu du noir, par exemple
Tiago Ferezin
2
@TiagoFerezin Ah, oui. Facile à faire. Dans les exemples qui utilisent le filtre pad, vous pouvez ajouter l' coloroption, telle que pad=1280:720:(ow-iw)/2:(oh-ih)/2:color=red(ou vous pouvez utiliser l'hexadécimal si vous préférez). Voir la liste des couleurs .
llogan
61

Voici la commande qui ajouterait pillar ou letterboxing pour une largeur de sortie fixe. C'est un peu long, mais vous devrez spécifier le rembourrage d'une manière ou d'une autre.

Tout d’abord, définissez dans votre shell la largeur et la hauteur de la sortie:

width=700
height=400

Puis lancez la commande:

ffmpeg -i in.mp4 -filter:v "scale=iw*min($width/iw\,$height/ih):ih*min($width/iw\,$height/ih), pad=$width:$height:($width-iw*min($width/iw\,$height/ih))/2:($height-ih*min($width/iw\,$height/ih))/2" out.mp4

Ceci est réduit au strict nécessaire pour redimensionner et garnir: ajoutez vos autres options vidéo et audio à votre guise. Notez que les nombres pour widthet heightdoivent être divisibles par 2 pour fonctionner avec la plupart des codecs.

Voici l'explication de ce qui se passe:

  • Mise à l'échelle:
    • Nous devons d’abord déterminer s’il faut redimensionner en largeur ou en hauteur.
    • Pour ce faire, nous divisons la largeur de sortie par la largeur d'entrée et la hauteur de sortie par la hauteur d'entrée. Cela nous donnera les facteurs d'échelle pour chaque dimension.
    • Nous vérifions ensuite lequel est le plus bas (avec min()) et choisissons uniquement ce facteur pour le redimensionnement.
    • Enfin, nous multiplions la largeur et la hauteur en entrée par ce facteur ( iw*min(…):ih*min(…)).
  • Rembourrage:
    • $width:$height est la largeur et la hauteur de sortie
    • Pour déterminer où placer la vidéo obtenue, nous devons soustraire la largeur mise à l'échelle de la largeur de sortie maximale et la hauteur mise à l'échelle de la hauteur de sortie maximale.
    • Les largeurs et les hauteurs mises à l'échelle sont les expressions du scalefiltre.
    • Nous divisons le décalage résultant par 2 pour ajouter des bordures des deux côtés.
slhck
la source
3
@JamieTaylor Envisagez d'ajouter -movflags +faststartà l'exemple de Slhck. Il permettra à votre vidéo téléchargée pour commencer progressivement la lecture avant la fin du téléchargement, et aussi voir le FFmpeg et x264 Guide de codage et FFmpeg et AAC Guide d' encodage pour plus d' instructions de codage et des exemples.
llogan
Vous pouvez raccourcir le filtre pad à ceci, je pense:pad=$width:$height:(ow-iw)/2:(oh-ih)/2"
jdi
1
@jdi Cela ne fonctionnera pas si vous effectuez une réduction d'échelle, car cela entraînera des valeurs négatives pour ow-iw.
Slhck
Merci pour le point de départ! Cependant, pour obtenir un rapport hauteur / largeur correct pour les vidéos avec un rapport hauteur / largeur d'échantillons! = 1, il faut multiplier chaque occurrence de "iw" par "sar". Par conséquent, CHAQUE occurrence de "iw" est remplacée par "(sar * iw)". dans l'expression du filtre fonctionne pour moi.
Schieferstapel
@slhck Hey, j'essaie dans Android mais ça ne semble pas fonctionner, pouvez-vous m'aider avec ça !!! ffmpeg -i input.mp4 -filter: échelle v = 640 * min (700/640, 400/360): 360 * min (700/640, 400/360), plage = 700: 400: (700-640 * min (700/640, 400) / 360)) / 2: (400-360 * min (700 / 640,400 / 360)) / 2 sorties.mp4
Nisarg
8

Il me semble que vous devez le faire en trois étapes:

  1. Vérifier le format d'image
  2. Redimensionnez les vidéos avec un DAR> 7/4 en largeur (modifiez la largeur en 700 et redimensionnez la hauteur pour conserver le rapport hauteur / largeur), puis redimensionnez les vidéos avec un DAR <7/4 en hauteur
  3. Compilez la vidéo afin qu'elle tienne dans l'espace 700: 400.

FFmpeg / avconv peut effectuer la mise à l'échelle / le remplissage avec des filtres vidéo en une seule étape, en transcodant une seule fois. Par exemple, pour prendre une vidéo 16: 9, redimensionnez-la en largeur, puis en letterbox, les résultats:

ffmpeg -i input.avi -filter:v 'scale=700:-1,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
-c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k output.mp4

... mais pour la première étape (détecter le rapport de format et le comparer au 7: 4 requis), vous devrez utiliser un script quelconque.

ffprobe input.avi 2>&1 | sed -n '/Video:/s/.*DAR \([0-9]*:[0-9]*\)].*/\1/p'

... vous obtiendrez le format de la vidéo, qui ressemblera à "16: 9" ou "4: 3". Dans un script bash, j'utiliserais quelque chose comme:

#!/bin/bash

##  Get the aspect ratio in the form x/y
dar=$(ffprobe test0.mp4 2>&1 | sed -n '/Video:/s/.*DAR \([0-9]*:[0:9]*\)].*/\1/p' | sed 's|:|/|')
##  use bc to do x/y*100 (bash can't handle floats)
DAR=$(bc <<< 'scale=2; $dar*100')

##  ${DAR%.00} will remove the trailing .00 left by bc
if [ ${DAR%.00} -ge 175 ]; then
    ffmpeg -i "$1" -filter:v 'scale=700:-1,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
    -c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k "${1%.*}.mp4
else
    ffmpeg -i "$1" -filter:v 'scale=-1:400,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
    -c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k "${1%.*}.mp4
fi

exit 0

Évidemment, vous devrez l'adapter à vos besoins.

maux de tête
la source
1
Il est possible de le faire en une seule étape, voir ma réponse.
Slhck
@slhck Maintenant, c'est plus facile. Voir la réponse avec guitare-mulet.
llogan
@ LordNeckbeard Merci! J'ai récemment vu cette option, rend beaucoup plus facile en effet.
Slhck