Skip to main content

shortsmith

Give it a topic, get back a captioned vertical short. On your machine, with no API key.

pipx install shortsmith · try it with nothing installed · docker compose run --rm shortsmith make "your topic"

shortsmith rendering a short in a terminal

A frame from a rendered short Another frame from a rendered short

Real frames, from examples/why-bread-goes-stale.json. Word-level caption highlighting is the karaoke effect — each word lights up as it is spoken.


shortsmith make "why bread goes stale"

Script, narration, backgrounds, word-timed captions, one mp4. It needs ffmpeg and nothing else — no Python dependencies at all, no Pexels key, no cloud voice, no account.

Why another one of these

MoneyPrinter has 45k stars between its two versions and a lot of people who cannot get it to run. The reasons are worth naming, because avoiding them is most of what this is:

Failure What happens here
Needs a Pexels API key for footage Backgrounds are generated by ffmpeg. Nothing to sign up for.
Needs a cloud TTS account Uses whatever speech engine you already have; renders silent with captions if you have none.
Python dependency tree that breaks yearly Zero runtime dependencies. Standard library plus ffmpeg.
One-shot pipeline; a failure at 90% loses everything Every step is cached and resumable. Change one line of narration and only that scene re-renders.
Fails cryptically deep in a filtergraph shortsmith doctor tells you what is missing and what it will cost you, before you spend five minutes.

Try it with nothing installed

shortsmith make "why bread goes stale" --provider offline

offline writes the script from a template rather than a model — no key, no GPU, no network. It is not pretending to write; it exists so you can watch the pipeline work on a clean machine before deciding whether to install anything.

Then check what you have:

$ shortsmith doctor

  ok   ffmpeg   /opt/homebrew/bin/ffmpeg
  ok   captions libass: burned-in, word-timed
  ok   say      Built into macOS. Fine, and already there.

  Script writing:
  ??   ollama   Local. Nothing leaves the machine.
  --   anthropic needs ANTHROPIC_API_KEY
  ok   offline  No model at all: a template.

Writing the script

shortsmith make "why bread goes stale" --provider ollama        # local, default
shortsmith make "..." --provider anthropic                      # needs a key
shortsmith make "..." --provider offline                        # no model at all

The prompt is short and opinionated, because a model asked for "a script about X" reliably writes an intro, and an intro is the one thing a short cannot afford. It asks for a hook under 12 words, no "in this video", numbers spoken as words, and nothing invented — if the model is unsure of a figure, leave it out.

Then it checks its own work:

  hook  Bread does not dry out. It recrystallises, which is why the freezer fixes it.
     2  Starch molecules that were loose after baking slowly line back up.
   ...

  Worth a look:
    · scene 3 contains "in this video", which wastes the hook
    · about 78s of narration; shorts are capped at 60

Split the two steps to edit in between — which is the point:

shortsmith script "why bread goes stale" -o bread.json
$EDITOR bread.json
shortsmith render bread.json

Narration

Speech engines are probed in order of quality and every one is optional:

Engine Notes
piper Neural, local, genuinely good. The one to install.
edge-tts Microsoft's voices. Free, but it is a network call.
say Built into macOS. Already there.
espeak-ng Robotic, works everywhere, needs nothing.
shortsmith make "..." --tts piper --voice ~/voices/en_GB-alba-medium.onnx
shortsmith make "..." --tts none          # silent cut, captions only

If none is installed the video still renders — silent, captioned, and the tool says so. That is more useful than refusing to run.

Every clip is loudness-normalised to −16 LUFS. A short that is quieter than the one before it in the feed gets scrolled past.

Backgrounds

Five styles, all generated by ffmpeg filtergraphs: gradient, drift, grain, pulse, solid. Each scene gets a different one, deterministically, so a rerun does not silently change the look.

The palettes are not decorative choices. Every one has an ink colour that clears 7:1 against both ends of its own gradient, and there is a test that fails if one does not — because a caption you cannot read at 60% phone brightness is a caption that did not exist.

shortsmith make "..." --style grain      # force one
shortsmith make "..." --music bed.mp3    # ducked under the narration

