Join MJPEG videos from a CritterCam
Ingredients: Intermediate I.T, Tinker-comfort, Google, and
latest ffmpeg, Linux etc, Sample at End.
ffmpeg is command line only tool which may seem weird for video but, hold up- a lot of video tasks like the following lend themselves really well to scripted heavy lifting- as here. There are literally hundreds of options. The heavyweights- YouTube, Facebook etc use ffmpeg to transcode and process stuff automagically– No GUI for them!.. It is a major & deceptively powerful player.
Critter-cams- you know, the ones that can record short video clips of daily+nightly beasties when motion is sensed?
How to join these video clips? Same story for car DVRs- AKA DashCams- those devices routinely produce a large array of short video files,
often non-contiguous in timing. I assume there is No Audio – Yet.
Not sure what happens if there IS : )
I thought it would be fun to join them together after discovering the movie video format was MJPEG also known as motion JPEG.
it’s not particularly well compressed because the video only contains JPEG frames that are themselves compressed but there is no optimisation between adjacent frames. It does make it easy to split out single JPEGs or join them without loss and do other clever tricks like the following one. Join a whole lot together! How?
First of all– check that the clips really ARE in MJPEG format,
This article will only describe how to join such simple files ‘natively’.
‘Real’ Video Files like h.264 & HEVC/h.265 require re encoding–
MJPEG format as here does not though, is simple,
and goes very quickly if done right. Let’s first of all check a single clip to see how it’s made by using ffmpeg without any output file specified:
$ffmpeg -hide_banner -i MFDC1354.AVI Input #0, avi, from 'MFDC1354.AVI': Duration: 00:00:10.00, start: 0.000000, bitrate: 3839 kb/s Stream #0:0: Video: mjpeg (Baseline) (MJPG / 0x47504A4D), yuvj422p(pc, bt470bg/unknown/unknown), 640x480, 3867 kb/s, 12.50 fps, 12.50 tbr, 12.50 tbn At least one output file must be specified
This is using ffmpeg without any output specified-
so this single clip is a 10s one in MJPEG format, at 640×480 resolution Good!
I have eighty-nine such AVI files in one folder from about 2 weeks.
Let’s get ffmpeg to join ’em in sequence.
Rather clunkily, we need a separate text-file ‘running order’ telling ffmpeg which files to join, let’s call it list.txt; It’s expected to contain one file path per line- there woudl be 89 lines. like:
you get the idea… Let’s automate that:
for f in *.AVI; do echo "file '$f'" >> list.txt; done
The list by default appears to be in chronological file time stamp order, so be careful NOT to touch the create/modify date too much:)
In Case You Wonder:
$cat *.AVI >> out.avi
will NOT work as each single file has ‘container’ data
(AVI in this case) that would also get jammed into the output where only the 1st 10 second header would be ‘seen’ and might just get played the first 10 seconds back, skipping the remaining 88 clips which it cannot ‘see’ as such : )
So. now Tell ffmpeg What to
$ffmpeg -f concat -safe 0 -i list.txt -c copy all.avi
We now have a far larger MJPEG file with all parts joined and the size being the sum of the parts, and No Music.
Do try Playing the (silent?) output Back before doing the Next Thing:
$ffmpeg -i all.avi -i music.m4a -shortest -c:v libx264 -pix_fmt yuv420p All_WithMusic_h264.mp4
This produces a highly compatible video file with decent compression, in my case 10x smaller with no discernible loss in quality.
You might try “-c:v libx265” rather than h264 for super compressed HEVC video, in my case, 20x smaller!
But it will be 4-5 times slower and may not be compatible with HTML5 Web Streaming.
The “-pix_fmt yuv420p” I cannot easily explain, except that there are weird color artifacts if you do not add that.
The “-i music.m4a” does the expected thing- adds a music-track, which must, not surprisingly, exist with the right name somewhere : )
“-shortest” will stop the video AND audio should the audio be longer, otherwise audio will keep playing if it’s longer than the video with the last video frame frozen : ).
Some google searches seem to suggest a far more complex command line- Latest ffmpeg seems to understand the defaults things you mean to do, in the given order though,
and worked for me
My music happens to be in “aac” format- other types could be used, it will depend on what program will be used to play your video+audio back;
ideally of course avoid uncompressed audio formats like WAV.
Squash ’em nicely, first. : )
I find with Some Delight that the Music Metatdata- Artist, title etc may also get copied and exist within the output file where tools like “mediainfo” can ‘see’ it.
I test my videos with wonderful VLC, by the way,
But Here it is through web based HTML5:
Moultrie Crittercam concatenated eighty-nine 10 second MJPEG clips over about 2 weeks into one h.264 Video 04:46 long compressed video with Music : ).
The icon at lower left is the moon-phase that this Critter Cam seems to know about : )