Welcome Stranger to OCC!Login | Register

Video Capture & Edit Guide

   -   
» Discuss this article (7)

Miscellaneous FFmpeg Uses:

Here I want to talk about two very different things you can also do with FFmpeg that can be useful. The first is exporting frames from a video and the second is how I made the Mod Slide videos for the Fallout 3 and Fallout: New Vegas reviews.

I have found exporting frames from a video with FFmpeg a more effective means of getting screenshots from videos, because it produces a large number of images I can pick from. It can also be useful for finding the exact time something happens in a video when cutting.

The two variables I have set at the beginning of the batch file are start and frames. Frames is just how many frames I want exported, so 60 frames is a second's worth. Start is the time when it should start exporting frames from.

The command is pretty simple and straightforward:

ffmpeg –ss %start% –i "%~1" –vframes %frames% "%~dp1Screenshots – %~n1\%~n1 – %%2d.png" –n

 

All I am doing here is telling FFmpeg how many frames I want it to go through with the -vframes flag and then set the output to be png images. It can also be set to export in the jpg format, but without messing with the quality settings, the results look pretty bad. It is useful if you just want to find the frame that something happens in, because it is quicker to export jpgs than pngs.

 

 

 

 

The output location is set to be a subfolder where the original video is located, with the folder name being Screenshots – the video's name. The screenshots themselves are named the video's name followed by a number. The %%2d entry here is telling FFmpeg to pad the number with zeroes, to make it two digits long (so 1 becomes 01, but 10 remains 10 and 100 remains 100). If I changed it to %%3d it would pad with enough zeroes to pad the number to three digits (1 becomes 001, 10 becomes 010, and 100 remains 100).

Exporting frames is pretty easy to do. The command for creating the Mod Slide videos is not so easy. Trying to get it to work took me a long time, but I gained a better understanding of FFmpeg as a result. Originally I was going to try a split screen effect, which I did put together, but decided that the slide effect is better for what I wanted. The actual name of the file is Left Slide.bat and I use a bit more FFmpeg and batch file magic in it than in other files, as you will soon see. Also it uses four inputs; two images and two videos.

Actually what I am about to describe is not the original command for making those videos. Originally the audio of the top video was used exclusively, but now I have the command set up to fade between the two audio streams at the same time as the video transition occurs. (Given that the action of original videos are very nearly identical, the audio not changing is not a significant issue, but now that I know how to do it better, I want to.)

In order to make the process as efficient as possible, and reduce the possibility of quality loss, I have put all of the instructions into a single command line. Because of how utterly messy that would look, making it harder to read and work on, I broke the command apart using variables and line breaks. Actually I just wanted to use the line breaks, but they broke in the FFmpeg command unless I put them in a variable. For this to work I had to escape the carriage return character with the ^ symbol. What that means is that when the variable is read, it skips the normally invisible carriage return symbol, so it behaves like it is a single line.

This command uses three variables: tstart for when the transition begins; tlength for how long the transition should last; and trimlen, which is the sum of the other two variables and is needed for the audio later. Instead of having to perform the addition myself, I am taking advantage of the /a flag for the set command. It causes the string to be evaluated as a numerical expression to be evaluated. The spaces on either side of the addition sign is necessary.

set /a trimlen=%tstart% + %tlength%

Now we can get to the actual FFmpeg command and the four (yes four) variables I have to broken into. The first variable is comFIFO and I am not fully able to explain what it does, but it is necessary. Without it the buffer fails and that breaks the output video.

set comFIFO=[0] fifo [first]; [1] fifo [second]

I already touched on the fifo commands, so you might be wondering what these bracketed things are. The [0] and [1] are the first and second input streams, because FFmpeg starts counting from zero. The [2] and [3] stream identifiers are for the third and fourth inputs, which are the two images. At this point you may have guessed that the input order for these files is important, and luckily there is an easy way to control this, even when dragging and dropping. First make sure the files are properly ordered, meaning the two images are together and the two videos are together (image-image-video-video or video-video-image-image) and the respective orders within these pairs are the same (base-modded-base-modded or modded-base-modded-base). Now select all four files and click-and-hold on the first video to drag them onto the batch file. The file you clicked on is considered the first file selected and the command goes down the list from there, to the second video, and then the two images. So if you have A-B-C-D selected and start dragging from C, the list is read C-D-B-A. This is how Windows does it, so you may find this useful information in other cases as well.

The [first] and [second] parts of the command are naming the output streams from the fifo command, so that FFmpeg can reference them later. They are just intermediary variables.

Now we can get back to the FFmpeg commands with the next variable, comOver:

set comOver=[first][2] overlay [base];^

[second][3] overlay [mod]

It is called comOver because I use the overlay command here. It overlays the second input onto the first, which in this case means the images are put on top of the video streams. In this case the images are simple png files the same resolution as the videos with BASE or MODDED placed where I want them to be on the videos, with transparency everywhere else. It is possible to have FFmpeg directly burn text into a video instead of using images like this, but that is an even more complicated process and honestly, I find this to be a much simpler and more capable process anyway. (The images do not have to be just words after all.) This is first time we see the ^ symbol used to escape a carriage return, but it will not be the last, and again we have intermediary streams here as [base] and [modded].

The next variable is comBlend, which contains the command to blend the videos followed by the scale command we have already seen. It might not be necessary for me to have the intermediate [blended] stream, but I put it there just in case. The [video] stream actually is important, but I will get to that later.

