From charlesreid1

No edit summary
No edit summary
 
Line 1: Line 1:
Notes on the use of ffmpeg, specifically for timelapse videos.
=Notes=


=Creating Video from Image Files=
==Naming Files==


These notes are based on the notes at the [[Ffmpeg]] page.
For notes on the quirky hoops you have to jump through to name files properly for Ffmpeg, see [[Ffmpeg]] or [[Timelapse/Processing]] pages.


==Renaming Files==
==Running ffmpeg==


One of the quirks of ffmpeg is that, if you are converting a large number of files, they have to be sequentially numbered, <u>starting with 0 OR 1</u>.
Running ffmpeg with "stock" settings for high quality and normal output format (mp4):
 
===Renaming Files: Test Run===
 
The best way to do this is to put all the photos you want to add to your timelapse into one big folder, in the order you want them. Then do a <code>/bin/ls -1</code> to list them all in order. Then use a bash for loop to name each file in a sequential fashion: 0001.jpg, 0002.jpg, etc.


<pre>
<pre>
#!/bin/sh
$ ffmpeg -i 20160730_%04d.jpg -q:v 1 -vcodec mpeg4 movie1.mp4
 
i=1
for file in `/bin/ls -1 *.jpg`; do
    filestrip=$(echo "$file" | sed 's/\.jpg//')
    newfile=$(printf "${filestrip}_%04d.jpg" "$i")
    echo "mv ${file} ${newfile}"
    i=$((i+1))
done
</pre>
 
The output of this file, run on a dummy directory with 8 dummy files (note that it preserves the original filename, without the extension)
 
<pre>
$ ./doit.sh
mv f1.jpg f1_0001.jpg
mv f2.jpg f2_0002.jpg
mv f3.jpg f3_0003.jpg
mv f4.jpg f4_0004.jpg
mv f5.jpg f5_0005.jpg
mv f6.jpg f6_0006.jpg
mv f7.jpg f7_0007.jpg
mv f8.jpg f8_0008.jpg
</pre>
 
===Renaming Files: Real Deal===
 
When it was time to run the real script, I copied the above script into the directory containing the downsampled pile of 8,000 photos, and made one modification: the line that actually EXECUTES, not just PRINTS, the mv command.
 
This strips out the six-digit time suffix, which changes from photo to photo. This gives all of the photos the same prefix, which is also essential for ffmpeg.
 
<pre>
#!/bin/sh
 
i=1
for file in `/bin/ls -1 *.jpg`; do
    filestrip=$(echo "$file" | sed 's/-[0-9]\{6\}\.jpg//')
    newfile=$(printf "${filestrip}_%04d.jpg" "$i")
    echo "mv ${file} ${newfile}"
    mv ${file} ${newfile}
    i=$((i+1))
done
</pre>
 
Ran it. It took almost a minute, but it renamed all the files like a charm.
 
Let's break down that sed expression:
 
<code>sed 's/-[0-9]\{6\}\.jpg//'</code>
 
This looks for an expression like <code>-000000</code> (the <code>[0-9]</code> means any digit, and the <code>\{6\}</code> means 6 in a row), followed by the expression <code>.jpg</code>. This is the six digit hour-minute-second timestamp at the end of the filename, before the suffix. We want to get rid of both the jpg suffix and the non-unique timestamp, so that all the photos will have the same filename prefix.
 
The double slash means, replace whatever you find with the empty string. A few before/afters:
 
<pre>
20160730-165955_8313.jpg
20160730_8313.jpg
 
20160730-170000_8314.jpg
20160730_8314.jpg
 
20160730-170005_8315.jpg
20160730_8315.jpg
 
20160730-170010_8316.jpg
20160730_8316.jpg
 
20160730-170015_8317.jpg
20160730_8317.jpg
 
20160730-170020_8318.jpg
20160730_8318.jpg
</pre>
 
==Using ffmpeg==
 
Now we get to use ffmpeg to stitch these image files together into movies.
 
A full treatment of ffmpeg would take a lot more space, so we'll leave that to the [[Ffmpeg]] page.
 
Here we'll just go through the bare minimum to make a viable timelapse movie.
 
===Reviewing Filenames===
 
Just a review: ffmpeg is very picky about filenames. It expects files to have a similar prefix, and to have a numbering scheme that starts with 0 or 1. Example of a scheme it likes:
 
<pre>
$ /bin/ls -1
20160730_0001.jpg
20160730_0002.jpg
20160730_0003.jpg
20160730_0004.jpg
20160730_0005.jpg
20160730_0006.jpg
20160730_0007.jpg
20160730_0008.jpg
20160730_0009.jpg
20160730_0010.jpg
20160730_0011.jpg
20160730_0012.jpg
20160730_0013.jpg
20160730_0014.jpg
20160730_0015.jpg
20160730_0016.jpg
20160730_0017.jpg
20160730_0018.jpg
20160730_0019.jpg
</pre>
</pre>


Make sure that's what you've got. That's what all the filename wrangling nonsense is about anyway.
This did give me some funny output, showing a frames per second of 56 or 58 (normal should be 26):
 
<pre>
ffmpeg -i 20160730_%04d.jpg -q:v 1 -vcodec mpeg4 movie_output.mp4
</pre>
 
