Not too long ago, I purchased a programmable remote for my DSLR camera so that I could take long exposures as well as multiple exposures in order to create time lapse videos. While the timer does a great job, I still needed a way to convert a series of images into a video.
Fortunately, ffmpeg does a great job of converting a pile of images into a video file, and I most certainly have ffmpeg installed on my laptop. Now all I need is a bit of code to:
- search for some files
- copy and rename the files
- always skip step 3 :)
- use ffmpeg to convert the files to a video
When the script runs, it looks for a directory named 'images' and recursively looks for files in that directory (my camera tends to make multiple directories of files). Then the files are copied into a temp folder and given a 6 digit name: 000001, 000002, 000003, etc. Finally, ffmpeg converts those 6 digit named files into a video.
Enter The Ruby
require 'fileutils'
require 'date'
#where will we look for files?
LOCAL_DIR = File.expand_path( File.dirname(__FILE__) )
TEMP_DIR = File.join(LOCAL_DIR, "temp")
IMAGES_DIR = File.join(LOCAL_DIR, "images")
#if the temp dir exists, delete it and its contents
if Dir.exists? TEMP_DIR
FileUtils.rm_rf TEMP_DIR
end
#make the temp dir
FileUtils.mkdir TEMP_DIR
#keep track of how many files we have
@file_count = 0
def copy_files(location)
files = []
dirs = []
Dir.foreach(location) do |name|
#ignore . and ..
if name!='.' and name!='..'
#what is the path of the item?
path = File.join(location,name)
#recurse if path is a directory
if Dir.exists? path
dirs << path
else
files << path
end
end
end
#sort the directories by name and recurse
dirs = dirs.sort()
dirs.each do |d|
puts "DIRECTORY: #{d}"
copy_files(d)
end
#sort the files by name and recurse
files = files.sort()
files.each do |d|
new_name = @file_count.to_s
#increment the file_count
@file_count+=1
## pad the new file name with 0
(6-new_name.length()).times do
new_name = "0"+new_name
end
#determine where the new file is going
new_file = File.join(TEMP_DIR, new_name)
#what is the command to copy the file?
copy_command = "cp #{d} #{new_file}"
puts copy_command
#run the command
`#{copy_command}`
end
end
#recursively get a list of all files in the current directory
copy_files(IMAGES_DIR)
#what day is it?
ymd = Date.today.strftime("%Y%m%d")
#what video command should we run?
cmd = "ffmpeg -y -f image2 -i temp/%06d -b:v 50000k #{ymd}_timelapse.avi"
#run the command
`#{cmd}`
By default, the ffmpeg command will create a video at 10 frames/second.
My first time lapse was during Sunset on the Equinox
Sadly, I didn't adjust the camera properly when capturing the April 4th Lunar Eclipse. However, considering I set everything up 7 hours before the eclipse, I think I did a fairly sweet job of determining where to point the camera. :)
Now quit reading, slow down, and speed up.