Open-source project
facebookresearch/videoseal avatar
facebookresearch/videoseal

VideoSeal: open invisible watermarking models for images and video

Open and efficient video and image watermarking

811 stars105 forksPythonMIT

At a glance

What is it?
VideoSeal is Meta's open release of invisible watermarking models, covering a stable 256 bit video model, a higher capacity 1024 bit model and a newer pixel model, with training code and evaluation tools under MIT. The Python package is a thin wrapper around a model registry that downloads checkpoints on first use, and there is a separate forger project for studying attack robustness.
Who is it for?
VideoSeal suits a team that needs invisible watermarking for provenance or copyright marking and wants to train or evaluate its own models rather than call a hosted service, and it suits a researcher who wants to attack watermarking, since the forger project is released alongside it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 113 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the project actually releases

VideoSeal is described as state of the art invisible watermarking models for images and videos, and the open source line in the highlights is explicit about the scope. All models, training code and evaluation tools are released under MIT license.

That combination is what distinguishes it. A watermark model on its own is a set of weights, and a set of weights is hard to evaluate, compare or improve. A watermark model plus its training code plus the evaluation harness is a research programme, and the paper is only reproducible in a meaningful sense if all three are available.

The repository layout matches that claim. There is videoseal/ for the package itself, train.py at the root, an inference_av.py for audio-visual watermarking, an inference_streaming.py, a scripts/ directory, a configs/ directory, a notebooks/ directory with three inference notebooks, an assets/ directory with sample videos, a docs/ directory, and a separate wmforger/ directory for the attack project.

The licence field on the repository says MIT, and the package metadata records Facebook AI Research as the author. The primary language is Python, and the last push was on 2026-07-02, with the recent releases section saying the repository has no GitHub releases, so the checkpoints are distributed as files rather than as tagged package versions.

The four models and what each one trades away

The model zoo is a table of trade-offs, and the table is more informative than any single claim of quality.

PixelSeal has a capacity of 256 bits and is listed as the state of the art for robustness and imperceptibility, with the status marked New. The README's highlight on this one is specific: it achieves a state of the art robustness and imperceptibility trade-off, positioning it at the Pareto frontier, and the mechanism is described as adversarial-only training combined with JND-based attenuation. That is a claim about where it sits on a curve rather than about it being best at one axis, which is the honest way to state it.

ChunkySeal has a capacity of 1024 bits and is described as a high capacity larger model. The highlight puts it at a 4x capacity increase, and the framing is that watermarking limits are far from reached. The interesting thing about it is the direction: most invisible watermarking work pushes capacity down to improve imperceptibility, and this model pushes it up, which is what you want when the payload is meaningful rather than a boolean flag.

VideoSeal v1.0 also has 256 bits but is marked Stable, and it is the one the quick start loads by default. The December 2024 initial release was a 96-bit baseline model, and that checkpoint is still in the table as VideoSeal v0.0 with the status Legacy.

Each row also has a model card, a checkpoint link and a paper. The model cards are yaml files under videoseal/cards/, and the README points to docs/training.md for the complete training checkpoints with optimizer states and discriminators, which are the things you need to resume training rather than just fine-tune.

The quick start for images

The API is deliberately small, and the whole image path is a handful of lines.

python
import videoseal
from PIL import Image
import torchvision.transforms as T

# Load any model by name (automatically downloads on first use)
model = videoseal.load("videoseal")     # VideoSeal v1.0 (256-bit, stable)
# model = videoseal.load("pixelseal")   # PixelSeal (SOTA imperceptibility & robustness)
# model = videoseal.load("chunkyseal")  # ChunkySeal (1024-bit high capacity)

# Watermark an image
img_tensor = T.ToTensor()(Image.open("image.jpg")).unsqueeze(0)
outputs = model.embed(img_tensor)
T.ToPILImage()(outputs["imgs_w"][0]).save("watermarked.jpg")

