113 lines
6.0 KiB
Markdown
113 lines
6.0 KiB
Markdown
# @suaveplan/media - Universal media detection, metadata extraction, and constraint validation. Magic-byte signature registry (pluggable), MIME-keyed type detection via @suaveplan/mime, Zod-validated constraints, typed MediaError hierarchy with stable MEDIA.* codes, OTel counters + histogram, injectable observability bundle, and an async validation pipeline supporting custom predicates.
|
|
|
|
Universal media detection, metadata extraction, and constraint
|
|
validation. Combines a pluggable magic-byte `SignatureRegistry` with the
|
|
MIME database from `@suaveplan/mime` to identify image, video, and audio
|
|
artefacts from raw bytes, filenames, or both. Ships typed errors via
|
|
`@suaveplan/error`, OpenTelemetry instrumentation, Zod-validated
|
|
constraints, and an async validation pipeline that supports custom
|
|
predicates and format-specific metadata extractors.
|
|
|
|
<!-- begin:auto-docs -->
|
|
## Documentation tree
|
|
|
|
- [detection](./src/detection/detection.md) — Byte-level and filename-level media type detection. The module pairs the pluggable `SignatureRegistry` from `signatures…
|
|
- [detection](./src/detection/detection.md) — Byte-level and filename-level media type detection. The module pairs the pluggable `SignatureRegistry` from `signatures…
|
|
- [errors](./src/errors/errors.md) — Owns the stable error-code registry, per-code metadata table, and the `MediaError` class that every public entrypoint t…
|
|
- [errors](./src/errors/errors.md) — Owns the stable error-code registry, per-code metadata table, and the `MediaError` class that every public entrypoint t…
|
|
- [metadata](./src/metadata/metadata.md) — Builds a `MediaMetadata` bundle (type, MIME, size, matched signature label) from raw bytes. The sync helper produces th…
|
|
- [metadata](./src/metadata/metadata.md) — Builds a `MediaMetadata` bundle (type, MIME, size, matched signature label) from raw bytes. The sync helper produces th…
|
|
- [observability](./src/observability/observability.md) — Constructs the OpenTelemetry instrument bundle threaded through every public entrypoint in `@suaveplan/media`. Each det…
|
|
- [observability](./src/observability/observability.md) — Constructs the OpenTelemetry instrument bundle threaded through every public entrypoint in `@suaveplan/media`. Each det…
|
|
- [signatures](./src/signatures/signatures.md) — Owns the magic-byte signature registry that powers byte-level detection. The module ships a frozen `BUILTIN_SIGNATURES`…
|
|
- [signatures](./src/signatures/signatures.md) — Owns the magic-byte signature registry that powers byte-level detection. The module ships a frozen `BUILTIN_SIGNATURES`…
|
|
- [validation](./src/validation/validation.md) — Validates media bytes against a `MediaConstraints` rule set covering size floors and ceilings, type allowlists, MIME al…
|
|
- [validation](./src/validation/validation.md) — Validates media bytes against a `MediaConstraints` rule set covering size floors and ceilings, type allowlists, MIME al…
|
|
<!-- end:auto-docs -->
|
|
|
|
## Install
|
|
|
|
```bash
|
|
bun add @suaveplan/media
|
|
```
|
|
|
|
## Quick start
|
|
|
|
```ts
|
|
import {
|
|
detectMediaType,
|
|
getMetadata,
|
|
validateMedia,
|
|
} from "@suaveplan/media";
|
|
|
|
const png = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a]);
|
|
|
|
detectMediaType(png); // "image"
|
|
|
|
const meta = getMetadata(png, { filename: "logo.png" });
|
|
// { type: "image", mimeType: "image/png", size: 6, signatureLabel: "PNG" }
|
|
|
|
const result = validateMedia(png, {
|
|
maxSize: 1_000_000,
|
|
allowedTypes: ["image"],
|
|
});
|
|
if (!result.valid) console.warn(result.errors);
|
|
```
|
|
|
|
## Modules
|
|
|
|
- [`detection/detection.md`](./src/detection/detection.md) — byte +
|
|
filename detection helpers.
|
|
- [`metadata/metadata.md`](./src/metadata/metadata.md) — sync + async
|
|
metadata extraction.
|
|
- [`validation/validation.md`](./src/validation/validation.md) —
|
|
constraint checking, async predicate support, assert helper.
|
|
- [`signatures/signatures.md`](./src/signatures/signatures.md) —
|
|
pluggable magic-byte registry.
|
|
- [`errors/errors.md`](./src/errors/errors.md) — `MEDIA_CODES`,
|
|
`MediaError`, metadata table.
|
|
- [`observability/observability.md`](./src/observability/observability.md)
|
|
— OpenTelemetry bundle factory.
|
|
- [`types/media.types.md`](./src/types/media.types.md) — public type
|
|
contracts + Zod schemas.
|
|
|
|
## Features
|
|
|
|
- Magic-byte detection covering PNG, JPEG, GIF, BMP, WEBP/RIFF, MP4/MOV,
|
|
WebM/MKV, MP3 (ID3 + sync), FLAC, OGG.
|
|
- Pluggable `SignatureRegistry` with `register` / `unregister` / `list`
|
|
/ `match` / `detect`; duplicate labels rejected with
|
|
`MEDIA.DUPLICATE_SIGNATURE`.
|
|
- MIME-keyed filename detection via `@suaveplan/mime`.
|
|
- Zod-validated `MediaConstraints` (`minSize`, `maxSize`, `allowedTypes`,
|
|
`allowedMimeTypes`, `minWidth`/`maxWidth`, `minHeight`/`maxHeight`,
|
|
`maxDuration`, custom predicate).
|
|
- Async metadata extractor hook for layering width / height / duration
|
|
/ codec onto the base bundle.
|
|
- `assertValidMedia` throwing variant for guard sites.
|
|
- Eight stable `MEDIA.*` error codes with per-code HTTP / severity /
|
|
retryable metadata.
|
|
- Four counters + two histograms emitted from every public entrypoint.
|
|
|
|
## Error codes
|
|
|
|
| Code | HTTP | Retryable | Severity |
|
|
| --------------------------------- | ---- | --------- | -------- |
|
|
| `MEDIA.EMPTY_INPUT` | 400 | no | warning |
|
|
| `MEDIA.INVALID_CONSTRAINTS` | 400 | no | error |
|
|
| `MEDIA.VALIDATION_FAILED` | 422 | no | warning |
|
|
| `MEDIA.UNSUPPORTED_TYPE` | 415 | no | warning |
|
|
| `MEDIA.PREDICATE_FAILED` | 500 | no | error |
|
|
| `MEDIA.DUPLICATE_SIGNATURE` | 409 | no | error |
|
|
| `MEDIA.METADATA_EXTRACTOR_FAILED` | 500 | no | error |
|
|
| `MEDIA.INVALID_SIGNATURE` | 400 | no | error |
|
|
|
|
## Observability
|
|
|
|
Four counters: `media_detect_total`, `media_metadata_total`,
|
|
`media_validate_total`, `media_error_total`. Two histograms:
|
|
`media_op_latency_ms`, `media_input_size_bytes`. Wire your meter via
|
|
`createMediaObservability({ meter })` and thread the bundle into every
|
|
call.
|
|
|