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

@baxcloud/baxstream

v1.0.5

Published

BaxStream SDK for Node.js — video conversion, HLS output, and AI categorization/moderation

Readme

@baxcloud/baxstream

Official BaxStream SDK for Node.js — video conversion to adaptive HLS, AI categorization, and content moderation.

For BaxStream webhook verification (and other BaxCloud product webhooks), use @baxcloud/baxcloud-server-sdk alongside this package.

Product-specific SDKs:

Installation

npm install @baxcloud/baxstream

Quick Start

import { BaxCloudStreamClient } from '@baxcloud/baxstream';

const stream = new BaxCloudStreamClient({
  projectId: process.env.BAXCLOUD_PROJECT_ID!,
  apiKey: process.env.BAXCLOUD_API_KEY!,
});

const job = await stream.createVideoConversionJob({
  inputUrl: 'https://example.com/video.mp4',
  outputFormats: ['720p', '1080p'],
  s3Config: {
    bucket: 'my-bucket',
    accessKey: process.env.S3_ACCESS_KEY!,
    secretKey: process.env.S3_SECRET_KEY!,
    cdnUrl: 'https://cdn.example.com',
  },
});

const status = await stream.getVideoConversionJob(job.id);
console.log(status.status, status.outputUrl);

Requires Node.js 18+. Only projectId and apiKey are required — the client connects to BaxCloud automatically.

Sync vs async (important)

BaxStream has two execution models. Do not assume everything is webhook-only.

| Flow | Endpoints / methods | How you get results | |------|---------------------|---------------------| | Standalone AI (sync) | createCategorizationJob, createModerationJob, uploadImageForModeration, createModerationBatchJob, uploadImagesForModeration | await the HTTP call — response has status: "COMPLETED" with full results (safe, violations, categories, batchItems, etc.). Webhooks are optional. | | HLS conversion (async) | createVideoConversionJob, uploadVideoForConversion | Job stays PENDING / PROCESSINGpoll getVideoConversionJob() or use video.conversion.* webhooks. Inline categorize / moderate results arrive on video.conversion.completed. |

Single-image moderation example — block until done, read result.safe directly:

const result = await stream.createModerationJob({
  inputUrl: 'https://example.com/photo.jpg',
  inputType: 'image',
  threshold: 0.30,
});

if (!result.safe) {
  console.log('Blocked:', result.violations);
}
// No webhook and no getModerationJob() required for standalone calls.

Use getModerationJob() / listModerationJobs() only to re-fetch stored jobs later (dashboard, audits, retries).

Usage Examples

Convert a video URL to adaptive HLS

Point BaxStream at a publicly reachable MP4/MOV. Output is written to your S3 bucket as HLS segments plus a master playlist.

const job = await stream.createVideoConversionJob({
  inputUrl: 'https://cdn.example.com/uploads/clip.mp4',
  outputFormats: ['360p', '720p', '1080p'],
  ffmpegPreset: 'fast',
  hlsTime: 6,
  s3Config: {
    bucket: 'my-videos',
    region: 'us-east-1',
    prefix: 'hls/my-app/',
    accessKey: process.env.S3_ACCESS_KEY!,
    secretKey: process.env.S3_SECRET_KEY!,
    cdnUrl: 'https://videos.example.com',
  },
  metadata: { userId: 'user_123', uploadId: 'up_456' },
});

console.log(job.id, job.status); // PENDING

When the job completes, outputUrl is the HLS master playlist URL and renditionUrls maps each resolution.

Upload a local file

Use uploadVideoForConversion when the source file is on your server (Express, NestJS, etc.) instead of a public URL.

import fs from 'node:fs';

const file = fs.createReadStream('./uploads/recording.mp4');

const job = await stream.uploadVideoForConversion(file, 'recording.mp4', {
  outputFormats: ['720p', '1080p'],
  s3Config: {
    bucket: 'my-videos',
    accessKey: process.env.S3_ACCESS_KEY!,
    secretKey: process.env.S3_SECRET_KEY!,
    cdnUrl: 'https://videos.example.com',
  },
});

Conversion + AI in one job

Run HLS conversion together with categorization and/or moderation on the same input:

const job = await stream.createVideoConversionJob({
  inputUrl: 'https://example.com/feed-video.mp4',
  outputFormats: ['720p'],
  categorize: true,
  moderate: true,
  s3Config: { /* ... */ },
});

// Poll until done (or use BaxStream webhooks — see below)
let status = await stream.getVideoConversionJob(job.id);
while (status.status === 'PENDING' || status.status === 'PROCESSING') {
  await new Promise((r) => setTimeout(r, 5000));
  status = await stream.getVideoConversionJob(job.id);
}

if (status.status === 'COMPLETED') {
  console.log('HLS:', status.outputUrl);
  console.log('Thumbnail:', status.thumbnailUrl);
}

Standalone AI categorization

Analyze a video or image without running a full conversion job. The call is synchronous — the returned job is already COMPLETED:

const result = await stream.createCategorizationJob({
  inputUrl: 'https://example.com/thumbnail.jpg',
  inputType: 'image',
  topK: 5,
});

console.log(result.primaryCategory, result.categories);
// e.g. [{ category: 'sports', confidence: 0.92 }, ...]

For video, omit inputType or set inputType: 'video'. Use maxFrames to cap frames analyzed on long clips.

Standalone image moderation (sync)

Moderate one image from a URL or upload. The HTTP response includes the verdict — no webhook required:

