Skip to content

Releases: fgilde/videola

Videola 0.9.1 — sound you can fix by name, twelve titles, eight looks

Choose a tag to compare

@github-actions github-actions released this 14 Aug 10:34

Videola 0.9.1

Sound that can be fixed by name, twelve ready-made titles, eight looks, and a written plan.

Sound

  • Bass and Treble — shelves, which is what "more bass" and "less hiss" actually mean:
    everything past a corner rather than a hill around a frequency. The equaliser beside them is a
    peaking band and cannot do it.
  • Hum filter — a narrow notch at the mains frequency, 50 Hz or 60. Its range stops at 70 Hz on
    purpose: a filter that could be dragged up into the voice would be a low cut with a misleading name.
    At the default sharpness the notch is about two hertz wide, so it takes the hum and leaves the note
    beside it — which is exactly what a low cut set high enough to catch hum cannot do.

Each is checked against a real graph on both sides: the far side moves, the near side does not. A shelf
that moved both would be a gain.

Titles and looks

  • Twelve ready-made titles in the Text panel — plain, lower third, headline, breaking news, neon,
    quotation, caption, outlined, credit line, sticker, upright hook, note. One press replaces the whole
    style, and a test refuses a move or a colour the renderer cannot draw, because both fall back
    silently and would look like a preset that does nothing.
  • Eight looks in the effect shelf — Vintage, Cinema, Summer, Night, Film noir, Dream, Comic, VHS.
    Twenty-three effects are unusable by somebody who does not know what "posterize" means; a look is the
    same effects arranged by somebody who does. One press, one step of undo.

Editing

  • Slow push (Ken Burns) on a clip: the move a photograph cannot make on its own, written as
    keyframes rather than a mode, so it can be dragged, retimed or deleted afterwards.
  • Fade in and out: four keys on the opacity for the two clips that have nothing to dissolve with,
    the first and the last.
  • Dragging a clip in the picture moves it by the distance dragged — it used to be thrown out of the
    frame, because the whole travel since the pointer went down was applied to a transform that already
    carried most of it. Four pointer moves, four times as far; a real drag reports dozens.

The site

videola.app is served from its own root now. The base was still /videola/ from the github.io days,
which is why the page came up without its stylesheet and every link pointed one directory too deep.

The plan

There is a written plan of record in the documentation now, in both languages: what comes next, in what
order, and what is deliberately not planned. Including the rule this project holds itself to — nothing
ships here that we do not own, which is why every template is a generator.

Videola 0.9.0 — titles that move, and menus you can find things in

Choose a tag to compare

@github-actions github-actions released this 13 Aug 22:38

Videola 0.9.0

Titles that move, six menus instead of one pile, and an export dialogue that explains what it is
offering.

Titles

  • The movement of a title is something you can build. A title could arrive rising, growing or
    fading, and no control anywhere set it: the presets lived in the renderer and in the shipped
    templates, so a template could show a move nobody could make, change or take away. The Text
    panel now carries five arrivals, five departures, a pulse, and the seconds each takes — plus the
    look: colour, weight, alignment, type size, text width and height in the frame.
  • The seconds field appears only once a move is chosen. A duration for an animation that does not
    happen is a question about nothing.
  • The bug underneath it, which was ours from 0.8.0: two of the shipped templates asked for moves
    the renderer does not draw, and the style reader takes the default rather than the word it does not
    recognise — so a mistyped move looked exactly like no move at all. Fixed, and pinned: a test walks
    every shipped template and refuses a move or a loop the renderer does not implement, naming the clip
    and the word.

Where things are

  • Six menus: File, Edit, Insert, Project, View, Help. Everything used to sit behind one overflow
    disclosure, and a list of fifteen unrelated actions is a list nobody reads twice. These are the
    names every editor uses, so "where is import" has the answer somebody already knows. Undo, redo,
    export and save stay on the bar.
  • On a phone the same six become groups inside one disclosure — same tree, one level deeper. On a
    tablet the wordmark and the export button come off the bar, because six German titles are 450 px
    and the bar was pushing the page wider than an 834 px window.

