{"id":3026,"date":"2017-07-10T00:00:24","date_gmt":"2017-07-10T07:00:24","guid":{"rendered":"http:\/\/192.168.3.4\/?p=3026"},"modified":"2025-09-12T05:17:26","modified_gmt":"2025-09-12T12:17:26","slug":"ffmpeg-side-by-side-and-tiling-video","status":"publish","type":"post","link":"https:\/\/www.cloudacm.com\/?p=3026","title":{"rendered":"FFMpeg Side by Side and Tiling Video"},"content":{"rendered":"<p>FFMpeg has an interesting ability to join multiple video feeds together.\u00a0 In the past, I had use other video editors to do this.\u00a0 They were limited to 2 camera views.\u00a0 In addition, the second camera screen was scaled down and much smaller than the first video.\u00a0 With FFMpeg, we can join more than 2 camera feeds without resizing.\u00a0 I&#8217;ll be quick and to the point in this post so try not to blink.<\/p>\n<p>In this example I have 4 cameras that were &#8220;filming&#8221; the start of the STP bicycle classic.\u00a0 I&#8217;m using 4 808-16 keychain cameras, all of which have external wide angle lenses attached.\u00a0 The format of these cameras uses 1280&#215;720 30fps H.264 video and 16 bit PCM mono audio sampled at 32000 Hz.\u00a0 Since all of my videos use the same format, not much else needs to be done before tiling with FFPmeg.\u00a0 Here are the 3 commands I used to tile my 4 videos.<\/p>\n<pre>ffmpeg -i \"Camera1_Left.MOV\" -vf \"[in] scale=iw:ih, pad=2*iw:ih [left];movie=Camera2_Right.MOV, scale=iw:ih [right]; [left][right] overlay=main_w\/2:0 [out]\" \"SideBySide_Top.MOV\"\r\nffmpeg -i \"Camera3_Left.MOV\" -vf \"[in] scale=iw:ih, pad=2*iw:ih [left];movie=Camera4_Right.MOV, scale=iw:ih [right]; [left][right] overlay=main_w\/2:0 [out]\" \"SideBySide_Bottome.MOV\"\r\nffmpeg -i \"SideBySide_Top.MOV\" -vf \"pad=iw:2*ih [top]; movie=SideBySide_Bottome.MOV [bottom]; [top][bottom] overlay=0:main_h\/2\" \"Tiled_4_Camera_View.MOV\"\r\n<\/pre>\n<p>The interesting thing about the tileing method used by FFMpeg is that only one of the cameras will be used as the audio source.\u00a0 The source used is the input video, not the filter video.\u00a0 In this example you will hear the audio from the top left camera.<\/p>\n<p><iframe loading=\"lazy\" title=\"STP 2012 Starting Line - Four Camera View\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/JOmd1SS2xJA?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<p>There are times when the source videos will not be the same format or orientation.\u00a0 For these particular cases, the source video must be processed so all are formatted the same.\u00a0 Otherwise, the results will be unpredictable.\u00a0 Here are the commands I used to make this adjustment to 4 video sources that had 3 different formats.<\/p>\n<pre>ffmpeg -i 20100717_STP.png -vf 'scale=640:360:force_original_aspect_ratio=decrease,pad=640:360:x=(640-iw)\/2:y=(360-ih)\/2:color=gray' 20100717_STP_Scaled.png\r\nffmpeg -i 201207140948.MOV.png -vf scale=iw*.5:ih*.5 201207140948.MOV_Scaled.png\r\nffmpeg -i MINI0014.MOV.png -vf scale=iw*.5:ih*.5 MINI0014.MOV_Scaled.png\r\nffmpeg -i REC_0008.MOV.png -vf scale=iw*.3333:ih*.3333 REC_0008.MOV_Scaled.png\r\n<\/pre>\n<p>I first established the format I wanted to use and started by resizing my first source to 640&#215;360.\u00a0 This camera was one of my earliest helmet cameras and shot at 640&#215;480 at 15fps.\u00a0 Since it had a native aspect ratio of 4:3, I needed to change it to 1.7:1.\u00a0 A simple scaling filter would result in distorted video with a stretch or squashed look.\u00a0 To avoid the spaghetti western effect, I added padding to fill in the dead space that the source video wouldn&#8217;t cover in the new aspect ratio.<\/p>\n<p>The last 3 commands simply scale the source video down to match the 640&#215;360 format I established from the onset.\u00a0 The first 2 videos in this group were from 808-16 1280&#215;720 cameras.\u00a0 The last video source is from a Mobius 1920&#215;1080 camera.\u00a0 I&#8217;m not using videos, but screenshots from those videos in this example.\u00a0 However, the same commands would be used for the videos.\u00a0 Here are the results.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2017\/07\/Quad.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3034 size-large\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2017\/07\/Quad-1024x576.png\" alt=\"\" width=\"640\" height=\"360\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2017\/07\/Quad-1024x576.png 1024w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2017\/07\/Quad-300x169.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2017\/07\/Quad-768x432.png 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2017\/07\/Quad-480x270.png 480w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2017\/07\/Quad.png 1280w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>I&#8217;ll cover some additional effects we can get from FFMpeg with the resize and padding filters.\u00a0 With it, we can create boarders around videos.\u00a0 This will be helpful to distinguish the different camera sources as I start to demonstrate overlays.<\/p>\n<p>I hope you have enjoyed this topic and look forward to covering more about FFMpeg and the features it offers.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>FFMpeg has an interesting ability to join multiple video feeds together.\u00a0 In the past, I had use other video editors to do this.\u00a0 They were limited to 2 camera views.\u00a0 In addition, the second camera screen was scaled down and much smaller than the first video.\u00a0 With FFMpeg, we can join more than 2 camera feeds without resizing.\u00a0 I&#8217;ll be quick and to the point in this post so try not to blink. In this example I have 4 cameras&#8230;<\/p>\n<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.cloudacm.com\/?p=3026\"> Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,6,3],"tags":[],"class_list":["post-3026","post","type-post","status-publish","format-standard","hentry","category-computer-vision","category-raspberry-pi","category-rd"],"_links":{"self":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/3026","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3026"}],"version-history":[{"count":9,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/3026\/revisions"}],"predecessor-version":[{"id":4998,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/3026\/revisions\/4998"}],"wp:attachment":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3026"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3026"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3026"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}