尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
A faithful reimplementation of the Panasonic MX-50 video mixer using web technology.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗A WebGPU browser recreation of the Panasonic WJ-MX50 — the 1990s two-bus digital A/V mixer — in pure vanilla TypeScript.
It's a proof of concept with high behavioural fidelity: can a dense piece of broadcast hardware be reproduced faithfully in the browser, block for block, driven by a single state store and rendered on WebGPU — with its behaviour pinned by executable specs derived from the manual? The domain model is complete and verified headlessly; the GPU renders the core signal path, with the most complex visuals documented as deferred (see below).
Status: proof of concept · Phases 0–8 complete · unit suite + 563 Gherkin scenarios (4137 steps) green · no UI framework, no bundler.
Modelled after the hardware's control blocks (reference §2–§18), all as pure domain logic behind one store:
The fixed signal flow the whole thing mirrors (ADR-0004):
Source → bus assignment → Colour Correction → Digital Effect → Mix/Wipe → Downstream Key → Fade → Program Out
Requires Node ≥ 20 and, to view it, a WebGPU browser (Chrome/Edge 113+, Safari 18+, or Firefox with WebGPU on).
npm install
npm run dev # banira dev server at http://127.0.0.1:8080 (open in a WebGPU browser)
npm test # typecheck + unit + Gherkin features + golden scaffolding — the full gate
npm run build # no-bundler ESM output to dist/
Individual gates: npm run typecheck · npm run test:unit · npm run test:features.
The website — descriptions and runnable demos for every block, built from this same tree
(the demos import src/ directly rather than copying it). Besides the GPU-free domain demos it has
live benches (small <mx-mixer>s with one block connected), the 28-pattern wipe wall, a six-step Learn the panel
tour, the manual's combination recipes played step by step from their Gherkin scenarios, and
Embed docs with runnable examples and a playground:
npm run site:build # static output to _site/ — no bundler, one ESM entry per route
npm run site:serve # build, then serve it locally
npm run site:check # resolve every module specifier + fetched asset
npm run site:smoke # load every route in headless Chrome, fail on any console error
npm run site:posters # maintainer step: re-capture stills, loops and the social card (needs a WebGPU Chrome)
It deploys to GitHub Pages from .github/workflows/pages.yml, gated on npm test — see
docs/WEBSITE.md for the concept and what is still outstanding.
Embed it: the mixer is a set of custom elements (ADR-0017). One tag gives you a picture; put
blocks inside it, or anywhere with for="id", for controls:
<mx-mixer feeds="pattern" preset="look.json">
<mx-dsk-block></mx-dsk-block>
</mx-mixer>
<script type="module">
import { defineMixer } from './src/ui/mixer.js';
import { defineBlocks } from './src/ui/blocks/index.js';
defineMixer();
defineBlocks();
</script>
Every attribute, event and block is listed on the site's Embed page, rendered from
src/ui/mixer-api.ts and src/ui/blocks/reference.ts.
Blend video feeds: on load, all four Sources are live video feeds with their own monitors (self-contained procedural clips — swap any of them for your own files with the monitor's Load clip… button; Pattern brings the clip back). Bus A starts on Source 1, Bus B on Source 2, transition MIX — drag the Mix/Wipe lever to blend them, or try NAM/WIPE, per-bus colour correction, and the digital effects on top.
The interesting part of the experiment is the architecture, not the artwork:
.feature files (written
from the WJ-MX50 manual) execute against the actual domain code with no GPU or DOM, alongside
node:test units. Behaviour is verified against the manual, not against a screenshot.The domain model is complete. What remains is inventoried — with a buildable-vs-out-of-scope split and a file/line pointer for each item — in docs/DEFERRED.md. In short: the rendered-pixel outcomes and browser-only surfaces are buildable (deferred only because this environment has no headless-WebGPU runner or device access — verify by browser smoke); a small set is genuinely not buildable without breaking fidelity (model-constrained scenarios) or is out of scope (analog/interlace behaviour, dropped by the clean-modern decision, ADR-0005).
GNU Affero General Public License v3.0 — see LICENSE (SPDX: AGPL-3.0-only).
The Affero clause is the deliberate part: §13 requires that anyone interacting with a modified version over a network be offered its source. If you host a fork of this mixer, that obligation applies to your users — the published site keeps a licence and source link in its footer for exactly that reason.
| Path | What's there |
|---|---|
src/ | the app — core/ (pure domain), state/ (store + reducer), engine/ (clock + loop + renderer), gpu/ (WebGPU passes + WGSL), audio/, control/, persistence/, ui/ |
features/ | the Gherkin/Cucumber specs — the executable behaviour contract |
test/ | unit/ (node:test), features/ (Cucumber world + steps), golden/ (image scaffolding) |
adr/ | 16 architecture decision records |
docs/ | architecture · ROADMAP (build history) · DEVELOPMENT (run & test) · DEFERRED · the WJ-MX50 feature reference |