Handing the cut on

  • File ▸ Hand off replaces three menu lines reading "Export EDL", "Export FCPXML", "Export
    Premiere XML". Each file is a card now: what it is in a sentence, which program opens it, and what
    it does not carry. Somebody who does not already know what an EDL is was choosing between three
    XML-ish names by their initials.
  • The two exports that belong to the project rather than the cut — the subtitles and the sound for
    Audiola — moved into the same dialogue. A card is switched off with its reason where this project
    has nothing to write: "This project has no subtitles".

Known

The effect shelf comes up without its tiles in the headless application harness — sixteen tiles, no
pictures, no error. It draws normally in a real browser. One hypothesis (the picture being read off
the WebGL canvas) was tested and ruled out this release, with the check kept; the cause is still open.

Videola 0.8.0 — templates that work before you have footage, and a cut Premiere opens

Choose a tag to compare

@github-actions github-actions released this 13 Aug 20:12

Videola 0.8.0

Templates that work before you have footage, a cut that opens in Premiere, and four defects in the
interface that were worth naming.

Templates

  • Every placeholder is optional, media included. A media placeholder used to be required, so no
    template could be used until something had been imported — backwards on the first run, and wrong
    anyway for half of what templates are for. A lower third, an end card, a quote card: those are
    wanted over an edit that already exists, and their own stand-in shot is in the way. A template used
    with nothing chosen comes back as its graphics.
  • Insert as tracks. The last step of the wizard has a second answer beside Create project: add
    the same result to the project already open, as tracks of its own. One press of undo takes the whole
    thing, however many tracks it brought, and it bakes at the open project's own size so nothing
    arrives cropped.
  • Two new templates, both made of generators end to endThree cards, three lines arriving one
    after another over a field that stays, for a chapter break or the front of a talk; and Upright hook,
    a 9:16 card with a disc behind the middle word, the first shipped template built on the shape
    generator. Fifteen ship now, and these two are the first that are the whole card with nothing
    imported.
  • An unanswered placeholder no longer leaves a bare track behind.

Handing the cut on

  • Final Cut Pro 7 XML (xmeml 5), which is the file Premiere Pro imports as a real sequence. A
    different format from FCPXML despite the similar name, and the one that actually opens: Resolve →
    FCPXML, Premiere → this. Counted in whole frames, files declared once and referenced after that, and
    project_handOff offers it to an agent as well.

The interface

  • The two menu entries that could not be used at allInsert and Change shape — are real
    groups now. They were selects inside a menu that closes on any click, so the click that opened the
    dropdown closed the menu underneath it.
  • The about dialogue was a bulleted list of links. It has a header band, a version chip, links as
    rows a finger can hit, and a footer.
  • The timeline context menu stays inside the window: flipped above the pointer where there is no
    room below, pulled back where it overhangs, capped in height with its own scroll where it is taller
    than the window.
  • The version in the about dialogue is the real one. It was two releases behind, because it was a
    constant somebody had to remember; it is compiled in from the release manifest now.
  • Gain reduction on every compressor and limiter — a bar and a number, read from the live node,
    which is the one thing about a compressor that cannot be derived from its settings.

Self-hosting

Three new ways in, all checked against the code rather than written from memory: a Proxmox helper
script
that builds an unprivileged LXC and waits for the container to answer, an Unraid Community
Applications template, and an Umbrel app. All three carry a mandatory token, because the server
refuses to listen on a reachable address without one. They install a new server package
videola-server-0.8.0.tar.gz, the editor, the API, MCP and the CLI in one tarball that needs nothing
but Node 22.

Also

  • Find the cuts inside a clip and split it there.
  • Give a clip a name; make a track taller or shorter.

Videola 0.7.0 — motion blur that is motion, noise reduction that is spectral, and surround

Choose a tag to compare

@github-actions github-actions released this 10 Aug 21:47

Motion blur that is really motion, noise reduction that is really spectral, surround, and the two
things an effect chain was missing: a way out and a bypass.

