Limits quick reference
Selected enforced ceilings, with their source enforcement points. Where a limit has a user-facing symptom, it is noted.
The checked source snapshot is recorded in the verification evidence. Line numbers are finding aids for that snapshot; named symbols identify the enforcing code.
Not verified: whether this table is exhaustive. It is every enforced ceiling found in a full read of the sources listed at the bottom of this page, plus a targeted enumeration of every file-size check in the tree. It is not a build-level proof that no other bound exists somewhere.
Composition structure
| Limit | Value | Symptom | Enforced at |
|---|---|---|---|
| Layers | 16 (minimum 1) | Layer add refused | Sources/VJCore/Transport.swift:681; open-time check Sources/VJMac/EngineController.swift:1624 |
| Banks | 32 (minimum 1) | "A set supports up to 32 banks."; the import menu item disables at 32 | Sources/VJCore/Transport.swift:490, Sources/VJMac/EngineController.swift:1874, Sources/VJMac/ULTIMATEVJApp.swift:41, Sources/VJMac/ConsoleBankImport.swift:39 |
| Columns | No cap found | Memory and screen space are the real bounds | Only index-overflow guards: Sources/VJCore/Transport.swift:711-729 |
| Recent-trigger stamps | No explicit cap; one stamp per clip, replaced on re-trigger | Recent can approach every clip you have touched |
Runtime dictionary keyed by clip: Sources/VJMac/EngineController.swift:1393 |
Composition size
| Limit | Value | Symptom | Enforced at |
|---|---|---|---|
| Core accepted dimensions | 1 … 8192 per side | Rejected at validation | Sources/VJCore/Transport.swift:368 |
| Composition set/edit range | 16 … 4096 per side | Clamped; above 4096 cannot match a display mode | Sources/VJMac/EngineController.swift:1972 |
| Render / thumbnail / recording clamp | 1 … 8192 per side | Sources/VJMac/ConsoleRenderer.swift:808-820, Sources/VJMac/ConsoleRecorder.swift:123 |
|
| Recording dimensions | Must be even, 2 … 8192 | "H.264 recording needs even output dimensions and 1–120 FPS." | Sources/VJMac/ConsoleRecorder.swift:123-126 |
Clips
| Limit | Value | Symptom | Enforced at |
|---|---|---|---|
| Cue points per clip | 16, names 1–80 chars | Add disabled with a message | Sources/VJCore/Model.swift:261, Sources/VJMac/ConsoleClipActionsMenu.swift:27 |
| Clip speed (signed) | −16 … 16 numeric field; −4 … 4 slider | Rejected or clamped | Sources/VJCore/Transport.swift:1077-1089, Sources/VJMac/ConsoleClipTransportView.swift:68-71 |
| Composition speed | 0.01 … 16 | Clamped | Sources/VJCore/Transport.swift:1290-1295 |
| Beats per clip | 0.25 … 128 (audio clips 0.25 … 65536) | Sources/VJMac/ConsoleClipTransportView.swift:64 |
|
| In/out minimum span | 0.000001 | Invalid apply retains the previous range | Sources/VJCore/Model.swift:257-271 |
Effects
| Limit | Value | Symptom | Enforced at |
|---|---|---|---|
| Effect instances per scope | 16 | Add refused; a preset with more is rejected wholesale | ConsoleEffectStack.maximumInstances Sources/VJMac/ConsoleEffectStack.swift:796, decode Sources/VJMac/ConsoleEffectStack.swift:820-825, validation Sources/VJMac/ConsoleEffectStack.swift:839 |
| Blend modes for effect instances | 22 | Others rejected with "Unsupported native effect blend" | ConsoleEffectStack.supportedBlendModes Sources/VJMac/ConsoleEffectStack.swift:799, message Sources/VJMac/ConsoleEffectStack.swift:772 |
| Blend modes for layers | 14 | Chaser and Mask are never offered |
Sources/VJCore/ControlRegistry.swift:190 |
| Effect instance name | Non-empty, ≤ 80 characters | "Effect names must contain 1–80 characters." | Sources/VJMac/ConsoleEffectStack.swift:764 |
| Envelope points | 2 … 64 | Add point disables at 64 | Sources/VJCore/ParameterModulation.swift:83 |
| Effect preset file | 1 MiB | Rejected when read | Sources/VJMac/EngineController.swift:779, Sources/VJMac/EngineController.swift:795 |
| Transform preset file | 16 KiB | Rejected | Sources/VJMac/ConsoleTransformPreset.swift:6, Sources/VJMac/ConsoleTransformPreset.swift:48 |
| RenderWave shader look file | 1 MiB | Rejected | Sources/VJMac/ConsoleShaderEditing.swift:80, Sources/VJMac/ConsoleShaderEditing.swift:94 |
Output and recording
| Limit | Value | Symptom | Enforced at |
|---|---|---|---|
| Output surfaces | 16 | Add surface disables |
Sources/VJMac/ConsoleOutputMapping.swift:100 |
| Output crop | Inside 0…1, each dimension > 0.000001 | Committed setup retained, error shown | Sources/VJMac/ConsoleOutputMapping.swift:17-24 |
| Output corners | Finite, −2 … 3, convex | Three distinct messages | Sources/VJMac/ConsoleOutputMapping.swift:60-79 |
| Output dimensions | 1 … 8192 per side | Black canvas plus an issue string | Sources/VJMac/ConsoleOutputMapping.swift:127 |
| Display-mode match | Both sides 16 … 4096 and verified mode | Menu shows · current composition |
Sources/VJMac/EngineController.swift:1973-1975 |
| Render frame rate request | 15, 30 or 60 fps — any other value resets to 30 | Silent reset, not clamping to the nearest option | Sources/VJMac/EngineController.swift:1755, Sources/VJMac/EngineController.swift:2012 |
| Recording frame rate | 1 … 120 | Same message as the even-dimension failure | Sources/VJMac/ConsoleRecorder.swift:123-126 |
| GPU frames in flight | 3 | Sources/VJMac/ConsoleFramePresentation.swift:225 |
|
| Clean output minimum size | 320 × 180 | Sources/VJMac/OutputManager.swift:163 |
|
| Output mapping preset | 1 MiB | "Output preset exceeds the supported file size." | Sources/VJMac/EngineController.swift:1936, Sources/VJMac/EngineController.swift:1949 |
Audio
| Limit | Value | Symptom | Enforced at |
|---|---|---|---|
| Simultaneous file-audio voices | 32 | "Audio transition capacity reached…" — transition hand-off voices count too | Sources/VJMac/ConsoleAudioPlayback.swift:82, Sources/VJMac/EngineController.swift:434 |
| Readable source channels | 1 … 32 | Above that rejected | Sources/VJMac/ConsoleAudioTransport.swift:59, Sources/VJMac/ConsoleAudioTransport.swift:262-263 |
Control
| Limit | Value | Enforced at |
|---|---|---|
| Keyboard mappings | 192, including cue keys | Sources/VJMac/ConsoleKeyboardMapping.swift:57 |
| MIDI mappings | 192 total: 64 note (including cue notes), 128 controller | Sources/VJMac/ConsoleMIDIMapping.swift:137-138 |
| MIDI inbox | 256 events; overflow releases held input | Sources/VJMac/ConsoleMIDIInput.swift:33, Sources/VJMac/ConsoleMIDIInput.swift:408-410 |
| MIDI per-drain work | 64 events, 2 ms per tick; remainder restored to the front | Sources/VJMac/ConsoleMIDIInput.swift:417-426 |
| MIDI feedback rate | 10 Hz; bursts coalesce to newest | Sources/VJMac/ConsoleMIDIOutput.swift:89-93 |
| MIDI feedback words per publication | 256 | Sources/VJMac/ConsoleMIDIOutput.swift:131 |
| Messages understood | Note On, Note Off, CC only — everything else dropped | Sources/VJMac/ConsoleMIDIInput.swift:51-69 |
Local control API
| Limit | Value | Enforced at |
|---|---|---|
| Clients / OSC peers / HTTP connections | 64 / 16 / 16 | Sources/VJMac/ConsoleRemoteControl.swift:30, Sources/VJMac/ConsoleRemoteTransport.swift:10, Sources/VJMac/ConsoleNIOHTTPServer.swift:10 |
| Client lease | 5 seconds | Sources/VJMac/ConsoleRemoteControl.swift:31 |
| Commands per envelope | 64 | Sources/VJCore/ControlRegistry.swift:119 |
| Queued groups / queued commands | 64 / 1,024 | Sources/VJCore/ControlRegistry.swift:120-121 |
| Held presses / receipts | 256 / 1,024 | Sources/VJCore/ControlRegistry.swift:122-123 |
| Receipt retention (remote only) | 600 seconds | Sources/VJCore/ControlRegistry.swift:125 |
| Future scheduling horizon | 2 seconds | Sources/VJCore/ControlRegistry.swift:124 |
| Handoff queue | 16 pending items | Sources/VJMac/ConsoleRemoteWorkQueue.swift:29 |
| HTTP body / total wire bytes | 64 KiB / 112 KiB | Sources/VJMac/ConsoleRemoteControl.swift:29, Sources/VJMac/ConsoleHTTPParser.swift:22 |
| OSC packet / string / args / elements / depth | 16 KiB / 4 KiB / 64 / 64 / 8 | Sources/VJCore/OSCCodec.swift:28-32 |
| OSC pattern address / brace depth / alternatives | 1,024 B / 4 / 64 | Sources/VJCore/OSCAddressPattern.swift:9-12 |
| WebSocket subscribers / OSC feedback subscribers | 8 / 8 | Sources/VJMac/ConsoleWebSocketEvents.swift:10, Sources/VJMac/ConsoleOSCFeedback.swift:7 |
| WebSocket message / frame | 256 KiB / 4 KiB | Sources/VJMac/ConsoleWebSocketEvents.swift:11, Sources/VJMac/ConsoleNIOHTTPServer.swift:40 |
| Targets per page / per state read | 16 / 8 | Sources/VJCore/ControlRemoteJSON.swift:6, Sources/VJCore/ControlRemoteJSON.swift:9 |
| Startup budget for both listeners | 3 seconds | Sources/VJMac/ConsoleRemoteTransport.swift:84-87 |
Interface layouts and presentation
| Limit | Value | Enforced at |
|---|---|---|
| Named layouts | 32; unique trimmed names of 1…80 characters | Sources/VJMac/ConsoleUILayout.swift (save, validName) |
| Inspector width | 25…55%, standard 39% | Sources/VJMac/ConsoleUILayout.swift (isValid), Sources/VJMac/Theme.swift (inspectorShare) |
| Saved window size | Width 1180…4096, height 760…2160 points; adapted to screen on application | Sources/VJMac/ConsoleUILayout.swift (isValid, applyWindowSize) |
| Saved layer area height | 0 automatic, or 92…2000 points; constrained by available space | Sources/VJMac/ConsoleUILayout.swift (isValid), Sources/VJMac/ContentView.swift (root layout) |
| Set versions read | 1…6 with feature-specific version guards | Sources/VJMac/EngineController.swift (ConsoleSession.isSupportedFormat) |
Import, media and decoding
| Limit | Value | Enforced at |
|---|---|---|
| Media file size | Separate-poster APNG inputs are capped at 256 MiB during normalization; no universal media-size limit is established here | See the enumeration note below |
| FFmpeg video dimensions | 8192 per side, 33,554,432 pixels | Sources/VJFFmpeg/UVJFFmpeg.c:161-169 |
| Animated image dimensions | 8192 per side, 33,554,432 pixels | Sources/VJMac/ConsoleAnimatedImageDecoder.swift:51-54 |
| Still-image decode | ImageIO scales to at most 8192 pixels per side; the FFmpeg pixel cap is not a shared still-image admission rule | Sources/VJMac/ConsoleVideoDecoder.swift:173-179 |
| Per-frame decoded video bytes | 128 MiB | Sources/VJFFmpeg/UVJFFmpeg.c:166-167 |
| Compressed packet | 64 MiB | Sources/VJFFmpeg/UVJFFmpeg.c:261-264 |
| Concurrent decode workers | 2, process-wide | Sources/VJMac/ConsoleVideoDecoder.swift:7-13 |
| Operation / frame deadlines | 5 seconds | Sources/VJFFmpeg/UVJFFmpeg.c:39, Sources/VJMac/ConsoleVideoDecoder.swift:988 |
| Animation frames | 100,000 | Sources/VJMac/ConsoleAnimatedImageDecoder.swift:34 |
| Separate-poster APNG rewrite | 256 MiB | Sources/VJMac/ConsoleAPNGPosterSource.swift:60-61 |
| Thumbnail cache | Cleared entirely past 256 entries | Sources/VJMac/ConsoleRenderer.swift:793 |
| Playback instances per source | 64 | Sources/VJMac/ConsoleRenderer.swift:1385 |
Files and storage
| Limit | Value | Enforced at |
|---|---|---|
| Bank import file | 16 MiB | Sources/VJMac/ConsoleBankImport.swift:6, Sources/VJMac/ConsoleBankImport.swift:26-27 |
| Clip pasteboard payload | 2 MiB | Sources/VJMac/ConsoleSystemClipboard.swift:8, Sources/VJMac/ConsoleSystemClipboard.swift:58 |
| Undo history | 32 steps, 0.4 s coalescing — the trim is applied to the undo stack | Sources/VJMac/ConsoleCompositionEditing.swift:27-34 |
| Cue / clip / layer / bank names | 1 … 80 characters | Sources/VJCore/Model.swift:268-271 |
| Recovery retention | Never pruned | Only writers found for ~/Library/Application Support/ULTIMATEVJ/Recovery |