# Detect watermarks
detected = model.detect(img_tensor)
hidden_message = (detected["preds"][0, 1:] > 0).float()  # Binary message

Three things are worth noting about that snippet.

The model is loaded by name and downloaded automatically on first use, so the checkpoint URL is not something you have to manage. The load call takes one of the three names, and the commented lines show the alternatives.

Embedding and detecting are separate calls on the same model object, and embed returns a dictionary whose imgs_w key holds the watermarked image. The watermarked image is written out as a normal image file, which is the point of an invisible watermark, that the artefact looks unchanged.

The detection output is a tensor of predictions, and the message is recovered by thresholding at zero and dropping the first element, which is a confidence or detection score rather than part of the payload. The comment calls the result a binary message. So the payload is a bit string, and the bit width is what the capacity column in the model zoo refers to.

Video, temporal consistency and the streaming variant

The video path differs mainly in the tensor layout, and the temporal aspect is where the model differs from its image counterpart.

python
import videoseal
import torchvision

# Load and watermark video
model = videoseal.load("videoseal")
video, _, _ = torchvision.io.read_video("video.mp4")
video = video.permute(0, 3, 1, 2).float() / 255.0

outputs = model.embed(video, is_video=True)
watermarked = (outputs["imgs_w"] * 255).byte().permute(0, 2, 3, 1)
torchvision.io.write_video("watermarked.mp4", watermarked, fps=30)

The frames are read as a time major tensor, permuted to channels first and scaled to a zero to one range, and the embed call is given is_video=True so the model knows it is handling a sequence rather than a single image. The output is converted back to bytes and permuted to the layout torchvision's writer expects.

The highlight for VideoSeal is that it does efficient image and video watermarking with temporal consistency, and temporal consistency is the hard part in video watermarking. A watermark that is stable frame to frame survives compression and re-encoding; one that flickers is perceptually obvious and does not survive anything.

For memory, there is a streaming notebook, notebooks/video_inference_streaming.ipynb, which the README describes as optimized for lower RAM usage, and the script inference_streaming.py at the root. The audio-visual script is the other direction: inference_av.py watermarks both the audio and the video of a video file, and the README warns that it loads the full video into memory, so it is not suitable for long videos. The three notebooks are image inference, video inference and the streaming variant.

Installing the dependencies

The requirements are specific and the version guidance is worth reading rather than skipping.

The README states Python 3.10, with pytorch above 2.3, torchvision 0.16.0, torchaudio 2.1.0 and cuda 12.1, and then gives the conda install line for pytorch.

bash
conda install pytorch==2.4.0 torchvision==0.19.0 torchaudio==2.4.0 pytorch-cuda=12.1 -c pytorch -c nvidia

The remaining dependencies come from the requirements file.

bash
pip install -r requirements.txt

For training there is an extra step, and it comes with a warning.

bash
pip install decord

The README points at a known issue thread for decord installation problems and says everything should work without decord for inference, but that there may be issues for training in that case. So decord is a training-time convenience for video decoding rather than a hard requirement, and a training run without it is likely to be slower or less reliable.

The package metadata gives a fuller picture. The build uses flit, requires Python 3.9 or newer, and depends on PyWavelets, av, calflops, decord, einops, lpips, omegaconf, opencv-python, pandas, pycocotools, pytorch_msssim, safetensors, scikit-image, scipy, tensorboard, timm at 0.9.16, torch at 2.3.1 or newer, tqdm and transformers.

Two of those are worth recognising. lpips and pytorch_msssim are perceptual metrics, which tells you the training loop optimises against perceptual similarity rather than pixel error. And calflops is a flops counter, which suggests the project cares about the compute cost of the model, consistent with a highlight that says efficient.

There is also a TorchScript guide at docs/torchscript.md for standalone usage without dependencies, with pre-compiled models, which is the route for a deployment that cannot carry a Python environment.

