Changelog¶
2026-07-06¶
- Rate-limit information now comes back as standard
X-RateLimit-*headers. Every API response used to carry a singleRATE_LIMITheader holding a JSON object — a shape no generated SDK could read as typed values and that no other API returns. It's now split into the conventional scalar headers:X-RateLimit-LimitandX-RateLimit-Remainingon every response (plusX-RateLimit-Concurrent-LimitandX-RateLimit-Concurrent-Remainingon endpoints that cap concurrency), so any HTTP client or SDK can read them directly. A429 Too Many Requestsadditionally returnsX-RateLimit-Reset(Unix time when the window resets) and a standardRetry-After, which most HTTP libraries honour automatically. See Limits.
2026-07-05¶
- Every video now carries a
previewreel URL — and public videos get a shareable one that never expires. The short hover-preview reel — moments sampled from across a video and played back-to-back, generated on the fly from its existing segments with no extra encoding or storage — is now apreviewfield on every video the API returns from Get video and List videos, instead of a separategetVideoPreviewrequest. For public videos thepreviewURL is fixed and never expires — its access token lives in the path, so it's unguessable yet cacheable at the CDN and safe to hand to any HLS player or drop straight into a page; private videos keep a signed, expiring URL.previewisnullwhile a video is still uploading or is audio-only. The reel uses sensible defaults for now; options to customize its length and sampling will return in a later release. The standaloneGET …/video/<id>/previewendpoint has been removed. See Hover Previews.
2026-07-03¶
- The embed-code dialog now shows the code up front — and copies with one click. Opening Embed for a video used to show an empty box and a "Get embed code" button; now the code is generated the moment the dialog opens and updates instantly as you change options, shown on a dark panel with its URL highlighted. A small thumbnail, title and details (duration, resolution, and whether it's public or private) tell you exactly which video you're embedding, and private videos get a clear note that the code carries their access token. Sizes are one-click pills — including a new Responsive option that scales to fit any page (what YouTube and Vimeo hand out) — and a single Copy code button replaces the manual "copy the code above".
- Upload from a list of URLs, and get an honest report. The video-upload page got a visual refresh — the drop area (and the new URL box) are now a clean dark “stage”, the two tabs became pills, and the per-upload settings read more clearly. Bigger change: “From a URL” now takes many links at once — paste one URL per line and each becomes its own video. After you fetch, a Fetch results card shows exactly what happened: an Added to your library list (each linking to its video) and, when some links don't work, a Couldn't be fetched list with the reason for each and a “Put back in form” button to fix and retry. A single URL still works exactly as before.
- The Player editor's settings and preview now match its polished logo panels. The Player settings and Player preview cards were still the old plain style while the three logo uploaders had already been refreshed; they now share the same look — a labelled icon, a one-line description, solid inputs, and a Save changes button — so the whole Player Edit page reads as one consistent design. Nothing about what the settings do changed.
- The Billing page got a clearer redesign. With a subscription, your plan now sits on a dark hero banner showing the price, when it renews ("Renews Jul 12 — in 12 days"), and since when you've been subscribed — with an Active status dot, or a clear prompt to update payment if something's wrong. Storage has a status-coloured bar that warns as it fills, and this billing month's usage is three clean tiles — Bandwidth, Encoding and AI generations, each marked Unlimited and linking to Analytics for the full breakdown. Without a subscription, the pricing page is now “Pick your storage”: every plan leads with how much you host (bandwidth, encoding and AI are unlimited on all of them), the shared features are listed once underneath, and the popular plan stands out on-brand instead of stock blue.
- Switch between projects right from the sidebar. The top of the sidebar now shows the project you're in — its initial, name, and your role — and clicking it opens a project switcher listing every project you can access, with All projects and New project shortcuts. Switching used to mean going back to the dashboard and finding the card. The sidebar is also clearer about scope: a Project section (Videos, Players, Users, Statistics, Settings) and an Account section (All projects, Analytics, Invitations, Account) are always labelled — and the project section now stays visible on account pages, so your project is always one click away. ("Dashboard" is now named All projects, which is what it always was.)
- The Analytics page now surfaces your processing & AI usage. Below delivery and storage, a new section shows what your account asked the pipeline to do: tiles for Encoding hours (with rendition and video counts), AI captions, AI translations, and AI chapters — each with its trend — plus a Processing activity chart (encoding hours per day and AI generations per day) and an AI languages breakdown of the caption and translation tracks you've generated. It's all drawn from usage your account already records; an account that hasn't used encoding or AI simply won't see the section.
- The account Analytics page is clearer and no longer mixes two scales on one chart. The bandwidth-and-storage chart used to plot a per-day flow (bandwidth) and a running level (storage) on two different y-axes in the same plot — a misleading overlap. They're now two stacked panels in a Delivery & storage card, each with its own scale. Above them sit three at-a-glance tiles — Bandwidth served (with the change vs the previous period), Storage today (and how much it grew), and your Busiest day — and the filters moved to a row on top with one-click 7d / 30d / 90d presets. Same numbers, just far easier to read.
- The video Edit page is easier to scan and act on. Each collapsible panel now has an icon and a one-line description, and shows a count at a glance — how many Posters and Downloads you have, how many Captions (with a "1 processing" flag while AI captions generate), and so on. The three creation tools (Create clip, Duplicate video, Swap video) are grouped under a Tools heading at the bottom. On the right, the preview and the video's details are now one card: the player at the top, then a Ready / Public status line, a clean list of facts (duration, created, source resolution & codec, storage, the exact renditions viewers get, and the video ID with a copy button), and Embed / Stats / Download buttons, with a quiet Delete video at the very bottom. Nothing you can do changed — only how it's laid out.
- The project Statistics page is now a proper analytics dashboard. The filters moved out of the side panel into a row at the top — one-click 7d / 30d / 90d presets beside a date picker that applies as soon as you pick a range. The headline tiles lost their coloured strips for a calmer look. The main chart now shows views and plays at full scale (watch time gets its own small panel beneath, so counts and minutes no longer fight over one axis) with a dashed previous-period line so you can see whether this week is normal. The completion funnel is a card of its own — each stage shows how far plays get and the drop-off to the next. Top videos now show a thumbnail and a bar you can compare at a glance, top countries show a flag, and big watch-time numbers read in hours. Nothing about how stats are collected changed.
- The Invitations page is clearer about what you're accepting. Each project you've been invited to is a row with the project's initial on a dark tile, its name, and who invited you ("Invited by …"), with a blue Accept invitation and a plain Decline beside it. A one-line note explains that accepting gives you access to that project, and when you have no invites you get a tidy "No pending invitations" message instead of a bare sentence.
- The project's Users page now reads like a team roster. Each member is a row with an avatar (their initial, tinted by state), their email, and their role — including your own row, marked "· you". A quiet badge shows whether they're Active, a Pending invite, or Inactive, and the member count sits at the top ("4 members in this project"). Suspending someone is now a subtle icon instead of a loud red button on every row, while reactivating a suspended member stays a clear Enable access button. The invite page is simpler too — one email field with a note that they'll get an invitation link. Who can do what is unchanged.
- The Players page now shows what each player looks like. Instead of a plain table of names, every player is a card that opens with a little preview of that player's own configuration — drawn live from its settings: whether it shows a title bar, your logos placed in the corners you chose, and a control bar with a play button and progress bar. A minimal player shows a bare frame; a branded one shows its logos where they'll appear. Below the preview: the player's name (with a Default tag on your project's default), its description, and an Edit player button. A dashed Add a player card ends the grid. The dead, permanently-disabled delete button is gone.
- Your projects are now a visual grid instead of a table. The account's All projects page shows each project as a card — a dark tile with the project's initial, its name, and its video count — with a big Open button plus quiet gear (settings) and trash (delete, for projects you administer) icons. A dashed Create a new project card sits at the end of the grid, and stands in as a friendly empty state when you have none. The old page's three loud ALL-CAPS buttons per row are gone; nothing about the projects themselves changed.
- The Webhooks page now tells you which endpoints are healthy. Each webhook is shown as a row with its URL, when it was added, and — the important part — a health badge: a green Healthy, or a red Failing since
· N retries when we've been unable to reach it. A broken integration finally announces itself instead of failing silently. The page also explains itself in one line ("Video lifecycle events are sent as JSON POSTs to every URL below."), the Add webhook button moved to the top, and the add form has a clearer prompt, an example URL, and an Add webhook button. Delivery and retries work exactly as before. - The Watermarks page now shows each watermark, not just its numbers. Instead of a table of raw values, every watermark appears as a preview on a dark video-like stage — your logo sits exactly where it will on the frame (corner or centre), at its real size and opacity — beside its name and a plain-language summary ("Lower right · 80% opacity · 15% scale · 5% padding"). The name links out to the full-size image, delete is a quiet trash icon, and an empty project gets a friendly prompt to add one. The Add watermark button moved to the top of the page, and the create form leads with a short explanation and a Create watermark button. What watermarks do is unchanged — you can just finally see them.
- API keys are easier to match and manage. The account's API keys page now shows each key's key ID in the list — the same value your API client puts in its config — so you can tell which row a given server is using, next to its label and creation date. The meaningless always-"Active" status column (keys can't be set to anything else) is gone. Creating a key is tidier too: its fields read Label / Key ID / Key secret (in monospace, with copy buttons) and the button is now Save API key. Nothing about how keys work changed.
- The Account settings page has been redesigned. It's now two clear cards side by side: Profile — your Gravatar avatar, the email you sign in with, and your Country (used on invoices and for VAT) — and Password, with Current / New / Confirm fields and a strength hint. Each card has its own Save profile / Change password button. Labels are sentence case and inputs match the rest of the dashboard. New passwords now need at least 8 characters (up from 6). The New project page got the same treatment: a single focused field with a one-line explanation of what a project is.
- The project Settings page is reorganized and explained. The eight settings that used to be one long, unlabeled list are now grouped into cards — Project (name, description, timezone), Playback (published, default player) and Encoding defaults (encoding tier, auto-generate captions, keep originals) — and every setting carries a one-line note on what it does ("Unpublishing blocks playback of every video in the project.", "Used for statistics day boundaries.", and so on). Deleting the project now has a clear home here too: a Delete this project box at the bottom of the Project card (visible to the project owner). The settings themselves are unchanged — only how they're laid out and described.
- Delete and access-change confirmations now show what you're about to do — and let you cancel. The pages that confirm a deletion (a video, project, watermark, webhook, caption track or API key) or a team access change (suspend or enable a member) used to be near-empty: a bare title and a red button, with no way out except the browser's Back button. Each now leads with what is affected — a video on its thumbnail with its duration, resolution and size; a project by its initial; a webhook by its URL; a teammate by their avatar — states the consequence in one plain sentence ("…and every embed of it stops playing immediately."), and adds a Cancel button beside the action. What the buttons do is unchanged; it's just clear what you're confirming, and easy to step back.
- The Videos page has a new gallery view — and it's the default. Your library now opens as a grid of large thumbnails (like a video platform's library) instead of a table: six across on a wide screen, each tile showing the poster with the duration in the corner, a lock chip on private videos, and the hover preview playing right on the tile. Hovering also reveals quick actions (edit, embed code, analytics), and a ⋮ menu on every tile carries the full set including delete. The familiar list view is one click away via the list/grid toggle at the top of the page, and the page remembers which view you prefer. See The Videos page.
- Select several videos and act on them at once. In the gallery view, tick the checkboxes that appear on tiles (or Select all in the header) and a floating bar offers Make public, Make private, and Delete for the whole selection — with a confirmation step before anything is deleted. Until now visibility and deletion were one-video-at-a-time. See The Videos page.
- The videos list is easier to scan. The list view's thumbnails now double as status: a video that's still encoding shows a spinner on its dark tile, a waiting upload shows an upload glyph, and a failed one is tinted red with a warning mark — visible at a glance, before you read any badge. Rows also gained the video's resolution ("4K", "1080p", …), visibility became a quiet icon next to the other facts instead of a second colored badge, and the search, visibility and status filters moved from the side panel to a bar at the top of the page, where the visibility/status dropdowns apply immediately on change (no Search button). The pager now says how many videos are on the page, with labeled Previous/Next buttons.
- Clip metadata is now honest about what a clip can control. The
clip/fastclipendpoints used to accept the full upload metadata object — includingsize,watermark_id,encoding_tier,normalize_audio— and silently ignore all of it: a clip's media derives from the source's already-encoded renditions, so those settings can't be chosen per clip. The clip request now documents only what applies (title,public), the clip inherits the source video's watermark, encoding tier, and audio-normalization metadata, and the dropped fields are still tolerated in requests so existing API clients keep working unchanged. See Clip a Video. - Fixed: deleting a fast clip's source from the dashboard is now blocked, and clipping a video being deleted at the same instant can't strand the clip. The rule that a source video can't be deleted while fast clips reference its segments was only enforced on the API endpoint — the dashboard's delete page bypassed it. The guard now applies everywhere (the dashboard shows the same "delete the clips first" warning the API returns), and a delete racing a fast-clip job in its first seconds now cleanly fails the clip instead of leaving it pointing at media scheduled for cleanup.
- Fast clips now reuse the source's audio too — including the low-bitrate HE-AAC rendition. A
/fastclipclip already reused the source video's encoded segments byte-for-byte; its audio boundaries, however, were re-encoded, and the HE-AAC (aac_60) rendition had to be fully re-encoded every time because re-encoded boundaries corrupted its decode. Fast clips now cut the source's own audio at frame granularity instead of re-encoding anything, so every audio rendition — HE-AAC included — is reused bit-for-bit: clips store even less, finish faster, and the clip's audio is identical to the source's. No API changes; existing clips are unaffected. - Fixed: a fast clip cut very close to a segment boundary no longer drops a fraction of a second. When a
/fastclipcut started within 0.25s before (or ended within 0.25s after) an internal segment boundary, up to 0.25s of frames could silently go missing at the seam and the clip's start could play with lip-sync up to 0.25s off for a few seconds. Such cuts now produce exactly the frames requested. - Fixed: fast-clipping past the end of a shorter audio track no longer misdeclares the clip's audio length. If a video's audio ended before the video (a trailing video-only stretch) and a fast clip's end time reached into that stretch, the clip's audio playlist declared several seconds of audio that didn't exist, which could confuse players near the end of the clip; the clip's audio track also reported the full clip length in the API. Both now report exactly the audio that exists.
- Get a video's preview reel via the API. The hover previews introduced yesterday are now available to your own apps:
GET /api/v1/project/<project_id>/video/<video_id>/previewreturns the URL of an HLS playlist that plays a short reel of moments sampled across the video — configurable stop count, sampling window, and per-stop duration — generated on the fly from the video's existing segments (no extra encoding or storage) and playable in any HLS player. See Hover Previews.
2026-07-02¶
- Hover a thumbnail in the Videos list to preview the video. Resting the pointer on a video's thumbnail in the dashboard's Videos list now plays a muted looping preview in place of the poster — a short reel of ~2-second moments sampled evenly across the whole video, so you can recognize a video without opening it. The reel is generated on the fly from the video's existing encoded segments and served through the CDN: no extra encoding, no extra storage, nothing to configure. Previews appear once a video is ready to play; while it's still encoding you'll see the poster as before. See Hover Previews.
- The embed player's control-bar clock now shows time remaining — click it to switch. The time readout to the right of the scrub bar used to show the video's total duration; it now shows the time remaining and clicking it (or pressing Enter/Space while it's focused) toggles between remaining time and total duration. This comes with a refresh of the player's underlying engine (Video.js 10), which also brings smoother menu and overlay animations, a cleaner buffering spinner, and snappier volume feedback. Everything else — the controls, menus, logos, overlays, and your player settings — is unchanged.
- Zoom panning now works on touch screens. When the player's Zoom menu is enabled and a viewer magnifies the video, dragging to pan around the zoomed picture previously only worked with a mouse — touch devices couldn't pan at all. Panning now works with a finger (or pen) too, and the picture re-clamps to its edges when the player is resized or switches in and out of fullscreen while zoomed. No settings changed — this applies wherever the zoom menu is enabled.
- The Share dialog is friendlier to keyboard and screen-reader users. Opening the player's Share dialog now moves keyboard focus into it, Tab cycles through its buttons and fields without escaping behind the dialog, Esc still closes it, and closing hands focus back to where the viewer was. It's also announced as a proper modal dialog to assistive technology. The dialog's look and its share options are unchanged; clicking the video title to open its link also no longer hands the opened page a reference back to the player page (a small tab-hygiene hardening).
2026-07-01¶
- Choose a specific player per embed with
?player_id=. By default an embed renders with the project's default player; you can now override that per embed by addingplayer_id=<player_id>to the embed URL — on both the public embed (/e/…?player_id=…) and the private token embed (/et/…?token=…&player_id=…). The player must belong to the project; an unknown or foreign id simply falls back to the project's default player rather than failing to load. Analytics record whichever player actually rendered. See Secure video playback. - Fixed: autoplay now works on the private (token) embed. Adding
autoplayto a private video's token embed URL (/et/<project_id>/?token=…&autoplay=1) had no effect — the token embed redirects to the token-less player page, and that redirect was silently dropping the query string, so the autoplay flag never reached the player. The redirect now preserves it, so a private token embed autoplays just like the public embed does. As always, browsers block autoplay with sound, so pair it with a muted player if you need playback to start reliably. Public embeds were unaffected. See Secure video playback. - Fixed: replacing a player logo now takes effect right away. When you uploaded a new logo (the in-player logo, the control-bar logo, or the title logo) over an existing one, the CDN could keep serving the old image for a long time, because a logo keeps the same storage path when replaced and our CDN caches by path. Logo URLs already carried a version marker to bust the cache, but the media CDN was ignoring it. The CDN now varies the cached logo on that version marker, so a replaced logo refreshes on the next load with no manual cache purge. Only logos are affected — video, thumbnails, and captions cache exactly as before. No action needed.
2026-06-30¶
- The player editor's logo panels have been given a visual refresh. The three logo uploaders on the Player Edit page — In-player logo, Control-bar logo, and Title logo — are now presented as polished, consistent cards. Each leads with a labeled icon and an Active / Not set status, previews your logo on a dark, video-like stage (with a faint checkerboard so transparent PNGs read clearly), and pairs it with a click-or-drop upload area that lights up as you drag an image over it. The in-player logo's corner picker is shown as a small player frame whose chosen corner fills in. The uploads, the live preview, the position setting, and everything these panels do are unchanged — only the presentation is nicer.
- Capturing a poster from a chosen frame is faster, and now works for clips. The dashboard's Capture from video panel (Video Edit → Posters) grabs the frame straight from the video's HLS playlist and seeks directly to the segment containing your chosen time, instead of scanning the whole rendition — so the capture returns quicker, especially for long videos. It also now captures correctly from a clip, whose media reuses the source video's segments; previously a capture at a time inside a reused part of a clip could fail. The captured frame is unchanged.
2026-06-29¶
- The embed player now opens with its controls showing, not a large center play button. The player used to display a big play button in the middle of the video and only reveal the control bar once you started playback. It now starts with the full control bar visible over the poster image — the scrub bar, time, volume, the settings (⚙) menu and fullscreen — and no center play button; press play from the control bar to start. The rest of the player (logos, title overlay, enabled controls) is unchanged. Nothing to configure.
2026-06-26¶
-
The embed video player is now a fully first-party build. The player has been rebuilt on plain video.js ⧉ with our own controls and styling, replacing the third-party nuevo plugin — and every feature carries over: quality, speed and zoom selection and the share dialog, gathered into a single settings (⚙) menu on the control bar (as before); captions and chapters; the storyboard scrub-bar preview; the in-player and control-bar logos; the title overlay; resume-from-last-position; keyboard shortcuts; and zoom drag-to-pan of the magnified video. The control bar keeps the familiar layout — current time, scrub bar, duration, then volume, the settings cog and fullscreen on the right. Your existing player settings (logos, enabled controls) keep working unchanged. This removes a third-party dependency from the playback path. No action needed.
-
Fixed: captions on a fast clip are no longer out of sync. When you made a fast clip (
/fastclip) of a video that had captions/subtitles, enabling them in the player showed them badly out of sync with the audio — shifted by the clip's start offset. A fast clip reuses the source's encoded segments by byte-range, so its media keeps the source's original timeline, but the clip's caption file had been rebased to start at zero, and nothing told the player how to line the two up. The clip's captions now carry an HLS timing marker (X-TIMESTAMP-MAP) that pins them to the reused media's timeline, so they play in sync. This affects fast clips only — full re-encoded clips (/clip) and ordinary videos were always in sync — and only newly created fast clips; re-create an existing fast clip to fix its captions. Chapters and the downloadable caption file are unchanged. See Clip a video. - HLS segments are now 6 seconds (down from 8). Newly encoded videos are split into 6-second HLS segments instead of 8-second ones. Shorter segments let the player switch quality (ABR) and respond to seeks a little faster, at the cost of marginally more playlist entries; the forced-keyframe interval moves in step, so every segment stays independently decodable. Already-encoded videos keep their existing segments until re-encoded — playback is unaffected either way.
- Scrub-bar preview thumbnails now avoid blank/black frames. The little preview images shown when you hover or drag the player's seek bar (the storyboard) are captured at a fixed interval across the video. Previously each one grabbed the exact frame at its timestamp, which could land on a fade, scene cut, or otherwise blank frame. Each thumbnail is now chosen as the most representative frame from the first second of its interval — skipping transient blank frames in favor of one with actual content — mirroring the same improvement already made to auto-generated posters. The thumbnails stay on the same fixed timeline (each still covers the same moment of the video), so seeking is unchanged; only the picture is a little better.
2026-06-25¶
- The dashboard now shows live encoding progress per quality. While a freshly uploaded video is still processing, the Video Preview panel on its Video Edit page shows live encoding progress in place of the player — a progress bar per quality (
1080p,720p,480p, …) plus an overall percentage — updating on its own with no need to refresh. Because encoding is two-pass, the moment the essential qualities are ready the player appears and you can watch, while a slim strip beneath it keeps showing the higher qualities still being prepared; each turns green as it finishes, and the strip disappears once everything's done. This surfaces, in the dashboard, the same per-rendition progress now available on the API'sencoding_progressfield. See Use Encoding Tiers. - See encoding progress per quality level while a video processes. The single-video API response (
GET …/video/{video_id}) now includes anencoding_progressfield — a map from preset id to a 0–1 fraction — for each rendition that's still encoding, so you can show a live per-rendition progress bar. It's populated only while the video is still processing (statusqueued/ready) and isnullonce encoding has finished; it's omitted from the videos list response to keep that response cheap. A rendition that's already done reads as1. - Long videos now encode in parallel, resumable chunks. Under the hood, a long video's renditions are encoded in fixed-length time chunks that run in parallel on the worker and are staged to object storage as they finish. If an encode is interrupted (a transient failure, a worker restart) it resumes by re-encoding only the chunks that hadn't completed yet — instead of starting the whole video over — so long videos finish sooner and recover cheaply. The chunks are deleted automatically once the video completes. Shorter videos are unaffected (they still encode in a single pass), and the output renditions are byte-for-byte the same as before.
2026-06-23¶
- Public videos' MP4 download links are now unguessable. A public video's downloadable progressive-MP4 URL — the preset's
static_mp4_link, handy as a direct download or a raw<video>source — used to be a fixed path built only from the project, video and preset ids, so anyone could reconstruct it by guessing those ids. The URL now ends in a token derived from the video's password, so it can no longer be reconstructed from the ids alone, while staying a permanent, shareable link that needs no signed, expiring token. Keep reading the link fromstatic_mp4_linkas before — private videos are unchanged (they still get a signed, expiring URL). Changing a video's password rotates its public MP4 URL, and a request carrying a wrong or stale token returns404. An empty password means no protection, the same as for the password-gated embed page. As before, the CDN caches these URLs, so rotating the password or unpublishing has a propagation delay. See Secure video playback. - You can now upload your own chapter track from the dashboard. The Video Edit → Chapters page gains an Upload a chapter file panel alongside Generate chapters with AI, so you can add hand-authored chapter markers (a WebVTT or SRT chapters file) instead of generating them from captions — handy for editing AI chapters (download, tweak, re-upload) or for videos without captions. As with generated chapters, a video can have only one chapter track, so the upload panel is hidden once a chapter exists (delete it to replace it). Uploading a chapter file was already possible through the API ("Create text track" with type
chapter); this restores the equivalent in the dashboard. See Auto-generated chapters.
2026-06-22¶
- The Billing page now shows your encoding and bandwidth used this month. On the Subscription Details card, the Encoding and Bandwidth tiles still show Unlimited (your plan doesn't cap them), but each now also reports how much you've actually used in the current billing month — mirroring the monthly figure already shown for storage. The usage covers all your projects for the month to date; the limits are unchanged.
- The interactive API reference has a new look and a built-in API client. The reference page (linked as Stream API Reference in the docs nav) is now powered by Scalar ⧉, replacing the unmaintained RapiDoc. Everything you had before is still there — browse every endpoint and schema, search, download the OpenAPI spec, and (when you're signed in with an API key) try requests live with your key pre-filled. New on top of that: ready-to-copy code samples in many languages (cURL, Python, JavaScript, Go, Java, C#, PHP, Ruby, …) for every endpoint, a faster full-text search (⌘/Ctrl-K), and a light/dark theme toggle. The deep-links throughout these docs jump straight to the relevant endpoint, as before.
- A poster can no longer be added to a video that failed to encode. Once a video's processing has terminally failed (status
errored), adding a custom poster for it is blocked — there's no playable video for the poster to front. This covers both ways to add one: the Upload new poster panel (and its REST endpoint, which now returns422 video_errored) and the dashboard's Capture from video panel. Both panels gray out on the Video Edit → Posters page with the reason. Posters can still be added to videos that are processing or ready, as before. - A text track can no longer be added to a video that failed to encode. Likewise, once a video's processing has terminally failed (status
errored), uploading a subtitle/caption/chapter track for it is blocked — there's no playable video for the track to accompany. This applies to the Upload a text track panel on the Video Edit page (which grays out with the reason) and its REST endpoint, which now returns422 video_errored. Tracks can still be added to videos that are processing or ready, as before. - The Swap Video panel now grays out when the video can't be swapped. Swapping a video's content with another requires both videos to be completed, so the Swap Video panel on the Video Edit page now disables itself up front — with the reason shown — when the current video isn't completed (for example one that failed to encode, or is still processing), instead of only rejecting the swap after you pick a target and submit. The underlying rule is unchanged (it still re-runs on submit); this only makes the dashboard state it proactively, consistent with the Duplicate and Create Clip panels.
- Auto-captions can now target a specific audio track. Captions are generated per audio track, so a video with more than one audio track (for example a dubbed track, or a separate director's commentary) can be captioned track-by-track — including two tracks in the same language (e.g. a main English track and an English commentary), which previously collapsed into a single caption. By default the video's main audio track is captioned; pass
audio_track_idto the "Generate auto captions" API endpoint (POST …/video/{video_id}/text_track/generate) to caption a particular alternate track. Each generated caption now records which audio track it was made from, and deleting an audio track also removes the captions generated from it. Single-audio videos are unaffected. See Auto-generated captions.
2026-06-20¶
- The Billing page's Choose Your Plan section has been given a visual refresh. The three plans — Start, Pro, and Advanced — are now presented as polished cards, each with a plan icon, a one-line description, and a consistent feature list (storage tier, unlimited bandwidth, unlimited encoding, and all features included). Pro is highlighted as the Most Popular plan, the Monthly / Annual switch now carries a "Save 50%" badge so the annual saving is obvious, and the cards lift gently on hover. The plans, prices, and checkout flow are unchanged.
- For subscribers, the Subscription Details card on the Billing page has also been refreshed. It now leads with your plan, price, and a color-coded status badge, shows your storage usage as a progress bar against your plan's limit, and lays the billing dates and unlimited encoding/bandwidth out as clean tiles. The information shown is unchanged.
- Generate video chapters with AI. You can now turn a video's captions into chapter markers automatically — the platform reads the existing caption track, splits the content into logical sections, writes a short title for each, and adds them as a chapter track that appears on the player timeline (and in the video's SEO metadata). Generate them in the dashboard's Video Edit → Text Tracks → Generate chapters with AI panel (optionally tuning the minimum/maximum chapters per hour), or via the new "Generate chapters" API endpoint (
POST …/video/{video_id}/text_track/chapters/generate). They're generated in the background — the chapter track shows asprocessing, thenready, the same as auto-captions. The video must be ready and already have a caption track (auto-generated or uploaded) — chapters are built from the captions, not the audio — and each video can have one chapter track, so delete the existing one to regenerate. See Auto-generated chapters.
2026-06-19¶
- Auto-generated posters now avoid blank/black frames. When a video is processed, its poster thumbnails are captured at a few points across the duration. Previously each one grabbed the exact frame at that timestamp, which often landed on a fade, scene cut, or otherwise blank/black frame with no detail. Each poster is now chosen as the most representative frame from a short window around its timestamp (it analyzes the next ~50 frames and keeps the one that stands out most), so it skips transient blank frames in favor of one with actual content. Manually capturing a poster from a chosen frame in the dashboard is unchanged — it still uses the exact frame you picked.
- The default poster is now the most detailed of the generated frames, not a random one. After a video's posters are generated, the one shown by default used to be picked at random — so even with good candidates the default could be the weakest (e.g. a near-blank) frame. The default is now chosen by scoring each generated poster for visual detail and keeping the most detailed one. For a video that's blank throughout there's still always a well-defined default (the least-blank frame) — it never fails or leaves the video without one. You can still set any poster as the default yourself; manually chosen defaults are untouched.
- Terminal failures of AI subtitle generation now surface on the subtitle tracks, matching the video behavior added on 2026-06-18. When subtitle generation fails for good (all retries exhausted), the subtitle tracks it was producing now report status
error(with asubtitle_processing_errorevent) instead of staying stuck atprocessing— previously only the "couldn't detect the audio language" case was reported.flask requeue-job <id>recovers them the same way it does videos: it resets the job and returns the affected subtitle tracks toprocessing. - Likewise, a terminal failure of an alternate audio track's encode now reports the track's status as
errored(with anaudio_processing_errorevent) instead of leaving it stuck atqueued. The uploaded audio file is validated up front, so this only ever reflects a failure of the encode step itself (e.g. transient infrastructure errors that exhaust all retries), not an invalid upload.flask requeue-job <id>returns the track toqueued. - Fixed: fast clips now actually reuse the source's segments instead of silently re-encoding the whole cut. A fast clip re-encodes only the frames at the two cut points and reuses every whole segment in between — but that only works when the re-encoded boundaries match the source's video headers exactly. They never did for normally-encoded videos (the platform encodes in a mode the boundary re-encode wasn't reproducing), so every fast clip of a normal video fell back to a full re-encode — correct output, but with none of the speed or size benefit (and no link back to the source). Fast clips now reproduce the source's encoding, so eligible cuts splice as intended: far faster, far smaller, and linked to the source. (Cuts too short to contain a whole segment still fall back, as documented.)
- A fast clip can no longer be clipped or fast-clipped — neither the
clip/fastclipAPI endpoints nor the dashboard's Create Clip panel will clip a video that is itself a fast clip. A fast clip's media is stored as byte-range references into its source video's segments rather than as an independent encode, so cutting a new clip from it has nothing standalone to reuse or re-encode. Clip from the original source video instead. The API returns422 cant_modify_fastclip(the same rule that already blocks duplicating, or adding tracks to, a fast clip), and on the dashboard the Create Clip panel grays out with the reason. Plain (fully re-encoded) clips stay independent and can still be clipped again. - The video edit page now shows where a fast clip came from: when the video you're editing is a fast clip, it names the source video, links straight to the source's edit page, and shows the cut range taken from it (start–end). This makes a fast clip's provenance obvious — and gives you a one-click way back to the original — where before nothing on the page indicated the video was a clip of another. The videos list also flags each fast clip with a small ⚡ badge. Plain videos and independent (fully re-encoded) clips show nothing of the sort.
- In the video edit page's Downloads (Progressive MP4) panel, every rendition of a fast clip now carries a small note (hover the ⓘ by the size) that the listed Size is the stored bytes only — because a fast clip reuses the source's segments, the actual download is usually larger than shown. Normal videos are unaffected.
- The video edit page now shows the video's total storage used — the combined size of every stored artifact (original upload, encoded renditions, posters, storyboards, and subtitle/audio tracks) — in a Video info panel beside the preview, alongside its duration and created date.
- The video edit page's Upload a text track and Generate captions with AI panels have been restyled into tidy cards — an icon, a short description, and a two-column field layout for uploads — matching the page's Posters and Create Clip panels. How tracks are uploaded or generated is unchanged; the subtitle file picker is now labeled "Subtitle / caption file".
- The video edit page's Choose a poster picker is now a tidy gallery — uniform 16:9 thumbnails on a responsive grid, with the current poster clearly marked (a highlighted border and a "Current" badge) and the others lifting on hover. Picking a poster works exactly as before.
- The videos list page has been refreshed and tightened up. Each video shows a thumbnail with its duration overlaid, its title and description, upload date and total storage, and clearly labeled status and Public/Private badges (replacing the old cryptic single-letter
E/Pbadges) next to the ⚡ Fast clip badge. The rows are denser and the header slimmer, and there's a friendly empty state that points you to upload your first video (or to clear your filters when a search turns up nothing). - Background processing now starts the moment you trigger it, instead of waiting for the next queue cycle. Jobs — video encoding, URL fetches, clips, duplicates, alternate audio-track encodes, AI subtitle generation, outgoing webhooks, and account emails (welcome, password reset, project invites) — previously waited to be picked up by the queue's polling cycle, which could add up to ~30 seconds of delay before the work even began. They now begin as soon as the action that created them is committed, so videos start encoding, webhooks fire, and emails send with noticeably less lag. When the relevant worker is already at capacity the job falls back to the normal queue exactly as before, so nothing is lost or double-run under load.
- The Statistics page layout has been refreshed. The Plays over time chart now spans the full width of the page, and the Completion funnel has been condensed into a compact strip in that chart's header — the five checkpoints (Played → 25% → 50% → 75% → Completed) shown as small percentages, with each checkpoint's play count and drop-off available on hover — rather than taking a half-width panel of its own. The headline metric tiles keep their own row above. The underlying metrics and funnel checkpoints are unchanged.
- The Statistics page now shows the active date range as a caption at the top (for example, "Last 30 days · 1 Jun – 30 Jun 2026"), so it's clear what period the numbers cover without opening the Filters drawer. The five headline metric tiles also gained a thin color accent along their top edge, matching each tile's trend-sparkline color, so they're easier to tell apart at a glance.
2026-06-18¶
- Videos created from clip, fastclip, or duplicate now start with status
queued("Queued for encoding") instead ofwaiting_for_upload. These videos are derived from an existing video and have their processing job queued the moment they're created — they never wait for an upload — sowaiting_for_uploadwas misleading (a clip still being processed, or one whose job failed, looked like an un-uploaded video). Thestatusfield in the API and thevideo.createdwebhook now reportqueuedfor these videos from creation. Uploaded and fetched-by-URL videos are unchanged: they still startwaiting_for_uploaduntil their bytes arrive, then move toqueued. (Duplicates already reportedqueuedon the video record, but theirvideo.createdwebhook still saidwaiting_for_upload; that webhook is now consistent too.) - When a video's processing job fails for good (all retries exhausted), the video is now marked errored with a
processing_errorevent and avideo.status_updatewebhook, instead of being left silently atqueued/waiting_for_uploadwith the failure only visible in error tracking. This covers upload, fetch, encode, clip and duplicate jobs. Operators can re-run a failed job with the newflask requeue-job <id>command, which resets the job and returns its video toqueued. - The player edit page's three logo uploads — In-player logo, Control-bar logo, and Title logo — have been redesigned. Each is now a single card showing a live preview of the current logo on a video-like checkered backdrop (so transparent PNGs read clearly), with an Active / Not set status. Picking a file — by clicking the drop zone or dragging an image onto it — shows the file's name and an instant preview before you save, and the Save button enables only once you've chosen one; Remove is available only when a logo is set. Each card states the accepted formats, the size limit, and the recommended dimensions for that logo (the help text was previously duplicated). Uploading and removing logos work exactly as before.
- The In-player logo card now also holds the Logo position control (previously in the Player settings form), since it sets where that logo sits over the video. It's a visual corner picker — a small video frame with the available corners (top-left, top-right, bottom-left) as selectable chips — with its own Save position button. Saving it is unchanged (it's still a player setting), and the Player settings form's Save changes still applies the position too.
2026-06-17¶
-
The video edit page has a new Create Clip panel — you can now clip a video from the dashboard (previously clipping was API-only). Scrub the preview to the start and press Set start, scrub to the end and press Set end, then choose Create clip (an independent, fully re-encoded copy) or Create fast clip (reuses the source's segments where possible — much faster and smaller, but stays linked to the source). Your chosen start and end are marked right on the preview's progress bar, with the selected range highlighted between them, and a Preview button next to each jumps the player to that point. The buttons enable once the selected range is at least one second, and the panel is grayed out (with the reason) when the video isn't eligible — not yet completed, or over your storage quota.
-
Dashboard forms whose operation can't currently run now disable themselves up front instead of only failing on submit. When a video isn't eligible for an action, the panel for that action is grayed out and shows the reason as a clear notice — before you fill anything in. This is driven by the same operation rules (preconditions) the API enforces, so the dashboard and the API never disagree about what's allowed; the rules still re-run on submit, so nothing slips through if the disabled state is bypassed.
- The Duplicate Video panel on the video edit page now grays out, with the reason shown, when the video can't be duplicated — for a fast clip, a not-yet-completed video, or when there isn't enough free storage for the copy. (Previously you could fill in the form and only learned it was blocked after pressing Duplicate.)
- The storage check for duplicating a video is now size-aware: because a copy adds another full copy of the source, the duplicate is rejected unless your account has free storage at least equal to the video's size (previously it was only blocked once you were already at or over your quota). The error is a new
403 not_enough_storagewhose message states how much storage the copy needs and how much you have free; the duplicate endpoint no longer returnsupload_quota_reached(the other operations — fetch, clip, fastclip, direct upload — are unchanged and still returnupload_quota_reached). The dashboard's Duplicate Video panel shows the same sized message. - The up-front graying-out now also covers the rest of the video edit page's panels: Upload text track and Generate captions with AI gray out for a fast clip (fast clips are fixed except for metadata and posters), and Upload poster grays out once a video already has the maximum number of posters. The AI-captions panel previously hid itself only when the video wasn't ready or had no audio — it now also reflects the fast-clip rule (which the API already enforced), and shows the reason consistently with the other panels.
- The video Password field on the edit page (Details) is now masked by default and reveals its value while you have the field focused. It's masked visually rather than being a real password field, so the browser won't offer to "remember" it or autofill saved logins into it.
- The video edit page's Posters panel can now capture a poster from the video itself: scrub the preview to the frame you want (pause where you like), click Use current frame, then Save as poster. The chosen timestamp's frame is extracted server-side from the best rendition and added as a new poster (subject to the same per-video poster limit as uploads).
2026-06-16¶
- The dashboard Statistics page has been redesigned. The period now opens with five headline tiles — Plays, Play rate, Watch time, Completion, and Unique viewers — each with a sparkline and a change badge comparing it to the previous equal-length period. The per-video engagement graph is now an Audience retention chart showing the share of plays still watching each moment with replays highlighted on top and a dashed average-engagement line. A new Completion funnel (Played → 25% → 50% → 75% → Completed) shows where viewers drop off, and the trend and retention charts use gradient fills for readability. Play rate, Completion, and Unique viewers are new on this page (Unique viewers counts distinct viewers; sessions without a viewer id aren't counted).
- The Audience retention chart gained several ways to read it at a glance: a hover preview that shows the video frame at the moment under the cursor (from the scrub-preview storyboard) alongside the timestamp, percentages, and current chapter; automatic key-moment callouts that mark the most-replayed moment (★) and the single biggest drop-off (▼); an engagement heatmap strip under the chart that colors the timeline from green (high retention) to red (low); chapter markers on the timeline when the video has a chapter track; and click-to-seek — clicking the graph opens the video at that exact moment in a new tab. The hover preview appears when the video has scrub-preview thumbnails.
- The dashboard Statistics page now shows the active country filter in the Filters panel (alongside the video filter), each with an × button to clear just that filter while keeping the rest of your selection (date range and the other filter). The country and video filters are now also preserved when you change the date range and press Search. When a country filter is active the Top countries table is hidden (it would only list the selected country) and Top videos expands to full width.
- After fetching a video by URL on the upload page, the new video now appears in an Added to your library panel below the form, with a card that links straight to the video's edit page (so you can set its details without hunting for it in the video list). The panel is built to list several videos once multi-URL fetching is added.
- The dashboard upload page has been redesigned: the drag-and-drop area is now the focal point, with an Upload / From a URL tab switcher, and the upload settings (privacy, watermark, encoding tier, captions) move into a panel beside it instead of stacked above. You can now record from your webcam or capture your screen directly in the uploader (Camera and Screen sources), and the uploader matches the dashboard's light/dark theme. The selected tab is reflected in the page URL (
?tab=…), so submitting a fetch-by-URL re-opens the From a URL tab on reload and its success/error message stays visible. - On the dashboard upload page you can now drop a video anywhere on the page to upload it, not only onto the dotted upload box. A full-page "Drop your video to upload" overlay appears while you drag a file over the window.
- The dashboard upload page now rejects obviously non-media files (e.g. a PDF or ZIP) the moment you pick them, instead of letting the whole upload run and fail afterwards. The check accepts video and audio broadly — any file the browser tags as video/audio, plus a wide list of container extensions (
.mkv,.ts,.mov,.webm,.flv, …) so valid videos the browser can't identify by type aren't wrongly blocked — so it only stops files that are clearly neither. The server remains the final authority on what can actually be processed. - The dashboard upload page has a new Make videos public toggle that applies to both upload methods (device upload and fetch-by-URL). It defaults to private — unchanged from how new videos have always been created — so leaving it off keeps videos requiring a signed link, and turning it on makes every video uploaded on the page publicly viewable. The direct-upload API also accepts a
publicfield in the upload metadata. - The embedded video player's Nuevo plugin was upgraded from 14.3.0 to 15.0.0 (the underlying video.js stays at 8.23.8). Viewers get the latest player UI and fixes across all skins; the player's configuration, skins, and behavior are otherwise unchanged. The player assets now load from
/static/videojs.15.0.0/— if you hard-code or cache player asset URLs anywhere, they move with the version.
2026-06-15¶
- Public videos now expose their downloadable MP4 rendition at a fixed, shareable URL that needs no signed token. A preset's
static_mp4_link(API) returns this unauthenticated URL for public videos, while private videos keep their signed, expiring URL; the MP4 is served and cached by the CDN as before. Note: because the public URL is cached at the CDN, making a previously-public video private (or deleting it) does not immediately stop the CDN from serving the already-cached MP4 — there is a propagation delay. - On the dashboard upload page, each device upload's thumbnail and filename become a link once the upload finishes — clicking it opens that video's edit page in a new tab, so you can jump straight to a freshly uploaded video without hunting for it in the video list.
- Device uploads on the dashboard upload page now resume after an interruption. If the page is reloaded or the tab is closed mid-upload, the uploader restores the in-progress upload and continues from where it stopped instead of restarting — only the chunks that never arrived are re-sent. Because browsers can't keep a selected file's bytes across a reload, large videos reappear as a "ghost" file prompting you to re-select the same file; once you do, the upload continues. Resuming must happen within the 24-hour multipart-upload window. (The underlying multipart API already supported this via list-parts; this enables it in the dashboard.)
2026-06-12¶
- Low-resolution renditions (240p/360p/480p) of high-frame-rate sources are now capped at 30 fps. Previously their frame rate was halved exactly once, so a 120 fps screen recording or 240 fps slow-motion upload shipped 60 fps or 120 fps low-resolution renditions — wasting bitrate at resolutions where the extra frames add nothing. Sources up to 60 fps are unaffected (their low rungs already landed at or below 30 fps), and the 720p+ renditions keep frame rates up to 60 fps as before.
- On the dashboard upload page, a fetch-by-URL rejected by an operation rule (e.g. over the storage quota) now shows the message as a form-level error above the fetch form; previously it was attached to the URL field as if the URL itself were invalid. URL-specific errors (e.g. a dead link) still show on the field.
- Swapping a video with itself (
swap_idequal to the video's own id) is now rejected with a new422cant_swap_same_videoerror instead of being accepted as a pointless no-op. The dashboard's Swap Video form was never affected (it doesn't offer the video itself). - Fast clips can no longer be duplicated (
422cant_modify_fastclip, on the API and the dashboard's Duplicate Video panel alike). A fast clip plays back from its source video's stored segments, so a "duplicate" of one was never independent: the copy lost the link to the source and wouldn't play. Duplicate the source video instead, or useclipto create a stand-alone video from the same section. - Generating AI captions now validates its preconditions during request validation: the video must not be a fast clip, must be ready, and must have audio. The
cant_modify_fastclip,video_not_readyandvideo_no_audioerrors (still422) are now reported against the request body; the error codes are unchanged, so clients matching on the code are unaffected. The dashboard's Generate captions form enforces the same rules inline. - The dashboard Swap Video form now requires both videos to be completed — the same rule the API already enforces. Previously the dashboard validated only the target video; a non-completed source is now rejected with an inline error instead of being accepted.
- API endpoint descriptions now list their operation preconditions as a bullet list at the end (e.g. "The video must be completed." for duplicate and clip, "Up to 20 posters are allowed per video." for poster upload), so the OpenAPI/reference docs state the rules a request must satisfy.
- The
duplicateendpoint's description now also lists its storage-quota precondition ("Subject to your account's storage quota.", since a copy doubles storage). Both the API and the dashboard's Duplicate Video form now enforce the quota through one shared precondition (the API keeps returning403 upload_quota_reached; the dashboard shows the same rule as an inline error) instead of a separate check on each side. - The storage-quota check on
fetch,clip,fastclipand the direct (multipart) upload start is now a request-body precondition (it was a separate pre-check). The status and code are unchanged (403 upload_quota_reached), and their descriptions now list "Subject to your account's storage quota." One consequence (forfetch/clip/fastclip): the quota check now runs after basic body validation, so an over-quota request whose body is also malformed gets the422body error first rather than the403. The dashboard upload page's fetch-by-URL now enforces the same quota (shown as an inline error) instead of skipping it. - For
clipandfastclip, the "video must be completed" check (video_not_complete, still422) is now reported against the request body rather than thevideo_idpath parameter. The error code is unchanged, so clients matching on the code are unaffected.
2026-06-11¶
- The dashboard video edit page now has a Duplicate Video panel that creates an independent copy of the video (optionally with a custom title), the same as the duplicate video API endpoint. A copy doubles storage, so it's subject to your account's storage quota — over-quota shows an inline form error.
2026-06-10¶
- The signing-key limit (
max_keys_reached) and the per-user project limit (max_projects_reached) are now reported as request-validation errors: the HTTP status changes from412to422. The error codes and messages are unchanged, so clients matching on the error code are unaffected. - Text-track uploads are now validated during request validation, and an unparseable subtitle returns a new, more accurate
invalid_subtitle_fileerror ("File must be a valid vtt or srt subtitle.") pointing at thefilefield — previously this case returnedtext_track_invalid_type, whose message describes the chapter-type rule. The status stays422; clients matching ontext_track_invalid_typefor upload failures should switch toinvalid_subtitle_file(text_track_invalid_typeis still returned when setting a chapter track as the default). Subtitle files are now also capped at 10 MB (value_too_large). - Video fetch (
POST /video/fetch): an unreachable URL is now rejected during request validation, so thehead_request_to_url_failederror (still422) points at theurlfield. Fixed fetch-by-URL from the dashboard's upload page, which errored on every submit; a dead link now shows an inline error on the URL field. - Generating AI captions from the dashboard now enforces the same preconditions as the API (video ready, has audio, not a fast clip). These precondition failures — and the rare duplicate-webhook race — now render as inline form errors on the dashboard instead of a JSON error response.
- Multipart form fields with string types now take submitted values literally: a title of
true,2024or1e5is stored as-is. Previously such values were JSON-interpreted, rejecting some (truebecame a boolean → "Input should be a valid string") and silently mangling others (1e5saved as"100000.0","quoted"lost its quotes). Applies to the multipart API endpoints (watermark, poster, logo and text-track uploads) and the dashboard forms. - Fixed the dashboard stats page interpreting the date-range picker with the project timezone's historical local-mean-time offset (minutes off, e.g. +00:19 instead of +01:00 for Europe/Tirane) — day boundaries now use the correct UTC offset for the selected dates.
- Editing a project with
player_id: 0(or any unknown player id) now returns a422resource_not_existserror instead of a 500.
2026-06-09¶
- Progressive (fMP4) video downloads now have their CDN bandwidth recorded in usage analytics, the same way streaming and progressive-MP4 bandwidth already are. Delivery itself is unchanged for viewers.
2026-06-08¶
- Video tag names containing NUL bytes no longer return a 500 when editing a video. Tags are now sanitized the same way other text fields are (NUL bytes replaced with
�) before being stored. - Performance stats (
GET /stats/performance) now returns a 422 whenend_dtis beforestart_dtinstead of silently returning an empty or incorrect response.
2026-06-07¶
- Editing a video with control characters (NUL bytes) anywhere in the free-form
metaobject no longer returns a 500. NUL bytes — which PostgreSQL cannot store — are now sanitized (replaced with the Unicode replacement character�) like other text fields, so the request succeeds. - Added a duplicate video endpoint (
duplicate) that creates an independent, byte-for-byte copy of a completed video — the original upload, every encoded preset, all audio and text tracks, posters and storyboards. Stored files are copied directly (no re-encode), the copy starts with zeroed analytics, and it neither inherits nor restricts the source video.
2026-06-05¶
- Added an API errors reference page listing every error code the REST API can return, with a stable anchor per code that error responses can link to.
- Added a fast clip endpoint (
fastclip) that creates clips much faster and far smaller by reusing the source video's already-encoded segments and only re-encoding the frames around each cut point. The existingclipendpoint (full re-encode) is unchanged. - Scrub-preview thumbnails (storyboards) are now split across multiple bounded image sheets instead of a single large sprite. Hover previews keep working on very long videos — previously a multi-hour video produced one oversized image that could exceed browser image-decode limits and render broken or blank thumbnails. For videos beyond ~3 hours the capture interval widens automatically so storage stays bounded.
- Added an API errors reference page listing every error code the REST API can return, with a stable anchor per code that error responses can link to.
- Video clipping now accepts fractional (decimal) start and end timestamps, so clips can be trimmed on sub-second boundaries (e.g.
start_time: 12.5). Whole-number timestamps continue to work unchanged. - A source video can no longer be deleted while fast clips of it still exist (delete the fast clips first).
- Fixed the clip
end_time_too_bigerror so its message shows the requested end time instead of a literal{end_time}placeholder.
2026-06-04¶
- Fixed a rare progressive-MP4 (download) corruption that could occur when a caption track was renamed while the file was partially cached on the CDN. The embedded caption label is now stored in a fixed-width field, so a rename can no longer shift the file's internal byte offsets.
- Caption track titles now appear as the subtitle track name when a downloaded MP4 is opened in players that show track titles (e.g. VLC, QuickTime).
- Audio track titles now appear as the audio track name in a downloaded MP4, across players that read either common location for it (e.g. Chrome, VLC, QuickTime).
2024-12-10¶
- Added Automatic Cold Storage
2024-09-09¶
- Added confirmation when exiting the page when video uploads are in progress
2024-08-17¶
- Added vertical videos HD encoding
2024-03-16¶
- Added alternate audio tracks
2024-02-16¶
- Added AI captions
2024-01-17¶
- Added audio normalization
2024-01-12¶
- Added encoding tiers
2024-01-09¶
2024-01-08¶
- Added webhooks
2024-01-01¶
- Added audio normalization option when uploading new videos.