Skip to main content

BestSource

build codespell

BestSource (abbreviated as BS) is a cross-platform wrapper library around FFmpeg that ensures always sample and frame accurate access to audio and video with good seeking performance for everything except some lossy audio formats.

It can be used as either a C++ library directly or through the combined VapourSynth and Avisynth+ plugin that's included.

Dependencies

  • FFmpeg 8.1.x and FFmpeg 8.0.x supported. Later releases may or may not work but FFmpeg API breakages are quite common and don't always generate compilation errors. Only libavcodec, libavformat, libavutil libraries are required.
  • xxHash

Windows Compilation

On Windows the easiest way to compile the the dependencies is to use vcpkg to install ffmpeg[avcodec,avdevice,avfilter,avformat,swresample,swscale,zlib,bzip2,core,dav1d,gpl,version3,lzma,nvcodec,qsv,vulkan,openssl,xml2]:x64-windows-static and xxhash:x64-windows-static. Do however note that this is without Little CMS2 support. Use the latest version of Visual Studio. It should automatically find all the required libraries if you used vcpkg.

Linux and MacOS Compilation

Requires pkg-config, meson and ninja-build.

git clone https://github.com/vapoursynth/bestsource.git --depth 1
cd bestsource
meson setup build
meson compile -C build
meson install -C build

Known issues and limitations

  • Seeking performance in mpeg/ts/vob files can be quite poor due to the FFmpeg demuxer
  • Seeking and decoding performance for lossy audio formats (aac, mp3, dts, ac3, vorbis) can be poor
  • VC1 codec is unseekable due to FFmpeg not having bitexact output after seeking
  • The unholy combination of VFR H264 in AVI has poor seeking performance
  • Needs FFmpeg compiled with Little CMS2 or the color information reported for most image files will be less complete
  • Mod files can't be decoded correctly using libmodplug due to the library not having repeatable bitexact output
  • Gray+alpha format isn't supported in Avisynth+ and as a result only the Y component is returned
  • Files with dimensions that aren't a multiple of the subsampling value will be cropped

VapourSynth usage

bs.AudioSource(string source[, int track = -1, int adjustdelay = -1, int threads = 0, bint enable_drefs = False, bint use_absolute_path = False, float drc_scale = 0, int cachemode = 1, string cachepath, int cachesize = 100, bint showprogress = True, maxdecoders = 0, int variableformat = 0])

bs.VideoSource(string source[, int track = -1, int variableformat = -1, int fpsnum = -1, int fpsden = 1, bint rff = False, int threads = 0, int seekpreroll = 20, bint enable_drefs = False, bint use_absolute_path = False, int cachemode = 1, string cachepath , int cachesize = 100, string hwdevice, int extrahwframes = 9, string timecodes, int start_number, int viewid = 0, bint showprogress = True, maxdecoders = 0, bool hwfallback = True, exporttimestamps = False, bint apply_rotation = True])

bs.TrackInfo(string source[, bint enable_drefs = False, bint use_absolute_path = False])

bs.Metadata(string source[, int track, bint enable_drefs = False, bint use_absolute_path = False])

bs.SetDebugOutput(bint enable = False)

bs.SetFFmpegLogLevel(int level = <quiet log level>)

The TrackInfo function only returns the most basic information about a track which is the type, codec and disposition. Its main use is to be able to implement custom track selection logic for the source functions. It returns one entry per track in tracktype, tracktypestr, codec, codecstr, disposition and dispositionstr, so the track number to pass to a source function is the index into those arrays.

The Metadata function returns all the file or track metadata as key-value pairs depending on whether or not track is specified.

Avisynth+ usage

BSAudioSource(string source[, int track = -1, int adjustdelay = -1, int threads = 0, bool enable_drefs = False, bool use_absolute_path = False, float drc_scale = 0, int cachemode = 1, string cachepath, int cachesize = 100, int maxdecoders = 0, int variableformat = 0])

BSVideoSource(string source[, int track = -1, int fpsnum = -1, int fpsden = 1, bool rff = False, int threads = 0, int seekpreroll = 20, bool enable_drefs = False, bool use_absolute_path = False, int cachemode = 1, string cachepath, int cachesize = 100, string hwdevice, int extrahwframes = 9, string timecodes, int start_number, int variableformat = 0, int viewid = 0, int maxdecoders = 0, bool hwfallback = True, bool apply_rotation = True])

