12

I'm using the fluent-ffmpeg Node.js library to perform batch manipulations on video files. The video filter which crops a 16:9 input, adds padding and burns subtitles into the padding.

In the next step, I would like to use a complex filter to overlay an image as a watermark.

ff.input(video.mp4)
ff.input(watermark.png)
ff.videoFilter([
  'crop=in_w-2*150:in_h',
  'pad=980:980:x=0:y=0:color=black',
  'subtitles=subtitles.ass'
])
ff.complexFilter([
  'overlay=0:0'
])
ff.output(output.mp4)

However, running this, I get the following error:

Filtergraph 'crop=in_w-2*150:in_h,pad=980:980:x=0:y=0:color=black,subtitles=subtitles.ass' was specified through the -vf/-af/-filter option for output stream 0:0, which is fed from a comple.
-vf/-af/-filter and -filter_complex cannot be used together for the same stream.

From what I understand the video filter and complex filter options can't be used together. How does one get around this?

Sebastien
  • 2,607
  • 9
  • 30
  • 40
  • You will have to put the overlay filter in one filter only. You cannot use 2 filtergraphs in ffmpeg in the same command. Try to study the complex filtergraphs and match your stream accordingly to the overlay filter. – Legolas Apr 01 '19 at 20:23
  • You can use multiple complex filtergraphs in the same command. You just can't refer to intermediate or output streams, created in one graph, in the other graphs. – Gyan Apr 02 '19 at 06:01

2 Answers2

44

Solved this by learning some basics about filter graphs. Here's the full ffmpeg command. I find the filter strings easier to read when they are written out line-by-line.

ffmpeg \
-i video.mp4 \
-i watermark.png \
-filter_complex " \
  [0]crop = \
    w = in_w-2*150 : \
    h = in_h \
    [a] ;
  [a]pad = \
    width = 980 : \
    height = 980 : \
    x = 0 :
    y = 0 :
    color = black
    [b] ;
  [b]subtitles = 
    filename = subtitles.ass
    [c] ;
  [c][1]overlay = \
    x = 0 :
    y = 0
  " \
output.mp4

Explanation:

[0]crop=...[a]; => Begin by applying crop filter to video input 0. Name the result a.

[a]pad=...[b]; => Apply the pad filter to the a stream. Name the result b.

[b]subtitles=...[c] => Apply the subtitles filter to the b stream. Name the result c.

[c][1]overlay... => Apply the overlay filter to stream c using input 1 (the png file).

Hope this helps someone struggling with filter graphs.

Sebastien
  • 2,607
  • 9
  • 30
  • 40
  • 3
    The filters that have a single input/output can be joined by commas which can simplify the command somewhat because you can omit unnecessary labeling such as `[0]crop,pad[bg];[bg][1]overlay,subtitles` or `[0]crop,pad,subtitles[bg];[bg][1]overlay`. – llogan Apr 01 '19 at 20:45
  • 1
    Your Q is about fluent-ffmpeg syntax. This answer relates to ffmpeg CLI syntax. – Gyan Apr 02 '19 at 05:58
  • Yes, but the filter graph was the issue. – Sebastien Apr 09 '19 at 16:05
  • Do you have the fluent-ffmpeg version? – lowcrawler Sep 30 '20 at 21:21
7

simple syntax with 3 logos and 1 text scroll

ffmpeg
    .complexFilter([

        {
            filter: 'overlay',
            options: { x: 100, y: 100 },
            inputs: 0, outputs: '1'

        },
        {
            filter: 'overlay',
            options: { x: 200, y: 200 },
            inputs: '1', outputs: '2'

        },
        {
            filter: 'overlay',
            options: { x: 300, y: 300 },
            inputs: '2', outputs: '3'

        },
        {
            filter: 'drawtext',
            options: {
            // outputs: 1,
            fontfile:'/usr/share/fonts/dejavu/DejaVuSans.ttf',
            text: 'some text',
            fontsize: 40,
            fontcolor: 'white',
            x: 'w-w/10*mod(t,10*(w+tw)/w)',
            y: 'h-line_h',
            shadowcolor: 'black',
            shadowx: 3,
            shadowy: 3,
            },
            inputs: '3',
          },
        ])
Giang Phong
  • 71
  • 1
  • 2