Skip to main content

clawID

Invisible & visible watermarking SDK for AI-generated images and video.

PyPI Python CI License: MIT

A research project by hawky.ai — the AI content provenance platform.

clawID embeds a UUID-based watermark into images and video frames — invisible to the human eye but detectable by the SDK. Inspired by Google SynthID. Built for AI-generated asset provenance tracking.

Links: PyPI · GitHub · Hugging Face Space · hawky.ai


Features

  • Invisible watermarking via DWT-QIM (Discrete Wavelet Transform + Quantization Index Modulation)
  • Resize-robust mode (algorithm='fm') — survives ±35% resize, JPEG compression, and minor edits
  • Visible watermarking — overlay text/logo with configurable opacity and position
  • Video support — watermark every Nth frame; detect from any single watermarked frame
  • REST API — FastAPI server with /embed and /detect endpoints
  • Storage backends — SQLite, PostgreSQL, MongoDB, Redis
  • CLI — clawid embed, clawid detect, clawid embed-video, clawid detect-video

Installation

# Core (images only)
pip install clawid

# With video support
pip install "clawid[video]"

# With REST API
pip install "clawid[api]"

# Everything
pip install "clawid[all]"

Quick Start

Images

from clawid import embed, detect

# Embed invisible watermark
meta = embed(
    source='photo.jpg',
    output_path='photo_wm.png',
    metadata={'uid': 'creator123', 'platform': 'hawky.ai'},
)
print(meta['clawid'])  # e.g. "3f2a1b4c-..."

# Detect
result = detect('photo_wm.png')
print(result['uid'])       # creator123
print(result['platform'])  # hawky.ai

Resize-robust mode

meta = embed(
    source='photo.jpg',
    output_path='photo_wm.png',
    metadata={'uid': 'creator123'},
    algorithm='fm',   # survives ±35% resize
)

Video

from clawid import embed_video, detect_video

meta = embed_video(
    'input.mp4',
    'output_wm.mp4',
    metadata={'uid': 'creator123', 'platform': 'hawky.ai'},
    frame_stride=5,   # watermark every 5th frame
)

result = detect_video('output_wm.mp4')
print(result['uid'])  # creator123

Visible watermark

meta = embed(
    source='photo.jpg',
    output_path='photo_wm.png',
    metadata={'uid': 'creator123'},
    mode='visible',     # or 'both' for invisible + visible
    opacity=0.6,
    position='bottom-right',
)

CLI

# Embed
clawid embed -i photo.jpg -o photo_wm.png --uid creator123 --platform hawky.ai

# Embed (resize-robust)
clawid embed -i photo.jpg -o photo_wm.png --uid creator123 --algorithm fm

# Detect
clawid detect -i photo_wm.png

# Video
clawid embed-video -i input.mp4 -o output_wm.mp4 --uid creator123
clawid detect-video -i output_wm.mp4

# Save to SQLite store on embed, enrich on detect
clawid embed -i photo.jpg -o wm.png --uid creator123 --store sqlite:///clawid.db
clawid detect -i wm.png --store sqlite:///clawid.db

REST API

pip install "clawid[api]"
clawid serve --store sqlite:///clawid.db --port 8000

Endpoints:

Method Path Description
POST /embed Upload image, get back watermarked image + metadata
POST /detect Upload image, get back detected metadata
GET /docs Interactive Swagger UI
# Embed via API
curl -X POST http://localhost:8000/embed \
  -F "file=@photo.jpg" \
  -F "uid=creator123" \
  -F "platform=hawky.ai" \
  --output photo_wm.png

# Detect via API
curl -X POST http://localhost:8000/detect \
  -F "file=@photo_wm.png"

Storage Backends

from clawid.storage import from_uri

# SQLite (local)
with from_uri('sqlite:///clawid.db') as store:
    store.save(meta['clawid'], meta)
    record = store.get(meta['clawid'])

# PostgreSQL
with from_uri('postgresql://user:pass@localhost/mydb') as store:
    store.save(meta['clawid'], meta)

# MongoDB
with from_uri('mongodb://localhost:27017/mydb') as store:
    store.save(meta['clawid'], meta)

# Redis
with from_uri('redis://localhost:6379/0') as store:
    store.save(meta['clawid'], meta)

How It Works

Invisible watermark (DWT-QIM)

The payload (UUID + metadata, CBOR-encoded + CRC-checked) is serialised to bits, then each bit is embedded by quantizing a coefficient in the Haar wavelet LL2 sub-band. Each LL2 coefficient represents a 4×4 pixel block, so a change of delta/16 ≈ 2+ pixels per block — above the uint8 quantization step — making the watermark survive JPEG compression and format round-trips.

Mode Delta PSNR Survives
qim (default) 32 ~51 dB PNG/JPEG q≥75, minor edits
fm (resize-robust) 192 ~36 dB ±35% resize, PNG/JPEG q≥75

Video watermarking

Each video is processed frame by frame. Every Nth frame (frame_stride, default 5) receives the same DWT-QIM watermark with the same clawid UUID. Detection samples up to 10 frames and uses majority vote — detection succeeds as long as at least one watermarked frame survives.


Docker

docker compose up
# API available at http://localhost:8000

Development

git clone https://github.com/Hawky-ai/clawID
cd clawid
pip install -e ".[dev,api,video]"
pytest

Links

PyPI https://pypi.org/project/clawid/
GitHub https://github.com/Hawky-ai/clawID
Hugging Face https://huggingface.co/spaces/Hawky-ai/clawID
hawky.ai https://hawky.ai

License

MIT — Copyright © 2024 hawky.ai

Metadata

Release files for clawid 0.2.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for clawid 0.2.4
File Size Uploaded
clawid-0.2.4.tar.gz 41.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for clawid 0.2.4
File Interpreter ABI Platform
clawid-0.2.4-py3-none-any.whl Python 3 none any Details

Total release size: 78.5 kB

Release files / clawid-0.2.4.tar.gz

Download URL clawid-0.2.4.tar.gz
Size 41.1 kB
Tags Source
SHA-256 checksum
How to use checksums
0f3d2e6379426b864a23123a5a0e2bfbde8549e9f39d51d5da2323e9792f733f
BLAKE2b-256 checksum
How to use checksums
f06bc0ecc2624930947237b4e6dcb244f80f7b002a2f2002bbb744715b7f0c8f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.2

Release files / clawid-0.2.4-py3-none-any.whl

Download URL clawid-0.2.4-py3-none-any.whl
Size 37.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
af4d05b579b991973ba189b945a61b53f1a444b49a06be516d2b297c4159fbce
BLAKE2b-256 checksum
How to use checksums
d12d5d056fbc2ac62afc39fa8abdffcfb2cd6bbc03aa13f7579abc7bcadd9bf7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.2

Release history Release notifications | RSS feed

This release

0.2.4 This release

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release 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