BSSource(string source[, int atrack = -1, int vtrack = -1, int fpsnum = -1, int fpsden = 1, bool rff = False, int threads = 0, int seekpreroll = 20, bool enable_drefs = False, bool use_absolute_path = False, int cachemode = 1, string cachepath, int acachesize = 100, int vcachesize = 100, string hwdevice, int extrahwframes = 9, string timecodes, int start_number, int vvariableformat = 0, int adjustdelay = -1, float drc_scale = 0, int viewid = 0, int maxdecoders = 0, bool hwfallback = True, bool apply_rotation = True, int avariableformat = 0])

BSSetDebugOutput(bool enable = False)

BSSetFFmpegLogLevel(int level = <quiet log level>)

Note that the BSSource function by default will silently ignore errors when opening audio and in that case only return the video track. However if atrack is explicitly set failure to open the audio track will return an error.

Argument explanation

source: The source filename. Note that image sequences also can be opened by using %d or %03d for zero padded numbers. Sequences may start at any number between 0 and 4 unless otherwise specified with start_number. It's also possible to pass urls and other ffmpeg protocols like concat.

track: Either a positive number starting from 0 specifying the absolute track number or a negative number to select the nth audio or video track. Throws an error on wrong type or no matching track.

adjustdelay: Adjust audio start time relative to a video track number. Pass -2 to disable and -1 to be relative to the first video track if one exists. Specifying a non-video track is equivalent to passing -2. Note that the offset is always relative to the first CPU-decodable frame in the stream meaning that it may not be the correct delay when hwdevice and variableformat are used.

variableformat: Selects which of the formats encountered in the track is used for the output. Pass 0 or greater to choose the nth one, and any frames not matching it are dropped. If the file is constant format (most are) this setting does nothing.

For video, -1 additionally allows the format to change in the output instead of picking one, which is the default in VapourSynth. Avisynth+ has no variable format clips and rejects -1, so its default is 0.

For audio the value must be 0 or greater in both plugins, since neither an Avisynth+ clip nor a VapourSynth audio node can change sample type, sample rate or channel count part way through. The default of 0 keeps the first format encountered and drops everything else.

In BSSource the two tracks are set separately as vvariableformat and avariableformat, following the same convention as vtrack/atrack and vcachesize/acachesize. Note that this replaces the old unprefixed variableformat argument, which applied to the video track only.

fpsnum: Convert the source material to constant framerate. Cannot be combined with rff.

fpsden: Convert the source material to constant framerate. Used in conjunction with fpsnum.

rff: Apply RFF flags to the video. If the video doesn't have or use RFF flags the output is unchanged compare to when the option is disabled. Cannot be combined with fpsnum.

threads: Number of threads to use for decoding. Pass 0 to autodetect.

seekpreroll: Number of frames before the requested frame to cache when seeking.

enable_drefs: Option passed to the FFmpeg mov demuxer.

use_absolute_path: Option passed to the FFmpeg mov demuxer.

drc_scale: Apply dynamic range compression to ac3 audio. 0 = None and 1.0 = Normal.

cachemode:

0 = Never read or write index to disk
1 = Always try to read index but only write index to disk when it will make a noticeable difference on subsequent runs and store index files in a subtree of *cachepath*
2 = Always try to read and write index to disk and store index files in a subtree of *cachepath*
3 = Always try to read index but only write index to disk when it will make a noticeable difference on subsequent runs and store index files with *cachepath* used as the base filename with track number and index extension automatically appended 
4 = Always try to read and write index to disk and store index files with *cachepath* used as the base filename with track number and index extension automatically appended

cachepath: The path where cache files are written. Note that the actual index files are written into subdirectories using based on the source location. Defaults to %LOCALAPPDATA% on Windows and $XDG_CACHE_HOME/bsindex if set otherwise ~/bsindex on other operation systems in mode 1 and 2. For mode 3 and 4 it defaults to source.

cachesize: Maximum internal cache size in MB.

