The @svta/cml-cmcd library provides composable validation functions. They verify that CMCD payloads conform to the CTA-5004 (v1) and CTA-5004-B (v2) specifications. Use them on the receiving side. Examples are an analytics server that collects CMCD event reports, and a CDN log processor that inspects CMCD request data.
There are four main validation functions, each for a different aspect of CMCD compliance:
| Function | Purpose |
|---|---|
validateCmcd |
Orchestrator: runs key, value, and structure checks |
validateCmcdRequest |
Validates a Request or HttpRequest as request-mode data |
validateCmcdEvents |
Validates a multi-line application/cmcd body as event-mode data |
validateCmcdEventReport |
Validates a full HttpRequest as an event-mode payload |
All validators return a CmcdValidationResult:
type CmcdValidationResult = {
valid: boolean; // true if zero errors (warnings are OK)
issues: CmcdValidationIssue[];
};
type CmcdValidationIssue = {
key?: string;
message: string;
severity: CmcdValidationSeverity; // 'error' | 'warning'
};
A common use case is validating CMCD v2 event reports received by POST. The payload is usually an application/cmcd body with newline-separated CMCD-encoded strings, or application/json.
validateCmcdEventsThe validateCmcdEvents function accepts a raw CMCD string and validates it as an event-mode payload. It supports multi-line application/cmcd bodies directly. It validates each non-empty line on its own and merges the results. An empty payload, with no non-empty lines, is an error.
import { validateCmcdEvents } from "@svta/cml-cmcd";
// Validate a complete application/cmcd POST body
const body = `e=ps,sid="session-1",ts=1700000000000,sta=p,v=2
e=t,sid="session-1",ts=1700000001000,bl=(5000),v=2`;
const result = validateCmcdEvents(body);
if (!result.valid) {
console.error("Invalid CMCD event:", result.issues);
}
A single-line string works as well:
import { validateCmcdEvents } from "@svta/cml-cmcd";
const result = validateCmcdEvents(
'e=ps,sid="session-1",ts=1700000000000,sta=p,v=2',
);
application/cmcd manuallyThe validateCmcdEvents function validates multi-line application/cmcd bodies directly. If you need to validate a single-line string, you can decode the CMCD string and validate the data yourself. validateCmcdRequest does the same internally.
import { decodeCmcd, validateCmcd } from "@svta/cml-cmcd";
// Simulated POST body (application/cmcd)
const body = `e=ps,sid="session-1",ts=1700000000000,sta=p,v=2
e=t,sid="session-1",ts=1700000001000,bl=(5000),v=2`;
// Parse each line and validate
const lines = body.split("\n");
for (const line of lines) {
const data = decodeCmcd(line);
const result = validateCmcd(data, { reportingMode: "event" });
if (!result.valid) {
console.error("Invalid CMCD event:", result.issues);
}
}
In request mode, CMCD data is attached to segment requests as query parameters or HTTP headers. The validator checks that event-only and response-only keys are absent.
validateCmcdRequestThe validateCmcdRequest function accepts a Request object or an HttpRequest object from @svta/cml-utils. It checks for CMCD headers first. If it finds any CMCD header shards, it delegates to validateCmcdHeaders, which verifies the shard placement. Otherwise, it extracts the CMCD query parameter from the URL.
import { validateCmcdRequest } from "@svta/cml-cmcd";
// From a Request with CMCD headers
const request = new Request("https://cdn.example.com/seg.mp4", {
headers: {
"CMCD-Object": "br=5000,d=4000,ot=v",
"CMCD-Request": "bl=25000",
"CMCD-Session": 'sid="abc"',
},
});
const headerResult = validateCmcdRequest(request);
// From a Request with CMCD in the query parameter
const queryRequest = new Request(
"https://cdn.example.com/seg.mp4?CMCD=br%3D5000%2Cbl%3D25000",
);
const queryResult = validateCmcdRequest(queryRequest);
// From an HttpRequest object
const httpRequestResult = validateCmcdRequest({
url: "https://cdn.example.com/seg.mp4?CMCD=br%3D5000%2Cbl%3D25000",
});
The validateCmcdRequest function validates the CMCD query parameter from the URL. If you need to validate the parameter yourself, extract it from the URL and validate the data with the validateCmcd function.
import { fromCmcdQuery, validateCmcd } from "@svta/cml-cmcd";
// Extract CMCD from a request URL's query string
const url = new URL(
"https://cdn.example.com/seg.mp4?CMCD=br%3D5000%2Cbl%3D25000%2Cd%3D4000%2Cot%3Dv%2Csid%3D%22abc%22",
);
const data = fromCmcdQuery(url.searchParams);
const result = validateCmcd(data, { reportingMode: "request" });
if (!result.valid) {
console.error("Invalid CMCD request data:", result.issues);
}
When CMCD is transmitted in HTTP headers, you can validate the headers yourself with the validateCmcdHeaders function.
import { validateCmcdHeaders } from "@svta/cml-cmcd";
// Pass raw header strings directly — decoding is handled internally.
// Request mode validation is applied automatically since headers are
// only used in request mode.
const result = validateCmcdHeaders({
"CMCD-Object": "br=5000,d=4000,ot=v",
"CMCD-Request": "bl=25000",
"CMCD-Session": 'sid="abc",sf=d,st=v',
});
if (!result.valid) {
// Issues may include shard placement errors and/or payload validation errors
console.error("Validation issues:", result.issues);
}
The validators detect the CMCD version from the v key in the payload. If v is absent, they assume version 1, per the specification. The version option overrides the detection.
import { validateCmcd } from "@svta/cml-cmcd";
// Version inferred from payload (v=2)
const v2Result = validateCmcd({ v: 2, br: [5000], sid: "abc" });
// Version explicitly set via options
const v1Result = validateCmcd({ br: 5000, sid: "abc" }, { version: 1 });
sta, ec, and ab, are rejected when validating as v1bl is an integer in v1 but an inner list (array) in v2v key. v1 payloads should omit itA payload is valid if it has zero errors. Warnings mark specification recommendations that are not strict violations.
import { validateCmcd, CMCD_VALIDATION_SEVERITY_ERROR } from "@svta/cml-cmcd";
const result = validateCmcd({ v: 2, bl: [150], sid: "abc" });
// Separate errors from warnings
const errors = result.issues.filter(
(i) => i.severity === CMCD_VALIDATION_SEVERITY_ERROR,
);
const warnings = result.issues.filter(
(i) => i.severity !== CMCD_VALIDATION_SEVERITY_ERROR,
);
console.log(`Valid: ${result.valid}`);
console.log(`Errors: ${errors.length}, Warnings: ${warnings.length}`);
// bl=150 produces a warning (should be rounded to nearest 100)
// but the payload is still valid
import { validateCmcdEvents } from "@svta/cml-cmcd";
function validateAndLog(body: string): boolean {
const result = validateCmcdEvents(body);
for (const issue of result.issues) {
const level = issue.severity === "error" ? "ERROR" : "WARN";
const key = issue.key ? `[${issue.key}] ` : "";
console.log(`${level}: ${key}${issue.message}`);
}
return result.valid;
}
All validators recognize custom keys: lowercase hyphenated keys that isCmcdCustomKey accepts, such as com.example-mykey. Keys that fail the check, including names with uppercase letters or a leading digit, are reported as unknown keys. For sending custom keys through CmcdReporter, including the naming rules and the enabledKeys requirements, see the User Guide.
validateCmcdKeys: accepts custom keys without errorvalidateCmcdValues: checks that custom key values are strings of at most 64 characters, and that the key name contains a hyphenvalidateCmcdHeaders: allows custom keys in any header shardimport { validateCmcdValues } from "@svta/cml-cmcd";
const result = validateCmcdValues({
"com.example-debug": "enabled",
"x-player-version": "2.1.0",
});
// result.valid === true