New

  • Motion blur, over eight real instants of the exposure. A clip carries a shutter — 0 off, 0.5 a
    180-degree shutter, 1 the whole frame — and the renderer draws it once per instant of that window.
    Each instant asks the core where the clip reads from then and where it stands then, and the
    decoder for that picture: a clip travelling across the frame smears along its own path, including a
    curved one, and material moving inside the shot smears because the samples land on different source
    frames. The samples are averaged additively into a target of the clip's own and composited once — a
    run of over operations would weigh the last one most and be a trail rather than a smear. In the
    preview and in the file, at the same eight instants. What it cannot invent is temporal detail the
    material does not have, and the effects chapter
    says exactly where that line is.
  • Spectral noise reduction. The thing the two cut filters cannot do: separate a voice from noise
    sharing its band. Noise is steady and speech is not, so the floor is learned from the pauses
    the quietest fifth of the clip, averaged bin by bin — and every window is then turned down per bin by
    however much of it is floor. Own radix-2 FFT, forty lines, checked against a discrete transform
    written out by hand. Measured: the noise inside the tone's own band drops by more than 9 dB while
    the tone stays within 2 dB.
  • Surround. A project is laid out over stereo or 5.1, chosen on the master strip, and every track
    has a position in that field: pan left to right, rear front to back, and an LFE send that is a band
    (a low-pass at the 120 Hz the specification names) rather than a place. Pairwise constant-power
    placement between adjacent speakers, so a sweep keeps its loudness; a stereo bed keeps its width and
    a bed panned inwards reaches the centre speaker. A 5.1 mix the browser cannot encode is delivered in
    stereo rather than in silence, with the placement kept.
  • Effects can be removed and bypassed. Until now one could be added and never taken off again, and
    Effect.enabled sat in the model since the first schema with no command able to set it — the
    renderer and the audio graph had honoured the flag the whole time. effect.remove,
    effect.setEnabled, and a bypass switch and a bin in every effect row.
  • A clip can be switched off. It keeps its place, its length and everything else; nothing draws it
    and nothing plays it. Dimmed and hatched on the timeline. That is how two takes are compared.
  • Keyboard. Undo had no key at all. Now: Ctrl+Z, Ctrl+Shift+Z (and Ctrl+Y), Ctrl+S,
    Ctrl+O, Ctrl+E on the window; S to cut at the playhead, Ctrl+A, Ctrl+D on the timeline;
    +, -, 0 and Home/End for the view.
  • The view follows a running transport, paging ahead to keep the playhead on screen and never
    scrolling itself while the transport stands still.
  • Rubber-band selection over empty timeline, selecting what it touches and giving it back when
    dragged shut.
  • Three effects: mosaic (a face, a plate, a screen — a blur strong enough to hide one leaves its
    shape readable), directional blur, and glow that spreads what is bright and keeps what is not.
  • Insert in the project menu: a lower third, a full-frame title, a credits card, a shape or a
    countdown, laid down at the playhead. There was no way to add a title at all before.
  • Shapes and the countdown are drawn. Both were in the model from the first milestone and nothing
    drew them.
  • Four more templates — quotation, before-and-after, interview, countdown — thirteen in five
    categories.
  • Export presets: 1080p, 4K, 720p, upright 1080 × 1920, square 1080. Sizes and frame rates only,
    never a bitrate.
  • One curve shape on every parameter of a clip. Written off once as needing the keys to line up,
    which it does not: an easing belongs to a key, not to a moment.

Fixed

  • The installer said the wrong company. Windows takes the publisher from the bundle identifier
    when nothing says otherwise, and that identifier was com.cargonerds.videola. It is
    org.gilde.videola now, with publisher: gilde.org stated outright. Changing an identifier moves
    where the operating system files the application, which is why this belongs before a release.
  • The download button swallowed its own label on hover. It went from #5b8cff to #7d9bff under
    white type — about 2.3:1. The fill stays put now and the light around the button answers the
    pointer. True of every hero button as well, so the fix is in the theme.
  • A field inside the timeline lost its keys: typing an m into a marker's name dropped a marker
    per letter.
  • A selection kept the ids of clips an undo had removed, so every action that asks "is there a
    selection" said yes and then found nothing to do.
  • project_handOff with an unknown format now names the two it has instead of quietly writing
    FCPXML.

What this round cost