The <code>%04d</code> just means, a 4-digit number that increments, starting at 0 or 1.
 
===Running ffmpeg===
 
When I ran the above ffmpeg command, I saw several lines like this:


<pre>
<pre>
Line 144: Line 24:
</pre>
</pre>


This didn't make much sense to me... 56 frames per second? However, the videos is 5:32, or 332 seconds long, and 332 seconds * 26 frames per second gives 8632, much closer to the actual count of photos in the directory. So, the video looks like it is actually 26 fps.
This didn't make much sense to me... 56 frames per second?  
 
However, the videos is 5:32, or 332 seconds long, and 332 seconds * 26 frames per second gives 8632 frames. That's much closer to the actual count of photos in the directory. So, the video looks like it is actually 26 fps.


====Stock ffmpeg====
===Stock ffmpeg===


The "stock" or baseline ffmpeg command I started with was:
The "stock" or baseline ffmpeg command I started with was:
Line 161: Line 43:
</html>
</html>


===Slower Framerate/Stop Motion===
==Slower Framerate/Stop Motion==


Next I tried a different frame rate, 15 fps, with the <code>-r 15</code> flag. This gives it much more of a stop-motion look - I'm not sure how it's filling in all the frames, but it moves at the same rate. In other words, halving the frame rate will not double the length of your video. Frames are simply removed from the original video. (It may be as crude as showing 15 frames, then stopping for 15 frames.)
Next I tried a different frame rate, 15 fps, with the <code>-r 15</code> flag. This gives it much more of a stop-motion look - I'm not sure how it's filling in all the frames, but it moves at the same rate. In other words, halving the frame rate will not double the length of your video. Frames are simply removed from the original video. (It may be as crude as showing 15 frames, then stopping for 15 frames.)

Latest revision as of 04:05, 31 July 2016

Notes

Naming Files

For notes on the quirky hoops you have to jump through to name files properly for Ffmpeg, see Ffmpeg or Timelapse/Processing pages.

Running ffmpeg

Running ffmpeg with "stock" settings for high quality and normal output format (mp4):

$ ffmpeg -i 20160730_%04d.jpg -q:v 1 -vcodec mpeg4 movie1.mp4

This did give me some funny output, showing a frames per second of 56 or 58 (normal should be 26):

$ ffmpeg -i 20160730_%04d.jpg -q:v 1 -vcodec mpeg4 movie1.mp4
[...]
frame= 3670 fps= 58 q=1.0 size=   32379kB time=00:02:26.80 bitrate=1806.9kbits/s speed=2.31x
frame= 4906 fps= 58 q=1.0 size=   42788kB time=00:03:16.24 bitrate=1786.2kbits/s speed=2.32x
frame= 6611 fps= 56 q=1.0 size=   70847kB time=00:04:24.44 bitrate=2194.8kbits/s speed=2.2
frame= 6639 fps= 56 q=1.0 size=   71354kB time=00:04:25.56 bitrate=2201.1kbits/s speed=2.2

This didn't make much sense to me... 56 frames per second?

However, the videos is 5:32, or 332 seconds long, and 332 seconds * 26 frames per second gives 8632 frames. That's much closer to the actual count of photos in the directory. So, the video looks like it is actually 26 fps.

Stock ffmpeg

The "stock" or baseline ffmpeg command I started with was:

$ ffmpeg -i 20160730_%04d.jpg -q:v 1 -vcodec mpeg4 movie1.mp4

This resulted in the movie below:

Raspberry Pi Timelapse: Midnight to Mid-Morning from charlesreid1 on Vimeo.

Slower Framerate/Stop Motion

Next I tried a different frame rate, 15 fps, with the -r 15 flag. This gives it much more of a stop-motion look - I'm not sure how it's filling in all the frames, but it moves at the same rate. In other words, halving the frame rate will not double the length of your video. Frames are simply removed from the original video. (It may be as crude as showing 15 frames, then stopping for 15 frames.)

$ ffmpeg -i 20160730_%04d.jpg -r 15 -q:v 1 -vcodec mpeg4 movie1.mp4

The slower framerate requires a faster capture rate as well - it's great for stop motion, but if people are running across the screen in 4 or 5 frames, you don't get much of a stop motion effect. Much better is to calibrate the frame rate to the height of the camera and the subject matter. A 15th floor camera above a city street can have a slower frame rate due to its wider field of vision and the slower scale of motion from the 15th floor. On the other hand, a 4th floor view of construction workers at a construction site may be closer to the movement, have a narrower range of view, and therefore require a faster frame rate to capture the relative scale of motion.

Proof the timing is exactly the same in both videos: here's a screenshot from both videos of 3:17, when the street lamp is on:

Lamp1.png Lamp2.png
26 fps 15 fps

then of 3:18, when the street lamp turns off:

Lamp3.png Lamp4.png
26 fps 15 fps

Capturing 1 frame every 2 seconds, and setting to 15 fps, almost looked right for stop motion, but everything was too fast by a factor of about 2.

Raspberry Pi Timelapse: Midnight to Mid-Morning (15 fps) from charlesreid1 on Vimeo.


Flags