// Public URL
const result = await stream.createModerationJob({
  inputUrl: 'https://example.com/photo.jpg',
  inputType: 'image',
  threshold: 0.30,
});

if (!result.safe) {
  console.log(result.violations);
}

Upload a local image

Use uploadImageForModeration when the file is on your server instead of a public URL. Also synchronous:

import fs from 'node:fs';

const result = await stream.uploadImageForModeration(
  fs.createReadStream('./uploads/avatar.jpg'),
  'avatar.jpg',
  { threshold: 0.30 },
);

console.log(result.safe, result.violations);

Moderate multiple images (batch)

Moderate up to 20 images in one synchronous job. The HTTP response includes aggregate fields plus batchItems[] per image (webhooks also fire if configured):

const batch = await stream.createModerationBatchJob({
  inputUrls: [
    'https://example.com/a.jpg',
    'https://example.com/b.jpg',
  ],
  threshold: 0.30,
});

for (const item of batch.batchItems ?? []) {
  console.log(item.index, item.inputUrl, item.safe, item.violations);
}

// Or upload local files:
const uploaded = await stream.uploadImagesForModeration([
  { stream: fs.createReadStream('./a.jpg'), filename: 'a.jpg' },
  { stream: fs.createReadStream('./b.jpg'), filename: 'b.jpg' },
], { threshold: 0.30 });

Standalone video moderation (sync)

Same synchronous model for standalone video moderation:

const result = await stream.createModerationJob({
  inputUrl: 'https://example.com/user-upload.mp4',
  inputType: 'video',
  threshold: 0.30,
  maxFrames: 8,
});

if (!result.safe) {
  console.log('Blocked:', result.violations);
  // e.g. [{ category: 'violence', confidence: 0.91, severity: 'high' }]
  console.log('Flagged frames:', result.flaggedFrames);
}

List and cancel jobs

const { items, total } = await stream.listVideoConversionJobs({
  status: 'PROCESSING',
  page: 1,
  pageSize: 20,
});

await stream.cancelVideoConversionJob(items[0].id);

const categorizationJobs = await stream.listCategorizationJobs({ status: 'COMPLETED' });
const moderationJobs = await stream.listModerationJobs({ pageSize: 50 });

Error handling

API failures throw BaxStreamError with a stable code, HTTP statusCode, and optional details.helpUrl:

import { BaxCloudStreamClient, BaxStreamError } from '@baxcloud/baxstream';

try {
  await stream.createVideoConversionJob({ inputUrl: 'https://example.com/v.mp4' });
} catch (err) {
  if (err instanceof BaxStreamError) {
    console.error(err.code, err.statusCode, err.message);
    if (err.details?.helpUrl) console.error('Help:', err.details.helpUrl);
  }
  throw err;
}

Webhooks

Webhooks are optional for standalone AI jobs — you already get results in the synchronous HTTP response. They are recommended for async HLS conversion and for backends that prefer event-driven architecture.

BaxStream emits lifecycle webhooks for conversion, categorization, and moderation:

| Event | When | Typical use | |-------|------|-------------| | video.conversion.started / completed / failed | HLS conversion pipeline (async) | Primary way to learn when HLS is ready | | categorization.started / completed / failed | Standalone categorization (sync API also returns result) | Optional duplicate notification | | moderation.started / completed / failed | Standalone moderation (sync API also returns result); batch jobs include items[] | Optional duplicate notification |

Verify them with the server SDK:

import express from 'express';
import { webhookMiddleware } from '@baxcloud/baxcloud-server-sdk';

const app = express();

app.post(
  '/webhooks/baxcloud',
  express.json({
    verify: (req: any, _res, buf) => { req.rawBody = buf; },
  }),
  webhookMiddleware(process.env.BAXCLOUD_WEBHOOK_SECRET!),
  (req: any, res) => {
    const event = req.baxcloudEvent;

    if (event.event === 'video.conversion.completed') {
      console.log('HLS ready:', event.data?.outputUrl);
    }

    res.json({ received: true });
  },
);

See BaxStream docs for event payloads and Server SDK for the full webhook catalog.

Environment Variables

BAXCLOUD_PROJECT_ID=your_project_id
BAXCLOUD_API_KEY=your_api_key          # BaxStream scope enabled

# Required when writing HLS output to your bucket
S3_ACCESS_KEY=...
S3_SECRET_KEY=...

API

| Method | Description | |--------|-------------| | createVideoConversionJob() | Start HLS conversion (+ optional AI) | | uploadVideoForConversion() | Multipart file upload | | listVideoConversionJobs() | List conversion jobs | | getVideoConversionJob() | Get job status | | cancelVideoConversionJob() | Cancel pending job | | createCategorizationJob() | Standalone AI categorization (sync — returns completed job) | | listCategorizationJobs() | List categorization jobs | | getCategorizationJob() | Re-fetch a stored categorization job | | uploadImageForModeration() | Multipart single-image upload (sync) | | createModerationJob() | Standalone moderation, one URL (sync) | | createModerationBatchJob() | Standalone batch image moderation, 1–20 URLs (sync) | | uploadImagesForModeration() | Multipart batch image upload (sync) | | listModerationJobs() | List moderation jobs | | getModerationJob() | Re-fetch a stored moderation job |

Related SDKs

License

MIT

Support

  • Help: https://baxcloud.tech/dashboard/help
  • Contact: https://baxcloud.tech/contact
  • Documentation: https://baxcloud.tech/docs/baxstream/sdk/node
  • Email: [email protected]