Written down because the mistakes are the useful part:

  1. A stationary test signal cannot be told from noise. The first denoise test used a sustained
    sine, so the floor was the tone and everything came out 18 dB down. Real material pauses; the
    tests do now too.
  2. An overlap-add synthesis divides by nearly zero at the ends. Without a window of padding the
    ends of every clip came out eighteen times too loud — invisible to every ratio measured inside
    the file, obvious to a peak reading.
  3. Mixing three amplitudes at once loses 3 dB. The first surround panner did, and the check that
    measures power at fifteen positions caught it.
  4. A generator has no decoder. A smeared title came out black until its samples took the painted
    picture; the export harness found it.
  5. paintShape fell through to its last branch and drew an ellipse for a shape name it did not
    know. A mutation test found that one.

Not there yet

Layouts beyond 5.1, true peak (dBTP), gain-reduction metering, stabilisation and tracking. Signing keys
for iOS, Android, macOS and the Tauri updater are the user's to provide — without them a release carries
no updater configuration, and the path itself is built and tested.

Checked

231 Rust tests in the core across 18 suites, 1860 JS tests, and five browser harnesses: 436 GPU pixel
checks, 75 export checks through ffprobe and ffmpeg, 423 application checks, 251 layout checks and the
server bundle. Every claim above is one of them.

Videola 0.6.0 — it updates itself, and it goes vertical

Choose a tag to compare

@github-actions github-actions released this 10 Aug 11:52

Updates on both sides, a download page that knows which system you are on, a shape change for
vertical cuts, freeze frames, and the browser build as an installable, offline-capable application.

New

  • Downloads that find you. The download page works
    out which system is asking, offers that build first and lists the others with their sizes. The list
    is read from the latest release at load time, because a page that spelled out file names would go
    on offering last spring's build months later. Sizes in the reader's own notation — 7,3 MB on the
    German page, 7.3 on the English one. Android and iOS say that they are missing from a release and
    why: they exist only where a signing key does.
  • The browser build updates itself. A tab left open for a week used to run whatever was current
    when it was opened. A service worker now notices a new build: the new worker installs beside the
    running one and waits, the editor offers a reload, and the swap happens on that reload. Nothing is
    exchanged under a running session — clients.claim() is deliberately absent.
  • And it installs, and works offline. A manifest makes it an application on the desktop or the
    home screen; the same worker serves it without a network. Two caching rules and both follow from
    how Vite names what it builds: a name carrying a content hash can never change, so it comes from
    the cache; everything else, the document above all, goes to the network first, because that is the
    request which tells the browser a new build exists.
  • A real update dialogue on the desktop. Which version, a button, and a bar that reports how far
    the download has got — or goes indeterminate where the host reports bytes with no total, because a
    bar that invented a number would lie about how long this takes. It cannot be dismissed mid-download,
    and a failure says the version in hand keeps working. (The updater still needs a signing key on the
    release; without one a build carries no updater configuration at all.)
  • Change shape. Portrait, square or 4:5 in one press, with every clip scaled to cover the new
    frame in the same step. The factor applies to what the author already chose, and placement scales by
    the axis it is measured on, so a lower third stays a lower third instead of ending up 1080 pixels
    from the middle of a taller frame.
  • Freeze frames. Two cuts and a rate of zero — the core has always meant a frame hold by that.
    The piece after the freeze is slipped back by the held duration, because the held piece consumed no
    source: without that, a freeze puts a jump at its own end.
  • A transition on every cut. A slideshow is fifty pictures and forty-nine dissolves. One choice
    dresses every cut where two clips actually meet, and its first entry takes them all away again.
  • Overshoot in the curve field. The field now reaches a third past the unit square at each end,
    which is what makes a bounce authorable: a handle above where the travel arrives sends the value
    past its destination and back. Two firmer lines mark where the travel sets off and arrives, and the
    unit square is kept square so the dashed diagonal is still a diagonal.
  • One easing on the whole track, paste attributes from the clip on the clipboard, an about
    dialogue
    , a keyboard shortcut sheet whose every row is a key the editor really answers, a
    splash screen
    for the desktop build, and a layout setting for the case detection gets wrong.

Two decisions worth reading

A service worker may cache files and nothing else. The first version cached every same-origin GET
and swept up the test harness's own control requests. Under a virtual clock each of those is a pause,
and a cache write hung on every one meant the editor never got a turn to draw — nought tiles of
thirteen. The narrow rule is the correct one anyway: an API answer served from an offline cache is a
wrong answer served confidently. And sw.js must never be cached long, because the worker that would
fetch a newer one is the stale one.

