feat: publish av-tools 0.2.0
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
# FFmpeg WebAssembly build record
|
||||
|
||||
av-tools ships the published ESM assets from `@ffmpeg/core` and
|
||||
`@ffmpeg/core-mt` **0.12.10**. The browser wrapper is `@ffmpeg/ffmpeg`
|
||||
**0.12.15** and helpers are `@ffmpeg/util` **0.12.2**. All versions are exact,
|
||||
not ranges.
|
||||
av-tools ships the locally rebuilt, reviewed core profile
|
||||
`0.12.10-reviewed-stack5m.1` in single-thread and multithread forms. The
|
||||
browser wrapper is `@ffmpeg/ffmpeg` **0.12.15** and helpers are
|
||||
`@ffmpeg/util` **0.12.2**. All versions and build inputs are exact, not ranges.
|
||||
|
||||
## Underlying build
|
||||
|
||||
The matching ffmpeg.wasm upstream release is `v12.15` at
|
||||
The base ffmpeg.wasm upstream release is `v12.15` at
|
||||
`71aa99d37c02a7b4c435275ca9ef50e612f6efa1`. Its Dockerfile selects:
|
||||
|
||||
- FFmpeg **n5.1.4** (libavcodec 59.37.100);
|
||||
@@ -15,6 +15,14 @@ The matching ffmpeg.wasm upstream release is `v12.15` at
|
||||
- production `-O3 -msimd128`;
|
||||
- pthread flags for the MT build and explicit thread disabling for ST.
|
||||
|
||||
The reviewed profile then applies upstream ffmpeg.wasm commit
|
||||
`b409e36475bc21f0451b5b1e1d126fa82871439a` to select a 5 MiB Emscripten stack.
|
||||
That upstream fix addresses the libopus zero-byte/out-of-bounds failures
|
||||
reported in issues `#591` and `#775`. The local driver additionally makes the
|
||||
upstream container-stage dependency isolation explicit, disables native x265
|
||||
assembly for the wasm32 build, bounds parallel jobs and refuses output that
|
||||
contains the maintainer's repository or SDK paths.
|
||||
|
||||
The build configuration embedded in both copied WASM files is:
|
||||
|
||||
```text
|
||||
@@ -35,8 +43,8 @@ The build configuration embedded in both copied WASM files is:
|
||||
--cxx=em++
|
||||
--objcc=emcc
|
||||
--dep-cc=emcc
|
||||
--extra-cflags='-I/opt/include -O3 -msimd128'
|
||||
--extra-cxxflags='-I/opt/include -O3 -msimd128'
|
||||
--extra-cflags='-I../../../../install/include -O3 -msimd128'
|
||||
--extra-cxxflags='-I../../../../install/include -O3 -msimd128'
|
||||
--enable-gpl
|
||||
--enable-libx264
|
||||
--enable-libx265
|
||||
@@ -76,16 +84,26 @@ respective branch tips. `SOURCE.md` records retrieval commands.
|
||||
|
||||
| Mode | File | Bytes | SHA-256 |
|
||||
| ---- | -------------------------- | -------: | ------------------------------------------------------------------ |
|
||||
| ST | `st/ffmpeg-core.js` | 111804 | `67a48f11645f85439f3fde4f2119042c16b374b910206b7a7a24f342e28dcae3` |
|
||||
| ST | `st/ffmpeg-core.wasm` | 32232419 | `9f57947a5bd530d8f00c5b3f2cb2a3492faa7e5d823315342d6a8656d0a6b7b7` |
|
||||
| MT | `mt/ffmpeg-core.js` | 128947 | `270a2e6ff945e173238610669a3f7132df5f9c52698a9bf708cf5c2ab6bda0de` |
|
||||
| MT | `mt/ffmpeg-core.wasm` | 32718323 | `be2c97605366b78f3f13e21b52e81a55a79e1f29c133b03a68ec187b1a2ec41a` |
|
||||
| ST | `st/ffmpeg-core.js` | 111804 | `80c05d79d0e4e9434977b76cb851d10ddf2bfd378570178700d2c43b8afdcb24` |
|
||||
| ST | `st/ffmpeg-core.wasm` | 32232580 | `fe41ddc77220cef6c04f5d48eeffcaaaef179ad270642e098f9945013aa0c9dc` |
|
||||
| MT | `mt/ffmpeg-core.js` | 128953 | `4f2650099ab70cb2583951c0421147c62bea6c18dfbba5cfae4d7698b5d0ab62` |
|
||||
| MT | `mt/ffmpeg-core.wasm` | 32718455 | `abbead010cb0448b26f01a36a3c8c03a6b04aca07812ddd4719a7f4b6bf4b645` |
|
||||
| MT | `mt/ffmpeg-core.worker.js` | 2115 | `f77898d631dc010b45c29c23cb4379c611a7d7b131bf591d08a656bb729a4ca3` |
|
||||
|
||||
`npm run vendor:ffmpeg` copies these files from `node_modules` to
|
||||
`public/vendor/ffmpeg/0.12.10/`; `npm run vendor:verify` checks versions,
|
||||
sizes, paths and digests. Vite then copies them unchanged into `dist`. A normal
|
||||
production build performs no network download.
|
||||
The deterministic five-file repository artifact is 21,338,974 bytes with
|
||||
SHA-256
|
||||
`ebc068c6d096de55ae3335b04b7121130665f5b0ffa7a828067122733f55185f`.
|
||||
|
||||
`npm run vendor:ffmpeg` verifies and unpacks the deterministic tracked core
|
||||
artifact to
|
||||
`public/vendor/ffmpeg/0.12.10-reviewed-stack5m.1/`;
|
||||
`npm run vendor:verify-runtime` checks the build profile,
|
||||
source/toolchain/patch identity, tracked artifact, generated paths, sizes and
|
||||
digests without requiring a release-directory download. The stricter
|
||||
`npm run vendor:verify` release gate also hashes the build-qualified
|
||||
Corresponding Source archive. Vite then copies the verified bytes into `dist`.
|
||||
A normal production build performs no network download and cannot fall back
|
||||
to the older published npm core bytes.
|
||||
|
||||
## Multithread Chromium guardrail
|
||||
|
||||
@@ -118,26 +136,42 @@ This is a conservative browser-memory guardrail, not a guarantee that sixteen
|
||||
large jobs or three large contact sheets fit in memory. Cancellation and
|
||||
failed filesystem-cleanup recovery continue to recreate the core immediately.
|
||||
|
||||
## Opus regression risk
|
||||
## Opus regression evidence
|
||||
|
||||
Pinned core 0.12.10 predates upstream ffmpeg.wasm fixes associated with stack
|
||||
size and Opus zero-byte/out-of-bounds failures (including upstream issues
|
||||
`#591` and `#775`). Therefore:
|
||||
Published core 0.12.10 predates the upstream stack-size fix and stalled in the
|
||||
real Opus preset path even though it advertised the `opus` muxer and
|
||||
`libopus` encoder. Capability discovery alone was therefore not accepted as
|
||||
enablement evidence.
|
||||
|
||||
- decoder/encoder listing is not enough to certify Opus;
|
||||
- real ST and MT fixture encodes must produce a non-empty, re-probeable output;
|
||||
- the Opus audio and VP9/Opus presets must remain disabled with a diagnostic
|
||||
if that smoke fails;
|
||||
- a core upgrade requires new checksums, capability snapshots, legal review
|
||||
and regression tests.
|
||||
On 2026-07-26 the Chromium harness used the checked
|
||||
`tests/fixtures/generated/tone.wav` fixture (32,102 bytes, SHA-256
|
||||
`0fd1f54d6be2f1cc7fd778775dd29cf184770d3716cf3394bf03ed54ac264c3c`)
|
||||
and the real built-in `audio-opus` preset/command planner. After rebuilding
|
||||
with the reviewed stack profile, the isolated ST and MT runs each:
|
||||
|
||||
This is a known pinned-core risk, not a claim that every Opus job fails.
|
||||
- loaded the requested mode rather than a fallback;
|
||||
- mapped PCM audio to `opus (libopus)`;
|
||||
- opened the declared Opus output and reported its libopus encoder;
|
||||
- returned non-empty bytes within its independent containment limit;
|
||||
- re-probed the result as positive-duration Opus audio.
|
||||
|
||||
```sh
|
||||
# Record JSON evidence.
|
||||
npm run evidence:opus
|
||||
|
||||
# Positive Opus enablement/release gate.
|
||||
npm run test:opus-regression
|
||||
```
|
||||
|
||||
The Opus audio and VP9/Opus presets are enabled only when the reviewed-core
|
||||
lock records both passing modes and runtime discovery finds every preset
|
||||
requirement. This is exact Chromium fixture evidence, not a claim about every
|
||||
browser, input or possible Opus build.
|
||||
|
||||
## Licence consequence
|
||||
|
||||
The core packages declare GPL-2.0-or-later and the actual build enables GPL and
|
||||
links external codecs. The wrapper/util are MIT. av-tools is
|
||||
GPL-3.0-or-later, and the distributed application must not be described as
|
||||
MIT-only. Publish the reviewed Corresponding Source and external notices with
|
||||
the binary release. See `LICENSE`, `LICENSES/`, `THIRD_PARTY_NOTICES.md` and
|
||||
`SOURCE.md`.
|
||||
The actual core build enables GPL and links external codecs. The wrapper/util
|
||||
are MIT. av-tools is GPL-3.0-or-later, and the distributed application must
|
||||
not be described as MIT-only. Publish the reviewed Corresponding Source and
|
||||
external notices with the binary release. See `LICENSE`, `LICENSES/`,
|
||||
`THIRD_PARTY_NOTICES.md` and `SOURCE.md`.
|
||||
|
||||
@@ -5,7 +5,7 @@ extensions or this document. The app queries muxers, demuxers, decoders,
|
||||
encoders and filters; a preset is disabled with missing components listed.
|
||||
Browser playback is a separate capability checked with MIME/media APIs.
|
||||
|
||||
## 0.1.0 candidate fixture matrix
|
||||
## 0.2.0 release fixture matrix
|
||||
|
||||
All 15 files are generated and re-probed with native FFmpeg 7.1.3 for test
|
||||
preparation and pass the checksum/probe verifier. That proves fixture
|
||||
@@ -41,20 +41,20 @@ browser may still be unable to preview the result.
|
||||
|
||||
Preset availability always depends on detected runtime requirements:
|
||||
|
||||
| Preset family | Required examples | Browser result preview |
|
||||
| ------------------ | ---------------------------------------- | ------------------------------------------------------ |
|
||||
| MP4 H.264/AAC | `mp4`, `libx264`, `aac` | usually, but verify actual output |
|
||||
| WebM VP9/Opus | `webm`, `libvpx-vp9`, `libopus` | browser-dependent; Opus core regression gate applies |
|
||||
| WebM VP8/Vorbis | `webm`, `libvpx`, `libvorbis` | commonly Chromium/Firefox |
|
||||
| Matroska H.264/AAC | `matroska`, `libx264`, `aac` | generally download-only in browsers |
|
||||
| animated WebP | `webp`, `libwebp_anim` | browser-dependent image preview |
|
||||
| GIF | `gif`, `gif`, `palettegen`, `paletteuse` | broadly image-previewable |
|
||||
| MP3 | `mp3`, `libmp3lame` | commonly playable |
|
||||
| M4A/AAC | `ipod`, `aac` | commonly playable |
|
||||
| Ogg Vorbis | `ogg`, `libvorbis` | browser-dependent |
|
||||
| Opus | `opus`, `libopus` | browser-dependent; pinned-core regression gate applies |
|
||||
| WAV/PCM | `wav`, `pcm_s16le` | commonly playable |
|
||||
| FLAC | `flac`, `flac` | browser-dependent |
|
||||
| Preset family | Required examples | Browser result preview |
|
||||
| ------------------ | ---------------------------------------- | -------------------------------------------------------- |
|
||||
| MP4 H.264/AAC | `mp4`, `libx264`, `aac` | usually, but verify actual output |
|
||||
| WebM VP9/Opus | `webm`, `libvpx-vp9`, `libopus` | enabled when the loaded core advertises all requirements |
|
||||
| WebM VP8/Vorbis | `webm`, `libvpx`, `libvorbis` | commonly Chromium/Firefox |
|
||||
| Matroska H.264/AAC | `matroska`, `libx264`, `aac` | generally download-only in browsers |
|
||||
| animated WebP | `webp`, `libwebp_anim` | browser-dependent image preview |
|
||||
| GIF | `gif`, `gif`, `palettegen`, `paletteuse` | broadly image-previewable |
|
||||
| MP3 | `mp3`, `libmp3lame` | commonly playable |
|
||||
| M4A/AAC | `ipod`, `aac` | commonly playable |
|
||||
| Ogg Vorbis | `ogg`, `libvorbis` | browser-dependent |
|
||||
| Opus | `opus`, `libopus` | Chromium ST/MT encode and re-probe recorded |
|
||||
| WAV/PCM | `wav`, `pcm_s16le` | commonly playable |
|
||||
| FLAC | `flac`, `flac` | browser-dependent |
|
||||
|
||||
“Lossless” applies only to a lossless audio codec such as PCM/FLAC relative to
|
||||
its decoded samples. It does not make a lossy source lossless. Stream-copy
|
||||
@@ -77,11 +77,30 @@ remux avoids re-encoding compatible streams but may change container metadata.
|
||||
- Normalized concat uses an explicit export preset and requires an explicit
|
||||
insert-silence, drop-all-audio or reject policy when clips have mismatched
|
||||
audio presence.
|
||||
- Normalized concat can overlap every edit with one uniform 0.04–10 second
|
||||
`xfade` and, when audio is retained, `acrossfade`. End clips must contain at
|
||||
least one transition duration and internal clips two; the active core must
|
||||
expose each required filter.
|
||||
- Crop, resize, frame-rate conversion, fades, normalization, burn-in and
|
||||
contact sheets require specific filters discovered at runtime.
|
||||
- Even-dimension correction is applied when the selected pixel format/encoder
|
||||
requires it and is reported in the plan/result.
|
||||
|
||||
## Images and scene selection
|
||||
|
||||
Thumbnail/contact-sheet scene mode first performs a bounded full-source
|
||||
analysis with `select`/`showinfo`, stopping after at most 100 qualifying
|
||||
frames. Extraction then selects those exact source PTS values; no guessed time
|
||||
rounding or remote analysis is used. If no frame meets the 0.01–0.95 threshold,
|
||||
the operation reports that result and asks for a lower threshold or a
|
||||
deterministic selection mode.
|
||||
|
||||
Contact-sheet labels require runtime `drawtext`. The app mounts only its
|
||||
same-origin DejaVu Sans 2.37 asset after verifying 757,076 bytes and SHA-256
|
||||
`7da195a74c55bef988d0d48f9508bd5d849425c1770dba5d7bfc6ce9ed848954`.
|
||||
No remote or host-system font fallback is used. `SOURCE.md` and
|
||||
`LICENSES/DEJAVU_FONTS.txt` provide provenance and terms.
|
||||
|
||||
## Subtitles
|
||||
|
||||
The text fixtures cover SRT, WebVTT and ASS import with explicit time shift.
|
||||
@@ -115,8 +134,9 @@ elements do not reliably expose them, so ffprobe round-trip is authoritative.
|
||||
- frame-accurate stream-copy trimming;
|
||||
- complete metadata erasure/anonymity;
|
||||
- browser preview of every FFmpeg-readable result;
|
||||
- Opus presets until real non-empty ST/MT encoding smoke passes for core
|
||||
0.12.10;
|
||||
- Opus on browsers, inputs or deployments outside the exact reviewed
|
||||
Chromium regression: both ST and MT pass the non-empty encode/re-probe gate,
|
||||
but runtime capability discovery and normal per-job limits still apply;
|
||||
- any capability omitted by the active core's runtime query.
|
||||
|
||||
Update this file only from re-probed generated/public-domain fixtures and
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Known limitations
|
||||
|
||||
This is the conservative 0.1.0 development baseline. A capability appearing in
|
||||
This is the conservative 0.2.0 release baseline. A capability appearing in
|
||||
FFmpeg output does not remove these product/browser/resource limits.
|
||||
|
||||
## Functional
|
||||
@@ -13,6 +13,9 @@ FFmpeg output does not remove these product/browser/resource limits.
|
||||
frame-accurate. Accurate mode requires decoding/re-encoding.
|
||||
- Stream-copy concatenate works only when selected streams and codec/container
|
||||
parameters are compatible. Other input needs normalized re-encoding.
|
||||
- Crossfades are uniform fade/triangular-curve transitions on normalized
|
||||
sequential joins, not arbitrary transition effects or overlapping timeline
|
||||
tracks. They require enough material on both sides of every internal edit.
|
||||
- Re-encoding is not lossless. PCM/FLAC can preserve decoded audio samples but
|
||||
cannot restore information already lost in a source.
|
||||
- Metadata removal is best effort. Muxers may add structural/encoder fields,
|
||||
@@ -26,6 +29,12 @@ FFmpeg output does not remove these product/browser/resource limits.
|
||||
page discards queued work.
|
||||
- A file-generating batch and its managed result collection are bounded to 255
|
||||
outputs, leaving the 256th ZIP entry available for an optional export report.
|
||||
- Scene analysis scans the source until it finds the requested changes or
|
||||
reaches the end, retains at most 100 exact PTS results and can therefore take
|
||||
about as long as a full decode. It does not begin an export implicitly when
|
||||
no frame meets the chosen threshold.
|
||||
- Labelled contact sheets require a core with `drawtext`; the reviewed local
|
||||
font does not make that filter available on a core that omits it.
|
||||
- Preview proxies are bounded, lossy H.264/AAC derivatives for local playback;
|
||||
they do not replace the source or guarantee that every browser can play the
|
||||
result.
|
||||
@@ -38,8 +47,9 @@ FFmpeg output does not remove these product/browser/resource limits.
|
||||
support fewer container/codec combinations.
|
||||
- Browser support, codec policy and memory differ across Chromium, Firefox and
|
||||
Safari and across desktop/mobile versions.
|
||||
- Core 0.12.10 has an Opus regression risk. Opus remains release-gated until
|
||||
non-empty, re-probeable ST and MT fixture outputs pass.
|
||||
- The reviewed 0.12.10 core profile passes the non-empty Opus encode/re-probe
|
||||
gate in isolated Chromium ST and MT runs. That evidence is not a
|
||||
cross-browser or every-input Opus guarantee.
|
||||
- MT needs HTTPS, COOP/COEP/CORP and `SharedArrayBuffer`. ST fallback works
|
||||
without isolation but is not a guarantee that a large job fits.
|
||||
- Top-level navigation is supported; iframe embedding is not.
|
||||
@@ -69,7 +79,7 @@ FFmpeg output does not remove these product/browser/resource limits.
|
||||
verification against the live container.
|
||||
- The application is GPL-3.0-or-later and its native legal files and pinned
|
||||
source identities are included in the release record. Publish the production
|
||||
ZIP/checksum, exact `v0.1.0` source and FFmpeg Corresponding Source bundle
|
||||
ZIP/checksum, exact `v0.2.0` source and FFmpeg Corresponding Source bundle
|
||||
together; development-only smoke artifacts must not be distributed.
|
||||
- Chromium covers a broad real pinned-core ST operation matrix, a real MT
|
||||
H.264/AAC conversion, MT-to-ST fallback, nested static/Toolbox-context
|
||||
|
||||
@@ -6,12 +6,13 @@ output at once. No hardware encoder is used.
|
||||
|
||||
## Fixed download footprint
|
||||
|
||||
Uncompressed self-hosted core assets for 0.12.10:
|
||||
Uncompressed self-hosted core assets for
|
||||
`0.12.10-reviewed-stack5m.1`:
|
||||
|
||||
| Mode | JavaScript/worker | WASM | Total |
|
||||
| ------------- | ------------------: | -----------: | -----------: |
|
||||
| single-thread | 111,804 B | 32,232,419 B | 32,344,223 B |
|
||||
| multithread | 128,947 B + 2,115 B | 32,718,323 B | 32,849,385 B |
|
||||
| single-thread | 111,804 B | 32,232,580 B | 32,344,384 B |
|
||||
| multithread | 128,953 B + 2,115 B | 32,718,455 B | 32,849,523 B |
|
||||
|
||||
Only the selected mode is loaded. HTTP compression may reduce JavaScript
|
||||
transfer but not necessarily WASM to the same degree; report transfer and
|
||||
@@ -72,9 +73,18 @@ Estimated output warns at 512 MiB and is blocked at 1 GiB. FFmpeg jobs are
|
||||
serial; the application retains at most eight scheduled operations in its
|
||||
in-memory queue. Timeline clips are capped at 100, streams per input at 64,
|
||||
images at 8192×8192/67,108,864 pixels, generated output files at 255,
|
||||
contact-sheet cells at 500 and runtime at four hours. The documented
|
||||
ffmpeg.wasm input ceiling is 2 GiB, but real limits can be substantially lower
|
||||
on mobile or memory-constrained browsers.
|
||||
contact-sheet cells at 500, scene-change results at 100, crossfades at 10
|
||||
seconds and runtime at four hours. Scene selection is a bounded two-step
|
||||
workflow but its analysis step can still decode the complete source when few
|
||||
frames meet the threshold. The documented ffmpeg.wasm input ceiling is 2 GiB,
|
||||
but real limits can be substantially lower on mobile or memory-constrained
|
||||
browsers.
|
||||
|
||||
Source inspection has a bounded, size-aware watchdog: 30 seconds for small
|
||||
files, a two-MiB-per-second scan budget for larger files, and a five-minute
|
||||
ceiling. Recognized local audio/video can begin browser playback from its
|
||||
temporary object URL while that worker inspection continues; completed probe
|
||||
metadata remains authoritative for editing and export.
|
||||
|
||||
Lowering resolution, duration, frame rate, passes and output count reduces
|
||||
work. MT can be faster but consumes more memory/CPU and requires isolation; ST
|
||||
|
||||
@@ -18,7 +18,7 @@ X-Content-Type-Options: nosniff
|
||||
|
||||
Serve `.wasm` as `application/wasm`, JavaScript modules as a JavaScript MIME
|
||||
type and JSON as `application/json`. Test real responses under
|
||||
`/apps/av/vendor/ffmpeg/0.12.10/...`; a file-extension allowlist alone does not
|
||||
`/apps/av/vendor/ffmpeg/0.12.10-reviewed-stack5m.1/...`; a file-extension allowlist alone does not
|
||||
prove the MIME type.
|
||||
|
||||
Suggested CSP:
|
||||
@@ -43,45 +43,36 @@ form-action 'none';
|
||||
`'unsafe-eval'` is unnecessary. `worker-src blob:` covers the wrapper-created
|
||||
worker path. `media-src blob:` permits local source/result previews.
|
||||
|
||||
## Immutable reference and active-worktree state
|
||||
## Reviewed Portal state
|
||||
|
||||
Portal revision `bda9da044d61c109afd9969d357cc27f76648938` already sends COOP
|
||||
`same-origin`, COEP `require-corp`, CORP `same-origin`, `script-src 'self'
|
||||
'wasm-unsafe-eval'`, and `worker-src 'self' blob:`. Its packaged nginx CSP does
|
||||
**not** declare `media-src`; `default-src 'self'` therefore blocks local
|
||||
`blob:` audio/video URLs. The expected browser diagnostic is equivalent to:
|
||||
Portal revision `5c052bc6d1073a66600cfddc44c0e16da34bede8` (tag `v0.6.0`)
|
||||
already sends COOP `same-origin`, COEP `require-corp`, CORP `same-origin`,
|
||||
`script-src 'self' 'wasm-unsafe-eval'`, `worker-src 'self' blob:` and
|
||||
`media-src 'self' blob:`. Its nginx profile also maps `.wasm` explicitly to
|
||||
`application/wasm`. Local source and result Blob previews therefore require no
|
||||
CSP exception beyond that reviewed narrow media directive.
|
||||
|
||||
```text
|
||||
Refused to load media from 'blob:…' because it violates
|
||||
"default-src 'self'".
|
||||
```
|
||||
As inspected on 2026-07-26, the active
|
||||
`/mnt/DATA/git/toolbox-portal/deploy/nginx.conf` has an additional worktree
|
||||
patch that extends the immutable FFmpeg cache rule from plain semantic versions
|
||||
to the one exact reviewed build profile
|
||||
`0.12.10-reviewed-stack5m.1`. The corresponding deployment tests accept the
|
||||
five reviewed core files and `version.json` while rejecting mutable-looking
|
||||
suffixes, malformed versions and unexpected paths. A clean temporary clone
|
||||
containing that exact patch passed the AV release assembly smoke without a
|
||||
known-header-gap override.
|
||||
|
||||
Smallest required Portal change: append exactly
|
||||
`media-src 'self' blob:;` to that CSP. This permits only same-origin and
|
||||
in-memory Blob media; it does not permit remote media hosts, inline script or
|
||||
eval. If the Portal is not changed, conversion/download can remain available
|
||||
but Blob source/result preview must show a clear disabled reason.
|
||||
|
||||
As inspected on 2026-07-24, the active
|
||||
`/mnt/DATA/git/toolbox-portal/deploy/nginx.conf` contains that exact directive
|
||||
as a local worktree patch. The worktree still resolves to the immutable
|
||||
revision above, so the patch is useful for local deployment testing but is not
|
||||
a committed Portal revision and must not be cited as published release
|
||||
evidence. The clean-reference assembly smoke therefore continues to require
|
||||
`--allow-known-header-gap` until a reviewed Portal commit contains the fix.
|
||||
|
||||
The nginx profile includes `.wasm` in its static allowlist/gzip types but
|
||||
relies on the base image `mime.types`. Verify `Content-Type:
|
||||
application/wasm` against the pinned image; add an explicit mapping if the
|
||||
response differs.
|
||||
Until the cache extension is committed, cite it only as staged integration
|
||||
evidence, not as a published Portal revision. The clean `v0.6.0` rule leaves
|
||||
the reviewed profile at `no-cache`; that affects performance, not loading,
|
||||
MIME type, isolation or preview correctness.
|
||||
|
||||
## Caching
|
||||
|
||||
The immutable Portal reference's cache map makes Vite content-hashed assets
|
||||
immutable but leaves versioned FFmpeg cores at `no-cache`. Correctness is
|
||||
unaffected.
|
||||
For performance, the exact directory
|
||||
`apps/av/vendor/ffmpeg/0.12.10/{st,mt}/` may receive:
|
||||
The staged Portal cache map makes Vite content-hashed assets, plain semantic
|
||||
versions and the explicitly reviewed profile immutable. For performance, the
|
||||
exact directory
|
||||
`apps/av/vendor/ffmpeg/0.12.10-reviewed-stack5m.1/{st,mt}/` may receive:
|
||||
|
||||
```text
|
||||
Cache-Control: public, max-age=31536000, immutable
|
||||
|
||||
@@ -1,28 +1,31 @@
|
||||
# Reference implementations
|
||||
|
||||
Inspection date: **2026-07-24**.
|
||||
Inspection dates: **2026-07-24** (initial implementation) and
|
||||
**2026-07-26** (remaining-slice integration).
|
||||
|
||||
The references were cloned beside av-tools under
|
||||
`/mnt/DATA/git/references/`; no reference repository was nested in this
|
||||
working tree. Revisions are full immutable commit ids.
|
||||
|
||||
| Repository | Revision inspected | Used for | Copied or adapted |
|
||||
| -------------------------------------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| av-tools, `git@git.add-ideas.de:zemion/av-tools.git` | no revision: canonical `main` was unborn and had no commits | canonical destination and licence/history check | the empty repository was scaffolded in place; no prior code existed |
|
||||
| Toolbox SDK, `https://git.add-ideas.de/zemion/toolbox-sdk.git` | `53c40a61ba1581246f65773fcbb1c1cfd31ac98e` (SDK 0.2.2) | manifest schema/definition, `AppShell`, context behavior, shared styles, token-free registry, nested-path checks and toolchain baseline | published 0.2.2 packages are direct dependencies; documented usage patterns were followed; no SDK source file was copied |
|
||||
| Toolbox Portal, `https://git.add-ideas.de/zemion/toolbox-portal.git` | `bda9da044d61c109afd9969d357cc27f76648938` | release ZIP/sidecar/lock formats, independent assembly, catalogue behavior, path security, nested deployment and production headers | no portal application source was copied; the documented artifact contract informed an independent release packager and smoke harness |
|
||||
| ffmpeg.wasm, `https://github.com/ffmpegwasm/ffmpeg.wasm.git` | `f876f907c7e9b9bf51d4ed0b913a855a63ae63fc` | current API, worker lifecycle, filesystem, loading, ST/MT behavior, licence documentation and build layout | no reference-worktree code was copied; exact published npm packages are dependencies and their five core assets are copied verbatim by the vendor script |
|
||||
| Repository | Revision inspected | Used for | Copied or adapted |
|
||||
| -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| av-tools, `git@git.add-ideas.de:zemion/av-tools.git` | no revision: canonical `main` was unborn and had no commits | canonical destination and licence/history check | the empty repository was scaffolded in place; no prior code existed |
|
||||
| Toolbox SDK, `https://git.add-ideas.de/zemion/toolbox-sdk.git` | `53c40a61ba1581246f65773fcbb1c1cfd31ac98e` (SDK 0.2.2) | manifest schema/definition, `AppShell`, context behavior, shared styles, token-free registry, nested-path checks and toolchain baseline | published 0.2.2 packages are direct dependencies; documented usage patterns were followed; no SDK source file was copied |
|
||||
| Toolbox Portal, `https://git.add-ideas.de/zemion/toolbox-portal.git` | `bda9da044d61c109afd9969d357cc27f76648938` initially; `5c052bc6d1073a66600cfddc44c0e16da34bede8` for final integration | release ZIP/sidecar/lock formats, independent assembly, catalogue behavior, path security, nested deployment and production headers | no portal application source was copied; the AV smoke harness consumes only an exact cloned Portal revision; the separate Portal worktree contains its own reviewed integration patch |
|
||||
| ffmpeg.wasm, `https://github.com/ffmpegwasm/ffmpeg.wasm.git` | `f876f907c7e9b9bf51d4ed0b913a855a63ae63fc`; pinned release baseline `71aa99d37c02a7b4c435275ca9ef50e612f6efa1` | current API, worker lifecycle, filesystem, loading, ST/MT behavior, licence documentation and build layout | no reference-worktree source was copied; wrapper/util remain exact npm dependencies, while the five core assets are rebuilt from the recorded source/toolchain/patch profile and verified against the build lock |
|
||||
|
||||
For the **pinned** package set, the more specific upstream release tag
|
||||
`v12.15` at `71aa99d37c02a7b4c435275ca9ef50e612f6efa1` was also inspected. It
|
||||
contains `@ffmpeg/ffmpeg` 0.12.15 and core/core-mt 0.12.10. That revision's
|
||||
build selects FFmpeg n5.1.4.
|
||||
contains `@ffmpeg/ffmpeg` 0.12.15 and the source configuration for core
|
||||
0.12.10. That revision's build selects FFmpeg n5.1.4. The shipped
|
||||
`0.12.10-reviewed-stack5m.1` assets additionally apply upstream ffmpeg.wasm
|
||||
commit `b409e36475bc21f0451b5b1e1d126fa82871439a`; exact build and source
|
||||
identities are in `SOURCE.md` and `docs/FFMPEG_BUILD.md`.
|
||||
|
||||
The user's active `/mnt/DATA/git/toolbox-portal` worktree still has Portal
|
||||
revision `bda9da044d61c109afd9969d357cc27f76648938` as `HEAD`, but currently
|
||||
contains a local `media-src 'self' blob:` nginx CSP patch. That mutable
|
||||
worktree state is documented for deployment testing only; it does not replace
|
||||
the immutable reference in the table.
|
||||
The active `/mnt/DATA/git/toolbox-portal` worktree has immutable revision
|
||||
`5c052bc6d1073a66600cfddc44c0e16da34bede8` as `HEAD`. Its staged cache-rule
|
||||
extension is documented separately and is not represented as a published
|
||||
revision.
|
||||
|
||||
Official behavior references:
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ The repository already declares the application licence and immutable
|
||||
third-party source identities. Before any distribution:
|
||||
|
||||
1. commit the reviewed GPL-3.0-or-later source;
|
||||
2. create and verify annotated tag `v0.1.0` at that exact commit;
|
||||
2. create and verify annotated tag `v0.2.0` at that exact commit;
|
||||
3. push the commit and tag to the canonical public repository;
|
||||
4. assemble, review and publish corresponding source and exact external
|
||||
notices for both core packages and linked libraries;
|
||||
notices for both reviewed core profiles and linked libraries;
|
||||
5. keep the manifest/package metadata, `SOURCE.md`, ZIP and tag version aligned.
|
||||
|
||||
`SOURCE.md` pins FFmpeg, ffmpeg.wasm, x264 and LAME by full commit. Do not
|
||||
@@ -44,6 +44,7 @@ Normal packaging validates the root GPL version 3 text and matching
|
||||
```sh
|
||||
npm run package:release
|
||||
npm run source:package
|
||||
npm run vendor:verify
|
||||
```
|
||||
|
||||
The legacy development-only escape hatch is retained only for checking an
|
||||
@@ -56,19 +57,19 @@ npm run package:release -- --allow-unlicensed-development-smoke
|
||||
Pass `--force` only to replace the exact same-version ZIP and sidecar. Output:
|
||||
|
||||
```text
|
||||
release/av-tools-0.1.0.zip
|
||||
release/av-tools-0.1.0.zip.sha256
|
||||
release/ffmpeg-core-0.12.10-corresponding-source.tar.xz
|
||||
release/ffmpeg-core-0.12.10-corresponding-source.tar.xz.sha256
|
||||
release/av-tools-0.2.0.zip
|
||||
release/av-tools-0.2.0.zip.sha256
|
||||
release/ffmpeg-core-0.12.10-reviewed-stack5m.1-corresponding-source.tar.xz
|
||||
release/ffmpeg-core-0.12.10-reviewed-stack5m.1-corresponding-source.tar.xz.sha256
|
||||
```
|
||||
|
||||
Verify independently:
|
||||
|
||||
```sh
|
||||
node scripts/checksum-release.mjs
|
||||
(cd release && sha256sum -c ffmpeg-core-0.12.10-corresponding-source.tar.xz.sha256)
|
||||
unzip -l release/av-tools-0.1.0.zip
|
||||
tar -tJf release/ffmpeg-core-0.12.10-corresponding-source.tar.xz
|
||||
(cd release && sha256sum -c ffmpeg-core-0.12.10-reviewed-stack5m.1-corresponding-source.tar.xz.sha256)
|
||||
unzip -l release/av-tools-0.2.0.zip
|
||||
tar -tJf release/ffmpeg-core-0.12.10-reviewed-stack5m.1-corresponding-source.tar.xz
|
||||
```
|
||||
|
||||
The packager:
|
||||
@@ -90,13 +91,13 @@ When used against a fixture without an application licence, the escape hatch add
|
||||
|
||||
## 4. Portal assembly smoke
|
||||
|
||||
Use the clean reference clone beside av-tools, never the user's active Portal
|
||||
worktree:
|
||||
Use a reviewed Portal Git repository beside av-tools. The harness reads its
|
||||
exact `HEAD` and clones that revision into a temporary directory:
|
||||
|
||||
```sh
|
||||
npm run portal:smoke -- \
|
||||
--artifact release/av-tools-0.1.0.zip \
|
||||
--allow-known-header-gap
|
||||
--artifact release/av-tools-0.2.0.zip \
|
||||
--portal-root ../toolbox-portal
|
||||
```
|
||||
|
||||
The smoke harness clones the exact Portal HEAD to a temporary directory,
|
||||
@@ -106,19 +107,23 @@ then verifies the generated catalogue/release records and copied FFmpeg assets.
|
||||
The temporary directory is removed unless `--keep-temp` is explicitly passed.
|
||||
No machine-specific path is committed and no Portal worktree is changed.
|
||||
|
||||
Without `--allow-known-header-gap`, the clean immutable Portal reference's CSP
|
||||
omission of `media-src blob:` is a failing deployment check. The override still
|
||||
reports the gap and is only for testing archive assembly. See
|
||||
`docs/PORTAL_REQUIREMENTS.md`.
|
||||
Portal `v0.6.0`
|
||||
(`5c052bc6d1073a66600cfddc44c0e16da34bede8`) already passes the isolation,
|
||||
Blob-media CSP and explicit WASM MIME checks. Its plain-semver cache rule does
|
||||
not match the reviewed core's build-profile suffix, so the harness reports a
|
||||
cache warning. The staged Portal extension accepts only the exact reviewed
|
||||
profile in addition to plain semantic versions and rejects malformed or
|
||||
mutable-looking suffixes; a temporary clean commit containing that patch passed
|
||||
this smoke without warnings.
|
||||
|
||||
The user's active `/mnt/DATA/git/toolbox-portal` worktree contains the narrow
|
||||
directive as a local patch, but the smoke intentionally does not consume that
|
||||
mutable worktree. Until the patch exists in a reviewed immutable Portal
|
||||
revision, retain the clean-reference failure/override behavior above.
|
||||
`--allow-known-header-gap` remains available only for deliberately testing an
|
||||
older Portal revision with a known required-header error. It is unnecessary
|
||||
for `v0.6.0` and must not suppress review of new gaps. See
|
||||
`docs/PORTAL_REQUIREMENTS.md`.
|
||||
|
||||
## 5. Publish only reviewed bytes
|
||||
|
||||
From a clean `v0.1.0` checkout, rerun all checks, create the ZIP once, verify
|
||||
From a clean `v0.2.0` checkout, rerun all checks, create the ZIP once, verify
|
||||
the sidecar, assemble that exact ZIP through Portal, and publish the immutable
|
||||
ZIP, `.zip.sha256`, manifest, changelog, Corresponding Source and notices. Put
|
||||
its exact lowercase digest/version/id/target in a reviewed Portal lock. Never
|
||||
|
||||
@@ -39,9 +39,10 @@ exportable diagnostics.
|
||||
Metadata is rendered as React text, never `dangerouslySetInnerHTML`. Subtitle
|
||||
text is parsed and rendered or sent through a generated local file; it is not
|
||||
inserted as HTML. Extracted URLs are inert text. The application does not open
|
||||
links from media automatically. No remote font is fetched; ASS burn-in uses
|
||||
packaged/system-generic font configuration only when the required local
|
||||
capability is available.
|
||||
links from media automatically. No remote font is fetched. Contact-sheet labels
|
||||
mount only the same-origin, size/SHA-256-verified DejaVu asset and fail closed
|
||||
without `drawtext`; ASS burn-in uses packaged/system-generic font configuration
|
||||
only when the required local capability is available.
|
||||
|
||||
Preview/download URLs are `blob:` values made from local bytes. They are
|
||||
revoked on replacement, project close and unmount. Browser support for a
|
||||
|
||||
Reference in New Issue
Block a user