The forger project and why it is released too

The wmforger/ directory is one of the most interesting parts of the release, and it is a separate project with its own paper, WmForger, accepted to NeurIPS 2025 as a Spotlight according to the October 2025 update in the README.

An attack on a watermarking system is the natural counterpart to the system itself. Without an attacker, a robustness claim is a number produced by the authors' own evaluation harness, and the only way to know whether a watermark survives realistic tampering is to have someone tamper with it. A forger is a model trained to remove or replace a watermark while keeping the image plausible, and releasing it alongside the watermarking models means the community can test both.

The repository also has documentation for the pieces needed to reproduce published comparisons. The baseline models are not included, because the project does not own any third-party models, so you have to download them manually, with a guide at docs/baselines.md. VMAF, the video quality metric, has its own guide at docs/vmaf.md for checking and installing it. Both of these are the kind of detail that saves an afternoon.

The evaluation side also includes a demo at aidemos.meta.com/videoseal and a Colab notebook, which is the fastest way to see what the models do before installing anything.

Where VideoSeal is the wrong tool

The first limitation is that invisibility and robustness are a trade-off, and the model zoo makes that explicit with the capacity, robustness and imperceptibility axes. A model tuned to survive compression and cropping will show its watermark more, and a model tuned to be invisible will not survive much. If your requirement is a watermark that survives heavy geometric transformation or physical re-recording of a video on a screen, the README's Pareto frontier framing is a warning that you are choosing a point on the curve, not getting all of it.

The second is that this is a pixel-domain model. There is no metadata embedding, so it does not help if your threat is a file whose metadata is stripped on upload. It is the right tool for provenance in a re-encoded image or video, and the wrong one for surviving a platform that re-compresses aggressively without any pixel-level work.

The third is the hardware requirement for training. The conda line pins a CUDA 12.1 build of PyTorch, and the training code with discriminators and optimizer states is a research-scale activity. Inference is much lighter, and the TorchScript route removes the dependency stack, but if you want to fine-tune, you need a GPU and time.

The fourth is the dependency weight for what the package does. The install pulls in opencv, scikit-image, scipy, transformers, timm, tensorboard and PyWavelets, some of which are only needed for training or evaluation. A production deployment that only embeds and detects would be better served by the TorchScript models.

The fifth is the release packaging. There are no GitHub releases, so the version you install from the package index is not the same as a tagged release, and the checkpoints are separate downloads at a public files host. An archive of exactly what you used needs pinning on both.

VideoSeal compared with Stable Signature, WEvade and a metadata steganography tool

A comparison with other open watermarking work is the natural one, and the paper link for both VideoSeal v1.0 and the legacy 96-bit model is the same arXiv entry, 2412.09492, which suggests the video model and its image predecessor share a paper. The practical difference for a user is the model zoo: four checkpoints with a documented capacity, a model card and a stated best use, rather than one model.

The comparison with the wider line of watermark removal research, including named works such as WEvade, is the one the forger project sits in. The release of a forger alongside the watermarking models means both sides of the same contest are available. If your concern is whether a watermark you embedded will survive an adversary, having the adversary in the repository is a genuine advantage, and the README's NeurIPS spotlight note for WmForger suggests it is competitive work rather than a toy.

The third comparison is with metadata steganography, the technique of hiding data in the file headers. The difference is in the threat model rather than the technique. Metadata survives a copy and dies on re-encode, and pixel watermarking dies on a crop and survives a re-encode, so the two are complementary rather than competing, and a serious provenance system for video uses more than one channel.

The fourth comparison is with a commercial watermarking API, where the difference is again ownership. A service gives you a guarantee and a detection endpoint you do not host. This gives you weights you can run, retrain and audit, which is what you want if the watermark has to survive your own pipeline and your own adversary.

Licence, provenance and how to evaluate before shipping