A wide window is not always a desktop. Three layout checks had been failing on CI for days, and
the cause was not a layout fault: the shell asks (any-pointer: fine), which is the only honest
question a page can ask about what is being pointed with, and a headless runner with no mouse answers
no. A 1440 px window was being laid out as a tablet, and the checks were reporting, correctly, that
the picture was 216 px tall — a true statement about a layout nobody meant to check. Every run now
pins the layout it names, and the application carries the choice behind that as a remembered setting.

What this build is

Desktop installers for Windows, Linux and macOS, plus a Docker image carrying the editor, the HTTP API
and the MCP server. The macOS disk image is unsigned unless an Apple certificate was configured, so
Gatekeeper will refuse it until you allow it by hand. Android and iOS assets exist only for releases
built with their signing keys.

FFmpeg is not bundled: the export runs on the browser engine's own encoders, and the server cannot
render.

Videola 0.5.0 — lookup tables, curves, locks, and the picture as a control

Choose a tag to compare

@github-actions github-actions released this 09 Aug 20:14

Lookup tables, a curve editor for keyframe easing, a lock that means something, and the geometry of
a shot on the shot itself. Five releases in, the picture is finally the largest thing in the window.

New

  • .cube lookup tables. A table is a library asset under the hash of its own bytes, with a
    media kind of its own — so it packs into a .videola with no line added to the writer, and
    nothing about it crosses postMessage. Proven at pixels through the preview, the decoded MP4 and
    a frame ffmpeg read back out of the written file.
  • A curve editor. Bezier handles were kept and honoured but could not be dragged. The field
    opens beside the picked key's interpolation, over the tracks; the line it plots comes out of
    segment_shape in the Rust core — the very function interpolate applies to move the picture —
    so a drawn curve and an animated one cannot disagree. Fifteen columns of measured difference at
    the same instant say it reached the frame.
  • Geometry on the picture. Select a clip and a box appears on the frame: a handle on every
    corner, one to turn by, and a drag inside it to move the shot. The corners come from the same
    matrix the compositor hands the GPU — checked against each other over translation, uneven scale,
    rotation, an off-centre anchor and every combination with a crop — so the handles sit on the
    picture rather than near it. A corner holds the corner across from it still; a rotation is the
    angle between the handle and the pointer, so a pointer that leaves the window and comes back
    lands where it is. The whole drag is one undo step.
  • track.locked is enforced. It sat in the model from the first commit and meant nothing. Now
    one gate in front of the whole command dispatch refuses every edit to a locked track's clips —
    their trims, speed, transforms, effects and keyframes, the track's own chain, and the track
    itself. The mixer, the name and the flags stay reachable, which is how it is unlocked again. An
    insert or overwrite ripples every track, so a single locked track anywhere refuses it outright:
    skipping it would move the picture out from under its own sound.
  • Beats as markers. A rise against a threshold that moves with the music, so the quiet half of
    a track yields the same hits as the loud half. Markers and not cuts — the beat is a suggestion to
    cut against, and a hundred cuts nobody asked for are a hundred clips to take back one at a time.
  • A mixing desk you open. The desk and the instruments both cost the picture about a fifth of
    the window each, and both stood there whether or not anyone was using them: with both open the
    preview was left sixty pixels of seven hundred and its canvas hung out over the toolbar. Both are
    now switches on the transport, folded away until asked for.

Two decisions worth reading

A lock is one gate, not twenty checks. Honouring it inside each handler would mean a lock that
half the commands respect, and the next command anyone adds would be a hole nobody notices. So it is
answered once, in front of the dispatch, by a function that names the tracks a command would change
clips on. Five deliberate mutations of that function were tried; all five died.

A LUT is a medium. The alternative was a new field on the project and a new entry in the
container writer. Under the hash of its own bytes in the library it is already everything the
.videola format knows how to carry, already deduplicated, and already something the export worker
can read without being handed it.

Also

The screenshots in the documentation now come out of the application harness and are cropped to the
page rather than to the window — headless Chrome lays the editor out in a window taller than the
page, and every desktop picture in the guide had carried a hundred and fifty pixels of black under
it. pnpm --filter videola-docs shots is the whole of that step.

What this build is

