npm.io
0.8.0 • Published 2d ago

@better-media/plugin-video-processing

Licence
MIT
Version
0.8.0
Deps
1
Size
126 kB
Vulns
0
Weekly
0
Stars
15

Better Media

Modular media pipeline framework for intake, validation, processing, and storage.

View Website App

Architecture

Core defines contracts. Adapters implement infrastructure. Framework orchestrates.

Layer Package(s) Responsibility
Core @better-media/core Interfaces only (StorageAdapter, DatabaseAdapter, JobAdapter, PipelinePlugin). No implementations.
Adapters @better-media/adapter-storage-memory, @better-media/adapter-storage-filesystem, @better-media/adapter-storage-s3, @better-media/adapter-db-memory, @better-media/adapter-db-kysely, @better-media/mongodb-adapter, @better-media/adapter-jobs Implement core contracts (MemoryStorageAdapter, FileSystemStorageAdapter, S3StorageAdapter, etc).
Framework @better-media/framework Orchestrate: wire adapters + plugins, run lifecycle. No infrastructure contracts or implementations.

Monorepo Structure

packages/
├── core/              # @better-media/core - Contracts (interfaces, types)
├── better-media/      # @better-media/framework - Framework entry, lifecycle engine
├── plugins/
│   ├── validation-plugin/     # @better-media/plugin-validation
│   ├── virus-scan-plugin/     # @better-media/plugin-virus-scan
│   └── media-processing-plugin/  # @better-media/plugin-media-processing
└── adapters/
    ├── storages/
    │   ├── storage-memory/       # @better-media/adapter-storage-memory
    │   ├── storage-filesystem/   # @better-media/adapter-storage-filesystem
    │   └── storage-s3/           # @better-media/adapter-storage-s3
    ├── databases/
    │   ├── db-memory/            # @better-media/adapter-db-memory
    │   ├── db-kysely/            # @better-media/adapter-db-kysely
    │   └── mongodb-adapter/      # @better-media/mongodb-adapter
    └── jobs/                     # @better-media/adapter-jobs

Plugin System

Plugins run in either synchronous or background execution modes.

Plugin
 ├─ name
 ├─ hooks (extensible lifecycle hooks)
 └─ execution mode
      ├─ sync      – run inline during upload
      └─ background – enqueue via job adapter

Job Adapter System

Background execution is powered by an optional job adapter. Default: in-memory.

  • sync – Plugin runs inline during upload
  • background – Plugin work is enqueued via job adapter (Redis, RabbitMQ, Kafka, etc.)
Worker Integration

Use media.runBackgroundJob(payload) from your worker process. The payload is serializable:

interface BackgroundJobPayload {
  fileKey: string;
  metadata: Record<string, unknown>;
  hookName: HookName;
  pluginName: string;
}

Example with Bull/BullMQ:

const media = createBetterMedia({ storage, database, jobs: bullAdapter, plugins });
const worker = new Worker("better-media:background", async (job) => {
  await media.runBackgroundJob(job.data);
});

Example with Inngest:

inngest.createFunction(
  { id: "better-media-job" },
  { event: "better-media/background" },
  async ({ event }) => {
    await media.runBackgroundJob(event.data.payload);
  }
);

The framework does not implement polling or scheduling—adapters and your worker own that.

Storage Adapters

Choose a storage implementation based on your environment:

Adapter Package Use case
Memory @better-media/adapter-storage-memory Development, tests
Filesystem @better-media/adapter-storage-filesystem Single-node, local disk
S3 @better-media/adapter-storage-s3 AWS S3, MinIO, S3-compatible

Filesystem (works with Multer in Express/NestJS):

import { FileSystemStorageAdapter } from "@better-media/adapter-storage-filesystem";

const storage = new FileSystemStorageAdapter({ baseDir: "/var/uploads" });

S3 (AWS or MinIO):

import { S3StorageAdapter } from "@better-media/adapter-storage-s3";

const storage = new S3StorageAdapter({
  region: "us-east-1",
  bucket: "my-media-bucket",
  accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  // For MinIO:
  // endpoint: "http://localhost:9000",
  // forcePathStyle: true,
});

Quick Start

pnpm install
pnpm build

Scripts

Command Description
pnpm build Build all packages
pnpm dev Watch mode for all packages
pnpm typecheck Type-check all packages
pnpm lint Lint all packages
pnpm test Run tests
pnpm format Format with Prettier
pnpm changeset Create a changeset for versioning

Testing with Postman

A Postman collection is provided in the root directory to help you test the examples:

The collection includes:

  • Multipart Uploads: Test Multer-based ingest.
  • Binary Uploads: Test raw buffer ingest.
  • Unified Presigned Uploads: Full flow for both PUT and POST methods (Step-by-step).

To use it:

  1. Import the JSON file into Postman.
  2. Start an example (e.g., cd examples/express && pnpm dev).
  3. Use the collection variables to switch between Express (Port 6000) and NestJS (Port 3000).

Adding a Plugin

  1. Create packages/plugins/<name>-plugin/ with package.json, tsconfig.json, tsup.config.ts
  2. Implement the PipelinePlugin interface from @better-media/core
  3. Add @better-media/core as a workspace dependency

Adding an Adapter

  1. Create packages/adapters/<name>/ (or add to existing storage/db)
  2. Implement the contract from @better-media/core (e.g. StorageAdapter, DatabaseAdapter)
  3. Export the implementation; re-export the interface from core for convenience
  4. Add to workspace in pnpm-workspace.yaml if using a new top-level adapter package

Keywords