Stem ZIPper is now delivered as an Electron application that combines a Vite powered React + TypeScript renderer with a modern desktop runtime. The tool keeps the original mission of preparing sample packs for platforms such as ccmixter.org by analysing folders full of audio files, splitting stereo WAV files if necessary and producing optimally filled ZIP archives.
- Modern desktop UI built with React, Tailwind CSS and Electron.
- Drag & drop or manual folder selection with live validation of the configured ZIP size target.
- Best-fit packing into
stems-XX.ziparchives including the classic Stem ZIPper stamp file. - Automatic mono-splitting for stereo WAV files that exceed the configured limit.
- Multilingual interface (EN, DE, FR, IT, ES, PT, DA, NO, SV, FI, NL, PL, JA, ZH, TH, KO, CS, RO, UK) that adapts to the operating system locale.
- Metadata automation with a dedicated modal that validates title/artist/license input, remembers preferred defaults and generates
PACK-METADATA.json,LICENSE.txt, andATTRIBUTION.txtalongside packed archives. - Deterministic ZIP estimates surfaced as renderer toasts that account for stereo split heuristics whenever scans finish or the maximum size changes.
- Deterministic 7Z estimates surfaced as renderer toasts that account for stereo split heuristics whenever scans finish or the maximum size changes. Also supports volumes natively.
- Developer utilities (available in dev mode) to generate dummy audio files for testing the packing workflow.
- JSON-based localisation catalogues shared between Electron and the renderer, backed by guard tests to ensure mirrored keys and placeholder integrity across languages.
Supported formats remain: .wav, .flac, .mp3, .aiff, .ogg, .aac, .wma.
- Contributor automation guide –
AGENTS.mdnow captures CI discipline, localisation rules and review expectations for automated contributions. - Metadata defaults & exports – The metadata modal persists artist name, URL and contact preferences to streamline repeated pack runs while emitting standard metadata files automatically.
- Predictable ZIP counts – A renderer toast reports how many archives the next pack will create, stays in sync with mono split decisions and clears as soon as packing succeeds.
- Localisation pipeline upgrade – Shared translations moved to flat JSON catalogues with typed helpers so renderer, preload and main processes stay aligned.
- Reliability improvements – Preferences now persist via the filesystem, locale catalogues participate in TypeScript watch mode, and the development runner spawns pnpm watchers directly to eliminate previous crashers and warnings.
-
Added: Automated cross-platform icon build; table checkboxes with estimate badges; accessible labels; deterministic estimatePackingPlan IPC; 7z support with volume splitting; ZIP vs 7z selector; shared getFileExtension helper.
-
Changed: Progress UI now a reducer-based state machine with clear phases and done/error; “Pack Now” is green, “~ no zip gain” is an info badge; better a11y/focus; debounced ZIP estimates; cleaner renderer shell; monorepo root pnpm scripts; modular pack strategies; sturdier stereo-split progress; reliable per-platform 7z binary resolution.
-
Fixed: Reliable 7z availability (bundled + PATH fallback); stable progress/toasts; correct volume reporting and overwrite behavior; Windows/ESM compatibility; clean pnpm run dev; stricter audio probing & split validation; localized badges/toasts; multiple robustness fixes to avoid stale or hanging UI states.
app/
├── electron/ # Main & preload processes and packaging services
├── src/ # React renderer (components, styling, localisation)
├── common/ # Shared constants, IPC contracts and helpers
├── index.html # Vite entry point
└── package.json # Electron/Vite workspace configuration
- Node.js 18.x or newer
- pnpm (enable via
corepack enable pnpmif it is not yet available). The workspace pinsnode-linker=hoistedvia.npmrcso that production dependencies are flattened for Electron packaging. - macOS, Windows or Linux desktop environment with file system access for Electron
✅ The legacy Python/Tkinter bundle has been retired on this branch. All features now ship with the Electron workspace under
app/.
Run the following steps from the repository root.
pnpm installThe post-install hook downloads the precompiled 7-Zip command-line binaries from the
7zip-bin package and stages them under app/resources/bin/<platform>/<arch>/. This keeps
packaging ready on fresh checkouts without relying on a system-level 7z installation.
pnpm run devPass an optional locale when launching the development workflow to override the interface language, for example:
pnpm run dev de
pnpm run dev -- --lang=frIf no locale is provided, the runners detect the operating system language and only fall back to English (en) when the locale
cannot be resolved.
This command starts the Vite dev server, compiles the Electron main & preload processes in watch mode and launches Electron once the renderer is ready. The runner uses concurrently with coloured [VITE], [MAIN], [PRELOAD] and [ELECTRON] prefixes so you can follow each worker at a glance. Closing the Electron window or pressing Ctrl+C terminates all watchers cleanly, avoiding zombie Node or Vite instances on every platform. Any change in src/ hot-reloads the UI, while updates to Electron code trigger a fast TypeScript rebuild.
ℹ️ The Electron launcher verifies that the native binary is available. If the post-install download was skipped (for example when
ELECTRON_SKIP_BINARY_DOWNLOAD=1was set globally), the script reruns the official installer before starting the desktop shell.
pnpm run lint
pnpm run typecheck
pnpm run testlintruns ESLint with the React/TypeScript configuration.typecheckexecutestsc --noEmitacross the Electron + renderer workspaces.testtriggers Vitest suites that cover the Node-based packing engine and helper utilities.
pnpm run build
pnpm run previewThe build pipeline produces two artefacts:
dist-renderer/– the production React bundle styled with Tailwind CSS.dist-electron/– compiled Electron main & preload scripts ready for packaging.
pnpm run preview launches the built application locally using the generated artefacts, allowing a final manual smoke test before packaging.
pnpm run cleanThe cleanup task removes the dist-electron/, dist-renderer/ and release/ directories. It is safe to run repeatedly and helps keep cross-platform builds reproducible.
| Area | Electron implementation |
|---|---|
| User interface | Single-window layout with a header toolbar, drag & drop surface, folder path breadcrumb and a responsive file table. The right-hand status rail mirrors the legacy progress readout, while action buttons (Pack Now, Cancel, Clear) stay anchored at the bottom for accessibility. |
| Internationalisation | The renderer resolves the OS locale (EN, DE, FR, IT, ES, PT, DA, NO, SV, FI, NL, PL, JA, ZH, TH, KO, CS, RO, UK) via the preload bridge, serving shared JSON catalogues from app/locales/*.json through typed helpers in app/common/i18n. Dialogs triggered from the main process reuse the same catalogue to avoid drift between Electron and React copies. |
| Developer tooling | Dev-mode exposes the familiar "Create Test Data" button which shells out to the Node dummy-data generator. File sizes, stems count and progress notifications follow the Python defaults to keep test scripts compatible. |
| ZIP logic | Audio analysis, stereo-to-mono splitting and best-fit-decreasing packing now run inside the Electron main process (app/electron/services/packer). The workflow persists the _stem-zipper.txt stamp file and emits sequential stems-XX.zip archives identical to the Tkinter run. |
- Header – Displays the application title and quick links to settings and documentation.
- Drop zone – Central card that accepts folders via drag & drop or manual selection. Provides immediate feedback on unsupported file types.
- Analysis table – Responsive table summarising detected files, duration, size and pending actions (pack, split, ignore). Rows highlight when splitting or multi-archive packing will occur.
- Progress rail – Right-aligned timeline showing current phase (scanning, splitting, packing) with an indeterminate spinner for long-running tasks.
- Action footer – Primary Pack Now button plus contextual secondary controls (Cancel, Clear Results) matching the previous keyboard shortcuts.
Need a visual reference? See the annotated UI description above or explore the interactive preview via
pnpm run dev.
- Choose or drop a folder containing supported audio files.
- Adjust the Max ZIP size (MB) field if required (defaults to 48 MB, capped at 50 MB).
- Review the analysed files in the table – the action column highlights when mono splitting or multi-archive packaging will occur.
- Click Pack Now to create
stems-XX.zipfiles in the source folder. Progress updates mirror the classic Tkinter interface. - In development builds, a Create Test Data (DEV) button generates random dummy audio files in a chosen directory.
~ no zip gainappears next to already-compressed formats (MP3, AAC, M4A, MP4, OGG, OPUS, WMA, WEBM, FLAC). ZIP archives rarely shrink these files.try 7z volumeshighlights compressed files that exceed the configured max ZIP size, nudging you toward the 7z split-volume pack method when needed.
pnpm run package:winNeed a platform-aware shortcut?
pnpm run packageautomatically calls the Windows or Linux packaging target based on the host operating system. macOS users should invoke the dedicated platform script directly once it becomes available.
Run this command from the repository root. It compiles the renderer and Electron processes and then uses electron-builder to generate an NSIS installer for 64-bit Windows. The packaging script automatically runs pnpm run clean first to clear previous releases, preventing Windows from holding on to files such as chrome_100_percent.pak between successive builds.
The Electron Builder configuration now whitelists only the production runtime packages (buffer-crc32, clsx, react, react-dom, scheduler, loose-envify, js-tokens, wavefile, yazl) so that development tooling such as Vite and ESLint is no longer copied into the installer. After running the packaging task you can inspect the generated archive with:
npx asar extract release/win-unpacked/resources/app.asar /tmp/app-asar
ls /tmp/app-asar/node_modulesThe extracted node_modules directory should only contain the runtime dependencies listed above, yielding a noticeably smaller app.asar and installer payload. Execute the task on Windows (or a Linux/macOS machine with Wine configured) to ensure the .exe is produced successfully.
- The workspace remains ready for additional tooling such as Electron Forge or custom
electron-buildertargets; integrate them on top of the generateddist-electronanddist-rendererartefacts. - Cross-platform signing/notarisation scripts should live alongside the Electron configuration inside
app/electron. - The retired PyInstaller flow lives in
docs/archive/python-legacy.mdtogether with notes on the final Tkinter build.
MIT License
© 2025 Björn Ahlers