Desktop installers for Windows, Linux and macOS, plus a Docker image carrying the editor, the HTTP
API and the MCP server. The macOS DMG is unsigned unless an Apple certificate is configured, so
Gatekeeper will block it. Android and iOS assets are absent whenever their signing keys are.

FFmpeg is not bundled: the export runs on the browser's own encoders, and the server cannot render.

Videola 0.4.0 — colour, captions, classical editing

Choose a tag to compare

@github-actions github-actions released this 09 Aug 15:49

Colour grading with scopes, subtitles, classical three-point editing, adjustment layers, and audio
finishing. Four releases in, the editor now covers most of what a day's work needs.

New

  • Colour. Waveform, vectorscope and histogram, read off the preview canvas that was already
    readable. Curves as a first-class parameter type, keyframable point by point — the "parameter
    that is not a float" hurdle named back in M3 is now cleared. Lift, gamma and gain wheels.
  • Subtitles. SRT and WebVTT in and out, on a caption track of its own — a separate track kind,
    because only that can answer which clips are subtitles rather than lower thirds. A millisecond is
    exactly 705,600 flicks, so the round trip is lossless by arithmetic; it is checked byte for byte
    through the parser and again through the real Rust core.
  • Three-point editing. Mark in and out in a medium, then insert or overwrite at the playhead.
    Insert opens the gap on every track — a gap on picture alone would put sound out of step for
    the rest of the film. Each is one command, so an insert across three tracks and a dozen clips is
    one press of undo.
  • Adjustment tracks. They existed in the model and drew nothing at all. Their clips' effects now
    run over everything below them, through the same channel a compound clip already used — zero
    compositor changes.
  • Audio finishing. Live meters per bus, normalise to a loudness target (and measure again rather
    than trust the arithmetic), ducking that writes keyframes you can see and edit, silence detection
    that cuts the pauses out.
  • J/K/L shuttle, markers with colours and notes, preview resolution, an effect browser whose
    every tile is that effect's own shader over the current frame, nine templates in five categories
    with baked preview cards, and a keyframe lane on the timeline.

Two decisions worth reading

A mask is an effect, not a model field. Everything a mask needs already existed for effects, so
masks cost zero lines of interface. Two masks in one chain intersect, and a mask is keyframable, both
for free.

track.locked is deliberately not enforced. A lock is honoured nowhere in the core; making one
command respect it would have made that command the sole authority on what a lock means.

How it is checked

488 Rust tests, 1513 JavaScript tests, and five harnesses needing only an installed Chrome:
366 pixel checks against a real WebGL2 driver, 41 export checks that hand the written file to
ffprobe and ffmpeg, 200 against real browser layout, 252 driving the built application on desktop,
tablet and phone viewports, and one driving the built server bundles over real stdio and HTTP.

Installers

Windows NSIS, Linux deb and AppImage, macOS DMG — all unsigned. Android and iOS are wired but
skipped without signing keys.

Videola 0.3.0 — nesting, keyframed transforms, agents that can see

Choose a tag to compare

@github-actions github-actions released this 08 Aug 21:47

Compound clips, keyframable transforms, agents that can see their own work, and a Docker image that
serves more than static files.

New in this release

  • Compound clips. Fold a selection into one clip. That the picture does not change is proven
    six ways, each against the render before the fold: the whole frame buffer at tolerance zero,
    the draw list at sixteen instants, the source mapping in Rust at 1/60 s steps, the recorded GPU
    batch replayed, and the audio render sample for sample — plus a counterweight so "the compound
    drew nothing" cannot pass.
  • Keyframable transforms. A clip's position, scale, rotation and anchor animate over time,
    resolved in the Rust core like every effect parameter, so the preview and the export cannot
    disagree. Clip::keyframes had existed since the first schema with nothing reading it.
  • Track and project effect chains have an address in the model, and the master volume has a
    command. Nothing renders or sounds them yet — that is the next step, and it is now unblocked.
  • project_getFrame and project_getAudioPeaks. An agent can look at what it just cut. The
    still comes out of the same wasm core, draw list and WebGL2 compositor the editor draws with, in
    headless Chrome, so it cannot show something the editor would not.
  • Autosave. Project state into OPFS every 30 s — not a .videola, because the media are
    already there under their content hash. The banner offers, never takes.
  • Docker that does something. One Node process serves the editor, the HTTP API, the MCP server
    and the CLI. nginx is gone. It refuses to start on a public address without VIDEOLA_TOKEN and
    says why.
  • A CLI: videola apply | describe | validate | schema.
  • Auto-update wired for the desktop builds, injected by CI only when both signing key halves
    exist.

