1

FFmpeg version: 4.3.2-2021-02-27-full_build-www.gyan.dev, Windows

When I apply the deshake filter to a video, e.g.:

ffmpeg -i input.mp4 -vf "deshake=rx=64:ry=64:edge=blank" -c:v h264_qsv output.mp4

Even though I specify edge=blank, the background ends up being a dark green, e.g.:

enter image description here

Why is that happening? How do I make it be black?

The filter docs say:

edge

Specify how to generate pixels to fill blanks at the edge of the frame. Available values are:

‘blank, 0’ - Fill zeroes at blank locations

...

My interpretation of "fill zeroes" was black, but that doesn't seem to be the case.


I think the answer below regarding YUV 0's being green is on the right track, but deshake seems to be forcing yuv444p and I'm not sure why.

For example, an attempt to convert to RGB, using showinfo to print the formats along the way (line breaks for clarity):

ffmpeg -i input.mp4 
       -vf "showinfo=checksum=false,
            format=rgb24,
            showinfo=checksum=false,
            deshake=edge=blank,
            showinfo=checksum=false" 
       -f null -

Outputs (abbreviated):

[Parsed_showinfo_0 @ 0000010c55ab2f40] n:  22 pts:     44 pts_time:0.733333 pos:   348574 fmt:yuv420p sar:0/1 s:1280x720 i:P iskey:0 type:P
[Parsed_showinfo_0 @ 0000010c55ab2f40] color_range:unknown color_space:unknown color_primaries:unknown color_trc:unknown
[Parsed_showinfo_2 @ 0000010c5860d500] n:  22 pts:     44 pts_time:0.733333 pos:   348574 fmt:rgb24 sar:0/1 s:1280x720 i:P iskey:0 type:P
[Parsed_showinfo_2 @ 0000010c5860d500] color_range:tv color_space:unknown color_primaries:unknown color_trc:unknown
[Parsed_showinfo_4 @ 0000010c5861df80] n:  22 pts:     44 pts_time:0.733333 pos:   348574 fmt:yuv444p sar:0/1 s:1280x720 i:P iskey:0 type:P
[Parsed_showinfo_4 @ 0000010c5861df80] color_range:tv color_space:unknown color_primaries:unknown color_trc:unknown

In other words, it's doing this:

input.mp4
    ↓  [yuv420p]
format=rgb24
    ↓  [rgb24]
deshake
    ↓  [yuv444p]   <--- ?????????
encoder / output

I'm not sure why that's happening. Just to confirm it wasn't something to do with the output format propagating backwards, I also tested this and verified it has the same issues (GIF output uses rgb8):

ffmpeg -i input.mp4 -vf "format=rgb8,deshake=edge=blank" -c:v gif output.gif

Also, along those lines, adding format=rgb24 again after deshake yields similarly confusing results:

input.mp4
    ↓  [yuv420p]
format=rgb24
    ↓  [rgb24]
deshake
    ↓  [yuv444p]   <--- ?????????
format=rgb24
    ↓  [rgb24]
encoder / output

I experimented a bit with the + option to -pix_fmt but couldn't get that working either: It's documented as disabling automatic conversions in filters, but I guess format filters also count as "automatic conversion" because it prevents those all from functioning as well.

2
  • PS: The input video I've been testing on was downloaded from here, if it's useful (although I have the same result with all inputs tested). - Note I am not the author.
    – Jason C
    Jul 14, 2021 at 14:00
  • Maybe try a colorkey filter with a black background image
    – Yorik
    Jul 14, 2021 at 14:29

2 Answers 2

1

in YUV color model a value of 0 for U and V results in Green color

https://en.wikipedia.org/wiki/YUV

you could try a color format that has 0 as black

without having tested it myself (and without knowing your pixel format), try something like -vf "format=rgb24,deshake=rx=64:ry=64:edge=blank"

3
  • Ok; you're definitely on to something I think. Can confirm input format is yuvj420p (which I probably shouldn't be using anyways, swscaler is complaining about deprecated formats) and the 0 -> green checks out. However, that format=rgb24 filter doesn't seem quite correct but I just did a quick test (a very non-minimal test too, in a more complex filter graph, so that could be making it weird too). I'm going to investigate a little more deeply into the color formats here and I'll let you know what I find. Thanks a lot, super helpful insight.
    – Jason C
    Jul 14, 2021 at 12:54
  • Still no luck; I added details about this to the question.
    – Jason C
    Jul 14, 2021 at 13:53
  • you can artificially force the green color to be replaced with black -vf "split[a][b];[a]deshake=rx=64:ry=64:edge=blank,colorkey=0x008000:blend=0:similarity=.05[a];[b]drawbox=color=black:t=fill[b];[b][a]overlay" but thats not ideal
    – Silentfury
    Jul 16, 2021 at 14:16
0

you could use vidstabdetect/transform instead of deshake

first run

ffmpeg -i input -vf vidstabdetect=shakiness=10:result=info.trf -f null -

and then run

ffplay -i input -vf vidstabtransform=input=info.trf:crop=black

(or an equivalent ffmpeg command with an output file) and play with the parameters

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .