Skip to content

Repository files navigation

ai-meta (Node.js)

CI License: MIT Node.js Release

@localtools/ai-meta is a native Node.js addon (N-API via node-addon-api, not NAN or raw V8) for detecting, extracting, stripping, and writing AI-generation metadata declared in image files.

It wraps the ai_meta C library and links prebuilt release binaries of that library (pinned by LIBAI_META_VERSION).

  • Repository: https://github.com/localtools/ai-meta-node
  • License: MIT — free and open source
  • Node.js: 18+ (N-API version 8)
  • Scope: declared metadata only — it does not analyze pixels to guess whether an undeclared image is AI-generated

Sibling projects: ai-meta (C), ai-meta-php.

Why

Generators and platforms increasingly embed provenance and generation parameters (Stable Diffusion parameters, EXIF/XMP, C2PA Content Credentials, IPTC). This package gives Node.js applications a small, dependency-light way to inspect and scrub that metadata while leaving pixel data and color profiles intact when requested.

Features

Capability Notes
Formats PNG, JPEG, WebP
Schemes PNG text (tEXt / iTXt / zTXt), EXIF, XMP, IPTC (JPEG), C2PA detect/strip/hints
Sync API scan / extract / strip / write for small buffers
Async API *Async Promise variants via Napi::AsyncWorker (preferred for large images)
Flags AiMetaFlags.STRIP_ALL_AI, KEEP_COLOR_PROFILE, …
Errors AiMetaError with messages from ai_meta_strerror()

C2PA signatures are not cryptographically verified (same as the C library).

Quick start

Requirements

  • Node.js 18+
  • A C++17 toolchain (python3 + node-gyp build deps)
  • zlib development headers (zlib1g-dev on Debian/Ubuntu; usually present on macOS)
  • A prebuilt ai_meta prefix (include/ + lib/) — fetched automatically on install when missing

Install & test

git clone https://github.com/localtools/ai-meta-node.git
cd ai-meta-node

npm install   # ensure-libai-meta + node-gyp-build
npm test

npm install runs scripts/ensure-libai-meta.js (downloads LIBAI_META_VERSION into deps/ai_meta when needed) then node-gyp-build. The addon statically links lib/libai_meta.a, so only zlib is required at runtime.

Alternative discovery:

npm run fetch-lib

# Or point at an unpacked release / make install prefix:
export AI_META_PREFIX=/path/to/ai_meta-0.1.0-linux-x86_64
npm run rebuild

See examples/basic.js.

Install from npm

Once published:

npm install @localtools/ai-meta

Consumers with a matching prebuild under prebuilds/ skip compilation; otherwise node-gyp builds the addon and still needs zlib + network (or a local AI_META_PREFIX) to obtain libai_meta.

Prebuilt packages

Addon (this repo)

GitHub Releases attach prebuildify binaries (platform/arch folders under prebuilds/):

npm run prebuild   # local: writes under prebuilds/

Tag a release to build assets, attach them to the GitHub Release, and publish @localtools/ai-meta to npm:

git tag v0.1.0
git push origin v0.1.0

Requires repository secret NPM_TOKEN (npm automation/granular token with publish rights for @localtools). The workflow merges platform prebuilds/ into the package before npm publish --access public --provenance.

Human-friendly tarball of the built .node + docs:

./scripts/package-dist.sh

Native library (dependency)

Item Location
Releases https://github.com/localtools/ai-meta/releases
Pin file LIBAI_META_VERSION
Fetch helper scripts/fetch-libai-meta.sh

This package does not vendor or compile libai_meta sources.

JavaScript API

scan(data: Buffer): { format: string; schemes: string[]; likelyAi: boolean }
extract(data: Buffer): Record<string, string>
strip(data: Buffer, flags?: number): Buffer
write(data: Buffer, key: string, value: string): Buffer

scanAsync(data: Buffer): Promise<>
extractAsync(data: Buffer): Promise<>
stripAsync(data: Buffer, flags?: number): Promise<Buffer>
writeAsync(data: Buffer, key: string, value: string): Promise<Buffer>

version(): string
const {
  scan,
  extract,
  strip,
  write,
  scanAsync,
  AiMetaFlags,
  AiMetaError,
} = require('@localtools/ai-meta');
const fs = require('fs');

const bytes = fs.readFileSync('in.png');

const info = scan(bytes);
if (info.likelyAi) {
  const fields = extract(bytes);
  // fields.parameters, fields.prompt, …

  const clean = strip(
    bytes,
    AiMetaFlags.STRIP_ALL_AI | AiMetaFlags.KEEP_COLOR_PROFILE
  );
  fs.writeFileSync('out.png', clean);
}

const stamped = write(bytes, 'parameters', 'Steps: 20, Seed: 1');

// Prefer async for larger images (avoids blocking the event loop):
const asyncInfo = await scanAsync(bytes);

On any non-OK library status, an AiMetaError (extends Error) is thrown.

TypeScript definitions: index.d.ts.

Flags (AiMetaFlags)

Flag Role
NONE No strip flags
STRIP_PNG_TEXT / STRIP_EXIF / STRIP_XMP / STRIP_IPTC / STRIP_C2PA Per-scheme strip
STRIP_ALL_AI All AI-related strip bits
KEEP_COLOR_PROFILE Preserve ICC / color profile when possible
KEEP_NON_AI_TEXT Keep benign PNG text when stripping

Conventions

Topic Rule
Errors Throw AiMetaError; message from ai_meta_strerror()
Memory Library buffers are freed inside the addon before return
Strip / write Always return a new Buffer
Color profiles Preserved when KEEP_COLOR_PROFILE is set (recommended)
Event loop Use *Async for large images

Design

  • Thin N-API wrapper over the buffer-based C API
  • Compiled dependency — links release artifacts of ai_meta, not a source copy
  • Runtime deps — zlib (and Node); static libai_meta.a is preferred at link time
  • Portability — Linux and macOS; CI covers Node.js 18 / 20 / 22
  • Safety — malformed / truncated metadata should fail with an exception, not crash the process

Out of scope

  • Pixel / ML-based “is this AI?” detection
  • Full C2PA claim verification and signing
  • Lossy re-encode of image payloads (metadata containers only)
  • Bundling or re-implementing the C library inside this repo

Testing

npm test

Coverage includes scan, extract, write/strip round-trip, async API, and error paths against small PNG fixtures under test/fixtures/.

CI: .github/workflows/ci.yml.

Project layout

package.json              npm metadata + install hooks
binding.gyp               node-gyp (links prebuilt libai_meta)
src/addon.cpp             N-API implementation
index.js / index.d.ts     JS entry + TypeScript types
examples/basic.js         Minimal consumer
scripts/fetch-libai-meta.sh
scripts/ensure-libai-meta.js
scripts/package-dist.sh
test/*.test.js            node:test suite
LIBAI_META_VERSION        Pinned ai_meta release
LICENSE NOTICE            MIT + third-party notices

Contributing

Contributions are welcome. See CONTRIBUTING.md and our Code of Conduct.

For security issues, see SECURITY.md — please do not open public issues for vulnerabilities.

Changelog

See CHANGELOG.md.

License

This project is licensed under the MIT License — see LICENSE and NOTICE.

Copyright (c) 2026 Local Tools and ai-meta-node contributors

You may use, modify, and distribute this software under the terms of that license.

The native ai_meta library is also MIT-licensed; prebuilt binaries are obtained from its GitHub Releases.

About

Node.js N-API addon for detecting, extracting, stripping, and writing AI-generation metadata in PNG/JPEG/WebP (wraps libai_meta).

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages