Video hosting for marketing: a player you control, heatmaps of who watched what, email capture inside the video and integration with marketing tools.
Build me video hosting that replaces Wistia — and know why this is ALMOST. The player and the delivery are ordinary work with existing pieces. What you are paying for is **engagement data per viewer**: who watched, how far, how many times, tied to a person in your marketing system. That is buildable, and it is also the part that deserves the most thought — because it is a record of individual attention, and treating it casually is how a marketing tool becomes a privacy problem. STACK - Node 20+ with Fastify, server-rendered HTML - SQLite through better-sqlite3, WAL mode - ffmpeg on a worker for transcoding - Object storage with a CDN in front - Caddy in front THE DATA MODEL - videos: id, slug, title, description, source_path, sha256, duration_ms, width, height, poster_path, status, created_at - renditions: id, video_id, height, bitrate, codec, path, bytes, status - captions: id, video_id, language, vtt_path, is_edited, is_machine - embeds: id, video_id, domain_allowlist_json, player_config_json - sessions: id, video_id, viewer_hash, identified_email_hash, started_at, ended_at, referrer_host, country, device, bot - heartbeats: id, session_id, position_ms, at — sampled every few seconds, which is what makes a real engagement curve possible - events: id, session_id, kind, position_ms, at — play, pause, seek, complete, rate change - gates: id, video_id, position_ms, kind, config_json — an email form or a call to action shown at a point in the video - captures: id, gate_id, session_id, email, created_at - Everything computed at query time from heartbeats. No stored totals DELIVERY - A ladder of renditions packaged as HLS so the player adapts to the connection. Transcoding is CPU-hours per video; queue it with a concurrency cap - Keep the original untouched, always - A CDN in front. Serving video from one machine is the mistake that makes everything feel slow, and it is the part money genuinely solves - Signed, expiring playback URLs where the video is not meant to be public, with the manifest and the segments both protected - A domain allow-list per embed, checked on the manifest request, so your video does not end up playing on somebody else's site THE PLAYER - Built on the browser's own video element with an HLS library. Do not write a player - Your colours, your logo, and no upstream branding - Captions on by default where they exist, a poster frame, keyboard controls, and a plain fallback for anything that cannot play HLS - Under 40KB and lazy: nothing loads until the player is near the viewport or clicked - Playback speed, quality selection, and a chapter list from a chapters file ENGAGEMENT, WHICH IS THE PRODUCT - Heartbeats every few seconds give you the curve: what proportion of viewers were still watching at each moment - That curve is the useful output. The drop at 0:20 tells you the opening is too long, and no total ever will - Rewatches: a segment watched twice by the same session, which is usually where the video was unclear - Play rate — plays over impressions — and completion, both with their definitions written beside them - Per video, per referrer, per country, computed from rows THE IDENTITY QUESTION, HONESTLY - A viewer is a salted hash of address and user agent unless they identify themselves - Identification happens when somebody submits an email gate, or when your own site passes a signed identifier for a known contact. Then earlier sessions from that hash can be attributed to them - **Be deliberate about this.** Knowing that a named person watched ninety seconds of your video is more intimate than most marketing data, and using it carelessly — quoting it back at them, scoring them without their knowledge — is the thing people find unsettling - Say in your privacy notice, in plain words, what is recorded and what it is used for - A retention on session-level data, enforced by a sweeper, with aggregates surviving - No third-party requests from the player, ever GATES AND CALLS TO ACTION - An email form at a chosen point, skippable or not — and if it is not, say so before the video starts rather than trapping somebody halfway - A call to action at the end with a link - Every capture recorded with the session, so 'which video produced this subscriber' is answerable OPERATIONS - .env: DATABASE_PATH, STORAGE_PATH, BASE_URL, SESSION_SECRET, CDN_URL, HASH_SALT, RENDER_CONCURRENCY - Migrations on boot, each once; measure bytes and egress per video, because that is the bill - Nightly backup of the database and the sources; renditions are regenerable - Health endpoint reporting queue depth and free disk WHAT MATTERS MOST The engagement curve and restraint about identity. The curve is why this beats a free video host; the restraint is what keeps it something you would be comfortable explaining to the person being measured.
What you lose
- Per-viewer engagement heatmaps showing exactly where people stopped watching
- A player with your branding, no recommendations and no advertising
- Transcoding into a resolution ladder with adaptive streaming, which is real infrastructure
If you would rather not build
- Mux, if you want the transcoding as a service
- ffmpeg plus object storage and a CDN
What it costs
read from their page 15 Aug 2026
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $79/mo | — | 15 Aug 2026 |
Their pricing page is where these came from. Seeing a different price? Tell us.
The escape hatch
open source · no votes, no paid placement
PeerTube
$0Self-hosted video with transcoding and a player already built.
Chocobozzz/PeerTubefree · open source
hls.js
$0Plays adaptive streams in browsers that do not support HLS natively.
video-dev/hls.jsfree · open source
Why this verdict
our own opinion · changed only by a person
52/100
Verdict kinda at 52. ffmpeg and HLS are well documented; the storage and bandwidth are what make hosting video yourself less cheap than it looks.
History
tracked since 10 Aug 2026 · nothing is ever overwritten
Questions about Wistia
answered from the record above
Is Wistia free?
No — the plan we track is $79 a month. Business at $79/month with 250 GB of storage; the lead-generation tier is $329. A free tier covers ten videos.
Can you replace Wistia by building your own?
ALMOST. A weekend of work, and real gaps remain. Replacement score 52 out of 100, build time a weekend. Read what you lose before you decide.
How much does Wistia cost?
$79 a month on Plus — $948 a year. Recorded 14 Aug 2026.
What do you lose by replacing Wistia?
Per-viewer engagement heatmaps showing exactly where people stopped watching; A player with your branding, no recommendations and no advertising; Transcoding into a resolution ladder with adaptive streaming, which is real infrastructure. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Wistia?
Yes: PeerTube, hls.js. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

