npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sign-ai-media

v0.1.2

Published

Sign media with C2PA metadata that declares it as AI-generated.

Readme

sign-ai-media is a small open-source Node.js package for adding signed C2PA manifests to generated images and videos. It writes a standards-based AI source signal, lets you control the generator identity shown in the manifest, and exposes both a CLI and a TypeScript API.

It is designed for model hosts, generation apps, internal media pipelines, dataset tooling, and any workflow that wants to label generated media without pretending to be another provider.

What It Writes

The default manifest includes:

  • A c2pa.actions.v2 assertion with action: "c2pa.created".
  • A configurable softwareAgent object with name and optional version.
  • The IPTC digital source type trainedAlgorithmicMedia.
  • A stds.schema-org.CreativeWork assertion for optional generator, model, producer, prompt, and custom metadata.
  • A C2PA signature. You can provide your own certificate/private key, or use the bundled development signer for lower-friction local use.

The default AI source marker is:

http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia

Installation

npm install sign-ai-media

You can also run the CLI without installing it first:

npx sign-ai-media input.png output.png --software-agent "my-generator"

This package uses @contentauth/c2pa-node, which ships native bindings. Prebuilt binaries are available for common macOS, Linux, and Windows platforms. Other platforms may need a local Rust toolchain.

CLI Usage

npx sign-ai-media input.png output.png \
  --software-agent "acme-image-model" \
  --version "1.0.0" \
  --generator "Acme Image API" \
  --model "acme-diffusion-v1" \
  --producer "Acme Labs"

For production provenance, pass your own signing credentials:

npx sign-ai-media input.png output.png \
  --software-agent "acme-image-model" \
  --certificate ./certs/signing-cert.pem \
  --private-key ./certs/signing-key.pem \
  --algorithm es256 \
  --tsa-url "https://timestamp.example.com"

Viewing Metadata

To inspect AI/C2PA metadata in a signed file, use --view with the input file:

npx sign-ai-media --view output.png

The viewer does not modify the file. It reads the active C2PA manifest, extracts the AI-generation fields written by this package, and prints a readable summary:

AI media metadata: output.png
Status: C2PA manifest found
Title: output.png
Format: image/png
Claim generator: acme-image-service/1.0.0
Generator: Acme Image API
Model: acme-diffusion-v1
Producer: Acme Labs
Software agent: {"name":"acme-image-model","version":"1.0.0"}
Action: c2pa.created
Created at: 2026-05-02T09:00:00.000Z
Digital source type: http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia
Validation: No validation issues reported.
Assertions:
  - c2pa.actions.v2
  - stds.schema-org.CreativeWork

If no C2PA manifest is present, the viewer prints:

AI media metadata: input.png
Status: No C2PA manifest found.

Useful metadata options:

--source-type ai-generated
--claim-generator "acme-image-service/1.0.0"
--prompt "A red fox in a snowy forest"
--prompt-file ./prompt.txt
--negative-prompt "low quality, blurry"
--seed 12345
--scheduler "euler-a"
--cfg-scale 7.5
--steps 30
--created-at "2026-05-02T09:00:00Z"
--digital-source-type "http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia"
--creative-work-json '{"usageInfo":"internal","copyrightNotice":"Acme Labs"}'
--mime-type image/png
--remote-manifest-url "https://cdn.example.com/manifests/image.c2pa"
--no-embed

Action/provenance options:

--action c2pa.created
--action-description "Generated from a text prompt"
--action-parameters-json '{"pipeline":"txt2img"}'
--ingredient ./source-image.png
--ingredient ./mask.png
--parent ./original.png
--model-uri "https://example.com/models/acme-diffusion-v1"
--model-hash "sha256:..."
--input-uri "https://example.com/inputs/reference.png"
--input-hash "sha256:..."

Training and data-mining policy options:

--ai-training-use notAllowed
--ai-generative-training-use notAllowed
--data-mining-use constrained
--ai-inference-use allowed
--training-constraint-info "See https://example.com/ai-use-policy"

Viewer options:

npx sign-ai-media --view output.png --json
npx sign-ai-media --view output.png --verify-trust --trust-anchors ./anchors.pem
npx sign-ai-media --view output.png --fetch-remote-manifest
npx sign-ai-media --view output.png --no-fetch-remote-manifest

Why not c2patool?

c2patool is the official general-purpose command line tool for C2PA. It can read C2PA manifest reports, inspect low-level manifest data, and add manifests to supported media files.

