Clean hockey videos, removing ads. https://spacecruft.org/deepcrayon/zamboni
  • Python 98.6%
  • Shell 1.4%
Find a file
2025-09-09 10:18:46 -06:00
configs rm unplanned SD usage for qwen 2025-09-07 12:26:57 -06:00
docs DRAFT: zamboni-clean 2025-09-07 11:33:48 -06:00
scripts DRAFT: zamboni-clean 2025-09-07 11:33:48 -06:00
src/zamboni Fix pyav issues 2025-09-09 10:18:46 -06:00
test fix clean tests 2025-09-07 11:49:24 -06:00
.gitignore Ignore .venv 2025-09-07 09:03:41 -06:00
CHANGELOG.txt v0.6.0 2025-09-07 20:01:20 -06:00
dataset.yaml Rename training config file 2025-04-08 09:08:22 -06:00
LICENSE-apache.txt Apache 2.0 License 2025-04-06 11:30:47 -06:00
LICENSE-CC.txt CC by SA 4.0 International 2025-04-06 11:30:56 -06:00
ORCHESTRATOR_PROMPT_FOR_IMPLEMENTATION.md DRAFT: zamboni-clean 2025-09-07 11:33:48 -06:00
pyproject.toml supposedly implement the actual plan, not make up garbage 2025-09-07 13:17:40 -06:00
README.md Use ffmpeg not moviepy to merge audio in mask video 2025-04-09 11:52:22 -06:00
SOTA_OPTICAL_FLOW_COMPARISON.md DRAFT: zamboni-clean 2025-09-07 11:33:48 -06:00
test_phase2_components.py DRAFT: zamboni-clean 2025-09-07 11:33:48 -06:00
test_phase3_integration.py DRAFT: zamboni-clean 2025-09-07 11:33:48 -06:00
ZAMBONI_CLEAN_COMPLETE_IMPLEMENTATION_PLAN.md DRAFT: zamboni-clean 2025-09-07 11:33:48 -06:00
ZAMBONI_CLEAN_COMPLETE_IMPLEMENTATION_PLAN_PART2.md DRAFT: zamboni-clean 2025-09-07 11:33:48 -06:00
zamboni_config.yaml.example rm unplanned SD usage for qwen 2025-09-07 12:26:57 -06:00

Zamboni

Zamboni cleans hockey game videos by removing ads from the hockey rink boards.

Installation

Thusly, suit to taste:

git clone https://spacecruft.org/deepcrayon/zamboni
cd zamboni/
python -m venv venv
source venv/bin/activate
pip install -U setuptools pip wheel
pip install -e .

The ffmpeg binary needs to be installed as well, such as:

apt install ffmpeg

Overview

To create a model that removes ads from the view, do this:

  • Record a video to an .mp4 file with zamboni-rec.
  • Optionally extract images from video with zamboni-vid2img.
  • Create labels of video frames using zamboni-label.
  • Train a new model using zamboni-train.
  • Create mask video using zamboni-mask.
  • Create final video using zamboni-clean (to be written).

Help

Usage help:

zamboni-rec

$ zamboni-rec  --help
usage: zamboni-rec [-h] [-a AUDIO_CODEC] [-A AUDIO_INPUT] [-c VIDEO_CODEC] [-D] [-C AUDIO_CHANNELS] [-d DIR] [-l] [-m] [-o] [-p PREFIX] [-r FRAMERATE] [-s SIZE] [-t TIME] [-T | -N] [-v] [-V]

Record screen and save to mp4