set comBlend=[base][mod] blend=all_expr='if(gte(X,W*(T–%tstart%)/%tlength%),TOP,BOTTOM)' [blended],^

[blended] scale=–1:'min(iw,1080)' [video]

 

The blend command tells FFmpeg to basically fade from one video to another, but can do so in many ways. Because we want it to be applied to every component of the pixels involved, we give it the all_expr flag. The if(gte(X,W*(T–%tstart%)/%tlength%) part means that it should blend the pixels if their X position is greater than or equal to (gte) the width of the video (W) multiplied by the timecode minus the start time I set, divided by the duration I want for the transition. To hopefully help explain this, I am going to start with just gte(X,T).

At the beginning of the video, when T is 0 the gte command will return 1 for every pixel that has an X position value greater than 0, which would be everywhere. If T is 960 then gte will return 0 for all pixels with an X position value from 0 to 959, and 1 for those with an X position value greater than or equal to 960 (which I picked because it is half of 1920).

If we subtract from the T value that same 960, then until we get to T=960, the gte command will always return 1 because the X values are all positive while the other expression will return negative values. Subtracting from T shifts the time the transition starts, giving us T–%tstart%.

By multiplying T by W, the width of the input video, the speed of the transition is increased so that by the time T is 1, every value of X will be less (W*(T–%tstart%)). Dividing by the 'tlength' variable slows the transition down again, so it takes more than one second. Now we have W*(T–%tstart%)/%tlength%) and I can continue when the transition starts and how long it lasts by changing the tstart and tlength variables.

Getting back to the blend command, the TOP and BOTTOM options identify the two input video streams, with TOP being the first stream, base, and BOTTOM being the second stream, mod. If the gte command returns a 1, then pixels from the TOP or base stream are used, and if the command returns 0 then pixels from the BOTTOM or mod stream are used instead.

The last variable is comAudio and was actually a lot harder to get everything in it to work than you might expect. It is actually why comFIFO is needed above.

set comAudio=[0:a] atrim=end=%trimlen% [0at];^

[1:a] atrim=start=%tstart% [1at];^

[0at][1at] acrossfade=d=%tlength% [audio]

The [0:a] and [1:a] labels are telling FFmpeg to use the audio streams from the first and second inputs and not the video. The atrim command can accept multiple flags, but in this situation I only need two. The first is end=%trimlen% and it tells FFmpeg to end the audio stream at some number of seconds, with trimlen being that number (in this case 10 seconds). The second is start=%tstart% and it means the audio stream should start at tstart seconds (which would be 5 seconds). Because the videos are running together, this trimming results in an overlap for the audio, which is as long as the tlength variable says it should be.

That overlap I just mentioned is necessary for the acrossfade command. Like the trim command, it can take many flags, but in this case just the duration flag is used, as d=%tlength%. (One can write out 'duration' in the command, but I did not feel like it.) Naturally this tells the command how long the crossfade is supposed to last. What it does is fade out the first audio stream it is given, [0at], starting however many seconds from its end, and fades in the second audio stream, [1at], for the same number of seconds at its beginning. It then layers those faded segments over each other, creating the crossfade effect. It is possible to set the curve for both fades, but I am happy with the default triangular, linear slope.

Now that we have covered these command variables, time to get to the full FFmpeg command:

ffmpeg –i "%~1" –i "%~2" –i "%~3" –i "%~4" –filter_complex "%comFIFO%,%comOver%,%comBlend%,%comAudio%" ^

–map [video] –map [audio] –crf 18 –preset slower "%~dp1%folder%\%~n1 – Slide.mp4" –y

You can see we have the four inputs followed by the –filter_complex flag. Both the overlay and blend filters are considered complex filters, so we need to call them with the –filter_complex flag, instead of the –vf flag we could use with the scale filter earlier.

The [video] stream identifier I mentioned earlier, and the [audio] stream that is listed but I did not mention, are both here now with the map command. Normally FFmpeg will select what video and audio streams it should put in the output file, but it is possible to tell it which ones specifically, and that is what the map command does. With it I am telling FFmpeg I want those specific video and audio streams, because after working with so many streams, I do not want it to get confused, and pick the wrong ones.

That is quite a lot I suspect, but it actually all works. Let me add just this one more bit on top. You may notice that in some of the command variables I use a semicolon between individual commands and in others I use commas. They actually do mean different things and can cause problems if you are not careful. Commas separate commands within one chain while semicolons separate entire chains, and this can impact FFmpeg's ability to imply what inputs to use for subsequent commands. Correctly using commas and semicolons will prevent these problems, as can properly labelling intermediate streams so nothing has to be implied. Chances are I am not using them in the most correct or efficient way, but it works and I can understand the commands, and in the end, that is what matters.

I covered quite a bit and there is even more I could cover. I also have a batch file for making GIFs, renaming, scaling, and converting the screenshots I take, cropping videos, burning arbitrary text onto a video, burning the timecode, concatenating videos, changing the volume, and the terrifying SplitScreen.bat file. (I pass it two videos, tell it if I want the split to be horizontal or vertical and if I want the 'screens' to mirror each other or be half-and-half, and by magic it actually works.) I think this is enough for you to get started with your own capturing and editing experiments, so have fun!




  1. Video Capture & Edit Guide - Introduction and Software
  2. Video Capture & Edit Guide - Capture and Editing Methods
  3. Video Capture & Edit Guide - Miscellaneous FFmpeg Uses
Related Products
Random Pic
© 2001-2017 Overclockers Club ® Privacy Policy
Elapsed: 0.1475708485   (xlweb1)