Use c2patool when you want a broad, standards-level C2PA utility.

Use sign-ai-media when you want a smaller tool focused on AI-generated media workflows:

  • It has simple flags for common AI metadata such as --software-agent, --model, --prompt, --source-type, --seed, and training/data-mining policy.
  • It writes an AI-oriented manifest shape by default, including c2pa.actions.v2, trainedAlgorithmicMedia, CreativeWork metadata, and optional CAWG training/data-mining assertions.
  • It includes a TypeScript API for Node.js apps, queues, media pipelines, and CMS integrations.
  • It includes a focused --view mode that extracts the AI/C2PA fields this package writes, instead of only showing a full generic manifest report.

In short: c2patool is the toolbox. sign-ai-media is the shortcut for signing and reading AI media provenance in apps and automation.

TypeScript API

import { signAiGeneratedMedia, viewAiGeneratedMedia } from "sign-ai-media";

await signAiGeneratedMedia({
  input: "input.png",
  output: "output.png",
  metadata: {
    softwareAgent: "acme-image-model",
    version: "1.0.0",
    claimGenerator: "acme-image-service/1.0.0",
    generator: "Acme Image API",
    model: "acme-diffusion-v1",
    modelVersion: "2026-05-02",
    producer: "Acme Labs",
    prompt: "A red fox in a snowy forest",
    negativePrompt: "low quality, blurry",
    seed: 12345,
    scheduler: "euler-a",
    cfgScale: 7.5,
    steps: 30,
    actionDescription: "Generated from a text prompt",
    trainingMining: {
      "cawg.ai_training": { use: "notAllowed" },
      "cawg.ai_generative_training": { use: "notAllowed" },
    },
  },
});

const metadata = await viewAiGeneratedMedia({
  input: "output.png",
});

viewAiGeneratedMedia() returns a JSON-serializable object, so it can be logged, sent from an API route, or stored directly:

console.log(JSON.stringify(metadata, null, 2));

Example result:

{
  "input": "output.png",
  "hasManifest": true,
  "metadata": {
    "title": "output.png",
    "format": "image/png",
    "claimGenerator": "acme-image-service/1.0.0",
    "generator": "Acme Image API",
    "model": "acme-diffusion-v1",
    "producer": "Acme Labs",
    "prompt": "A red fox in a snowy forest",
    "softwareAgent": {
      "name": "acme-image-model",
      "version": "1.0.0"
    },
    "digitalSourceType": "http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia",
    "createdAt": "2026-05-02T09:00:00.000Z",
    "action": "c2pa.created",
    "signatureIssuer": "Example Signing Cert",
    "signatureTime": "2026-05-02T09:00:00+00:00"
  },
  "validationStatus": [],
  "assertionLabels": ["c2pa.actions.v2", "stds.schema-org.CreativeWork"]
}

When no manifest is found, the result is:

{
  "input": "input.png",
  "hasManifest": false,
  "metadata": null,
  "validationStatus": [],
  "assertionLabels": []
}

Pass a signer when you want the manifest signed with your own production identity:

import {
  SigningAlgorithm,
  createLocalSigner,
  signAiGeneratedMedia,
} from "sign-ai-media";

const signer = await createLocalSigner({
  certificatePath: "./certs/signing-cert.pem",
  privateKeyPath: "./certs/signing-key.pem",
  algorithm: SigningAlgorithm.ES256,
  tsaUrl: "https://timestamp.example.com",
});

await signAiGeneratedMedia({
  input: "input.png",
  output: "output.png",
  signer,
  metadata: {
    softwareAgent: "acme-image-model",
    version: "1.0.0",
    claimGenerator: "acme-image-service/1.0.0",
    generator: "Acme Image API",
    model: "acme-diffusion-v1",
    producer: "Acme Labs",
    prompt: "A red fox in a snowy forest",
  },
});

Metadata Fields

metadata.softwareAgent is required. It should name the model, service, app, or pipeline that created the media.

