web-dev-qa-db-fra.com

Montage vidéo en ligne de commande sous Linux (couper, rejoindre et prévisualiser)

J'ai des besoins d'édition assez simples: je dois découper certaines vidéos, peut-être insérer des PNG entre elles et les joindre (vous n'avez pas besoin de transitions, d'effets, etc.). pitivi ferait ce que je veux - sauf que j'utilise des AVI 640x480 30 ips avec une caméra et que, dès que j'ai mis quelques minutes de ce type de matériel, pitivi se fige en prévisualisation et devient donc inutilisable.

J'ai donc commencé à chercher un outil de ligne de commande pour Linux; Je suppose que seulement ffmpeg ( ligne de commande - Utilisation de ffmpeg pour couper la vidéo - Super utilisateur ) et mplayer ( Sam - Éditer un fichier vidéo avec mencoder sous linux ) sont pour l’instant candidats, mais je ne trouve pas d’exemples de l’utilisation que j’envisage.

En gros, j'imagine qu'il existe un encodeur et des outils de lecture (tels que ffmpeg vs ffplay; ou mencoder vs mplayer) - tels que, pour commencer, la séquence d'édition puisse être spécifiée directement sur la ligne de commande, de préférence avec une résolution de trame - un pseudocode ressemblerait à ceci:

videnctool -compose --file=vid1.avi --start=00:00:30:12 --end=00:01:45:00 --file=vid2.avi --start=00:05:00:00 --end=00:07:12:25 --file=mypicture.png --duration=00:00:02:00 --file=vid3.avi --start=00:02:00:00 --end=00:02:45:10 --output=editedvid.avi

... ou, il pourrait avoir un fichier texte "playlist", comme:

vid1.avi      00:00:30:12 00:01:45:00 
vid2.avi      00:05:00:00 00:07:12:25 
mypicture.png -           00:00:02:00
vid3.avi      00:02:00:00 00:02:45:10 

... afin qu'il puisse être appelé avec

videnctool -compose --playlist=playlist.txt --output=editedvid.avi

