43

Vertical video with blurred background sides

How to make this by using FFmpeg?

Example without FFmpeg:
Adobe After Effects
Sony Vegas Pro

Community
  • 1
  • 1
Andrey
  • 1,183
  • 1
  • 9
  • 10

6 Answers6

62

I solved!

ffmpeg -i input.mp4 -lavfi '[0:v]scale=ih*16/9:-1,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1[bg];[bg][0:v]overlay=(W-w)/2:(H-h)/2,crop=h=iw*9/16' -vb 800K output.webm

Input: https://www.youtube.com/watch?v=17uHCHfgs60
Output: http://www.youtube.com/watch?v=CgZsDLfzrTs

Andrey
  • 1,183
  • 1
  • 9
  • 10
  • This does not work on ubuntu 16.04 with ffmpeg version 2.8.11-0ubuntu0.16.04.1 – Benoit Aug 18 '17 at 04:57
  • There is an error for a video: Invalid too big or non-positive size for width '312' or height '176' @Adrian I really need this script or command, Please fix it. – X 47 48 - IR Aug 27 '18 at 22:58
  • 2
    You must have the GPL enabled in order to use the `boxblur` filter. [This](https://stackoverflow.com/questions/30789367/ffmpeg-how-to-convert-vertical-video-with-black-sides-to-video-169-with-blur#comment97756806_54618683) solution is 60% faster and is not included in the GPL license. – lasnow Apr 04 '19 at 23:51
  • 1
    how can I resize for 1280x720 with that args ? – alpertayfun Apr 26 '19 at 16:08
  • Full build is required to do this on Windows. It can be downloaded from here: https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-full.7z (source mentioned on official ffmpeg website). – Kamil Oct 17 '21 at 22:31
19

I made a universal solution for any type of videos. Suitable for vertical and horizontal videos. It's resizing video to 1080p (you can use it and for 720p) and fills all empty space with blurred video of this.

ffmpeg -i input.mp4 -lavfi "[0:v]scale=1920*2:1080*2,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1[bg];[0:v]scale=-1:1080[ov];[bg][ov]overlay=(W-w)/2:(H-h)/2,crop=w=1920:h=1080" output.mp4

Result 1: Result 1

Result2: Result 2

MarianD
  • 13,096
  • 12
  • 42
  • 54
Leonid Pavlov
  • 671
  • 8
  • 13
16

The accepted answer here takes forever to execute because it is doing so much unnecessary computation. We don't need to blur the pixels which we definitely know that will be out of viewport in the output video.

So, a better solution would be to first crop the part of the video which will be visible in the output. We then scale this part to "fill" the viewport. Finally, we overlay the original video on top of it.

Below example assumes that input video has greater
aspect ratio than output video.
                    ┌─────────────┐
┌─────────────┐     │             │
│ Input video │     │   Output    │
│             │     │   video     │
└─────────────┘     │             │
                    │             │
                    └─────────────┘

We will use filter graph to achieve this. Our filter will like below in dot notation:

                [original]
 input --> split -------------------------------> overlay --> output
        │                                          ^
        │[copy]                           [blurred]│
        └──────> crop ──> scale ──> gblur ─────────┘

Assuming the resolution for input video is 1280 x 720, the command looks like below:

ffmpeg -i input.mp4 -vf 'split [original][copy]; [copy] crop=ih*9/16:ih:iw/2-ow/2:0, scale=1280:2282, gblur=sigma=20[blurred]; [blurred][original]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2' output.mp4
Abhinav Chauhan
  • 1,900
  • 1
  • 18
  • 18
  • 8
    Hi! In my case your solution is 80% faster... but the output does not have a 16:9 resolution. I managed to change the crop & scale properties to satisfy the resolution asked `ffmpeg -i input.mp4 -vf 'split[original][copy];[copy]scale=ih*16/9:-1,crop=h=iw*9/16,gblur=sigma=20[blurred];[blurred][original]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2' output.mp4` with this change it is 60% faster than the accepted answer. – lasnow Apr 04 '19 at 23:38
  • @lasnow Was you input resolution also 1280 x 720? – Abhinav Chauhan Apr 10 '19 at 03:26
  • 2
    No, my input is a vertical video and I want a 1280x720 or 16:9 output video. I think it is what was asked. – lasnow Apr 10 '19 at 16:06
  • @lasnow This is the reason why you didn't get expected result. The answer assumes the input resolution to be 1280 x 720 – Abhinav Chauhan Apr 11 '19 at 05:30
  • 1
    Yep, you are right, your solution has a 1280x720 input but returns a 1280x2282... the person who asked in this post and me were looking for a output aspect ratio of 16:9 which your solution doesn't have – lasnow Apr 12 '19 at 19:49
  • @lasnow You should make that an answer, worked as expected for me and is miles faster than most other answers on here. – Hashim Aziz Apr 20 '21 at 00:41
  • 1
    I made a couple of changes. First a lot of TV shows has black edges, so to fix that I added a crop. Also some videos don't have square pixels, so this doesn't work for them. I adjusted by dar for that: `ffmpeg -i in.mkv -vf 'crop=w=iw*0.96,split[original][copy];[copy]scale=w=iw*16/9/dar:h=ih*16/9/dar,crop=h=ih*9/16*dar,gblur=sigma=20[blurred];[blurred][original]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2' out.mkv` – redfish64 Dec 14 '22 at 06:02
7

I couldn't get either of the previous solutions provided to work using ffmpeg 3.4.2 on Windows.

However this did work:

ffmpeg -i <input_file> -filter_complex "[0:v]scale=ih*16/9:-1,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1[bg];[bg][0:v]overlay=(W-w)/2:(H-h)/2,crop=h=iw*9/16" <output_file>

Don't forget to replace <input_file> and <output_file> with the appropriate file names.

Richard
  • 1,471
  • 7
  • 23
  • 47
4

You can try overlaying the video on a blur image like this.

ffmpeg -i input_video -loop 1 -i input_image -t 10 -filter_complex "
[0:v]scale=-1:720[scaled_video];
[1:v]scale=1280:720,boxblur=50[blur_image];
[blur_image][scaled_video]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[outv]" -c:v libx264 -aspect 1280/720 -map [outv] -map 0:a -c:a copy output_video

Input image will be looped through the duration of the output video by -loop 1. And -t 10 will limit the output video duration to 10 seconds. In this example I used 1280:720 as the output video resolution and scaled the inputs to match this ratio. 0:v refer to the input video and it will be scaled to height of 720 where width will be adjusted accordingly.

Here I used boxblur filter where there are several other like sab, smartblur and unsharp. map will get the specified processed input streams and map the to the output stream accordingly.

Hope this will help you!

Chamath
  • 2,016
  • 2
  • 21
  • 30
0

I believe this can be more efficient method to get blurred background with no need to blur high res images like in other answers:

ffmpeg -i <input_file> -vf 'scale=1280:720:force_original_aspect_ratio=decrease:flags=fast_bilinear,split[original][copy];[copy]scale=32:18:force_original_aspect_ratio=increase:flags= fast_bilinear,gblur=sigma=2,scale=1280:720:flags=fast_bilinear[blurred];[blurred][original]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,setsar=1' <output_file>

enter image description here

My point is to resize original image to smallest possible size (32x18px to get best results) and apply gblur with really small sigma. You can adjust blur amount and scale algorithms any time.

350D
  • 11,135
  • 5
  • 36
  • 49