One clip · every shape · every platform
Going vertical throws away 68% of a 16:9 frame. Every other tool throws away the middle 68% and hopes. Framelock finds the action first, cuts every shape your destinations actually want, and posts to all of them at once.
Self-hosted and open source. Four destinations work the moment you add credentials — no app review, no subscription.
SOURCE · 2560×1440 · 16:9
Why it matters
The action is left of centre, which is where action usually is — you were tracking someone. Here is what each crop keeps.
What you get from every other scheduler, and from posting a 16:9 file to a vertical feed.
Motion centroid per frame, smoothed, speed-limited, then reduced to a handful of keyframes.
The killfeed is still a casualty — so put it back. Framelock can crop the HUD elements a vertical frame lost out of the original and composite them into the output, in one ffmpeg pass. Your kill counter survives the crop that geometrically deleted it.
Every shape, once
Not one render per platform — one per shape. Deduplicated automatically from whatever you armed.
| Output | Resolution | FPS | Goes to | Why it exists |
|---|---|---|---|---|
| 9:16 | 1080×1920 | 60 | TikTok, Reels, Shorts, Facebook Reels, Threads, Bluesky | The vertical feed shape. |
| 4:5 | 1080×1350 | 60 | Instagram feed, Facebook feed | The tallest the feed allows. Post 9:16 here and Instagram re-crops you, badly. |
| 1:1 | 1080×1080 | 60 | X, Mastodon, LinkedIn | Square survives every timeline layout. |
| 16:9 | 1920×1080 | 60 | YouTube, Telegram, Reddit | No crop at all — the source shape. |
| 16:9 | 1280×720 | 30 | Discord | Exists purely because a webhook caps at 25 MB. |
| 2:3 | 1000×1500 | 30 | The only destination that wants 2:3. |
TikTok, Reels and Shorts each paint a button rail and a caption block over the frame. Framelock shows the dead bands per platform and computes the rectangle that is visible on all of them.
Pick your game and Framelock knows where the HUD lives. Every crop is checked against it across the whole clip — not just frame one — and reports the worst moment.
Box the camera where OBS burned it into the corner and Framelock cuts it back out and re-places it — or upload a separate camera track. Overlay it, or stack it in a band with the gameplay below.
Shorts caps at 60 s, Bluesky at 60 s, Reels at 90 s, TikTok at 10 min. A clip that is too long for one destination is skipped with a reason, not failed after a four-minute encode.
Honest status
Most of the work in a tool like this is not code — it is app review. Here is where every platform actually stands.
| Platform | In v1.0 | What is in the way |
|---|---|---|
| Bluesky | Works today | Nothing. Free, open, no review. Build against this one first. |
| Telegram | Works today | Nothing. Bot token and a chat id. |
| Discord | Works today | Nothing. A webhook URL, and a 25 MB ceiling. |
| Mastodon | Works today | Nothing. Limits vary per instance; Framelock asks the instance. |
| YouTube & Shorts | Implemented | OAuth, plus 1 600 quota units per upload out of 10 000/day. Unaudited apps force uploads private. |
| TikTok | Implemented | Content Posting API audit. Until it passes, every post is locked to SELF_ONLY. |
| Instagram Reels & feed | Implemented | Meta app review, and it fetches media from a public URL rather than accepting an upload. |
| Threads | Implemented | Same Meta review, same public-URL requirement. |
| X | Not yet | OAuth 1.0a signing and chunked upload. X bills per call now rather than $200/month, but a chunked video upload bills every call — initialize, each append, finalize, then the post. |
| Facebook Reels & feed | Not yet | Uses a start/transfer/finish protocol rather than media containers, so it needs its own adapter. |
| LinkedIn · Pinterest · Reddit | Not yet | Each needs its own access upgrade before an adapter is worth writing. |
| Snapchat | Never | No public posting endpoint. Creative Kit only opens the app from a phone. |
| Twitch | Never | Clips are cut from live streams. Nothing accepts an upload. |
Anything that claims to post to Snapchat or Twitch is driving a headless browser session. That breaks on every UI change and gets accounts flagged. Framelock says no instead.
Run it
Node 20+ and ffmpeg on PATH. Nothing else — no database server, no Redis, no native build step.
# install and configure npm install cp .env.example .env # fill in BLUESKY_* or TELEGRAM_* to start # run npm run dev # studio on http://localhost:8080 # the maths is unit-tested without needing a video file npm test # 71 passing
ffprobe reads the real dimensions. A downscaled greyscale pass finds the motion centroid at 8 fps — cheap enough to run on upload.
Every shape previews against your actual video. Drag any crop to override the solver; the framing verdict updates as you drag.
One encode per shape, one upload job per destination, retries with backoff, and a live per-destination status board. Partial failure is expected and survivable.