The licence field on the repository says MIT, and the README confirms that all models, training code and evaluation tools are released under MIT. The package metadata names Facebook AI Research as the author and uses flit as the build backend.

MIT is a permissive licence with no copyleft obligation, which means the weights and the code can be used inside a commercial product without a licensing fee and without publishing your own modifications, though the notice has to travel with the code.

The provenance of the models matters for a watermark in a way it does not for a classifier. These checkpoints come from a specific training run, and the README points to the complete training checkpoints with optimizer states and discriminators in docs/training.md, and to per-model model cards in the videoseal/cards directory. The model card is the document to read before shipping a checkpoint, because it is where the capacity, the intended use and the reported behaviour are recorded, and because a watermark's properties depend on the model rather than on the format.

Four things to check before a watermark goes into production.

Read the model card for the exact checkpoint you use, since the four models differ in capacity and in what they are optimised for.

Measure the trade-off yourself on your own content. The published robustness numbers come from the authors' own evaluation harness, and the README is explicit that the baseline models are not included, which means reproducing a published comparison is work you have to do rather than a script you can run.

Decide the attack model, because a watermark is only strong against the attacks you have in mind, and having the forger in the repository means you can test against a trained attacker instead of only against compression.

And check the payload semantics. The detection output gives you a bit string and a confidence value, and what those bits mean, whether a flag, a model identifier or a link to a registry, is a design decision the model does not make for you.

Editorial conclusion

VideoSeal suits a team that needs invisible watermarking for provenance or copyright marking and wants to train or evaluate its own models rather than call a hosted service, and it suits a researcher who wants to attack watermarking, since the forger project is released alongside it. It is the wrong tool if you need a watermark that survives heavy geometric transformation or physical re-recording, because the robustness claim in the README is a trade-off curve rather than a guarantee, and it is the wrong choice if you want metadata watermarking, since this is a pixel-domain model. Before adopting it, read the model cards in the videoseal/cards directory for the specific checkpoint, and note that the third party baseline models have to be downloaded by hand because the project does not redistribute them.

Frequently asked questions

What models does VideoSeal provide?

Four entries in the model zoo. PixelSeal at 256 bits for state of the art robustness and imperceptibility, ChunkySeal at 1024 bits for high capacity, VideoSeal v1.0 at 256 bits marked stable, and the legacy VideoSeal v0.0 at 96 bits. Each has a model card, a checkpoint and a paper.

How do I watermark an image with VideoSeal?

Load a model by name with videoseal.load, which downloads the checkpoint on first use, convert the image to a tensor, call model.embed on it and save the imgs_w entry of the returned dictionary. To read the message back, call model.detect and threshold the preds tensor at zero.

What are the installation requirements for VideoSeal?

The README states Python 3.10 with pytorch above 2.3, torchvision 0.16.0, torchaudio 2.1.0 and cuda 12.1, gives a conda install line for PyTorch 2.4.0 with a CUDA 12.1 build, and then pip install -r requirements.txt for the rest. decord is recommended for training, with known installation issues, but inference works without it.

What is WmForger and why is it in the VideoSeal repository?

WmForger is a separate project in the wmforger/ directory, a model for attacking watermarks, accepted to NeurIPS 2025 as a Spotlight according to the README. It is released alongside the watermarking models so that the robustness of the watermarks can be tested against a trained adversary.

Why do I have to download the baseline models myself?

The README states the project does not own any third-party models, so they have to be downloaded manually, and docs/baselines.md has the guide. There is a separate guide at docs/vmaf.md for checking and installing the VMAF video quality metric used in evaluation.

What licence is VideoSeal released under?

MIT. The README states that all models, training code and evaluation tools are released under the MIT license, and the package metadata names Facebook AI Research as the author.

Official sources

  1. facebookresearch/videoseal on GitHub
  2. Issues
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/facebookresearch-videoseal.svg)](https://hysenlabs.com/projects/facebookresearch-videoseal)

Was this useful?