hwdevice: The interface to use for hardware decoding. Depends on OS and hardware. On windows d3d11va, cuda and vulkan (H264, HEVC and AV1) are probably the ones most likely to work. Defaults to CPU decoding. Will throw errors for formats where hardware decoding isn't possible.

extrahwframes: The number of additional frames to allocate when hwdevice is set. The number required is unknowable and found through trial and error. The default may be too high or too low. FFmpeg unfortunately is this badly designed.

timecodes: Writes a timecode v2 file with all frame times to the file if specified. Note that this option will produce an error if any frame has an unknown timestamp which would result in an invalid timecode file.

start_number: The first number of image sequences.

viewid: The view id to output, this is currently only used for some mv-hevc files and is quite rare.

showprogress: Print indexing progress as VapourSynth information level log messages.

maxdecoders: The maximum number of decoder instances kept around, defaults to 4 but when decoding high resolution content it may be beneficial to reduce it to 1 to reduce peak memory usage. For example 4k h264 material will use approximately 250MB of ram in addition to the specified cache size for decoder instance. Passing a number outside the 1-4 range will set it to the biggest number supported.

hwfallback: Automatically fall back to CPU decoding if hardware decoding can't be used for the current video track when hwdevice is set. Note that the fallback only happens when a hardware decoder is unavailable and not on any other category of error such as hwdevice having an invalid value.

apply_rotation: Apply the vertical flip and the rotation stored in the video track's display matrix so the output has the orientation the video is meant to be shown in. Note that mirroring is always reported as a vertical flip followed by a rotation. The FlipVertical and Rotation frame properties are set to 0 when enabled since the transform has already been applied. Only rotations that are a multiple of 90 degrees can be applied and anything else is an error. A 90 or 270 degree rotation of a format with non-square chroma subsampling, such as 4:2:2, is handled differently by the two plugins. Avisynth+ resamples the chroma planes and is therefore not lossless, whereas VapourSynth swaps the subsampling axes losslessly and outputs a different format than the source, 4:4:0 for a 4:2:2 source. In VapourSynth a rotation that isn't a multiple of 180 degrees additionally requires a constant format clip, so it can't be combined with a variableformat of -1 on a file that actually changes format.

exporttimestamps: Returns an additional array of all frame timestamps and its timebase in timebasenum and timebaseden containing all frame times addition to the video clip. Note that unknown timestamps can be set to AV_NOPTS_VALUE. Cannot be combined with rff and fpsnum modes.