Optional metadata:

  • version: version of the software agent or model.
  • claimGenerator: C2PA user-agent style claim generator. Defaults to softwareAgent/version.
  • generator: friendly generator name for CreativeWork metadata.
  • model: model name for consumers that display richer generator details.
  • modelVersion: model revision or version.
  • modelUri and modelHash: model or model-card reference.
  • inputUri and inputHash: remote input reference.
  • producer: organization, service, or creator responsible for the output.
  • prompt: prompt text to embed. Treat this as public metadata.
  • negativePrompt: negative prompt text to embed. Treat this as public metadata.
  • seed, scheduler, cfgScale, and steps: generation parameters.
  • createdAt: ISO timestamp. Defaults to the current time.
  • digitalSourceType: override the IPTC source type URL.
  • action: C2PA action name. Defaults to c2pa.created.
  • actionDescription: free-text action description.
  • actionParameters: extra action parameters for advanced C2PA workflows.
  • trainingMining: CAWG Training and Data Mining assertion entries.
  • creativeWork: extra properties merged into the schema.org CreativeWork assertion.

Digital Source Presets

Use --source-type for common source types without remembering the full vocabulary URL:

  • ai-generated: created by a trained generative AI model.
  • ai-edited: human or tool edits using generative AI, such as inpainting or outpainting.
  • algorithmic: algorithmic media not based on sampled training data.
  • algorithmically-enhanced: algorithmic enhancement such as denoise or sharpen.
  • composite-ai: composite media with at least one generative AI element.
  • composite: composite of several elements.
  • composite-capture: composite where all elements are captures of real life.
  • capture: digital camera or sensor capture.
  • screen-capture: screen capture.
  • human-edited: non-generative human edits.
  • digital-art, digital-creation, software-image, and data-driven: other common IPTC source categories.
  • empty: C2PA empty asset source type.
  • ai-data: C2PA trained algorithmic data source type for non-media data.

You can still pass a full URL with --digital-source-type.

Ingredients and Parents

Use --ingredient to attach source media that contributed to the signed output. Repeating the flag adds multiple componentOf ingredients:

npx sign-ai-media output.png signed.png \
  --software-agent "acme-image-model" \
  --ingredient ./reference.png \
  --ingredient ./mask.png

Use --parent when the output is derived from an original asset:

npx sign-ai-media edited.png signed.png \
  --software-agent "acme-editor" \
  --parent ./original.png \
  --action c2pa.edited \
  --action-description "Inpainted background"

Training and Data Mining

The --ai-training-use, --ai-generative-training-use, --data-mining-use, and --ai-inference-use flags write a cawg.training-mining assertion using the CAWG Training and Data Mining Assertion.

Each flag accepts allowed, notAllowed, or constrained. When using constrained, add --training-constraint-info to explain the policy or link to a license.

Supported Media

MIME type is inferred from common media extensions:

  • .png
  • .jpg and .jpeg
  • .webp
  • .avif
  • .tif and .tiff
  • .mp4
  • .mov
  • .avi

Pass --mime-type or mimeType when the extension is missing or unusual.

Signing Credentials

C2PA manifests need a signer, but this package does not require users to bring a certificate/private-key pair just to get started. If no signer is provided, signAiGeneratedMedia() and the CLI use bundled test credentials.

For production provenance, pass a local certificate/private-key pair through createLocalSigner() or another compatible @contentauth/c2pa-node signer object. Do not use another company's name, certificate, or identity fields.

Where to get production certificates

Production C2PA signing credentials should come from a certificate authority on the C2PA trust list. The official Content Authenticity Initiative docs explain that conforming generator products must use a certificate that chains back to a trusted C2PA certificate authority, and that C2PA maintains separate trust lists for claim-signing certificates and timestamp authorities.

Start here:

Certificate authorities listed by the CAI docs include:

Provider availability, onboarding requirements, and assurance levels can change, so use the official C2PA trust-list sources above as the source of truth before issuing production credentials.

Development certificates

The bundled signer is only for local development and demos. It can prove that the package writes and signs a manifest, but it does not give your output a production identity that verifiers should trust.

Use development/test credentials for:

  • Local CLI experiments.
  • Integration tests.
  • Demo assets where trust is not implied.

Use production credentials for:

  • Public releases.
  • User-facing generated media.
  • Workflows where platforms or verifiers should recognize your organization as the signer.

Verifying Output

After signing, inspect the output with a C2PA-compatible verifier such as the Content Authenticity Initiative Verify tooling or another C2PA reader. For PNG files, the embedded manifest appears in a caBX chunk and should include c2pa.actions.v2 plus the trainedAlgorithmicMedia source type.

Development

npm install
npm run build
npm run typecheck
node dist/cli.js --help

The package is intentionally small. Most of the heavy lifting is delegated to @contentauth/c2pa-node; this project focuses on shaping a clear AI-generation manifest and giving applications a stable CLI/API around it.

License

GPL-3.0-or-later