# Vship and FFVship

Canonical URL: https://encode.wiki/tools/utilities/vship/
Content version: ca42e61ede0a24f789d7287a0001244ad22f4abf
Status: current
License: CC BY-SA 4.0
Checksum (SHA-256): c870cf521d942195af984b57655c2babde0384786db3792b42e8dc00b39da743

> **Repository:** [Line-fr/Vship](https://codeberg.org/Line-fr/Vship). A Library for GPU-accelerated visual fidelity metrics, featuring SSIMULACRA2, Butteraugli and CVVDP. Latest release: [v5.1.2](https://codeberg.org/Line-fr/Vship/releases/tag/v5.1.2), Oct 6, 2026. Last commit: Oct 6, 2026. Stars: 28.

Vship is a GPU implementation of three perceptual metrics: [SSIMULACRA2](/reference/metrics/ssimulacra2/), [Butteraugli](/reference/metrics/butteraugli/) and [CVVDP](/reference/metrics/cvvdp/). These are the metrics the encoding community prefers for comparing encodes, and they are slow on a CPU, so Vship is what makes scoring whole videos practical. Tools such as [Av1an](/tools/utilities/av1an/) and auto-boost scripts use it for target-quality encoding.

It comes in three forms:

- **FFVship**, a command-line tool that decodes the two videos itself and prints or saves the scores;
- a **VapourSynth plugin** (namespace `vship`) for use inside scripts;
- a **C API** (libvship) for other programs.

The current release is 5.1.2 (October 2026). 5.1.1 fixed wrong decoding of full-range YUV and a CVVDP accuracy bug, so rescore anything measured with older versions before comparing.

## Install

Windows builds of FFVship and the library are on the [releases page](https://codeberg.org/Line-fr/Vship/releases), in CUDA (NVIDIA) and Vulkan versions. On Linux, build from source:

```sh
make build BACKEND=Vulkan
make buildFFVSHIP
sudo make install PREFIX=/usr
```

Use `BACKEND=Cuda` (needs the CUDA toolkit) or `BACKEND=HIP` (needs ROCm/HIP) for the native NVIDIA and AMD paths. FFVship also needs FFMS2, the libavutil headers and `pkg-config`. `make install` also links the library into `$PREFIX/lib/vapoursynth`, where VapourSynth loads plugins; the default `/usr/local` prefix may not be on its search path.

| Backend  | GPUs                  | Notes                                                                                                                            |
| -------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `Cuda`   | NVIDIA                | Fastest on NVIDIA in the author's benchmarks, especially for SSIMULACRA2 and CVVDP                                              |
| `HIP`    | AMD                   | The author currently recommends Vulkan on AMD because of an AMD driver bug; `MITIGATE_MALLOC_ASYNC=on` builds a slower workaround |
| `Vulkan` | Any GPU with a Vulkan driver | Most portable; close to CUDA for Butteraugli, slower for the other two. Even runs on a CPU through Mesa's lavapipe, slowly |

## FFVship

```sh
FFVship --source reference.mkv --encoded distorted.mkv -m SSIMULACRA2 --json scores.json --svg scores.svg
```

It prints the mean, standard deviation, median, 5th and 95th percentiles, minimum and maximum of the per-frame scores. For CVVDP it prints a single video score instead.

| Option                                  | Use                                                                                                    |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `--source`/`-s`, `--encoded`/`-e`       | Reference and distorted video                                                                          |
| `-m`, `--metric`                        | `SSIMULACRA2` (default), `Butteraugli` or `CVVDP`                                                      |
| `--json FILE`                           | Per-frame scores; Butteraugli gives `[q-norm, 3-norm, max-norm]` per frame, CVVDP a running video score |
| `--svg FILE`                            | Graph of the per-frame scores                                                                          |
| `--start`, `--end`, `--every N`         | Score a range, or every Nth frame for a quick estimate                                                 |
| `--encoded-offset N`                    | Shift the encode by N frames if the files don't start on the same frame                               |
| `--cropTopSource` and similar           | Crop either input before scoring                                                                       |
| `-g`, `--gpu-threads`                   | Frames in flight on the GPU (default 3); lower it to save VRAM                                         |
| `-t`, `--threads`                       | Decoder processes (default 1); raise to 2–3 if decoding can't keep the GPU busy                        |
| `--gpu-id`, `--list-gpu`                | Pick a GPU on multi-GPU systems                                                                        |
| `--intensity-target`, `--qnorm`         | Butteraugli display brightness in nits (default 203) and extra norm (default 2)                        |
| `--displayModel`, `--resizeToDisplay`   | CVVDP display model (default `standard_fhd`) and scaling to its resolution                             |
| `--cache-index`                         | Keep the FFMS2 index files so repeat runs start faster                                                 |
| `--verbose`                             | Print the size, range, matrix, transfer and primaries FFVship used for each file                       |

Note that `-e` means `--encoded`, not `--every`. If the two videos have different sizes, FFVship resizes the encode to match the reference; crop first if the difference is borders rather than scaling.

FFVship converts to RGB using each file's colour tags and guesses any that are missing, so an untagged file can score very differently from the same file tagged correctly. Check with `--verbose`, and tag the reference and encodes (for example BT.709, limited range) when the source is untagged.

## VapourSynth plugin

| Function                                 | Main arguments                                                                       | Per-frame properties                                                 |
| ---------------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
| `core.vship.SSIMULACRA2(ref, dist)`      | `numStream`, `gpu_id`                                                                | `_SSIMULACRA2`                                                       |
| `core.vship.BUTTERAUGLI(ref, dist)`      | `qnorm=2`, `intensity_multiplier=203`, `distmap=0`, `numStream`, `gpu_id`            | `_BUTTERAUGLI_QNorm`, `_BUTTERAUGLI_3Norm`, `_BUTTERAUGLI_INFNorm`   |
| `core.vship.CVVDP(ref, dist)`            | `model_name="standard_fhd"`, `resizeToDisplay=0`, `distmap=0`, `disableTemporal=0`   | `_CVVDP` (running score for frames 0 to *n*)                         |

Both clips must have the same dimensions and length. `numStream` limits how many frames are on the GPU at once and so the VRAM used; it defaults to the number of VapourSynth threads. `distmap=1` returns a greyscale difference map instead of scores, which you can step through in a previewer. For CVVDP, request the frames in order and read `_CVVDP` from the last one.

Run scripts that print scores with `python`, not `vspipe`:

```python
import vapoursynth as vs
core = vs.core

ref = core.bs.VideoSource("reference.mkv")
dist = core.bs.VideoSource("distorted.mkv")
clip = core.vship.SSIMULACRA2(ref, dist)
scores = [f.props["_SSIMULACRA2"] for f in clip.frames()]
print(sum(scores) / len(scores))
```

The metric pages show complete scripts that summarise the scores with a mean, a low percentile and the worst frames.

## Licence

Vship's README calls it MIT-licensed, but the `LICENSE` file is a modified "MIT NON-AI License" that forbids using the code, or including it in datasets, for training machine-learning systems.
