Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

90 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tamper

CI License: Apache 2.0 Python 3.14+

Run degradation operations on media files (compression, blur, noise, transcoding etc), and record every input, operation, and output as a queryable RDF provenance graph.

Overview

Tamper is a framework for describing multimedia assets and the media operations that transform them. It works by recording media assets as provenance entities and operations as activities. Together, they form provenance chains that are semantically queryable. These chains form the basis of Tamper datasets.

flowchart BT
    a0[("original.png")]
    a1[("compressed.jpg")] -- wasGeneratedBy --> op1["Compress"] -- used --> a0
    a2[("noisy.jpg")] -- wasGeneratedBy --> op2["AddGaussianNoise"] -- used --> a1
    a3[("thumbnail.png")] -- wasGeneratedBy --> op3["Resize"] -- used --> a0
    a4[("blurred.png")] -- wasGeneratedBy --> op4["GaussianBlur"] -- used --> a3
    b0[("original.mp4")]
    b1[("transcoded.webm")] -- wasGeneratedBy --> op5["Transcode"] -- used --> b0
    classDef asset fill:#e8f0fe,stroke:#4285f4,color:#1a1a1a;
    classDef op fill:#fef7e0,stroke:#f9ab00,color:#1a1a1a;
    class a0,a1,a2,a3,a4,b0,b1 asset;
    class op1,op2,op3,op4,op5 op;
Loading

Installation

Requirements

  • Python 3.14+
  • uv for dependency management
  • System packages ffmpeg (video/audio probing and transcoding) and libmagic (MIME-type detection)

Install dependencies

# Initialize the environment
uv venv
source .venv/bin/activate

# Install dependencies
uv sync
uv pip install -e .

Usage

MCP server

The Tamper MCP server is the recommended way to use Tamper. It exposes tools and vocabularies so an AI agent (or any MCP client) can track assets, author operation plans, run them, and query the resulting graph.

# Run the MCP server (uses fastmcp.json)
fastmcp run

fastmcp.json configures the server to listen over HTTP on 0.0.0.0:8000 and sets TAMPER_HOME to ~/.tamper by default. This directory is where Tamper will store operation plans, media assets, and the RDF dataset.

Using the core library

There is a set of core classes available for interfacing with the graph. Each class instance is mapped to a resource in the graph:

from tamper.core import ImageAsset, load_asset_from_file
from tamper.ops import Compress
from rdflib import Graph, BNode

# All of our data lives in a graph
ctx = Graph()

# Load an image asset
img_asset = ImageAsset.from_file(ctx, "some-image.png")

# Load an audio asset
audio_asset = AudioAsset.from_file(ctx, "some-audio.wav")

# Load a video asset
video_asset = VideoAsset.from_file(ctx, "some-video.mp4")

# Run an operation on the image
op = Compress.new(ctx, BNode())
op.format = "jpeg"
op.quality_factor = 90          # compress with quality 90
op.used(img)                    # uses the image asset

# Generate the compressed image and save it in /media 
op.mutate(out_dir="/media")

The data model

