Recently I purchased a kayak. I wanted to take photos with my GoPro mounted to the top. Seemed simple enough. It was, and thus was totally unacceptable.
Let’s make this user story more complicated.
The Story
I wanted to be able to create a time lapse video quickly to send to my friends. From there, I’d send the video to anyone who was with me that day. If they wanted an original high resolution image used to create the video, they could give me the time stamp. From there, I could send the dozen or so images that created that second of video easily.
Put another way: I was in essence creating a quick way to preview the thousands of photos GoPro can take in a short time.
Naïve First Try
Seems simple enough:
- Hit record on GoPro
- Kayak
- Download Images
- Let GoPro Studio do its thing
That didn’t work.
That shakiness makes it impossible to watch. Ain’t nobody got no time for that.
Second Pass
I came to realizing no filter GoPro could provide would help that. Manually rotating and lining up all frames would take forever. Time to automate.
First I created script stabilize
:
#!/bin/bash # Copyright 2016 Tim Doerzbacher <tim at tim-doerzbacher.com> MELT=melt # Stabilization options MELT_FILTERS="-filter vidstab shakiness=8 smoothing=20 optzoom=0 maxangle=0.05" # Encoding options MELT_OPTIONS="vcodec=libx264 b=16000k acodec=aac ab=128k tune=film preset=slow" if [ -z "$1" ] ; then echo "Usage: $0 <infile> [outfile]" exit 1434; fi SRC="$1" DEST="`echo $1 | sed -r 's/\.(mp4|mpg|mov)/.stabilized.m4v/'`" MLT_FILE="`echo $1 | sed -r 's/\.(mp4|mpg|mov)/.stabilized.mlt/'`" if [ ! -z "$2" ] ; then DEST="$2" fi if [ "$SRC" = "$DEST" ]; then echo "Did not recognize that file type." exit 1 # Not random fi echo "Stabilizing: ${SRC}" echo "Destination: ${DEST}" echo echo "======== Round #1 ========" echo $MELT "$SRC" $MELT_FILTERS -consumer "xml:${MLT_FILE}" all=1 echo echo "======== Round #2 ========" echo $MELT "$MLT_FILE" -audio-track "$SRC" -consumer "avformat:${DEST}" $MELT_OPTIONS
So the new order of things was:
- Hit record on GoPro
- Kayak
- Download Images
- Let GoPro Studio do its thing
- Process resultant video with
stabilize
This method left a bit of weirdness at the edges. I tried using the auto-zoom functionality but didn’t like the result. Since GoPro studio already threw out a lot of the original resolution, zooming in further throws away even more information. The end result is far from optimal and looks blurry:
There Must Be a Better Way
There was a better way. I have a large amount of sequentially named files and a snazzy Linux server. I’m losing a lot of resolution by stabilizing the video after its already been scaled down.
Time to make a new script: encode
.
#!/bin/bash FFMPEG=ffmpeg $FFMPEG -pattern_type glob -i '*.JPG' -c:v libx264 video.mp4
Now I have an easy way to create one video out of all images taken that day.
$ encode JPG; stabilize video.mp4
At this point, I can take video.stabilized.m4v
and import it into GoPro. Now I have full resolution video that I can then crop as necessary. The result works out quite a bit better:
Still, I’m having problems smoothing the video out. At this point, I began I wonder how it would work with better data. The water drops taking up so much of the field of view. It is probably affecting the stabilization.
Better Data
A few days later I had the opportunity to revisit the lake to do some plein air painting.
After that was done, I recorded and processed another time lapse using the scripts above:
Ultimately, I’m pretty happy with the last few attempts at making a kayak trip bearable. Things are still not perfect. I’m not aware of a way to make the GoPro take more than two frames per second. That’s causing the Flux processing in GoPro Studio to really make a mess of things.
With any luck I’ll have a another post soon explaining how to mitigate these issues.
References
Here are some of the pages I referenced while creating this. Thanks, guys!