Video Editing Individual Frames
When using video editing software like FlowBlade or OpenShot, there are occasions when a single frame needs to be extracted, either to observe, to use as an image or to adjusted and re-inserted.
While packages have means to change content even on a single frame level, sometimes bespoke actions are needed. One way to do this is with ffmpeg.
While packages have means to change content even on a single frame level, sometimes bespoke actions are needed. One way to do this is with ffmpeg.
What is ffmpeg?
ffmpeg is a command line tool - i.e. you use it by typing ffmpeg followed by various options on the command line. ffmpeg in fact sits on top of a number of libraries. It uses these libraries to do manipulation of video files. It supports, basically, all video formats.
For the purposes of this blog, we're interested a small aspect of ffmpeg's functionality, namely that pertaining to individual video frames.
Finding the Frame
In order to extract (for whatever purpose) a single frame from a video, first that frame must be located. With FlowBlade and OpenShot, sequencing of videos within an application is by hours/minutes/seconds and then frames. Typically this is specified as hh:mm:ss:fr, so the 33rd frame of a 60 FPS video at half past 10pm and 25 seconds would be 22:30:25:33.
In order to extract a frame you call ffmpeg with the appropriate arguments. However, to pick out a particular frame within a second (i.e. not the first frame) ffmpeg requires it identified in the hundredths of a second - not the frame number. The translation is not difficult - the following formula can be used:
hundredth-of-second = 100 x (frame-number/frames-per-second)
On the ffmpeg command like this is then written as hh:mm:ss.hd (where hd represents hundredths of a second). Therefore the above becomes 22:30:25.55 since 100 x (33/60) is 55. When the result is not an integer, the correct course is to round up (assuming there are less than 100 frames per second): the beginning of the next millisecond should be in the same frame in that case.
Extracting
The format for the command line is:
ffmpeg -i <name>.<video input file extension> -frames:v <number of frames> -ss <hh>:<mm>:<ss>.<hr> <frame name root><distinguishing format>.<output image file extension>
ffmpeg uses the extensions to work out the required formats (they can be specified explicitly - see the docs). Many frames can be extracted if needed - the frames:v option specifies how many. In that case, the distinguishing format is used to name the output files (one for each frame) differently: for example the "%02d" below inserts the 2 digit number of the frame extracted in the file-name. The file naming format is a subset of the C/C++ printf command restricted to integer formats.
If the video is MyVideo.mp4 then the command-line to extract the above is:
ffmpeg -i MyVideo.mp4 -frames:v 1 -ss 22:30:25.55 MyFrame%02d.png
While the above seems cumbersome, ffmpeg is efficient, so typically runs quickly. With most shells successive runs can easily be created from earlier ones by up-arrowing through the command history.
Comments
Post a Comment