We Built a Loom Replacement Into Loadout
Why we stopped paying for Loom and built a self-hosted video posting system with auto-generated intro slides, FFmpeg processing, and zero external dependencies.
We Built a Loom Replacement Into Loadout
Loom is great. You record a video, share a link, people watch it. Simple.
But we were paying for something we could build ourselves, and more importantly, we wanted videos to live on our platform -- not on someone else's. When a client clicks a video link, we want them on loadout.ca, not loom.com.
So we built it. Including the screen recording.
What Loom Does (That We Actually Use)
Let's be honest about what we needed from Loom:
- Record your screen
- Upload or share the recording
- Show a nice thumbnail/preview
- People watch it in a browser
That's it. We weren't using Loom's editing tools, viewer analytics, CRM integrations, or team features. We were paying for a video hosting service with a pretty player and a screen recorder.
What We Built
A full video system inside the Loadout Rails app: screen recording in the browser, upload processing, auto-generated intro slides, and a public video gallery. One model, one service, one background job, and some FFmpeg magic.
Screen Recording (The Loom Killer)
This is the part that actually replaces Loom. We built a browser-based screen recorder using the MediaRecorder API and getDisplayMedia.
When you hit "Record" in the admin panel, the browser prompts you to share your screen (full screen, window, or tab). The recording captures directly in the browser -- no plugins, no extensions, no desktop app. When you stop recording, the video is uploaded directly to Loadout as a new Video record.
It works in Chrome, Edge, and Firefox. Safari support is limited (Apple's implementation of getDisplayMedia is still catching up), but for our use case -- recording tutorials and walkthroughs from a dev machine -- Chrome covers it.
The recording captures at whatever resolution your screen runs at. For most of us, that's 1080p or higher. The output is WebM (Chrome) or MP4 depending on the browser, and our processing pipeline handles both formats.
No Loom extension. No desktop app. No monthly subscription. Just click a button in your browser and start recording.
The Video Model
The core is simple: a Video record with ActiveStorage attachments.
- video_file -- The actual video (MP4, MOV, WebM, AVI, up to 2GB)
- thumbnail -- Auto-extracted first frame
- intro_slide_image -- Auto-generated composite image (this is the cool part)
- avatar_image -- The creator's profile photo
Plus metadata: title, description (markdown), category, featured flag, publication date, and a slug for clean URLs.
Categories keep things organized: general, tutorial, case-study, interview, behind-the-scenes.
Auto-Generated Intro Slides
This is the feature that made the whole thing worth building.
When you upload a video to Loom, the thumbnail is whatever frame happened to be showing when you started recording. Usually it's your desktop, half-loaded, with Slack notifications visible. Not great.
Our system generates a professional intro slide automatically. Here's what happens after you upload (or finish recording):
- FFmpeg extracts the duration from the video file
- FFmpeg grabs the first frame as a thumbnail
- The IntroSlideGeneratorService kicks in:
- Downloads a background image from Unsplash (you provide the URL)
- Downloads the creator's avatar image
- Composites the avatar as a circle (120px) in the top-left corner
- Overlays the video title in large white text (64px, bold, with drop shadow) next to the avatar
- Adds a duration badge in the bottom-right corner with a semi-transparent background
- Saves the final 1920x1080 composite as a JPEG
The result is a clean, branded preview image that looks like it was designed in Figma. Generated automatically from the title, avatar, and a background image. No design work required.
The Processing Pipeline
After a video is saved (whether from screen recording or file upload), a VideoProcessingJob fires via after_create_commit. The whole pipeline takes 15-30 seconds:
- Intro slide generation: 5-10 seconds
- Thumbnail extraction: 2-5 seconds
- Duration extraction: near-instant
When you update the title or swap the background image, the system detects that intro slide inputs changed and regenerates it automatically.
The Player
Nothing fancy. HTML5 video tag with native browser controls. The intro slide serves as the poster image, so before anyone hits play, they see the branded slide instead of a random frame.
Videos are served directly from ActiveStorage. No CDN, no transcoding service, no external dependency. For our use case (sharing tutorials and case studies with clients), this is more than enough.
Social Sharing
Each video page includes share buttons for Twitter/X, Facebook, LinkedIn, and a copy-to-clipboard link. The intro slide doubles as the Open Graph image, so when someone shares a video link on social media, it shows the branded preview.
The Admin Interface
Videos are managed through the existing Loadout admin panel:
- Record -- Hit the record button, share your screen, stop when done
- Upload -- Drag-and-drop for pre-recorded files
- Edit metadata (title, description, category)
- Preview the generated intro slide
- Download the intro slide as a JPEG (useful for social posts)
- Publish/unpublish with date control
The Public Gallery
The videos page shows a grid of intro slide thumbnails with a hover effect (play button overlay). Click to watch. Each video page shows the player, description, metadata, and share buttons.
Clean URLs via slugs: loadout.ca/videos/building-a-shopify-sync-engine instead of loadout.ca/videos/124.
Dependencies
The whole thing runs on:
- MediaRecorder API -- Browser-native screen recording (no plugins)
- FFmpeg -- Video processing, duration extraction, thumbnail generation
- ImageMagick (via MiniMagick) -- Image composition for intro slides
- HTTParty -- Downloading Unsplash backgrounds and avatar images
- ActiveStorage -- File storage and serving
All standard tools. FFmpeg and ImageMagick were already installed on our server. The screen recording runs entirely client-side in the browser. Zero new infrastructure.
The Numbers
- Models: 1 (Video)
- Services: 1 (IntroSlideGeneratorService)
- Background jobs: 1 (VideoProcessingJob)
- External services: 0
- Monthly cost: $0 (runs on existing server)
- Previous Loom cost: $15/month per user
Why This Works For Us
We're a small team. We share maybe 5-10 videos a month with clients. Loom's collaboration features, analytics, and team management were overhead we didn't use.
What we did want was brand consistency and screen recording without a subscription. Every video link goes to our domain. Every preview image has our look. Every share on LinkedIn shows our branding, not Loom's. And we can record our screen without installing anything or paying anyone.
For a solo dev or small agency, building this takes a day. The screen recorder is about 50 lines of JavaScript using standard browser APIs. The intro slide generator is about 80 lines of Ruby with MiniMagick.
Sometimes the best SaaS replacement is a few hundred lines of code in your existing app.
Built into Loadout. Want a self-hosted video and screen recording system for your Rails app? Let's talk.
FREE Shopify Product Migration
Moving to Shopify? We'll migrate your product catalog for free. New stores only.