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

@qualabs/c2pa-live-dashjs-plugin

v1.1.0

Published

Framework-agnostic dash.js plugin for real-time C2PA segment validation

Downloads

231

Readme

@qualabs/c2pa-live-dashjs-plugin

npm version license

Framework-agnostic dash.js plugin for real-time C2PA segment validation. Validates each DASH segment as it is downloaded using @svta/cml-c2pa, the SVTA Common Media Library C2PA validator.

Installation

npm install @qualabs/c2pa-live-dashjs-plugin

dash.js must be installed separately as a peer dependency:

npm install dashjs

Quick Start

attachC2pa must be called before player.initialize().

import dashjs from 'dashjs';
import { attachC2pa, C2paEvent } from '@qualabs/c2pa-live-dashjs-plugin';

const player = dashjs.MediaPlayer().create();
const c2pa = attachC2pa(player);

c2pa.on(C2paEvent.SEGMENT_VALIDATED, (e) => {
  console.log(`Segment ${e.segmentNumber}: ${e.status}`);
});

player.initialize(videoElement, 'https://example.com/stream.mpd', true);

How It Works

The plugin registers as a dash.js SegmentResponseModifier, intercepting every downloaded segment before it reaches the media buffer. Init segments are processed first to extract session keys (for the VSI method). Each subsequent media segment is then validated through @svta/cml-c2pa's validation functions, which verify cryptographic signatures, check sequence continuity, and detect replay or reorder attacks. Results are emitted as typed events that any UI layer can consume.

Internally the plugin is a thin adapter on top of an internal, player-agnostic validation engine (@qualabs/c2pa-live-player-core, bundled into this package's published output — you never install it separately). The adapter's only job is to translate dash.js chunks into the engine's generic MediaSegmentInput shape. The same engine will back future hls.js and Shaka plugins.

API

attachC2pa(player, options?): C2paController

Attaches C2PA validation to a dash.js player instance.

| Parameter | Type | Description | |-----------|------|-------------| | player | dashjs.MediaPlayer | An initialized (but not yet started) dash.js player | | options | C2paOptions | Optional configuration |

Returns a C2paController instance.

C2paOptions

type C2paOptions = {
  mediaTypes?: ('video' | 'audio')[];  // Default: ['video', 'audio']
  logger?: Logger | false;             // Custom logger or false to disable all logs
};

C2paController

Event methods

c2pa.on(C2paEvent.SEGMENT_VALIDATED, (e) => { ... });
c2pa.once(C2paEvent.INIT_PROCESSED, (e) => { ... });
c2pa.off(C2paEvent.SEGMENT_VALIDATED, handler);

Lifecycle methods

c2pa.reset();    // Clear all state (call when changing streams)
c2pa.detach();   // Full cleanup — removes all listeners and disables validation

Events

segmentValidated

Fired after each media segment is validated.

type SegmentRecord = {
  segmentNumber: number;
  mediaType: MediaType;
  keyId: string | null;
  hash: string | null;
  status: SegmentStatusValue;
  sequenceReason?: SequenceAnomalyReasonValue;
  timestamp: number;
  errorCodes?: readonly ValidationErrorCode[];
  manifest?: C2paManifest | null;
  previousManifestId?: string | null;
};

SegmentStatusValue can be one of: 'valid', 'invalid', 'replayed', 'reordered', 'missing', 'warning', 'unverified'. Import the SegmentStatus runtime constant for type-safe comparisons:

import { SegmentStatus } from '@qualabs/c2pa-live-dashjs-plugin';

if (record.status === SegmentStatus.VALID) { ... }

initProcessed

Fired after the init segment is processed.

type InitProcessedEvent = {
  success: boolean;
  sessionKeysCount: number;
  manifestId: string | undefined;
  errorCodes?: readonly string[];
  error?: string;
};

segmentsMissing

Fired when a gap attack is detected (missing sequence numbers).

type SegmentsMissingEvent = { from: number; to: number; count: number };

error

Fired on unexpected internal errors.

type ErrorEvent = { source: string; error: unknown };

Runtime constants

The following enum-like objects are exported as runtime values and can be used for type-safe comparisons:

import {
  C2paEvent,            // event name keys: SEGMENT_VALIDATED, INIT_PROCESSED, SEGMENTS_MISSING, ERROR
  SegmentStatus,        // status values: VALID, INVALID, REPLAYED, REORDERED, MISSING, WARNING, UNVERIFIED
  SequenceAnomalyReason,// DUPLICATE, OUT_OF_ORDER, GAP_DETECTED, SEQUENCE_NUMBER_BELOW_MINIMUM
  ValidationErrorCode,  // all C2PA and live-video error codes
} from '@qualabs/c2pa-live-dashjs-plugin';

Validation Methods

The plugin automatically selects the appropriate C2PA validation method:

  • VSI (§19.4): Used when session keys are available in the init segment. Validates via COSE_Sign1 signatures in EMSG boxes. Detects replays, reorders, and gaps.
  • ManifestBox (§19.3): Fallback when no session keys are present. Each segment carries its own C2PA manifest.

Multiple Players

Each attachC2pa() call creates isolated state — multiple players on the same page will not interfere with each other.

const c2paPlayer1 = attachC2pa(player1);
const c2paPlayer2 = attachC2pa(player2);
// Each has its own session key store, segment history, etc.

Error Codes

import { ERROR_CODE_MESSAGES, C2paEvent } from '@qualabs/c2pa-live-dashjs-plugin';

c2pa.on(C2paEvent.SEGMENT_VALIDATED, (e) => {
  for (const code of e.errorCodes ?? []) {
    console.error(ERROR_CODE_MESSAGES[code] ?? code);
  }
});

| Code | Meaning | |------|---------| | livevideo.init.invalid | Init segment is invalid (contains mdat box) | | livevideo.manifest.invalid | C2PA manifest failed validation | | livevideo.segment.invalid | Cryptographic verification failed | | livevideo.assertion.invalid | Live video assertion invalid | | livevideo.continuityMethod.invalid | Continuity chain broken | | livevideo.sessionkey.invalid | Session key is invalid or expired |

Limitations

  • dash.js has no API to unregister extensions. After calling detach(), the SegmentResponseModifier becomes a pass-through but remains registered.
  • attachC2pa() must be called before player.initialize().