options:
  -h, --help            show this help message and exit
  -a AUDIO_CODEC, --audio-codec AUDIO_CODEC
                        Audio codec to use (default: aac)
  -A AUDIO_INPUT, --audio-input AUDIO_INPUT
                        Audio input source (default: pulse)
  -c VIDEO_CODEC, --video-codec VIDEO_CODEC
                        Video codec to use (default: hevc_nvenc)
  -D, --debug           Debugging
  -C AUDIO_CHANNELS, --audio-channels AUDIO_CHANNELS
                        Number of audio channels (default: 2)
  -d DIR, --dir DIR     Directory to save the output video file
  -l, --loop            Loop input until stream is terminated manually
  -m, --mouse           Record the mouse cursor (default false)
  -o, --overwrite       Overwrite existing files (default: true)
  -p PREFIX, --prefix PREFIX
                        Prefix for the output video file name
  -r FRAMERATE, --framerate FRAMERATE
                        Framerate for recording (default: 30)
  -s SIZE, --size SIZE  Video size (default: 1920x1080)
  -t TIME, --time TIME  Length of recording in HH:MM:SS format (default: 00:01:00)
  -T, --timestamp       Add timestamp to filename (default)
  -N, --no-timestamp    Do not add timestamp to filename
  -v, --verbose         Increase output verbosity
  -V, --version         Show version

zamboni-vid2img

$ zamboni-vid2img --help
usage: zamboni-vid2img [-h] [-D] [-f FILENAME] [-o OUTPUT] [-p PREFIX] [-s FPS] [-v] [-V]

Extract images from video

options:
  -h, --help            show this help message and exit
  -D, --debug           Debugging
  -f FILENAME, --filename FILENAME
                        File name of video (default: hockey.mp4)
  -o OUTPUT, --output OUTPUT
                        Output directory (default: datasets/train/images)
  -p PREFIX, --prefix PREFIX
                        Filename prefix (default: hockey)
  -s FPS, --fps FPS     Frames per second to extract (default: 1)
  -v, --verbose         Increase output verbosity
  -V, --version         Show version

To process an entire directory of .mp4 files, run something like this:

for i in *.mp4 ; do echo $i ; mkdir -p `basename $i .mp4` ; zamboni-vid2img -f $i -o `basename $i .mp4` -p `basename $i .mp4` ; done

zamboni-label

$ zamboni-label --help
usage: zamboni-label [-h] [--reset-config] [--logger-level {debug,info,warning,fatal,error}] [--output OUTPUT] [--config CONFIG] [--nodata] [--autosave] [--nosortlabels] [--flags FLAGS] [--labelflags LABEL_FLAGS] [--labels LABELS]
                     [--validatelabel {exact}] [--keep-prev] [--epsilon EPSILON]
                     [filename]

positional arguments:
  filename              image or label filename; If a directory path is passed in, the folder will be loaded automatically

options:
  -h, --help            show this help message and exit
  --reset-config        reset qt config
  --logger-level {debug,info,warning,fatal,error}
                        logger level
  --output OUTPUT, -O OUTPUT, -o OUTPUT
                        output file or directory (if it ends with .json it is recognized as file, else as directory)
  --config CONFIG       config file or yaml-format string (default: /home/jebba/.ailabelerrc)
  --nodata              stop storing image data to JSON file
  --autosave            auto save
  --nosortlabels        stop sorting labels
  --flags FLAGS         comma separated list of flags OR file containing flags
  --labelflags LABEL_FLAGS
                        yaml string of label specific flags OR file containing json string of label specific flags (ex. {person-\d+: [male, tall], dog-\d+: [black, brown, white], .*: [occluded]})
  --labels LABELS       comma separated list of labels OR file containing labels
  --validatelabel {exact}
                        label validation types
  --keep-prev           keep annotation of previous frame
  --epsilon EPSILON     epsilon to find nearest vertex on canvas

Steps:

  • Run zamboni-label.
  • Open directory of images, datasets/train/images or datasets/valid/images, with File --> Open Dir.
  • Alternatively, use File --> Open Video to convert a video to images. When importing images, optionally using 1 to convert every frame, to 30 to select one image per second.
  • Click the "AI" button in the left hand column.
  • At Auto No Model dropdown, select Segment Anything 2 Video (Large). The first time it runs, it will download the model.
  • Select Point (q) and click on an ad.
  • Select Point (e) and click outside the ad, to exclude an area if too large of an area was selected.
  • Repeat this select over and over on the image.
  • Save image with Ctrl+S.
  • Hit right-arrow or d to move to next image.
  • Repeat selections on new image until all images are processed.
  • Add a file datasets/train/images/classes.txt and datasets/valid/images/classes.txt with the line Advertisement.
  • Click on Export --> Export YOLO-Seg Annotations.
  • For Select a specific classes file, use datasets/train/images/classes.txt.
  • For Export options use path datasets/train/labels. Leave unchecked both options Save with images? and Skip empty labels?.