level: The log level of the FFmpeg library. By default quiet. See FFmpeg documentation for allowed constants. Mostly useful for debugging purposes.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vapoursynth_bestsource-21.0.tar.gz (71.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

vapoursynth_bestsource-21.0-py3-none-win_amd64.whl (12.3 MB view details)

Uploaded Python 3Windows x86-64

vapoursynth_bestsource-21.0-py3-none-musllinux_1_2_x86_64.whl (14.6 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

vapoursynth_bestsource-21.0-py3-none-musllinux_1_2_aarch64.whl (13.2 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

vapoursynth_bestsource-21.0-py3-none-manylinux_2_28_x86_64.whl (13.6 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ x86-64

vapoursynth_bestsource-21.0-py3-none-manylinux_2_28_aarch64.whl (12.3 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARM64

vapoursynth_bestsource-21.0-py3-none-macosx_15_0_x86_64.whl (10.6 MB view details)

Uploaded Python 3macOS 15.0+ x86-64

vapoursynth_bestsource-21.0-py3-none-macosx_15_0_arm64.whl (9.0 MB view details)

Uploaded Python 3macOS 15.0+ ARM64

File details

Details for the file vapoursynth_bestsource-21.0.tar.gz.

File metadata

  • Download URL: vapoursynth_bestsource-21.0.tar.gz
  • Upload date:
  • Size: 71.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for vapoursynth_bestsource-21.0.tar.gz
Algorithm Hash digest
SHA256 76ddfeeec6bb69ab18985a5c2e45b240f11fa40fc2f7f48a9e101c839bbcc7ba
MD5 4f407cfa326c16a53289f87e10187786
BLAKE2b-256 4370f409aebadadd6d0d983026ab069b91b9d834fd8789db46035df6cfb98efa

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_bestsource-21.0.tar.gz:

Publisher: build.yml on vapoursynth/bestsource

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_bestsource-21.0-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for vapoursynth_bestsource-21.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 f1003f5e610acc80ae1bd23752ba182455f807922c83db9958a299991f272ea4
MD5 8f3a5eee4a050434ccc8a8d43780508e
BLAKE2b-256 31f9148bcf3d22910b0b3c574aeb4fea522e585313c1998694662c61084622e5

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_bestsource-21.0-py3-none-win_amd64.whl:

Publisher: build.yml on vapoursynth/bestsource

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_bestsource-21.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for vapoursynth_bestsource-21.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e437caa96102babf0a787b65900f41f140ecf4e50e5915571002b5a5ddf6f035
MD5 8e39e52f93ba21e5829fe7f856037a85
BLAKE2b-256 4d324ab8ca0cc6d6aeb4b7287edc32577605daeff3f1e78fbc28d4d54bbb3f89

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_bestsource-21.0-py3-none-musllinux_1_2_x86_64.whl:

Publisher: build.yml on vapoursynth/bestsource

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_bestsource-21.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for vapoursynth_bestsource-21.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 cc0d3265ece647cfaed7a23ad7e2376834bec1bc49c883f196ff55cb3be16f24
MD5 644a4605557e7d00106483c5b06d4ef5
BLAKE2b-256 10db799e1bcf91f4a5434b8b3f4078b0fbff6779b3227bcabc4c4e62ab7b5987

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_bestsource-21.0-py3-none-musllinux_1_2_aarch64.whl:

Publisher: build.yml on vapoursynth/bestsource

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_bestsource-21.0-py3-none-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for vapoursynth_bestsource-21.0-py3-none-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 14a932a0ae50e5f24bf73cabfb60ea61940def1d1c6ab0ba134ab9bfaeb077ee
MD5 a445d26dc980c02a4daa12b069a995e8
BLAKE2b-256 86b394c257b4a7dd60e4d039478a68f72fcdec0e00f14e2a51b1b45f06be17e3

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_bestsource-21.0-py3-none-manylinux_2_28_x86_64.whl:

Publisher: build.yml on vapoursynth/bestsource

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_bestsource-21.0-py3-none-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for vapoursynth_bestsource-21.0-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 1fa252bfee315cb4d1f59455158bfc744b933a92947e5b6e5fcd8b067f2aacff
MD5 827c6f545ceb08692e4df682140106e9
BLAKE2b-256 6f350e71d6b30ca31c0498f0b0b46087ba8abd1940433f5d0fd695df14b82473

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_bestsource-21.0-py3-none-manylinux_2_28_aarch64.whl:

Publisher: build.yml on vapoursynth/bestsource

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_bestsource-21.0-py3-none-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for vapoursynth_bestsource-21.0-py3-none-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 f15f983ad83a348f6e7265c1e4a4c3bbe47061b0ffd25b3ac73ca4c447c5ebac
MD5 f4d098ba57a16bc92424ef118a027e0a
BLAKE2b-256 c3c1f4e170cd0f25bcd338afebd3e4caf2a9a4e389327583d7f8589ab22735b2

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_bestsource-21.0-py3-none-macosx_15_0_x86_64.whl:

Publisher: build.yml on vapoursynth/bestsource

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vapoursynth_bestsource-21.0-py3-none-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for vapoursynth_bestsource-21.0-py3-none-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 cd805dc79a624d6546e2643c7f32ae25e0d2f330a0c1573d250ac321ed60d2c0
MD5 f76af9cf54242e6b59d802aff7cfb0a8
BLAKE2b-256 255fcccf886171ada2c7b0ac6f25579d003eaa3102e322623f674cf242b4c07e

See more details on using hashes here.

Provenance

The following attestation bundles were made for vapoursynth_bestsource-21.0-py3-none-macosx_15_0_arm64.whl:

Publisher: build.yml on vapoursynth/bestsource

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

21.0 This release

8 files

20.0

8 files

19.0

8 files

18.0

10 files

17.0

6 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page