{"_id":"brat-canvas","_rev":"16-9043190a18c3f486656744f32b98e068","name":"brat-canvas","dist-tags":{"latest":"1.0.30"},"versions":{"1.0.0":{"name":"brat-canvas","version":"1.0.0","keywords":["brat","canvas","image","generator","emoji"],"author":{"name":"Hann Universe"},"license":"MIT","_id":"brat-canvas@1.0.0","maintainers":[{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"}],"dist":{"shasum":"e2c76be1c59eb1c34feaa8a267762be965e30812","tarball":"https://registry.npmjs.org/brat-canvas/-/brat-canvas-1.0.0.tgz","fileCount":10,"integrity":"sha512-wCaCY9e6IVP5GobWtuxCv0hSq+R0F3AuR56yJOfTjBDzr/SQORvTfGoapIZsFqRg4m3Rzsk/e8ccijDt4Vl7LQ==","signatures":[{"sig":"MEUCIQCKEEFRJuuMHJsgt+cvo8kYcng/t42sl8+YlVXWXuHkDwIgQCzUDqEsNYdGla9TMAyMsjBk2ThQX8HD7sLFnzXTlWQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":81135350},"main":"dist/cjs/index.js","type":"module","module":"dist/esm/index.js","engines":{"node":">=16"},"exports":{".":{"import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"scripts":{"build":"rollup -c","prepublishOnly":"npm run build"},"_npmUser":{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"},"_npmVersion":"11.6.2","description":"Generate brat-style images with emoji support using @napi-rs/canvas","directories":{},"_nodeVersion":"24.11.1","dependencies":{"js-yaml":"^4.1.0","emoji-db":"^1.0.0","@napi-rs/canvas":"^0.1.44","@rollup/plugin-commonjs":"^29.0.2","@rollup/plugin-node-resolve":"^16.0.3"},"_hasShrinkwrap":false,"devDependencies":{"rollup":"^4.60.1"},"_npmOperationalInternal":{"tmp":"tmp/brat-canvas_1.0.0_1775356106996_0.2616915047560624","host":"s3://npm-registry-packages-npm-production"}},"1.0.11":{"name":"brat-canvas","version":"1.0.11","keywords":["brat","canvas","image","generator","emoji"],"author":{"name":"Hann Universe"},"license":"MIT","_id":"brat-canvas@1.0.11","maintainers":[{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"}],"dist":{"shasum":"31548014cbf87a6fe256c7f392db3c7d8fcff022","tarball":"https://registry.npmjs.org/brat-canvas/-/brat-canvas-1.0.11.tgz","fileCount":12,"integrity":"sha512-UbtGBk6H7e8M8xVeVrwHNMcoXumnD2Y5pmPxYT2gZ9GqjNL3SEpGbZZ700WDSdFACmEU1y3XWBnUi822b1RMPA==","signatures":[{"sig":"MEUCIEYINKdcuu/lFCv5iKajE57IPlgpX0/McwndeafnFoqaAiEAwd3zHi4hW3uQY3jystu06YNUhthloT99x2eW8UqfrTE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":81182681},"main":"dist/cjs/index.cjs","type":"module","module":"dist/esm/index.js","engines":{"node":">=16"},"exports":{".":{"import":"./dist/esm/index.js","require":"./dist/cjs/index.cjs"}},"scripts":{"build":"rollup -c","prepublishOnly":"npm run build"},"_npmUser":{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"},"_npmVersion":"11.6.2","description":"Generate brat-style images with emoji support using @napi-rs/canvas","directories":{},"_nodeVersion":"24.11.1","dependencies":{"emoji-db":"^1.0.0","@napi-rs/canvas":"^0.1.44","@rollup/plugin-json":"^6.1.0","@rollup/plugin-commonjs":"^29.0.2","@rollup/plugin-node-resolve":"^16.0.3"},"_hasShrinkwrap":false,"devDependencies":{"rollup":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/brat-canvas_1.0.11_1775382184858_0.8368355861611616","host":"s3://npm-registry-packages-npm-production"}},"1.0.23":{"name":"brat-canvas","version":"1.0.23","keywords":["brat","canvas","image","generator","emoji"],"author":{"name":"Hann Universe"},"license":"MIT","_id":"brat-canvas@1.0.23","maintainers":[{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"}],"dist":{"shasum":"422a0f34804b6cb1a75702591e0b0690cd2dcdf3","tarball":"https://registry.npmjs.org/brat-canvas/-/brat-canvas-1.0.23.tgz","fileCount":17,"integrity":"sha512-0kPmuOlWXG5IkxpmOx9mQi7XED0JN3sPOury+94JBshORDwzhEH0p8NyA60GZEqv6ewi7nrVaq40oDI5CzpF9Q==","signatures":[{"sig":"MEYCIQDPod7RqU90d3A+kcIAKlHTXG1fsHBJmryi2De7kUC8PAIhAK+lkze0BRg7eeucpSVucvJ4KjPIWvpzoBq/vfYJXiRK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":81353594},"main":"dist/cjs/index.cjs","type":"module","module":"dist/esm/index.js","engines":{"node":">=16"},"exports":{".":{"import":"./dist/esm/image.js","require":"./dist/cjs/image.cjs"},"./image":{"import":"./dist/esm/image.js","require":"./dist/cjs/image.cjs"},"./video":{"import":"./dist/esm/video.js","require":"./dist/cjs/video.cjs"}},"scripts":{"build":"rollup -c","prepublishOnly":"npm run build"},"_npmUser":{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"},"_npmVersion":"11.6.2","description":"Generate brat-style images with emoji support using @napi-rs/canvas","directories":{},"_nodeVersion":"24.11.1","dependencies":{"emoji-db":"^1.0.0","@napi-rs/canvas":"^0.1.44"},"_hasShrinkwrap":false,"devDependencies":{"rollup":"^4.0.0","@rollup/plugin-json":"^6.1.0","@rollup/plugin-commonjs":"^29.0.2","@rollup/plugin-node-resolve":"^16.0.3"},"_npmOperationalInternal":{"tmp":"tmp/brat-canvas_1.0.23_1775771756148_0.574211633084988","host":"s3://npm-registry-packages-npm-production"}},"1.0.24":{"name":"brat-canvas","version":"1.0.24","keywords":["brat","canvas","image","generator","emoji"],"author":{"name":"Hann Universe"},"license":"MIT","_id":"brat-canvas@1.0.24","maintainers":[{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"}],"dist":{"shasum":"c4c56f0d2401282f1f811282224cff43942fc5e4","tarball":"https://registry.npmjs.org/brat-canvas/-/brat-canvas-1.0.24.tgz","fileCount":17,"integrity":"sha512-HPofTNFuZqbVgF/bUOissg09r/Uq6zhfAGIzQObOlHxS/hLIL9w7khU8SCwNkjmWaUk6QS16YAGVw8N1GBIsug==","signatures":[{"sig":"MEUCIQCLk049X7b8utAYrtT4SXk0y5i5Bpy/XGnshXp6r8tPugIgcfUMEA0YHt+dni2TKtNLGnN7lryONPBvOuJt1ujZIKc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":81353155},"main":"dist/cjs/index.cjs","type":"module","module":"dist/esm/index.js","engines":{"node":">=16"},"exports":{".":{"import":"./dist/esm/image.js","require":"./dist/cjs/image.cjs"},"./image":{"import":"./dist/esm/image.js","require":"./dist/cjs/image.cjs"},"./video":{"import":"./dist/esm/video.js","require":"./dist/cjs/video.cjs"}},"scripts":{"build":"rollup -c","prepublishOnly":"npm run build"},"_npmUser":{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"},"_npmVersion":"11.6.2","description":"Generate brat-style images with emoji support using @napi-rs/canvas","directories":{},"_nodeVersion":"24.11.1","dependencies":{"emoji-db":"^1.0.0","@napi-rs/canvas":"^0.1.44"},"_hasShrinkwrap":false,"devDependencies":{"rollup":"^4.0.0","@rollup/plugin-json":"^6.1.0","@rollup/plugin-commonjs":"^29.0.2","@rollup/plugin-node-resolve":"^16.0.3"},"_npmOperationalInternal":{"tmp":"tmp/brat-canvas_1.0.24_1775773701826_0.4865668807048198","host":"s3://npm-registry-packages-npm-production"}},"1.0.26":{"name":"brat-canvas","version":"1.0.26","keywords":["brat","canvas","image","generator","emoji"],"author":{"name":"Hann Universe"},"license":"MIT","_id":"brat-canvas@1.0.26","maintainers":[{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"}],"dist":{"shasum":"bccb29549c6fb93ea23fae5358aaef87ad96c53e","tarball":"https://registry.npmjs.org/brat-canvas/-/brat-canvas-1.0.26.tgz","fileCount":17,"integrity":"sha512-eNS9doOthkRAaSub5Iu0rdTg4PbrFf/iWDCZ3P+kSl62+LFvmT5XfIevSz0YocufnBPzrkOZOCGAF0nosPMM7w==","signatures":[{"sig":"MEUCICT14tBhd9JX74Kkn5/8HiUIHDTVJmUlHhHpgpqXergBAiEAu9lavJCNGU4CE8UeL/OYTmgAilIIkz70rb/xjqoODyc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":81381108},"main":"dist/cjs/index.cjs","type":"module","module":"dist/esm/index.js","engines":{"node":">=16"},"exports":{".":{"import":"./dist/esm/image.js","require":"./dist/cjs/image.cjs"},"./image":{"import":"./dist/esm/image.js","require":"./dist/cjs/image.cjs"},"./video":{"import":"./dist/esm/video.js","require":"./dist/cjs/video.cjs"}},"scripts":{"build":"rollup -c","prepublishOnly":"npm run build"},"_npmUser":{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"},"_npmVersion":"11.6.2","description":"Generate brat-style images with emoji support using @napi-rs/canvas","directories":{},"_nodeVersion":"24.11.1","dependencies":{"emoji-db":"^1.0.0","@napi-rs/canvas":"^0.1.44"},"_hasShrinkwrap":false,"devDependencies":{"rollup":"^4.0.0","@rollup/plugin-json":"^6.1.0","@rollup/plugin-commonjs":"^29.0.2","@rollup/plugin-node-resolve":"^16.0.3"},"_npmOperationalInternal":{"tmp":"tmp/brat-canvas_1.0.26_1775878169784_0.0213224506051104","host":"s3://npm-registry-packages-npm-production"}},"1.0.30":{"name":"brat-canvas","version":"1.0.30","description":"Generate brat-style images with emoji support using @napi-rs/canvas","type":"module","main":"dist/cjs/index.cjs","module":"dist/esm/index.js","exports":{".":{"import":"./dist/esm/image.js","require":"./dist/cjs/image.cjs"},"./image":{"import":"./dist/esm/image.js","require":"./dist/cjs/image.cjs"},"./video":{"import":"./dist/esm/video.js","require":"./dist/cjs/video.cjs"}},"scripts":{"build":"rollup -c","prepublishOnly":"npm run build"},"keywords":["brat","canvas","image","generator","emoji"],"author":{"name":"Hann Universe"},"license":"MIT","dependencies":{"@napi-rs/canvas":"^0.1.44","emoji-db":"^1.0.0"},"devDependencies":{"rollup":"^4.0.0","@rollup/plugin-commonjs":"^29.0.2","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^16.0.3"},"engines":{"node":">=16"},"_id":"brat-canvas@1.0.30","_nodeVersion":"24.11.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-8pSs/b3sOsYNsXU3CM9zwzMKi0ZAJclxkZR7keuisuiAKsBu447qcRuIyfF4Anwf9H6eN2O+HogfQoNTtgSf2w==","shasum":"7b09a5c7682bac6fbf41d1751ecd8c56fa1ea1c9","tarball":"https://registry.npmjs.org/brat-canvas/-/brat-canvas-1.0.30.tgz","fileCount":17,"unpackedSize":81399927,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIH1EwQ+R1zCHf/aPkrOIirlyBg2xGBTGtN2NQgWVcgWTAiEAgIF9PvN1A85PVgm0FQk3QvJJWzFvaUDSXr7XasidpjM="}]},"_npmUser":{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"},"directories":{},"maintainers":[{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/brat-canvas_1.0.30_1776981091627_0.975731624325771"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-05T02:28:26.995Z","modified":"2026-04-23T21:51:33.181Z","1.0.0":"2026-04-05T02:28:28.469Z","1.0.10":"2026-04-05T03:27:46.462Z","1.0.12":"2026-04-05T04:06:26.977Z","1.0.15":"2026-04-05T04:36:04.964Z","1.0.1":"2026-04-05T05:06:32.637Z","1.0.13":"2026-04-05T06:03:55.443Z","1.0.11":"2026-04-05T09:43:06.343Z","1.0.23":"2026-04-09T21:55:57.642Z","1.0.24":"2026-04-09T22:28:23.299Z","1.0.26":"2026-04-11T03:29:31.191Z","1.0.30":"2026-04-23T21:51:33.083Z"},"author":{"name":"Hann Universe"},"license":"MIT","keywords":["brat","canvas","image","generator","emoji"],"description":"Generate brat-style images with emoji support using @napi-rs/canvas","maintainers":[{"name":"hannuniverse","email":"hanzzrillnopekpek@gmail.com"}],"readme":"# brat-canvas\n\nGenerate **brat-style images and videos (MP4/GIF)** with clean text layout.\nText in → image or video out.\n\n## ✨ Features\n * Generate **images (PNG)**\n * Generate **videos (MP4 / GIF)** with progressive text reveal\n * Smart text wrapping & justification\n * Auto font scaling (always fits inside the box)\n * **Emoji Support**: Native emoji rendering with brand selection (Apple, Google, etc.)\n * Theme support\n * Fast / memory-safe rendering modes (parallel frame processing)\n\n## 📦 Installation\n\n### npm\n```bash\nnpm install brat-canvas\n```\n\n## 🖼️ Generate Image\n```javascript\nimport { writeFile } from 'fs/promises';\nimport { bratGen } from 'brat-canvas';\n\nconst buf = await bratGen('kangen masa lalu ya?');\n\nawait writeFile('output.png', buf);\nconsole.log('Done!');\n```\n\n## 🎬 Generate Video\n```javascript\nimport { writeFile } from 'fs/promises';\nimport { bratVid } from 'brat-canvas/video';\n\nconst buf = await bratVid('mending tidur gweh mah', {\n  outputFormat: 'mp4'\n});\n\nawait writeFile('output.mp4', buf);\nconsole.log('Done!');\n```\n\n## ⚙️ Image Options (bratGen)\n```typescript\ntype ImageOptions = {\n  theme?: string; // Theme name (e.g., 'brat', 'apple')\n  emojiStyle?: 'apple' | 'google' | 'twitter' | 'facebook' | 'samsung' | 'microsoft';\n  debugMode?: boolean; // Print detailed logs (canvas, font size, lines, emoji) (default: false)\n\n  // Layout\n  W?: number; // Canvas width (default: 1024)\n  H?: number; // Canvas height (default: 1024)\n  BOX_W?: number; // Text box width\n  BOX_H?: number; // Text box height\n  BOX_PAD?: number; // Padding inside the box\n\n  // Text behavior\n  LINE_H?: number; // Line height multiplier\n  FS_MIN?: number; // Minimum font size\n  FS_MAX?: number; // Maximum font size\n  BASELINE_ADJ?: number; // Vertical text adjustment (default: 1)\n\n  // Colors\n  C_BG?: string; // Background color (hex/rgb)\n  C_BOX?: string; // Box color\n  C_TEXT?: string; // Text color\n\n  // Effects\n  BLUR?: number; // Text blur amount\n\n  // Fonts\n  FONT_NAME?: string;\n  FONT_WEIGHT?: string | number;\n  FALLBACK_FONT?: string;\n  fontPaths?: string[]; // Array of paths to local .ttf/.otf files\n}\n```\n\n## ⚙️ Video Options (bratVid)\n```typescript\ntype VideoOptions = {\n  outputFormat?: 'mp4' | 'gif'; // default: 'mp4'\n  fast_progress?: boolean; // parallel rendering (faster but uses more RAM)\n  debugMode?: boolean; // Print detailed logs (tokens, layers, frames, durations) (default: false)\n\n  // Lyric & Timing Controls\n  lyric?: {\n    maxWordPerLayer?: number; // Max words per layer before reveal resets (default: Infinity = 1 layer)\n\n    // Choose one timing option:\n    frameDuration?: number; // flat duration per frame (default: 0.7s)\n    lastFrameDuration?: number; // hold time for last frame of each layer (default: 1.5s)\n    bpm?: number; // auto-calculate duration based on Beats Per Minute\n    tempo?: number[]; // array of durations (seconds) per token\n    timestamps?: number[]; // array of absolute timestamps (ms) for each word\n  };\n\n  // Callback & Control\n  onProgress?: (data: { current: number, total: number, text: string }) => void;\n  signal?: AbortSignal; // used to cancel the generation process\n\n  // Styling\n  theme?: string;\n  brat?: ImageOptions; // forwarded to bratGen for every frame\n}\n```\n\n## 🧠 Advanced Options Explained\n\n**BPM (Beats Per Minute)** Sync word reveals to the beat of a track automatically.\n```javascript\nlyric: { bpm: 120 }\n```\n\n**Timestamps** Used for precise lyric syncing. Accepts an array of absolute time in milliseconds.\n```javascript\nlyric: { timestamps: [0, 450, 900, 1350] }\n```\n\n**maxWordPerLayer** Resets the progressive reveal every N words. Useful for lyric videos where each line should appear independently.\n```javascript\nlyric: { maxWordPerLayer: 5 }\n\n// tokens: [A, B, C, D, E, F, G]  maxWordPerLayer: 3\n// layer 1 frames → \"A\" · \"A B\" · \"A B C\"\n// layer 2 frames → \"D\" · \"D E\" · \"D E F\"\n// layer 3 frames → \"G\"\n```\n\n**onProgress** Useful for creating progress bars in CLI or web interfaces.\n```javascript\nonProgress: ({ current, total, text }) => {\n  console.log(`Processing frame ${current}/${total}: ${text}`);\n}\n```\n\n**fontPaths** Register local font files without needing to install them on the host system.\n```javascript\nfontPaths: ['./assets/fonts/BratFont-Bold.ttf']\n```\n\n**debugMode** Prints detailed internal logs. Available on both `bratGen` and `bratVid`.\n```javascript\n// image\nbratGen('teks', { debugMode: true });\n\n// video\nbratVid('teks', { debugMode: true });\n```\n\n## 🧪 Full Example (Lyric Sync)\n```javascript\nimport { writeFile } from 'fs/promises';\nimport { bratVid } from 'brat-canvas/video';\n\nconst vid = await bratVid('akugweh hann', {\n  fast_progress: true,\n  theme: 'brat',\n  debugMode: true,\n  lyric: {\n    bpm: 130,\n    maxWordPerLayer: 5,\n    lastFrameDuration: 2,\n  },\n  onProgress: (p) => console.log(`Progress: ${p.current}/${p.total}`),\n  brat: {\n    BLUR: 3,\n    emojiStyle: 'twitter'\n  }\n});\n\nawait writeFile('akugweh.mp4', vid);\n```\n\n## 🛠 Requirements\n * Node.js 18+\n * **ffmpeg** must be installed and available in your system's PATH\n```bash\nffmpeg -version\n```\n","readmeFilename":"README.md"}