Music is sidechain-compressed against the voice track, which is the difference between "has background music" and "you can hear the narrator".

Captions

ASS subtitles with per-word karaoke timing, burned in. Word timing is weighted by length rather than split evenly — "the" and "extraordinarily" do not take the same time to say, and an even split visibly drifts by the end of a sentence.

An .srt and the .ass are written next to the video either way. Every platform accepts an .srt on upload.

Resumable

out/
  bread.mp4
  bread.ass
  bread.srt
  .bread/
    manifest.json      what has been built, and from what
    audio/             one wav per scene
    scenes/            one mp4 per scene

Each step records a fingerprint of its inputs. Rerun after editing scene 3 and scenes 1, 2, 4 and 5 are reused untouched — including their narration, which is the slow part.

Two things that will bite you, and what to do

Your ffmpeg may not be able to draw text. Plenty of builds ship without libass and libfreetype, and captions are most of what a short is. doctor says so up front, the render continues without burned-in text, and the sidecar files are written so you can burn them in later:

ffmpeg -i out.mp4 -vf subtitles=out.ass final.mp4

Fonts are resolved to a file path, never a family name. drawtext=font=Arial asks fontconfig to find it, and on a machine with no font cache — a static build, a fresh container, a CI runner — that can take minutes or hang outright. It cost an afternoon to find. shortsmith searches the standard directories itself and always passes fontfile=.

Options

--provider ollama|anthropic|openai|offline
--model <name>
--scenes <n>                    how many beats (default 5)
--preset vertical|square|horizontal|vertical-fast
--fps <n>
--tts auto|none|piper|edge-tts|say|espeak
--voice <name or model path>
--rate <wpm>
--music <file>  --music-gain <0-1>
--style gradient|drift|grain|pulse|solid
--font <name or path>
--no-captions  --no-on-screen
--crf <n>                       quality; lower is bigger and better
--project <dir>                 where the working files live

What this will not do

  • It will not upload for you. Automated posting is how accounts get banned, and an OAuth token in a config file is a liability. The mp4 and the caption files are yours to post.
  • It will not scrape stock footage. No Pexels key required means no Pexels terms to violate.
  • It will not make you money. It makes a video. What you put in it is the entire variable, and no tool can supply that.

Contributing

pip install -e ".[dev]"
pytest

54 tests. The ones needing ffmpeg skip cleanly without it, so pytest is still useful on a machine that has none.

Most useful contributions, in order:

  1. A background style. One function in visuals.py returning a filtergraph.
  2. A speech engine. One branch in tts.py.
  3. An ffmpeg build it breaks on. Those are the real bugs — see the two above.

MIT. Fork it, rename it, ship it.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

shortsmith-0.1.0.tar.gz (348.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

shortsmith-0.1.0-py3-none-any.whl (32.8 kB view details)

Uploaded Python 3

File details

Details for the file shortsmith-0.1.0.tar.gz.

File metadata

  • Download URL: shortsmith-0.1.0.tar.gz
  • Upload date:
  • Size: 348.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for shortsmith-0.1.0.tar.gz
Algorithm Hash digest
SHA256 52c917cedbbbe7aba81c264174609d660d6b2f2cf0a519d02eba476549c5633a
MD5 140ca0f83a62e7abb1523e5c03653e40
BLAKE2b-256 187af4838a2009635e45de843c804020429ac4a6928f38a79da61ce7625c671e

See more details on using hashes here.

Provenance

The following attestation bundles were made for shortsmith-0.1.0.tar.gz:

Publisher: release.yml on mohitagw15856/shortsmith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file shortsmith-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: shortsmith-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 32.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for shortsmith-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4593e0dda31cb5274239c6663c11faf62bb86650ca52697f0df8e3bf3a17050f
MD5 8c6e506da09d64de9a1c0c311ef2869c
BLAKE2b-256 7856e2a1ee0d578411c83a625dbb61ff6e4743c813626418e817697809c400f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for shortsmith-0.1.0-py3-none-any.whl:

Publisher: release.yml on mohitagw15856/shortsmith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page