Ffmpeg wrapper for transcoding between video formats with an emphasis on maintaining quality and color depth in video production pipelines
Project description
vtcff
🚧 This project is a draft and is not intended to be used by anyone.
vtcff
is a library for transcoding between video formats with an emphasis on
maintaining quality and color depth in video production pipelines.
It generates arguments for ffmpeg
– the least intuitive video tool ever
created.
Install
$ pip3 install vtcff
This command will install the package, but not ffmpeg itself.
other options
Install pre-release from GitHub:
$ pip3 install git+https://github.com/rtmigo/vtcff_py@staging#egg=vtcff
Basic example
import subprocess
from vtcff import FfmpegCommand, Scale, Transpose, Hevc
cmd = FfmpegCommand()
cmd.src_file = '/path/to/source.mov'
cmd.dst_file = '/path/to/target.mov'
# set set some filters
cmd.scale = Scale(1920, 1080)
cmd.transpose = Transpose.CLOCKWISE
# set compression format
cmd.dst_codec_video = Hevc(mbps=100)
# run command
subprocess.check_call(list(cmd))
Getting the generated arguments
import subprocess, os
from vtcff import FfmpegCommand, Prores
cmd = FfmpegCommand()
cmd.src_file = 'source.mov'
cmd.dst_file = 'target.mov'
cmd.dst_codec_video = Prores()
print(str(cmd))
# ffmpeg -i source.mov -vcodec prores_ks target.mov
print(list(cmd))
# ['ffmpeg', '-i', 'source.mov', '-vcodec', 'prores_ks', 'target.mov']
# running in different ways:
os.system(str(cmd))
subprocess.run(list(cmd))
Custom arguments
The object allows you to manually specify ffmpeg arguments. Arguments given in this way take precedence over arguments generated by the object.
from vtcff import FfmpegCommand
cmd = FfmpegCommand()
# set arguments as string
cmd.custom.video.string = "-vcodec libx265"
cmd.custom.video.string += "-x265-params lossless=1"
# or as list
cmd.custom.video.list = ["-vcodec", "libx265"]
cmd.custom.video.list.extend(["-x265-params", "lossless=1"])
The cmd.custom
contains four fields, that can be modified independently.
Arguments to be inserted before -i source
:
custom.before_i
Arguments to be inserted after -i source
:
custom.after_i
custom.video
custom.audio
zscale vs scale
ffmpeg
has two filters for color and frame size conversions:
scale
(libswscale) is more versatilezscale
(zimg) gives a more predictable quality
By default, vtcff
uses zscale
. Sometimes it may lead to error "no path
between colorspaces". This error would not occur with scale
.
The use_zscale
property which to use.
from vtcff import FfmpegCommand, Scale
cmd = FfmpegCommand()
assert cmd.use_zscale # by default, it's zscale (zimg)
cmd.use_zscale = False # switching to libswscale
# properties affected:
cmd.scale = Scale(1920, 1080)
cmd.src_color_space = 'bt709'
cmd.dst_color_space = 'bt709'
cmd.src_range_full = False
cmd.dst_range_full = False
It is worth clarifying that even with use_zscale=True
, the use of the usage
of zimg library is guaranteed only for explicit conversions specified by the properties
of the FfmpegCommand
object. If the input/output formats or filter combination
would require implicit color conversions, ffmpeg may use libswscale to do this.
Crop and scale
from vtcff import FfmpegCommand, Scale, Crop
# crop 10 pixels, then scale
a = FfmpegCommand()
a.crop = Crop(left=10)
a.scale = Scale(1920, 1080)
# scale, then crop 10 pixels
b = FfmpegCommand()
b.scale = Scale(1920, 1080)
b.crop = Crop(left=10)
Scale proportionally
from vtcff import FfmpegCommand, Scale
cmd = FfmpegCommand()
# set height to 1080, automatically compute width
cmd.scale = Scale(-1, 1080)
# set height to 1080, select the width as the closest factor
# of two to the proportional size
cmd.scale = Scale(-2, 1080)
Change color range
from vtcff import FfmpegCommand
cmd = FfmpegCommand()
# Full/Data/PC range to Limited/Video/TV
cmd.src_range_full = True
cmd.dst_range_full = False
# rec.709 to rec.2020
cmd.src_color_space = 'bt709'
cmd.dst_color_space = 'bt2020'
Target formats
Encoding to HEVC (H.265)
from vtcff import FfmpegCommand, Hevc, VcPreset
cmd = FfmpegCommand()
# ideal quality
cmd.dst_codec_video = Hevc(lossless=True)
# best for bitrate quality
cmd.dst_codec_video = Hevc(near_lossless=True, mbps=100)
# default quality
cmd.dst_codec_video = Hevc(mbps=100)
# all modes can be tweaked with optional speed presets:
cmd.dst_codec_video = Hevc(mbps=100,
preset=VcPreset.N7_SLOW)
By default, the near_lossless
is set to slowest possible
VcPreset.N10_PLACEBO
, because we are trying to maximize quality.
By default, the lossless
is set to fastest possible
VcPreset.N1_ULTRAFAST
, because we are not losing any quality here. The
resulting size will be roughly comparable to ProRes HQ/XQ and the encoding time
is reasonable.
Encoding to Apple ProRes
from vtcff import FfmpegCommand, Prores, ProresProfile
cmd = FfmpegCommand()
# by default it will encode to ProRes 4:2:2
cmd.dst_codec_video = Prores()
# encode to ProRes 4:2:2 HQ instead
cmd.dst_codec_video = Prores(profile=ProresProfile.HQ)
Images to videos
Converting timelapses or CGI frame sequences to ProRes video file.
import subprocess
from vtcff import FfmpegCommand, Prores, ProresProfile
cmd = FfmpegCommand()
# input directory will be automatically transformed
# to a pattern like '/my/dir_with_frames/img_%04.png'
cmd.src_file = '/my/dir_with_frames'
cmd.src_fps = 29.97
cmd.dst_file = '/videos/timelapse.mov'
cmd.dst_codec_video = Prores(profile=ProresProfile.HQ)
# images usually have Full/Data/PC color range,
# but most NLEs assume that videos have Limited/Video/TV range
cmd.src_range_full = True
cmd.dst_range_full = False
# we will treat sRGB like Rec.709,
# although it's a little sad
cmd.src_color_space = 'bt709'
cmd.dst_color_space = 'bt709'
# run command
subprocess.check_call(list(cmd))
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.