Package: vtcff
vtcff🚧 This project is a draft and is not intended to be used by anyone.vtcffis a library for transcoding between video formats with an emphasis on
maintaining quality and color depth in video production pipelines. In studio
tasks, video seconds take up gigabytes and quality compromises are least
desirable.vtcfftends to maximize quality, sacrificing speed and disk space.vtcffis actually a wrapper forffmpeg– the least intuitive video tool ever
created.Install$pip3installvtcffThis command will install the package, but notffmpegitself.other optionsInstall pre-release from GitHub:$pip3installgit+https://github.com/rtmigo/vtcff_py@staging#egg=vtcffBasic exampleimportsubprocessfromvtcffimportFfmpegCommand,Scale,Transpose,Hevccmd=FfmpegCommand()cmd.src_file='/path/to/source.mov'cmd.dst_file='/path/to/target.mov'# set set some filterscmd.scale=Scale(1920,1080)cmd.transpose=Transpose.CLOCKWISE# set compression formatcmd.dst_codec_video=Hevc(mbps=100)# run commandsubprocess.check_call(list(cmd))Getting the generated argumentsimportsubprocess,osfromvtcffimportFfmpegCommand,Prorescmd=FfmpegCommand()cmd.src_file='source.mov'cmd.dst_file='target.mov'cmd.dst_codec_video=Prores()print(str(cmd))# ffmpeg -i source.mov -codec:v prores_ks target.movprint(list(cmd))# ['ffmpeg', '-i', 'source.mov', '-codec:v', 'prores_ks', 'target.mov']# running in different ways:os.system(str(cmd))subprocess.run(list(cmd))Custom argumentsThe object allows you to manually specify ffmpeg arguments. Arguments given in
this way take precedence over arguments generated by the object.fromvtcffimportFfmpegCommandcmd=FfmpegCommand()# set arguments as stringcmd.custom.video.string="-codec:v libx265"cmd.custom.video.string+="-x265-params lossless=1"# or as listcmd.custom.video.list=["-codec:v","libx265"]cmd.custom.video.list.extend(["-x265-params","lossless=1"])Thecmd.customcontains four fields, that can be modified independently.Arguments to be inserted before-i source:custom.before_iArguments to be inserted after-i source:custom.after_icustom.videocustom.audiozscale vs scaleffmpeghas two video filters for color and frame size conversions:scale(libswscale)
is more versatilezscale(zimg)
gives a more predictable qualityBy default,vtcffuseszscale. Sometimes it may lead to error "no path
between colorspaces". If other methods do not help, you can simply replacezscalewithscale.cmd.use_zscale == Truemeanszscaleis usedcmd.use_zscale == Falsemeansscaleis usedfromvtcffimportFfmpegCommand,Scalecmd=FfmpegCommand()assertcmd.use_zscale==True# by default, it's 'zscale' (zimg)cmd.use_zscale=False# switching to 'scale' (libswscale)# properties affected:cmd.scale=Scale(1920,1080)cmd.src_color_space='bt709'cmd.dst_color_space='bt2020ncl'cmd.src_range_full=Truecmd.dst_range_full=Falseuse_zscale=True, means that zimg will be used for conversionsexplicitlyset by object properties. This is good because these conversions
will be of high quality.However,implicitconversions may also be required. For example, before
processing 16-bit PNG withzscale, we need to convert the pixel format fromrgba64betogbrap16le🤪. Ffmpeg will do it automatically withlibswscaleregardless of theuse_zscaleproperty.Crop and scalefromvtcffimportFfmpegCommand,Scale,Crop# crop 10 pixels, then scalea=FfmpegCommand()a.crop=Crop(left=10)a.scale=Scale(1920,1080)# scale, then crop 10 pixelsb=FfmpegCommand()b.scale=Scale(1920,1080)b.crop=Crop(left=10)Scale proportionallyfromvtcffimportFfmpegCommand,Scalecmd=FfmpegCommand()# set height to 1080, automatically compute widthcmd.scale=Scale(-1,1080)# set height to 1080, select the width as the closest factor# of two to the proportional sizecmd.scale=Scale(-2,1080)Change color rangefromvtcffimportFfmpegCommandcmd=FfmpegCommand()# Full/Data/PC range to Limited/Video/TVcmd.src_range_full=Truecmd.dst_range_full=False# rec.709 to rec.2020cmd.src_color_space='bt709'cmd.dst_color_space='bt2020ncl'Target formatsEncoding to Apple ProResfromvtcffimportFfmpegCommand,Prores,ProresProfilecmd=FfmpegCommand()# by default it will encode to ProRes 4:2:2cmd.dst_codec_video=Prores()# encode to ProRes 4:2:2 HQ insteadcmd.dst_codec_video=Prores(profile=ProresProfile.HQ)Encoding to  HEVC (H.265)fromvtcffimportFfmpegCommand,Hevc,VcPresetcmd=FfmpegCommand()# ideal qualitycmd.dst_codec_video=Hevc(lossless=True)# best for bitrate qualitycmd.dst_codec_video=Hevc(near_lossless=True,mbps=100)# default qualitycmd.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, thenear_losslessis set to slowest possibleVcPreset.N10_PLACEBO, because we are trying to maximize quality. You may
want to choose a faster preset so that the result appears within a
lifetime.By default, thelosslessis set to fastest possibleVcPreset.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.Copying streamsThe media streams can be copied without re-encoding and without quality loss.However, there may be some loss of metadata – for example, information
about color ranges and color spaces.fromvtcffimportFfmpegCommand,VideoCopy,NoAudiocmd=FfmpegCommand()# changing container from mp4 to movcmd.src_file="source.mp4"cmd.dst_file="source.mov"# keeping video, removing audiocmd.dst_codec_video=VideoCopy()cmd.dst_codec_audio=NoAudio()Images to videosConverting timelapses or CGI frame sequences to ProRes video file.importsubprocessfromvtcffimportFfmpegCommand,Prores,ProresProfilecmd=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.97cmd.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 rangecmd.src_range_full=Truecmd.dst_range_full=False# we will treat sRGB like Rec.709,# although it's a little sadcmd.src_color_space='bt709'cmd.dst_color_space='bt709'# run commandsubprocess.check_call(list(cmd))