zamboni-train

Note, Ultralytics may save defaults and override options with values set in these files:

  • ~/.config/Ultralytics/settings.json
  • ~/.config/Ultralytics/settings.yaml

You may need to remove these files or remove the entire ~/.config/Ultralytics directory.

$ zamboni-train --help
usage: zamboni-train [-h] [-b BATCH] [-D] [-d DATA] [-e EPOCHS] [-m MODEL] [-s IMGSZ] [-v] [-V]

Train a model

options:
  -h, --help            show this help message and exit
  -b BATCH, --batch BATCH
                        Batch size (default: 8)
  -D, --debug           Debugging
  -d DATA, --data DATA  Data file (default: dataset.yaml)
  -e EPOCHS, --epochs EPOCHS
                        Number of epochs (default: 100)
  -m MODEL, --model MODEL
                        Model to use (default: yolo11x-seg.pt)
  -s IMGSZ, --size IMGSZ
                        Image size (default: 1920)
  -v, --verbose         Increase output verbosity
  -V, --version         Show version

zamboni-download

$ zamboni-download --help
usage: zamboni-download [-h] [-D] [-u URL] [-v] [-V]

Download model

options:
  -h, --help         show this help message and exit
  -D, --debug        Debugging
  -u URL, --url URL  URL for model (default: https://spacecruft.org/deepcrayon/zamboni-model/media/branch/main/zamboni.pt)
  -v, --verbose      Increase output verbosity
  -V, --version      Show version

zamboni-mask

$ zamboni-mask  -h
usage: zamboni-mask [-h] [-D] [-f FILENAME] [-H HEIGHT] [-m MODEL] [-o OUTPUT] [-v] [-V] [-w WIDTH]

Create mask for a video

options:
  -h, --help            show this help message and exit
  -D, --debug           Debugging
  -f FILENAME, --filename FILENAME
                        Video file to process (default: hockey.mp4)
  -H HEIGHT, --height HEIGHT
                        Video height size, must be factor of 4 (default: 1088)
  -m MODEL, --model MODEL
                        Model to use (default: zamboni.pt)
  -o OUTPUT, --output OUTPUT
                        Video output file name (default: hockey-mask.mp4)
  -v, --verbose         Increase output verbosity
  -V, --version         Show version
  -w WIDTH, --width WIDTH
                        Video width size, must be factor of 4 (default: 1920)

scripts/rename-images.sh

Crufty script to rename images to unique names.

Dataset

The datasets/ directory with test/, train/, and valid/ subdirectories should be in the parent directory of the zamboni directory (e.g. one directory above zamboni/).

The training datasets directory should be laid out thusly:

datasets/train/images/classes.txt

datasets/train/images/00000.jpg
...
datasets/train/images/99999.jpg

datasets/train/images/00000.json
...
datasets/train/images/99999.json

datasets/train/labels/00000.txt
...
datasets/train/labels/99999.txt

The validation datasets directory is similar to above:

datasets/valid/images/classes.txt

datasets/valid/images/00000.jpg
...
datasets/valid/images/99999.jpg

datasets/valid/images/00000.json
...
datasets/valid/images/99999.json

datasets/valid/labels/00000.txt
...
datasets/valid/labels/99999.txt

Status

Alpha.

Under development.

Most parts minimally work.

Masking is used to remove ads with a single color.

Eventually inpainting will be used to remove ads as it will match colors better.

License

Apache 2.0 or Creative Commons CC by SA 4.0 International. You may use this code, files, and text under either license.

Unofficial project, not related to upstream projects.

Upstream sources under their respective copyrights.

Copyright © 2025 Jeff Moe.