Every file is described as an asset with a content-addressed identifier (trn:asset:<sha256>, derived from the file's contents, so identical bytes always get the same id, media type, and technical metadata. Here is a PNG image and the operation that produced it:

@prefix tamper: <https://example.org/tamper/core#> .
@prefix prov: <http://www.w3.org/ns/prov#> .

<trn:asset:aad96d410d92b5589d41e8462507e3af57682022db3d3711a236c0245fcf296e> a tamper:ImageAsset ;
    tamper:checksum "sha256:aad96d410d92b5589d41e8462507e3af57682022db3d3711a236c0245fcf296e" ;
    tamper:height 566 ;
    tamper:mediaType "image/png" ;
    tamper:pixelFormat "PNG" ;
    tamper:width 850 ;
    prov:wasGeneratedBy <trn:operation:tknRPmvjBrB4sms5> .

<trn:operation:tknRPmvjBrB4sms5> a tamper:Compress ;
    prov:endedAtTime "2026-05-23T16:51:08.113923"^^xsd:dateTime ;
    prov:startedAtTime "2026-05-23T16:51:08.097677"^^xsd:dateTime ;
    prov:used trn:asset:45f0867c530cdb68df8d0a38e49f8d7084b0d2bf1a056570751dcdfca24777d6 ;
    tamper:format "jpeg" ;
    tamper:qualityFactor "80"^^xsd:nonNegativeInteger .

See the data model reference for image, audio, and video examples.

Available operations

See the operations reference for the full list of supported operations with their parameters and value ranges.

Operation plans

To mutate the graph, you submit an operation plan: a description of the new assets you want to derive from existing ones. A plan has two parts:

  • Variables — placeholders for the assets that flow through the plan (the input you start with, plus each intermediate and final result).
  • Steps — the media operations that consume one variable and produce another.

Together, the steps and variables form a directed acyclic graph (DAG). Tamper executes it in dependency order: as soon as a step's input variable is ready, it runs concurrently with every other ready step (via Ray).

flowchart RL
    a0[("Variable<br>(The original image)")]
    a1[("Variable<br>(The compressed image)")]
    a2[("Variable<br>(The noisy, compressed image)")]
    op1["Step<br>Compres"] -- hasInputVariable --> a0
    op1 -- hasOutputVariable --> a1
    op2["Step<br>AddGaussianNoise"] -- hasInputVariable --> a1
    op2 -- hasOutputVariable --> a2
    classDef asset fill:#e8f0fe,stroke:#4285f4,color:#1a1a1a;
    classDef op fill:#fef7e0,stroke:#f9ab00,color:#1a1a1a;
    class a0,a1,a2 asset;
    class op1,op2 op;
Loading

Plans are written in RDF using the plan: vocabulary. Each step points at a plan:parameters bundle that names the tamper: operation to run and its parameters. The plan below has three variables (v0v1v2) and two steps: step s1 compresses the input image, then step s2 adds Gaussian noise to the result.

@prefix plan:   <https://example.org/tamper/plan#> .
@prefix tamper: <https://example.org/tamper/core#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .

<trn:plan:example> a plan:OperationPlan .

# Variables (each bound to a media asset at execution time)
<trn:plan:example:v0> a plan:Variable ;
    plan:isVariableOfPlan <trn:plan:example> ;
    rdfs:label "The original image" .

<trn:plan:example:v1> a plan:Variable ;
    plan:isVariableOfPlan <trn:plan:example> ;
    rdfs:label "The compressed image" .

<trn:plan:example:v2> a plan:Variable ;
    plan:isVariableOfPlan <trn:plan:example> ;
    rdfs:label "The noisy, compressed image" .

# Steps (media operations)
<trn:plan:example:s1> a plan:Step ;
    plan:isStepOfPlan <trn:plan:example> ;
    plan:hasInputVariable <trn:plan:example:v0> ;
    plan:hasOutputVariable <trn:plan:example:v1> ;
    plan:operationType tamper:Compress ;
    plan:parameters [        
        tamper:format "jpeg" ;
        tamper:qualityFactor 90
    ] .

<trn:plan:example:s2> a plan:Step ;
    plan:isStepOfPlan <trn:plan:example> ;
    plan:hasInputVariable <trn:plan:example:v1> ;
    plan:hasOutputVariable <trn:plan:example:v2> ;
    plan:operationType tamper:AddGaussianNoise ;
    plan:parameters [        
        tamper:gaussianMean 0.0 ;
        tamper:gaussianStd 12.0
    ] .

With the MCP server running, hand the plan to your agent and bind its input variable (trn:plan:example:v0) to a tracked asset. Every generated asset is linked to the operation that produced it via PROV (prov:wasGeneratedBy, prov:used), so the resulting graph records the full derivation history.

MCP tools

The server exposes the following tools to an MCP client:

Tool Purpose
InspectCatalog Return the catalog graph listing all available datasets.
ExportCatalog Export the entire catalog and all referenced media files to a tarball.
CreateDataset Create a new named dataset with a title and description.
DescribeDataset Retrieve top-level metadata about a dataset.
GetDatasetGraph Return the full RDF graph of a dataset's contents.
LoadMediaAsset Load an asset file into a dataset.
CreatePlan Saves an operation plan for later use.
ListPlans List saved plans.
GetPlan Retrieve a saved plan's graph.
DeletePlan Delete a saved plan by name.
SubmitPlan Submit a plan for async execution against a dataset.
QuerySPARQL Run a read-only SPARQL SELECT/ASK/CONSTRUCT/DESCRIBE against the graph.

MCP resources

Vocabularies are served as MCP resources so an agent can fetch them before writing plans or queries:

Resource URI Contents
vocabulary://tamper/core The Tamper core ontology (asset and operation terms).
vocabulary://tamper/plan The Tamper plan vocabulary (steps and variables).
vocabulary://prov-o The PROV-O ontology (provenance relationships).

About

A tool for tampering with media files

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages