@contentauth/c2pa-js
    Preparing search index...

    Module @contentauth/c2pa-web - v0.5.7

    c2pa-web

    The SDK for interacting with C2PA metadata on the web.

    As a guiding philosophy, c2pa-web attempts to adhere closely to the API paradigms established by c2pa-rs.

    npm install @contentauth/c2pa-web
    

    Due to specific requirements around handling WASM modules, there are two methods of importing the library. One optimizes for performance, the other for convenience.

    The recommended method of using the library requires that the WASM binary be hosted separately, to be fetched over the network at runtime.

    With Vite:

    import { createC2pa } from '@contentauth/c2pa-web';

    import wasmSrc from '@contentauth/c2pa-web/resources/c2pa.wasm?url';

    const c2pa = createC2pa({ wasmSrc });

    Use a solution appropriate to your tooling. Alternatively, the binary can be requested from a CDN:

    import { createC2pa } from '@contentauth/c2pa-web';

    // Ensure that [PACKAGE VERSION] matches the currently-installed version of @contentauth/c2pa-web.
    const c2pa = await createC2pa({
    wasmSrc:
    'https://cdn.jsdelivr.net/npm/@contentauth/c2pa-web@[PACKAGE VERSION]/dist/resources/c2pa_bg.wasm',
    });

    In environments where it is not possible or not convenient to request a separate resource over the network, the "inline" SDK can be used. The WASM binary is encoded as a base64 string and included in the JavaScript file, so no (additional) network request is necessary. However, this adds significant size to the JavaScript bundle, and cannot take advantage of the higher-performance WebAssembly.compileStreaming() API.

    import { createC2pa } from '@contentauth/c2pa-web/inline';

    const c2pa = await createC2pa();

    Fetch an image and provide it to the Reader:

    const response = await fetch(
    'https://spec.c2pa.org/public-testfiles/image/jpeg/adobe-20220124-C.jpg'
    );
    const blob = await response.blob();

    const reader = await c2pa.reader.fromBlob(blob.type, blob);

    const manifestStore = await reader.manifestStore();

    console.log(manifestStore);

    // Free SDK objects when they are no longer needed to avoid memory leaks.
    await reader.free();

    The Builder API allows you to create C2PA manifests and add ingredients (source assets) to document the provenance chain.

    The builder intent describes the type of operation being performed on the asset. This influences how the manifest is structured and what assertions are automatically added.

    create: This is a new digital creation, a DigitalSourceType is required. The Manifest must not have have a parent ingredient. A c2pa.created action will be added if not provided.

    edit: This is an edit of a pre-existing parent asset. The Manifest must have a parent ingredient. A parent ingredient will be generated from the source stream if not otherwise provided. A `c2pa.opened action will be tied to the parent ingredient.

    update: A restricted version of Edit for non-editorial changes. There must be only one ingredient, as a parent. No changes can be made to the hashed content of the parent. There are additional restrictions on the types of changes that can be made.

    const builder = await c2pa.builder.new();

    await builder.setIntent({
    create: 'http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia',
    });

    await builder.setIntent('edit');

    await builder.setIntent('update');

    The create intent accepts a DigitalSourceType that describes the origin of the asset. Common values include:

    • 'http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia' - AI-generated content
    • 'http://cv.iptc.org/newscodes/digitalsourcetype/digitalCapture' - Digital camera capture
    • 'http://cv.iptc.org/newscodes/digitalsourcetype/composite' - Composite of multiple sources

    For a complete list of digital source types, see the C2PA specification and IPTC digital source type vocabulary.

    For more details on builder intents, see the c2pa-rs Builder documentation.

    When you have access to the ingredient asset, use addIngredientFromBlob to include both the metadata and the asset data:

    // Fetch or load the ingredient asset
    const ingredientResponse = await fetch('path/to/source-image.jpg');
    const ingredientBlob = await ingredientResponse.blob();

    // Create a builder
    const builder = await c2pa.builder.new();

    // Add the ingredient with its blob
    await builder.addIngredientFromBlob(
    {
    title: 'source-image.jpg',
    format: 'image/jpeg',
    instance_id: 'ingredient-123',
    relationship: 'parentOf',
    },
    'image/jpeg', // Format
    ingredientBlob // The actual asset bytes
    );

    const definition = await builder.getDefinition();
    console.log(definition.ingredients); // Contains the ingredient with embedded data

    await builder.free();

    You can add multiple ingredients to document complex provenance chains:

    const builder = await c2pa.builder.new();

    // Fetch ingredient assets
    const background = await fetch('background.jpg').then((r) => r.blob());
    const overlay = await fetch('overlay.png').then((r) => r.blob());

    // Add first ingredient
    await builder.addIngredientFromBlob(
    {
    title: 'background.jpg',
    format: 'image/jpeg',
    instance_id: 'background-001',
    relationship: 'componentOf',
    },
    'image/jpeg',
    background
    );

    // Add second ingredient
    await builder.addIngredientFromBlob(
    {
    title: 'overlay.png',
    format: 'image/png',
    instance_id: 'overlay-002',
    relationship: 'componentOf',
    },
    'image/png',
    overlay
    );

    const definition = await builder.getDefinition();
    console.log(definition.ingredients.length); // 2

    await builder.free();

    Builder archives allow you to save a builder's state (including ingredients) and reuse it later:

    // Create a builder with ingredients
    const builder = await c2pa.builder.new();

    const ingredientBlob = await fetch('source.jpg').then((r) => r.blob());
    await builder.addIngredientFromBlob(
    {
    title: 'source.jpg',
    format: 'image/jpeg',
    instance_id: 'source-123',
    },
    'image/jpeg',
    ingredientBlob
    );

    // Save as an archive
    const archive = await builder.toArchive();
    await builder.free();

    // Later, recreate the builder from the archive
    const restoredBuilder = await c2pa.builder.fromArchive(new Blob([archive]));

    // The ingredients are preserved
    const definition = await restoredBuilder.getDefinition();
    console.log(definition.ingredients); // Contains the ingredient

    await restoredBuilder.free();

    The Ingredient type supports the following properties:

    • title: Human-readable title for the ingredient
    • format: MIME type of the ingredient asset (e.g., 'image/jpeg')
    • instance_id: Unique identifier for this specific instance
    • document_id (optional): Identifier for the source document
    • relationship (optional): Relationship to the parent asset ('parentOf', 'componentOf', etc.)
    • thumbnail (optional): Thumbnail reference for the ingredient
    • validation_status (optional): Validation results if the ingredient has C2PA data

    For complete type definitions, see the API reference.

    API docs are available here.

    Ensure the repo-wide prerequisites NX and pnpm are installed.

    c2pa-wasm's prerequisites must also be installed.

    To build the library:

    nx build c2pa-web
    

    This library relies on Vitest to run its tests in a headless browser. Before the tests can be run, the test browser binaries must be installed:

    pnpx playwright install
    

    To run the tests:

    nx test c2pa-web
    

    Modules

    index
    inline