Hold the decode ladder the benchmark plays

One row per rung. The app downloads a rung, which measures the link on a file
large enough to escape TCP slow start, then plays it from local storage, which
measures the decoder with the network out of the picture. Keeping those apart is
the point: on the box that actually stutters the connection is fine and the
hardware is not, and a test that streamed while it measured would blame the
wrong one.

A collection rather than files in the image: 76 MB does not belong in something
rebuilt on every push, and a ladder that can be re-cut without shipping a
release is one that will be maintained.

Clips are Big Buck Bunny, Blender Foundation, CC-BY 3.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Claude 2026-09-05 20:58:14 +02:00
parent 2d6782780a
commit bc6ab04673

View file

@ -0,0 +1,69 @@
/// <reference path="../pb_data/types.d.ts" />
// The decode ladder the device benchmark plays.
//
// One row per rung. The app downloads a rung (which measures the link, on a
// file big enough to escape TCP slow start) and then plays it from local
// storage (which measures the decoder, with the network out of the picture).
// Keeping those two apart is the whole point: on the owner's father's box the
// connection is fine and the hardware is not, and a test that streamed while it
// measured would blame the wrong one.
//
// Why a collection rather than files baked into amber-api: 76 MB does not
// belong in a Docker image that is rebuilt on every push, and a ladder that can
// be re-cut without shipping a release is a ladder that will actually be
// maintained.
//
// The clips are cut from Big Buck Bunny (c) Blender Foundation,
// peach.blender.org, CC-BY 3.0. Same ten seconds of high-motion footage at every
// rung, so only resolution, codec and bitrate differ. Each carries an E-AC3 5.1
// track on purpose: the television decodes compressed audio in-app through
// FFmpeg, so that cost is part of what "can this box play this file" means.
//
// The file is deliberately NOT protected. There is nothing to gate (the source
// is CC-BY) and an unprotected URL can be handed straight to a player. Listing
// still needs a signed-in account, like everything else here.
migrate(
(app) => {
const clips = new Collection({
type: "base",
name: "benchmark_clips",
listRule: "@request.auth.id != ''",
viewRule: "@request.auth.id != ''",
createRule: null,
updateRule: null,
deleteRule: null,
fields: [
// Stable identifier the app switches on; the label is what a person reads.
{ type: "text", name: "key", required: true, max: 20 },
{ type: "text", name: "label", required: true, max: 40 },
// Rungs are ordered, and the order is the answer: the highest rung that
// plays clean is what the box can do.
{ type: "number", name: "rung", required: true, min: 1, onlyInt: true },
{ type: "number", name: "width", required: true, min: 1, onlyInt: true },
{ type: "number", name: "height", required: true, min: 1, onlyInt: true },
{ type: "text", name: "codec", required: true, max: 20 },
{ type: "number", name: "bitrateBps", required: true, min: 1, onlyInt: true },
{ type: "number", name: "durationS", required: true, min: 1 },
{
type: "file",
name: "file",
required: true,
maxSelect: 1,
maxSize: 104857600,
protected: false,
},
{ type: "autodate", name: "created", onCreate: true },
{ type: "autodate", name: "updated", onCreate: true, onUpdate: true },
],
indexes: [
"CREATE UNIQUE INDEX idx_benchmark_clips_key ON benchmark_clips (key)",
],
});
app.save(clips);
},
(app) => {
app.delete(app.findCollectionByNameOrId("benchmark_clips"));
},
);