L’idée ici serait que toutes les vidéos soient dans le même format - ce qui permet à l’outil d’éviter le transcodage et de créer simplement une "copie brute" (comme dans mencoder's copy codec: "-oac copy -ovc copy") - ou faute de cela, un fichier audio/vidéo non compressé serait OK (bien que cela prenne un peu de place). Dans le cas de l'image fixe, l'outil utiliserait l'encodage défini par les fichiers vidéo.

Le fait est que, jusqu’à présent, je peux voir que mencoder et ffmpeg peuvent fonctionner sur des fichiers individuels; par exemple. couper une section unique à partir d’un fichier unique ou joindre des fichiers (mencoder a également la liste des décisions à modifier (EDL) , qui peut être utilisée pour effectuer frame-exact de coupe - vous pouvez donc définir plusieurs régions de coupe, mais elles sont à nouveau attribuées à un seul fichier). Ce qui implique que je doive commencer par couper des morceaux dans des fichiers individuels (chacun nécessitant son propre fichier temporaire sur disque), puis les joindre dans un fichier vidéo final.

J'imagine alors qu'il existe un outil de lecture correspondant, capable de lire le même fichier de format d'option/liste de lecture en ligne de commande que l'outil de codage, à la différence qu'il ne générera pas de fichier de sortie mais lira la vidéo. par exemple. en pseudocode:

vidplaytool --playlist=playlist.txt --start=00:01:14 --end=00:03:13

... et, avec suffisamment de mémoire, il générerait un aperçu vidéo basse résolution dans la RAM et le lirait dans une fenêtre tout en offrant une interaction limitée (comme les raccourcis clavier de mplayer pour jouer, mettre en pause, revenir en arrière, image par image). Bien sûr, j'imagine que les heures de début et de fin se réfèrent à la liste de lecture entière et incluent tout fichier susceptible de se retrouver dans cette région dans la liste de lecture.

Ainsi, le résultat final de tout cela serait: opération en ligne de commande; pas de fichiers temporaires lors de l'édition - ni de fichiers temporaires (ni de transcodage) lors du rendu de la sortie finale ... ce qui, à mon avis, serait bien.

Donc, même si je pense que tout ce qui précède peut être un peu exagéré - existe-t-il quelque chose qui se rapprocherait du flux de travail décrit ci-dessus?

32
sdaau

Oui il y a. Essayez d'utiliser l'application appelée "Melt". Voir la documentation ici:

https://www.mltframework.org/docs/melt/

Si vous utilisez une distribution dérivée de Debian:

apt-get install melt
17
Ielton

Ok, étant donné que je ne trouve pas grand chose à propos de l'utilisation de la ligne de commande melt, voici quelques notes .. (et après cela, voyez cette réponse Utilisation de la substitution de processus pour piéger des programmes, avec des extensions spécifiques comme argument ? - Unix et Linux Stack Exchange pour un exemple de script via bash)

Pour commencer, il existe un paquet Ubuntu/Debian pour melt (j'ai Ubuntu 11.04 avec MLT melt 0.6.2); le lien indiqué par @ Ielton est destiné au wiki "Media Lovin 'Toolkit" (MLT), dont melt fait partie (mais aussi openshot et kdenlive ). Voici le lien vers les fichiers texte de la documentation de leur git: mltframework.org/mlt.git/tree - docs/ ; notez que le wiki a une page sur BuildScripts .

Pour l'instant, le plus gros (unique) problème que j'ai avec elle est que je ne trouve pas le moyen d'exporter une composition vidéo non compressée (sous la forme d'images png ou d'un format vidéo non compressé).

Tout d'abord, dans la ligne de commande melt, vous pouvez contrôler la lecture par le biais d'images. par exemple, pour "créer" un blanc vierge de 15 images de long et l'afficher avec le lecteur melt intégré, utilisez

melt -blank 15

Lorsque vous affichez avec melt, vous obtiendrez également une information de ligne de commande sur stderr pour le lecteur intégré:

$ melt -blank 15 
+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
|1=-10| |2= -5| |3= -2| |4= -1| |5=  0| |6=  1| |7=  2| |8=  5| |9= 10|
+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
+---------------------------------------------------------------------+
|               H = back 1 minute,  L = forward 1 minute              |
|                 h = previous frame,  l = next frame                 |
|           g = start of clip, j = next clip, k = previous clip       |
|                0 = restart, q = quit, space = play                  |
+---------------------------------------------------------------------+
Current Position:         15

Une fois que melt est terminé, la lecture n’est pas terminée. Vous devez donc saisir q pour la quitter.

Notons qu'il existe des prétendus "producteurs" et "consommateurs" dans melt. Si rien n'est spécifié, le "consommateur" par défaut est une fenêtre SDL (Simple DirectMedia Layer) lisant la vidéo; la commande ci-dessus est donc la même chose que:

melt -blank 15 -consumer sdl

Ainsi, si nous voulons enregistrer ce que melt affiche, nous devons changer le consommateur en quelque chose qui supportera un format de fichier. Pour obtenir une liste de consommateurs:

$ melt -query "consumers"
---
consumers:
  - sdl
  - sdl_audio
  - sdl_preview
  - sdl_still
  - gtk2_preview
  - avformat
  - libdv
  - xml
  - decklink
  - null
...

Le consommateur libdv générera des données au format DV directement dans stdout. Pour enregistrer la vidéo dans un fichier .dv, procédez comme suit:

melt -blank 15 -consumer libdv > test.dv

Notez que parmi les utilisateurs répertoriés, le seul format que j'ai essayé, pouvant également être ouvert dans une autre application, est libdv (j'ai utilisé vlc comme autre application); cependant, cela peut échouer pour un type de transcodage différent (. Par exemple, si au lieu d’un blanc, j’essaie de convertir un extrait de code à partir d’un fichier .flv, le fichier .dv résultant s’ouvre et est lu dans vlc, mais est corrompu ).

Passons maintenant à la partie d'édition ; vous pouvez essentiellement spécifier une série de strophes nom de fichier /in/out directement sur la ligne de commande; disons que vous avez un fichier, video.avi - alors vous pourriez faire:

melt video.avi in=30 out=79 -blank 15 video.avi in=30 out=79

ou légèrement mieux formaté:

melt \ 
video.avi in=30 out=79 \ 
-blank 15 \
video.avi in=30 out=79

Cela signifie que video.avi de son image 30 à son image 79 sera joué; puis une ébauche de 15 images; et ensuite la séquence video.avi de la trame 30 à la trame 79 à nouveau.

Pour utiliser des images (par exemple, .png) dans une composition de montage vidéo:

melt \
video.avi in=30 out=79 \
test.png in=0 out=15 \
video.avi in=30 out=79 \
-blank 15

Notez que pour test.png, le paramètre in= n'a pas besoin d'être à 0. Cependant, l'image sera affichée pendant out-in temps; dans ce cas, il serait plus simple de simplement laisser le paramètre in=0 complètement.

La bonne chose est que cette séquence d’édition peut être enregistrée - ou comme melt l’appelle, sérialisée - dans un fichier; notez qu'il existe deux méthodes de cette sérialisation: "simple" ou XML. Par exemple, pour enregistrer la commande ci-dessus en tant que fichier "simple" sérialisé, il suffit d'ajouter le commutateur -serialise [filename] à la commande:

$ melt video.avi in=30 out=79 -blank 15 video.avi in=30 out=79 -serialise file.melt 
Project saved as file.melt.

Maintenant, le file.melt contient:

video.avi
in=30
out=79
-blank
15
video.avi
in=30
out=79

Apparemment, ce format de fichier sérialisé "simple" ne contient pas de caractère "de commentaire" - si j'essaie d'ajouter une ligne "# comment", melt se plaint avec: ' Impossible de charger "# comment" '(mais à part ça, il semble qu'une telle ligne est ignorée et la lecture continue quand même). ".melt" semble être une extension que melt reconnaît comme un fichier sérialisé simple.

Maintenant, pour relire ce fichier sérialisé, nous pourrions en principe simplement appeler melt file.melt - cependant, une ligne de commande plus complète serait:

melt melt_file:file.melt -consumer sdl

... ce qui voudrait dire: utilisez le melt_file "producteur" pour ouvrir file.melt et restituer ses images dans le "consommateur" sdl (fenêtre).

Notez que j’ai l’expérience que (par exemple) les vidéos .flv sont lues sans problème sur la ligne de commande. Toutefois, elles entraînent une erreur de segmentation lorsqu’elles sont spécifiées dans le fichier sérialisé file.melt! Les vidéos .dv produites par melt elle-même semblent bien fonctionner dans file.melt...

Le type de sérialisation XML peut être obtenu en utilisant le commutateur -consumer xml: ( au lieu de -serialise). L’exemple ci-dessus serait donc:

melt video.avi in=30 out=79 -blank 15 video.avi in=30 out=79 -consumer xml:file.mlt

Pour "lire" le fichier XML file.mlt nouvellement généré, on peut maintenant faire directement melt file.mlt - ou une ligne de commande plus complète serait:

melt xml:file.mlt -consumer sdl

... ce qui voudrait dire: utilisez la xml "producteur" ( remarque, auparavant c'était un consommateur ) pour ouvrir file.mlt et restituer ses cadres sur le "consommateur" sdl (fenêtre).

Notez que dans ce cas, j'ai constaté que les mêmes vidéos .flv qui ont causé segfault avec un simple fichier de sérialisation - fonctionnent parfaitement avec un fichier de sérialisation XML!

Dans ce cas, le fichier XML file.mlt résultant contient beaucoup plus de paramètres, tels que la résolution, la fréquence d'images, les informations de codec, etc. - mais il est également plus difficile de travailler directement dans un éditeur de texte:

<?xml version="1.0" encoding="utf-8"?>
<mlt root="/path/to" title="video.avi">
  <profile description="automatic" width="320" height="240" progressive="1" sample_aspect_num="1" sample_aspect_den="1" display_aspect_num="320" display_aspect_den="240" frame_rate_num="25" frame_rate_den="1" colorspace="601"/>
  <producer id="producer0" in="30" out="79">
    <property name="mlt_type">producer</property>
    <property name="aspect_ratio">1.000000</property>
    <property name="length">125</property>
    <property name="eof">pause</property>
    <property name="resource">video.avi</property>
    <property name="meta.media.nb_streams">2</property>
    <property name="meta.media.0.stream.type">video</property>
    <property name="meta.media.0.stream.frame_rate">25.000000</property>
    <property name="meta.media.0.stream.sample_aspect_ratio">0.000000</property>
    <property name="meta.media.0.codec.frame_rate">25.000000</property>
    <property name="meta.media.0.codec.pix_fmt">yuv420p</property>
    <property name="meta.media.0.codec.sample_aspect_ratio">1.000000</property>
    <property name="meta.media.0.codec.colorspace">601</property>
    <property name="meta.media.0.codec.name">mpeg4</property>
    <property name="meta.media.0.codec.long_name">MPEG-4 part 2</property>
    <property name="meta.media.0.codec.bit_rate">0</property>
    <property name="meta.media.1.stream.type">audio</property>
    <property name="meta.media.1.codec.sample_fmt">s16</property>
    <property name="meta.media.1.codec.sample_rate">22050</property>
    <property name="meta.media.1.codec.channels">1</property>
    <property name="meta.media.1.codec.name">mp2</property>
    <property name="meta.media.1.codec.long_name">MP2 (MPEG audio layer 2)</property>
    <property name="meta.media.1.codec.bit_rate">64000</property>
    <property name="seekable">1</property>
    <property name="meta.media.sample_aspect_num">1</property>
    <property name="meta.media.sample_aspect_den">1</property>
    <property name="meta.attr.title.markup"></property>
    <property name="meta.attr.author.markup"></property>
    <property name="meta.attr.copyright.markup"></property>
    <property name="meta.attr.comment.markup"></property>
    <property name="meta.attr.album.markup"></property>
    <property name="audio_index">1</property>
    <property name="video_index">0</property>
    <property name="mlt_service">avformat</property>
  </producer>
  <producer id="producer1" in="30" out="79">
    <property name="mlt_type">producer</property>
    <property name="aspect_ratio">1.000000</property>
    <property name="length">125</property>
    <property name="eof">pause</property>
    <property name="resource">video.avi</property>
    <property name="meta.media.nb_streams">2</property>
    <property name="meta.media.0.stream.type">video</property>
    <property name="meta.media.0.stream.frame_rate">25.000000</property>
    <property name="meta.media.0.stream.sample_aspect_ratio">0.000000</property>
    <property name="meta.media.0.codec.frame_rate">25.000000</property>
    <property name="meta.media.0.codec.pix_fmt">yuv420p</property>
    <property name="meta.media.0.codec.sample_aspect_ratio">1.000000</property>
    <property name="meta.media.0.codec.colorspace">601</property>
    <property name="meta.media.0.codec.name">mpeg4</property>
    <property name="meta.media.0.codec.long_name">MPEG-4 part 2</property>
    <property name="meta.media.0.codec.bit_rate">0</property>
    <property name="meta.media.1.stream.type">audio</property>
    <property name="meta.media.1.codec.sample_fmt">s16</property>
    <property name="meta.media.1.codec.sample_rate">22050</property>
    <property name="meta.media.1.codec.channels">1</property>
    <property name="meta.media.1.codec.name">mp2</property>
    <property name="meta.media.1.codec.long_name">MP2 (MPEG audio layer 2)</property>
    <property name="meta.media.1.codec.bit_rate">64000</property>
    <property name="seekable">1</property>
    <property name="meta.media.sample_aspect_num">1</property>
    <property name="meta.media.sample_aspect_den">1</property>
    <property name="meta.attr.title.markup"></property>
    <property name="meta.attr.author.markup"></property>
    <property name="meta.attr.copyright.markup"></property>
    <property name="meta.attr.comment.markup"></property>
    <property name="meta.attr.album.markup"></property>
    <property name="audio_index">1</property>
    <property name="video_index">0</property>
    <property name="mlt_service">avformat</property>
  </producer>
  <playlist id="playlist0">
    <entry producer="producer0" in="0" out="49"/>
    <blank length="16"/>
    <entry producer="producer1" in="0" out="49"/>
  </playlist>
  <tractor id="tractor0" title="video.avi" global_feed="1" in="0" out="115">
    <track producer="playlist0"/>
  </tractor>
</mlt>
22
sdaau

La solution de ffmpeg à ce problème ressemble à ceci:

mkfifo temp1 temp2 temp3
ffmpeg -i input.wmv -ss 30 -to 60 -c copy output.wmv temp1 2> /dev/null & \
ffmpeg -i input2.wmv -t 60 -c copy temp2 2> /dev/null & \
ffmpeg -i input3.wmv -i image.png -filter_complex "[0:v][1:v] \
overlay=25:25:enable='between(t,0,20)'" -pix_fmt yuv420p -c:a copy temp3 2> /dev/null & \
ffmpeg -f mpegts -i "concat:temp1|temp2|temp3" -c copy output.mp4

Il utilise des canaux nommés. Il est donc impossible de créer des fichiers temporaires sur le disque. Il vous permet de découper des morceaux de clips vidéo et d'ajouter des images.

Cet exemple utilise les temps 30 à 60 de la première entrée, puis ajoute la première minute de la deuxième entrée, puis insère un fichier image, puis la troisième vidéo entière.

Code levé de:

ffmpeg concaténer la page: https://trac.ffmpeg.org/wiki/Concatenate

page superutilisateur Utilisation de ffmpeg pour couper une vidéo

page de superutilisateur https://video.stackexchange.com/questions/12105/add-an-image-in-front-of-video-using-ffmpeg

6
codeMonkey

Moi aussi, je recherchais un tel outil et il semble bien que la fusion soit l'outil idéal pour le travail. Cependant, la documentation est presque impossible à comprendre/manquante. Vous pouvez faire presque n'importe quelle combinaison de montage. J'avais quelques images de "action cam" ... le son était cependant inutilisable. J'ai rejoint la vidéo (h264) ensemble, ajouté un fondu de 60 images et remplacé le son par une piste sonore utilisant:

% melt -video-track vid1.avi vid2.avi -mix 60 -mixer luma vid3.avi \
   -mix 60 -mixer luma -audio-track vorbis:track1.ogg vorbis:track2.ogg \
   -consumer avformat:OUT.avi acodec=libmp3lame vcodec=libx264

Vous pouvez en lire plus à ce sujet ici . Le site Web principal est ici .

4
user196805