Fixed along the way

Media imported through the API got a library entry with no duration, no dimensions and no channel
count — which silently dropped every such clip from the draw list and from the audio. A get_frame
on a server-imported video would have shown the background and reported success. Both hosts now
build the entry through the same function.

What is still missing

No masks, motion paths, motion blur or LUT import. No EQ or compressor. No noise reduction, ducking
or beat detection. A compound clip is flattened rather than isolated, so opacity, effects and blend
apply per nested clip. The magnetic timeline is deliberately absent — the useful half is ripple
delete and trim, and the rest would change an overlap rule that transitions, layering and roll/slide
all depend on. FFmpeg is not bundled.

How it is checked

385 Rust tests, 1022 JavaScript tests, and five harnesses needing only an installed Chrome: 198
pixel checks against a real WebGL2 driver, 35 export checks that hand the written file to ffprobe
and ffmpeg, 52 against real browser layout, 167 driving the built application on desktop, tablet
and phone viewports, and one driving the built server bundles over real stdio and HTTP.

The application harness is not a CI gate: it depends on font metrics, core count and devtools
timing. Loosening what it asserts would be worth less than the assertions.

Installers

Windows NSIS, Linux deb and AppImage, macOS DMG — all unsigned. Android and iOS are wired but
skipped without signing keys.

Videola 0.2.0 — it edits

Choose a tag to compare

@github-actions github-actions released this 08 Aug 17:45

Videola edits now. Drop a video in, cut it on the timeline, add effects and keyframes, mix the
audio, and export a file a player opens — on a desktop, a tablet or a phone.

What is in this release

  • Editing — ripple delete and trim, roll, slip, slide, multi-selection, groups, clipboard,
    markers, snapping, zoom from one frame to a whole project. One Pointer Events path for mouse,
    pen and finger; a whole drag is one undo step.
  • Playback — WebCodecs decoding into a WebGL2 compositor, the audio clock leading, a
    frame-accurate transport.
  • Effects and transitions — brightness, contrast, saturation, colour temperature, vignette,
    blur, sharpen, chroma key; cross dissolve, wipe, slide, zoom, dip-to-colour; a text generator
    with in/out/loop animation. Every parameter keyframable, interpolated in the Rust core so the
    preview and the export read the same values.
  • Audio — mixer with volume, pan, mute and solo, fades as scheduled automation, waveforms,
    EBU R128 loudness checked against the Tech 3341 conformance cases.
  • Export — MP4 with H.264 and AAC, or WebM with VP9 and Opus. A browser that can encode a
    format's picture but not its sound writes a silent file rather than failing.
  • Templates.videolat is the same container as .videola plus one entry, so a template is
    a project with questions attached. Four ship, none carrying footage.
  • An HTTP API and an MCP server — the whole 37-command catalogue, generated from the Rust enum.

What is not in it

No masks, motion paths, motion blur or LUT import. No nesting of compound clips, no magnetic
timeline, no autosave recovery. No EQ or compressor: the browser has the DSP, the model has nowhere
to persist a track-level effect yet. FFmpeg is not bundled — the export uses the browser's own
encoders.

How it is checked

Four harnesses that need no Playwright, only an installed Chrome: 192 pixel checks against a real
WebGL2 driver, an export verified with ffprobe and ffmpeg by decoding the file it wrote, 52 checks
against real browser layout, and 167 that drive the built application with a real video file on
desktop, tablet and phone viewports. Plus 348 Rust and 923 JavaScript tests.

The last of those four is not a CI gate: it depends on font metrics, core count and devtools
timing, and loosening what it asserts would be worth less than the assertions. It is green on a
developer machine.

Installers

Windows NSIS, Linux deb and AppImage, macOS DMG. All unsigned — macOS Gatekeeper will block the DMG
until signing certificates are configured. Android and iOS are wired but skipped without keys.