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

brat-canvas

v1.0.30

Published

Generate brat-style images with emoji support using @napi-rs/canvas

Readme

brat-canvas

Generate brat-style images and videos (MP4/GIF) with clean text layout. Text in → image or video out.

✨ Features

  • Generate images (PNG)
  • Generate videos (MP4 / GIF) with progressive text reveal
  • Smart text wrapping & justification
  • Auto font scaling (always fits inside the box)
  • Emoji Support: Native emoji rendering with brand selection (Apple, Google, etc.)
  • Theme support
  • Fast / memory-safe rendering modes (parallel frame processing)

📦 Installation

npm

npm install brat-canvas

🖼️ Generate Image

import { writeFile } from 'fs/promises';
import { bratGen } from 'brat-canvas';

const buf = await bratGen('kangen masa lalu ya?');

await writeFile('output.png', buf);
console.log('Done!');

🎬 Generate Video

import { writeFile } from 'fs/promises';
import { bratVid } from 'brat-canvas/video';

const buf = await bratVid('mending tidur gweh mah', {
  outputFormat: 'mp4'
});

await writeFile('output.mp4', buf);
console.log('Done!');

⚙️ Image Options (bratGen)

type ImageOptions = {
  theme?: string; // Theme name (e.g., 'brat', 'apple')
  emojiStyle?: 'apple' | 'google' | 'twitter' | 'facebook' | 'samsung' | 'microsoft';
  debugMode?: boolean; // Print detailed logs (canvas, font size, lines, emoji) (default: false)

  // Layout
  W?: number; // Canvas width (default: 1024)
  H?: number; // Canvas height (default: 1024)
  BOX_W?: number; // Text box width
  BOX_H?: number; // Text box height
  BOX_PAD?: number; // Padding inside the box

  // Text behavior
  LINE_H?: number; // Line height multiplier
  FS_MIN?: number; // Minimum font size
  FS_MAX?: number; // Maximum font size
  BASELINE_ADJ?: number; // Vertical text adjustment (default: 1)

  // Colors
  C_BG?: string; // Background color (hex/rgb)
  C_BOX?: string; // Box color
  C_TEXT?: string; // Text color

  // Effects
  BLUR?: number; // Text blur amount

  // Fonts
  FONT_NAME?: string;
  FONT_WEIGHT?: string | number;
  FALLBACK_FONT?: string;
  fontPaths?: string[]; // Array of paths to local .ttf/.otf files
}

⚙️ Video Options (bratVid)

type VideoOptions = {
  outputFormat?: 'mp4' | 'gif'; // default: 'mp4'
  fast_progress?: boolean; // parallel rendering (faster but uses more RAM)
  debugMode?: boolean; // Print detailed logs (tokens, layers, frames, durations) (default: false)

  // Lyric & Timing Controls
  lyric?: {
    maxWordPerLayer?: number; // Max words per layer before reveal resets (default: Infinity = 1 layer)

    // Choose one timing option:
    frameDuration?: number; // flat duration per frame (default: 0.7s)
    lastFrameDuration?: number; // hold time for last frame of each layer (default: 1.5s)
    bpm?: number; // auto-calculate duration based on Beats Per Minute
    tempo?: number[]; // array of durations (seconds) per token
    timestamps?: number[]; // array of absolute timestamps (ms) for each word
  };

  // Callback & Control
  onProgress?: (data: { current: number, total: number, text: string }) => void;
  signal?: AbortSignal; // used to cancel the generation process

  // Styling
  theme?: string;
  brat?: ImageOptions; // forwarded to bratGen for every frame
}

🧠 Advanced Options Explained

BPM (Beats Per Minute) Sync word reveals to the beat of a track automatically.

lyric: { bpm: 120 }

Timestamps Used for precise lyric syncing. Accepts an array of absolute time in milliseconds.

lyric: { timestamps: [0, 450, 900, 1350] }

maxWordPerLayer Resets the progressive reveal every N words. Useful for lyric videos where each line should appear independently.

lyric: { maxWordPerLayer: 5 }

// tokens: [A, B, C, D, E, F, G]  maxWordPerLayer: 3
// layer 1 frames → "A" · "A B" · "A B C"
// layer 2 frames → "D" · "D E" · "D E F"
// layer 3 frames → "G"

onProgress Useful for creating progress bars in CLI or web interfaces.

onProgress: ({ current, total, text }) => {
  console.log(`Processing frame ${current}/${total}: ${text}`);
}

fontPaths Register local font files without needing to install them on the host system.

fontPaths: ['./assets/fonts/BratFont-Bold.ttf']

debugMode Prints detailed internal logs. Available on both bratGen and bratVid.

// image
bratGen('teks', { debugMode: true });

// video
bratVid('teks', { debugMode: true });

🧪 Full Example (Lyric Sync)

import { writeFile } from 'fs/promises';
import { bratVid } from 'brat-canvas/video';

const vid = await bratVid('akugweh hann', {
  fast_progress: true,
  theme: 'brat',
  debugMode: true,
  lyric: {
    bpm: 130,
    maxWordPerLayer: 5,
    lastFrameDuration: 2,
  },
  onProgress: (p) => console.log(`Progress: ${p.current}/${p.total}`),
  brat: {
    BLUR: 3,
    emojiStyle: 'twitter'
  }
});

await writeFile('akugweh.mp4', vid);

🛠 Requirements

  • Node.js 18+
  • ffmpeg must be installed and available in your system's PATH
ffmpeg -version