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

shorts-maker

v0.4.0

Published

Split a video into consecutive shorts titled from its name, add hashtags, and publish them to Facebook — runs locally in your browser.

Readme

shorts-maker

Split a long video into consecutive parts — the whole thing, in order, cut on natural pauses — each titled Main Title part-N #hashtags, ready to post as a series to YouTube / Instagram / TikTok.

TypeScript on Bun with a React + Tailwind v4 frontend that Bun bundles and hot-reloads itself — no Vite, no webpack, no PostCSS. No AI, no accounts. The only runtime binary it shells out to is ffmpeg; a 90-minute video processes in seconds.

How it works

video ──► find pauses (ffmpeg silencedetect) ──► split into parts ──► cut (stream-copy) ──► parts/ + captions
  • Every second is covered — parts are contiguous from 0:00 to the end. No highlight-picking.
  • Cuts land on a pause, so parts don't end mid-sentence. (Stream-copy snaps to the nearest keyframe, so a cut may shift a second or two.)
  • Part length is a cap, not a quota — a 15-min target splits a 96-min video into 7 parts of ~14 min each (evenly), not 6 full 15-min parts plus a 6-min stub. If even parts would come out under ~12 min, one part is dropped and the rest stretch a little to absorb it.
  • Titles = the video name (auto-derived from the file, editable in the form) + part-N
  • Your source is already 1080×1920 (9:16 vertical), so no cropping is needed.

Quick start

You need two things on your machine: Bun and ffmpeg.

curl -fsSL https://bun.sh/install | bash   # Bun (skip if installed)
brew install ffmpeg                         # ffmpeg — macOS; use your package manager elsewhere
brew install yt-dlp                         # optional — only to import from a video link

yt-dlp is only needed if you paste a link (YouTube, Dailymotion, or a direct video URL) instead of uploading a file.

YouTube “Sign in to confirm you’re not a bot”? YouTube blocks some anonymous downloads. Point the app at your browser’s login: bunx shorts-maker --serve --cookies-from-browser chrome (or safari / firefox / edge / brave), or set SHORTS_MAKER_COOKIES_FROM_BROWSER=chrome. Failed link jobs also retry automatically through alternate players before giving up.

Then run it straight from npm — no clone, no install step:

cd ~/videos                  # any folder — this is where output/ and config/ will be written
bunx shorts-maker --serve    # → http://localhost:4321   (bare `bunx shorts-maker` prints help)

--serve starts the app from your current folder: generated clips land in ./output/, staged uploads in ./uploads/, and your saved credentials in ./config/. Run it wherever you want that data to live.

shorts-maker --serve [options]

  -s, --serve       Start the web app (required — nothing runs without it)
  -p, --port <n>    Port to listen on            (default 4321, or $PORT)
  -d, --dir <path>  Folder to read/write data in (default: current folder,
                                                  or $SHORTS_MAKER_DIR)
  -v, --version     Print the version and exit
  -h, --help        Show this help and exit

From source

git clone https://github.com/subasshrestha/ShortsMaker && cd ShortsMaker
bun install
bun dev        # development  →  http://localhost:4321  (hot reload / React Fast Refresh)
bun start      # production   →  builds dist/ then serves the optimized bundle

At runtime it needs Bun + ffmpeg; everything else is bundled.

Using the app

The same server process serves both the React app and the API — one port, no second dev server.

  • Pick a source three ways: upload a video (click or drag-and-drop, with a live progress bar), paste a link, or choose one you already have under From uploads.
  • Sources are kept, not thrown away. Everything you upload — and every video fetched from a link — lands in uploads/ and stays there, so you can re-split it without re-uploading or re-downloading. Manage them right in the From uploads tab: each entry shows its size and date, with a trash icon to delete it and a Clear all to empty the folder. Deleting a job never deletes its source video.
  • The title auto-fills from the filename; adjust it, plus part length, hashtags-per-part, and the hashtag pool (pre-filled from hashtags.txt) — all from the form.
  • Hit Split and watch the logs stream live.
  • Every run is saved in the History sidebar — it survives refreshes and restarts. Click a job to replay its logs, preview each part inline, copy captions, download clips, reveal a clip in Finder (when running locally), or delete the whole run (files included).

Output

Each run lands in its own folder under output/:

output/<name>__<timestamp>/
  parts/
    01_hacker-vs-coder.mp4
    01_hacker-vs-coder.txt   # "Hacker VS Coder part-1 #tags" — paste-ready caption
    02_...
  manifest.json              # every part with timestamps + caption

Hashtags are drawn from hashtags.txt — one per line, # lines are comments. Edit that file to fit your niche.

Publish to social media

Each finished part card has a one-click Publish button. Facebook Pages are supported today (more platforms are planned — the code is structured to drop them in). Uploads use Facebook's chunked video upload (upload_phase start → transfer → finish), with resume + retry and a live progress bar on the card.

  1. Open Settings (gear in the sidebar) → Facebook Page, and follow the built-in Setup guide to get a Page ID and a long-lived Page Access Token.
  2. Paste them in and Save — it verifies with Facebook first and only stores if it works. (Test connection also checks that the token has the pages_manage_posts permission.)
  3. On any part card, hit Publish to Facebook. The clip is uploaded to your Page with its caption; the card then shows Posted ✓ with a link, and remembers it.

Credentials are stored locally in config/social.json (gitignored) and are never returned to the browser or sent anywhere except Facebook's Graph API.

Project layout

src/
  cli.ts              # `shorts-maker` command: --help/--version/--port/--dir, then serves
  server.ts           # Bun.serve: React app (dev bundler / prod dist) + REST/SSE API
  build.ts            # pre-builds frontend → dist/ (Bun.build + Tailwind plugin)
  paths.ts            # package-asset dirs vs. the user's data dir (cwd)
  files.ts            # shared fs helpers (safeJoin, uniqueName, video extensions)
  jobs/
    store.ts          # job registry — SQLite (bun:sqlite, output/jobs.db) + SSE subscribers
  pipeline/
    pipeline.ts       # orchestration (probe → pauses → split → cut → titles)
    media.ts          # ffprobe/ffmpeg wrappers (probe, silence detect, cut)
    parts.ts          # part model + splitter
  social/
    config.ts         # credential store (config/social.json)
    facebook.ts       # Graph API verify + video upload
frontend/
  index.html          # entry — Bun bundles main.tsx from here
  main.tsx            # React mount + BrowserRouter
  App.tsx             # routes + app-shell layout
  styles.css          # Tailwind v4 entry: @import + @theme design tokens
  pages/              # routes: NewSplitForm, JobDetail, Settings, Guide
  components/         # shared: Sidebar, Brand, Dot, Icons, ConfirmDialog
  lib/
    api.ts            # typed fetch helpers (+ streaming upload)
    util.ts           # formatting helpers
    types.ts          # shared Job/Part types
bunfig.toml           # registers bun-plugin-tailwind for the dev bundler
hashtags.txt          # default hashtag pool (a hashtags.txt in your run folder overrides it)