record-free.openapps.xyz

Source

This app’s code and revision history are public. Download a copy or explore the files below.

Public
The app’s code and revision history are public.
Owned app · rev 1c51a6b34b9a
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone 46e773698d4102c284d30369
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
← All files
src/lib/media.ts
// Rewrites a recording into a clean file, optionally cut to a start and end, with Mediabunny
// (https://mediabunny.dev). Loaded only when a recording is saved or trimmed; runs on this device.
//
// The browser's recorder writes files as a stream, without their length and with few points a player
// can seek to. Rewriting them (no re-encoding) adds both, so the file shows its length and seeks
// everywhere. Trimming re-encodes the video with the browser's own encoder, so the cut lands exactly
// where the person put it, not on the nearest key frame.
import { BlobSource, Conversion, Input, MP4, Mp4OutputFormat, Output, StreamTarget, WEBM, WebMOutputFormat, type StreamTargetChunk } from "mediabunny";

const read = (blob: Blob) => new Input({ source: new BlobSource(blob), formats: [MP4, WEBM] });

export async function remake(blob: Blob, cut: { start: number; end: number } | null, onProgress: (done: number) => void): Promise<{ blob: Blob; duration: number }> {
  const type = blob.type;
  // Built as a Blob, not one big buffer, so long recordings do not have to fit in memory at once.
  let out = new Blob([]);
  const target = new StreamTarget(
    new WritableStream<StreamTargetChunk>({
      write({ data, position }) {
        out = new Blob([out.slice(0, position), data, out.slice(position + data.byteLength)]);
      },
    }),
    { chunked: true },
  );
  const output = new Output({ format: type.includes("mp4") ? new Mp4OutputFormat() : new WebMOutputFormat(), target });
  const conversion = await Conversion.init({
    input: read(blob),
    output,
    trim: cut ?? undefined,
    // Audio packets are copied as they are, shifted by at most a few hundredths of a second to line up with
    // the cut. Video is re-encoded unless a key frame falls on the cut.
    copy: cut ? { boundaryTolerance: 0.05, shiftTolerance: 0.05 } : {},
    showWarnings: false,
  });
  if (!conversion.isValid) throw new Error("This browser cannot edit this recording.");
  conversion.onProgress = onProgress;
  await conversion.execute();
  const file = new Blob([out], { type });
  return { blob: file, duration: await read(file).computeDuration() };
}

Change history

Point store links to openapps.free
1c51a6b34b · 18 hours ago
Bind agent address in policy
50f7c610b7 · 19 hours ago
Link OpenApps pages and add contribution strip
99dc7c6d18 · 19 hours ago
Bounded source sync
16c8400957 · 2 days ago
Bounded source sync
c07b7aea64 · 2 days ago
Bounded source sync
f19b8997d3 · 2 days ago