41

I have rather simple editing needs - I need to cut up some videos, maybe insert some PNGs in between them, and join these videos (don't need transitions, effects, etc.). Basically, pitivi would do what I want - except, I use 640x480 30 fps AVI's from a camera, and as soon as I put in over a couple of minutes of that kind of material, pitivi starts freezing on preview, and thus becomes unusable.

So, I started looking for a command line tool for Linux; I guess only ffmpeg (command line - Using ffmpeg to cut up video - Super User) and mplayer (Sam - Edit video file with mencoder under linux) are so far candidates, but I cannot find examples of the use I have in mind.

 

Basically, I'd imagine there's an encoder and player tools (like ffmpeg vs ffplay; or mencoder vs mplayer) - such that, to begin with, the edit sequence could be specified directly on the command line, preferably with frame resolution - a pseudocode would look like:

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

... or, it could have a "playlist" text file, like:

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 

... so it could be called with

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

The idea here would be that all of the videos are in the same format - allowing the tool to avoid transcoding, and just do a "raw copy" instead (as in mencoder's copy codec: "-oac copy -ovc copy") - or in lack of that, uncompressed audio/video would be OK (although it would eat a bit of space). In the case of the still image, the tool would use the encoding set by the video files.

 

The thing is, I can so far see that mencoder and ffmpeg can operate on individual files; e.g. cut a single section from a single file, or join files (mencoder also has Edit Decision Lists (EDL), which can be used to do frame-exact cutting - so you can define multiple cut regions, but it's again attributed to a single file). Which implies I have to work on cutting pieces first from individual files first (each of which would demand own temporary file on disk), and then joining them in a final video file.

I would then imagine, that there is a corresponding player tool, which can read the same command line option format / playlist file as the encoding tool - except it will not generate an output file, but instead play the video; e.g. in pseudocode:

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

... and, given there's enough memory, it would generate a low-res video preview in RAM, and play it back in a window, while offering some limited interaction ( like mplayer's keyboard shortcuts for play, pause, rewind, step frame). Of course, I'd imagine the start and end times to refer to the entire playlist, and include any file that may end up in that region in the playlist.

Thus, the end result of all this would be: command line operation; no temporary files while doing the editing - and also no temporary files (nor transcoding) when rendering final output... which I myself think would be nice.

So, while I think that all of the above may be a bit of a stretch - does there exist anything that would approximate the workflow described above?

2
  • 1
    I also often use mkvmerge when I need to split/join videos.
    – Vi.
    Nov 25, 2011 at 21:53
  • Thank for that, @Vi. - had never heard about mkvmerge before, will make sure I check it out.. Cheers!
    – sdaau
    Nov 26, 2011 at 16:00

5 Answers 5

20

Yes, there is. Try using the app called "Melt". See the documentation here.

If you use a Debian derived distro:

apt-get install melt
1
  • on mac: brew install mlt Dec 17, 2018 at 13:53
27

Ok, since I cannot find much about melt command line usage, here are some notes.. (and after this, see this answer Using process substitution to trick programs expecting files, with specific extensions as argument? - Unix & Linux Stack Exchange for a script example via bash)

To begin with - there is a Ubuntu/Debian package for melt (I have Ubuntu 11.04 with MLT melt 0.6.2); the link given by @Ielton is for the "Media Lovin' Toolkit" (MLT) Wiki, which melt is a part of (but also openshot and kdenlive). Here is the link to the documentation text files from their git: mltframework.org/mlt.git/tree - docs/; note the wiki has a page about BuildScripts.

For now, the biggest (only) problem I have with it, is that I cannot find a way to export an uncompressed video composition (either as png frames, or some uncompressed video format).

 

First, in command-line melt you can control playback through frames; for instance, to "create" a 15-frame long white blank, and view it with the built-in melt player, use

melt -blank 15

When you view with melt, you will also get a command line info to stderr for the built-in player:

$ 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

Once melt is done playing back, it will not exit - so you should type q to exit it.

We should note there are so-called "producers" and "consumers" in melt. If nothing is specified, then the default "consumer" is an SDL (Simple DirectMedia Layer) window playing back the video; so the above command is the same as:

melt -blank 15 -consumer sdl

Thus, if we want to save what melt displays, we should change the consumer to something that will support a file format. To get a list of consumers:

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

The libdv consumer will output DV formatted data directly to stdout, so to save the video to a .dv file you'd do:

melt -blank 15 -consumer libdv > test.dv

Note that from the listed consumers, the only format I have tried, that can also be opened in another application is libdv (I used vlc as another application); however, this may fail for a different type of transcoding (e.g. if instead of a blank, I try to convert a snippet from an .flv file, the resulting .dv file opens and plays in vlc, but is corrupt).

 

Now for the editing part; essentially, you can specify a series of file-name/in/out stanzas directly on the command line; say you have a file, video.avi - then you could do:

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

or slightly better formatted:

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

This means video.avi from its frame 30 to its frame 79 will be played; then a 15-frame blank; and then the video.avi sequence from frame 30 to frame 79 again.

To utilize images (say, .png) in a video edit composition:

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

Note that for test.png, in= parameter doesn't need to be 0 - however, the image will be displayed for out-in time; in this case, it would be easiest to simply leave the in=0 parameter out altogether.

 

The good thing is that this editing sequence can be saved - or as melt calls it, serialized - to a file; note there are two ways of such serialization: "simple" or XML. For instance, to save the above command as a "simple" serialized file, we can just add the -serialise [filename] switch to the command:

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

Now the file.melt contains:

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

Seemingly, this "simple" serialized file format doesn't contain a "commenting" character - if I try to add a "# comment" line, melt complains with: 'Failed to load "# comment"' (but apart from that, seems that such a line is ignored, and playback continues anyways). ".melt" seems to be an extension that melt recognizes as simple serialized file.

Now, to re-play back this serialized file, we could in principle just call melt file.melt - however, a more complete command line would be:

melt melt_file:file.melt -consumer sdl

... which would mean: use the melt_file "producer" to open file.melt, and render its frames on the "consumer" sdl (window).

Note that I have the experience, that (say) .flv videos play without a problem on the command line - however, cause a segmentation fault when they are specified in the file.melt serialized file! .dv videos produced by melt itself, seem to work fine in file.melt...

 

The XML type of serialization can be achieved by using the -consumer xml: switch (instead of -serialise) - so the above example would now be:

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

To "play back" the newly generated file.mlt XML file, one can now do directly melt file.mlt - or, a more complete command line would be:

melt xml:file.mlt -consumer sdl

... which would mean: use the xml "producer" (note, previously it was a consumer) to open file.mlt, and render its frames on the "consumer" sdl (window).

Note that in this case, I've experienced that the very same .flv videos that caused segfault with a simple serialization file - work just fine with an XML serialization file!

In this case, the resulting file.mlt XML file has a lot more settings, such as resolution, frame rate, codec information etc - but it is also more difficult to work with in a text editor directly:

<?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>
2
8

The ffmpeg solution to this problem looks something like this:

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

It uses named pipes, so there's no creating temp files on disk, and allows you to cut up chunks of the video clips, and add images.

This examples uses time 30-60 of the first input, and then adds the first minute of the second input, then inserts a image file, and then the entire third video.

Code lifted from:

ffmpeg concatenate page: https://trac.ffmpeg.org/wiki/Concatenate

superuser page Using ffmpeg to cut up video

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

2
  • Thanks for that, I also recently learned of ffmpeg-concat, which is written in JavaScript (and you need npm to install it), so I thought I'd mention it
    – sdaau
    Jan 18, 2019 at 8:16
  • I would argue that using ffmpeg for video editing is ok for a very short video, image slideshow, etc. When you need to edit a complex video with hundreds of scenes, it seems more reasonable to use a video editor such as flowblade to do the cutting and then either directly export the video from the video editor, or export the project to MLT XML file and use either MLT or ffmpeg to do the actual transcoding.
    – Witiko
    Dec 15, 2019 at 15:23
5

I too have been looking for such a tool and it does appear that melt is the tool for the job, however the documentation is almost impossible to understand/missing. You can do almost any combination of editing. I had some 'action cam' footage... the sound was unusable though. I joined the (h264) video together, added a 60 frame fade and replaced sound with a sound track using:

% 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

You can read more about it here. The main website is here.

0
2

If you need something dead simple, then maybe you can use this tool I created (which uses ffmpeg) called EDITLY.

Here's how to use it in your case:

npm install -g editly

Create a file edit.json5, with this content:

{
  defaults: {
    // editly defaults to randomizing transitions, but since you wanted no transitions, set it to null
    transition: null,
  },
  clips: [
    // cutFrom/cutTo values are in seconds
    { layers: [{ type: 'video', path: 'vid1.avi', cutFrom: 30.12, cutTo: 105 },
    { layers: [{ type: 'video', path: 'vid2.avi', cutFrom: 300, cutTo: 432.25 },
    { duration: 2, layers: [{ type: 'image', path: 'mypicture.png' },
    { layers: [{ type: 'video', path: 'vid3.avi', cutFrom: 120, cutTo: 165.1 },
  ],
}

Now run:

editly edit.json5 --out editedvid.mp4

You may also want some of the other features like title screens, text or subtitle overlay and generated backgrounds.

See project page for more info: https://github.com/mifi/editly

3
  • 1
    Please read How do I recommend software for some tips as to how you should go about recommending software. You should provide at least a link, some additional information about the software itself, and how it can be used to solve the problem in the question.
    – DavidPostill
    Apr 22, 2020 at 16:02
  • Thanks for the feedback. Have now added a more detailed explanation Apr 22, 2020 at 17:16
  • 1
    Perfect. Well done :)
    – DavidPostill
    Apr 22, 2020 at 17:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .