Fernando Swenson
Fernando Swenson

Reputation: 41

I have trouble converted ffmpeg command to ffmpeg-python

I am trying convert from HDR to SDR by using the following ffmpeg command, which works

ffmpeg -i input.mov -vf zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p -c:v libx264 -crf 0 -preset ultrafast -tune fastdecode output.mp4

However, I have trouble converting this in ffmpeg-python format. Could you give me guidance on how to deal with semicolons, equals and weird = = cases?

ffmpeg.input("input.mov", r=fps).filter('zscale', t='linear:npl').filter('format', 'gbrpf32le') ...

Upvotes: 0

Views: 2040

Answers (1)

Rotem
Rotem

Reputation: 32144

The conversion is quite straightforward:

ffmpeg.input('input.mov')\
    .video.filter('zscale', t='linear', npl=100)\
    .filter('format', pix_fmts='gbrpf32le')\
    .filter('zscale', p='bt709')\
    .filter('tonemap', tonemap='hable', desat=0)\
    .filter('zscale', t='bt709', m='bt709', r='tv')\
    .filter('format', pix_fmts='yuv420p')\
    .output('output.mp4', vcodec='libx264', crf=0, preset='ultrafast', tune='fastdecode')\
    .run()

  • Arguments of ffmpeg.input(...) begins with input file name followed by input arguments.
  • .video followed by .filter(...).filter(...).filter(...) applies chain of video filters.
  • filter(...) begins with filter name followed by filter parameters as arguments.
    The syntax is <param_name0>=param_value0, <param_name1>=param_value1...
  • output(...) begins with output file name followed by output arguments.

The only caveat is the format filter.
The parameter name of format filter is pix_fmts (we usually skip it).
One way for getting the parameter name is using FFmpeg help (in command line):

ffmpeg -h filter=format

Output:

Filter format
  Convert the input video to one of the specified pixel formats.
    Inputs:
       #0: default (video)
    Outputs:
       #0: default (video)
(no)format AVOptions:
   pix_fmts          <string>     ..FV....... A '|'-separated list of pixel formats

Here we can see that the parameter name is pix_fmts.


When using ffmpeg-python, it is recommended to add .overwrite_output() (equivalent to -y argument).

For testing it is recommended to add .global_args('-report') for creating a log file (remove .global_args('-report') after finish testing).

ffmpeg.input('input.mov')\
    .video.filter('zscale', t='linear', npl=100)\
    .filter('format', pix_fmts='gbrpf32le')\
    .filter('zscale', p='bt709')\
    .filter('tonemap', tonemap='hable', desat=0)\
    .filter('zscale', t='bt709', m='bt709', r='tv')\
    .filter('format', pix_fmts='yuv420p')\
    .output('output.mp4', vcodec='libx264', crf=0, preset='ultrafast', tune='fastdecode')\
    .global_args('-report').overwrite_output().run()

The log shows us the actual FFmpeg command:

ffmpeg -i input.mov -filter_complex "[0:v]zscale=npl=100:t=linear[s0];[s0]format=pix_fmts=gbrpf32le[s1];[s1]zscale=p=bt709[s2];[s2]tonemap=desat=0:tonemap=hable[s3];[s3]zscale=m=bt709:r=tv:t=bt709[s4];[s4]format=pix_fmts=yuv420p[s5]" -map "[s5]" -crf 0 -preset ultrafast -tune fastdecode -vcodec libx264 output.mp4 -report -y

As you can see, ffmpeg-python uses -filter_complex instead of -vf, and uses temporary naming as [s0], [s1], [s2]...
The result is equivalent to your original command.

Upvotes: 2

Related Questions