Speech Bubbleinator: Encoding to Fit a Hard Ceiling
A Discord bot that overlays a speech bubble on any image, GIF or video the user can point at. Every upload has to land under the server's tier limit, so the encoder negotiates quality downward until the file fits instead of failing.
- 4-step progressive encode ladder
- Media resolved through a 6-step fallback chain
- Hard timeouts: 15s fetch · 45s ffmpeg
- TypeScript
- Bun
- discord.js
- sharp
- ffmpeg
The problem
Two constraints fight each other. Discord rejects an upload over the server’s tier limit, and the same overlay job produces wildly different file sizes depending on whether the input is a 200 KB still, a twelve-second GIF or a phone video. A single fixed encoding setting either wastes quality on small inputs or fails outright on large ones.
The approach
The bot treats the size limit as a budget to negotiate. It reads the guild’s premium tier, encodes at the best profile, and if the result overshoots, re-encodes at the next step down (dropping FPS, scale and color count for GIFs, raising CRF for MP4s) up to four attempts.
Getting the media at all is its own problem: users paste links as often as they attach files. The resolver walks attachments, explicit URLs, Open Graph meta tags up to three redirects deep with loop detection, embeds, links in the message body, and finally the replied-to message. Every fetch carries a 15-second timeout and every ffmpeg process a 45-second one, so a hostile input stalls one job rather than the bot.
The outcome
Any media a user can reference comes back bubbled, under the limit, in the right format for its type, and the original trigger message is cleaned up behind it.