0

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') ...

2
  • Remember that the Python ffmpeg module just builds up a command line and executes it. If you have a command line that works, then just use subprocess.run to run that command line. Commented Aug 23, 2022 at 4:52
  • Looks good so far. What's the problem exactly? Is there an error message? Commented Aug 23, 2022 at 4:54

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.