Files
djaudiovisualizer/src/control.html
T
lucianoandClaude Opus 4.8 47728d0d2a Effects engine, SVG/VU/silhouette categories, pad bank, MP4 recording, dual-window UI
- Parametric effect engine: 23 shader families × palettes × variants (~2300 presets)
  with a filterable library and an effect sequence (auto-cycle by time or beat).
- Effect categories: fractals/abstract, dancing silhouettes, SVG/Image source
  (loads any SVG/image as a recolourable audio-reactive effect; 50+ bundled CC0 SVGs),
  and VU-Meter (32-band spectrum bars, analogue needle, stereo LEDs).
- Dual-window architecture: control panel + fullscreen output on an external display
  (reliable via simple-fullscreen); tabbed control UI (Audio, Effetti, Pad, Immagini,
  Testo, Registra, Schermo).
- Audio: file playback + live input + output device selection, per-band visual EQ,
  audio playlist (reorder, hotkeys, per-track play/pause, repeat).
- Pad bank: 5×4 launchpad with persistent assignments; pressing a pad stops the current.
- Overlays: slideshow images (resizable), two freely positioned/resizable logos,
  scrolling ticker text.
- MP4 recording of the composited output (visual + overlays + audio) via MediaRecorder
  + ffmpeg, with selectable aspect ratios (16:9, 9:16, 1:1, 4:3, 3:4, 21:9).
- App icon (.icns) and dock icon; author Dj LuZa.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 15:25:39 +02:00

255 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; img-src 'self' blob: data:; style-src 'self' 'unsafe-inline'; script-src 'self'" />
<title>DJ Visualizer — Controlli</title>
<link rel="stylesheet" href="style.css" />
</head>
<body class="control">
<header id="topbar">
<strong>🎛 DJ Visualizer</strong>
<span id="status"><span id="fps">–</span> · <span id="scene-name">—</span></span>
</header>
<nav id="tabs">
<button data-tab="audio" class="active">🎵 Audio</button>
<button data-tab="effetti">🌀 Effetti</button>
<button data-tab="pad">🎹 Pad</button>
<button data-tab="immagini">🖼 Immagini</button>
<button data-tab="testo">🔤 Testo</button>
<button data-tab="registra">🔴 Registra</button>
<button data-tab="schermo">🖥 Schermo</button>
</nav>
<main id="content">
<!-- ============ AUDIO ============ -->
<div class="tab-panel active" data-tab="audio">
<section>
<label>Sorgente audio</label>
<button id="btn-play" class="wide" disabled>⏸ Pausa</button>
<label>Input live</label>
<select id="device-select"><option value="">— Input live (mic/line/BlackHole) —</option></select>
<button id="btn-use-input" class="wide">🎤 Usa input selezionato</button>
<label>Uscita audio (casse)</label>
<select id="output-select"><option value="">— Uscita predefinita —</option></select>
</section>
<section class="meters">
<label>Livelli</label>
<div class="meter"><span>BASS</span><div class="bar"><i id="m-bass"></i></div></div>
<div class="meter"><span>MID</span><div class="bar"><i id="m-mid"></i></div></div>
<div class="meter"><span>HIGH</span><div class="bar"><i id="m-treble"></i></div></div>
</section>
<section class="span2">
<label>Playlist <span id="playlist-count">0 brani</span></label>
<div class="row">
<button id="btn-add-tracks">➕ Aggiungi brani</button>
<button id="btn-clear-playlist">🗑 Svuota</button>
<label class="chk"><input type="checkbox" id="repeat-playlist" /> Ripeti</label>
</div>
<input type="file" id="tracks-input" accept="audio/*" multiple hidden />
<ol id="playlist" class="playlist"></ol>
<div class="hint-mini">Trascina ⠿ per riordinare · ⌨ tasto rapido · ▶/⏸ avvia/pausa</div>
</section>
<section>
<label>Reattività <span id="gain-val">1.0×</span></label>
<input type="range" id="gain" min="0" max="3" step="0.05" value="1" />
<label>Velocità <span id="speed-val">1.0×</span></label>
<input type="range" id="speed" min="0" max="3" step="0.05" value="1" />
</section>
<section>
<label>Equalizzatore visual</label>
<label class="band band-bass">Bassi <span id="bass-gain-val">1.0×</span></label>
<input type="range" id="bass-gain" min="0" max="3" step="0.05" value="1" />
<label class="band band-mid">Medi <span id="mid-gain-val">1.0×</span></label>
<input type="range" id="mid-gain" min="0" max="3" step="0.05" value="1" />
<label class="band band-treble">Alti <span id="treble-gain-val">1.0×</span></label>
<input type="range" id="treble-gain" min="0" max="3" step="0.05" value="1" />
</section>
</div>
<!-- ============ EFFETTI ============ -->
<div class="tab-panel" data-tab="effetti">
<section class="span2" id="effects-section">
<label>Libreria effetti <span id="effects-count"></span></label>
<div class="row">
<select id="effect-family"><option value="-1">Tutte le famiglie</option></select>
<input type="text" id="effect-search" class="textfield" placeholder="Cerca effetto…" />
</div>
<div id="effect-list" class="effect-list"></div>
</section>
<section class="span2" id="svg-section">
<label>Effetti SVG / immagini</label>
<select id="svg-select"><option value="-1">— Scegli una sagoma… —</option></select>
<button id="btn-svg-load" class="wide">📂 Carica un SVG/immagine…</button>
<input type="file" id="svg-input" accept="image/svg+xml,image/*" hidden />
<div class="hint-mini">Scegli una sagoma → diventa un effetto reattivo. Per cambiare colori/stile filtra la libreria su “SVG/Immagine”.</div>
</section>
<section class="span2" id="effect-seq-section">
<label>Sequenza effetti <span id="seq-count">0 in sequenza</span></label>
<div class="row">
<button id="btn-seq-add">➕ Aggiungi corrente</button>
<button id="btn-seq-clear">🗑 Svuota</button>
</div>
<div class="row">
<label class="chk"><input type="checkbox" id="seq-auto" /> Auto-cambio</label>
<label class="chk"><input type="checkbox" id="seq-beat" /> Sul beat</label>
<label class="chk"><input type="checkbox" id="seq-shuffle" /> Shuffle</label>
</div>
<label>Intervallo auto-cambio <span id="seq-interval-val">8.0s</span></label>
<input type="range" id="seq-interval" min="1" max="60" step="0.5" value="8" />
<ol id="effect-seq" class="playlist"></ol>
<div class="hint-mini">Clic in libreria = applica · ➕ = in sequenza · ⌨ tasto rapido · 1-9 = primi 9</div>
</section>
</div>
<!-- ============ PAD ============ -->
<div class="tab-panel" data-tab="pad">
<section class="span2">
<label>Pad — 20 brani al volo (5×4, salvati automaticamente)</label>
<div class="row">
<button id="btn-pad-stop">⏹ Stop</button>
<button id="btn-pad-clear">🗑 Svuota tutti</button>
</div>
<div id="pad-grid" class="pad-grid"></div>
<input type="file" id="pad-input" accept="audio/*" hidden />
<div class="hint-mini">Clic su un pad vuoto (o trascina un brano) per assegnarlo · clic su un pad pieno per avviarlo · premendone un altro ferma quello in corso · <b>tasto destro</b> per ricaricare · ✕ per svuotare.</div>
</section>
</div>
<!-- ============ IMMAGINI ============ -->
<div class="tab-panel" data-tab="immagini">
<section>
<label>Immagini overlay</label>
<div class="row">
<button id="btn-images">🖼 Carica…</button>
<button id="btn-images-clear">Pulisci</button>
</div>
<input type="file" id="image-input" accept="image/*" multiple hidden />
<div class="row">
<label class="chk"><input type="checkbox" id="img-slideshow" /> Slideshow</label>
<label class="chk"><input type="checkbox" id="img-beat" checked /> Pulsa beat</label>
</div>
<label>Dimensione <span id="img-size-val">70%</span></label>
<input type="range" id="img-size" min="10" max="100" step="1" value="70" />
<label>Durata slideshow <span id="img-interval-val">5.0s</span></label>
<input type="range" id="img-interval" min="1" max="20" step="0.5" value="5" />
<label>Fusione</label>
<select id="img-blend">
<option value="screen">screen (luminoso)</option>
<option value="normal">normale</option>
<option value="overlay">overlay</option>
<option value="multiply">multiply</option>
<option value="lighten">lighten</option>
</select>
</section>
<section class="logo-ctl" data-logo="0">
<label>Logo 1</label>
<div class="row">
<button class="logo-load" data-logo="0">🖼 Carica</button>
<button class="logo-clear" data-logo="0">Rimuovi</button>
</div>
<input type="file" class="logo-input" data-logo="0" accept="image/*" hidden />
<label>Orizzontale <span class="logo-x-val">50%</span></label>
<input type="range" class="logo-x" data-logo="0" min="0" max="100" step="0.5" value="50" />
<label>Verticale <span class="logo-y-val">50%</span></label>
<input type="range" class="logo-y" data-logo="0" min="0" max="100" step="0.5" value="50" />
<label>Dimensione <span class="logo-size-val">20%</span></label>
<input type="range" class="logo-size" data-logo="0" min="2" max="80" step="0.5" value="20" />
<label>Opacità <span class="logo-op-val">100%</span></label>
<input type="range" class="logo-op" data-logo="0" min="0" max="100" step="1" value="100" />
</section>
<section class="logo-ctl" data-logo="1">
<label>Logo 2</label>
<div class="row">
<button class="logo-load" data-logo="1">🖼 Carica</button>
<button class="logo-clear" data-logo="1">Rimuovi</button>
</div>
<input type="file" class="logo-input" data-logo="1" accept="image/*" hidden />
<label>Orizzontale <span class="logo-x-val">50%</span></label>
<input type="range" class="logo-x" data-logo="1" min="0" max="100" step="0.5" value="50" />
<label>Verticale <span class="logo-y-val">50%</span></label>
<input type="range" class="logo-y" data-logo="1" min="0" max="100" step="0.5" value="50" />
<label>Dimensione <span class="logo-size-val">20%</span></label>
<input type="range" class="logo-size" data-logo="1" min="2" max="80" step="0.5" value="20" />
<label>Opacità <span class="logo-op-val">100%</span></label>
<input type="range" class="logo-op" data-logo="1" min="0" max="100" step="1" value="100" />
</section>
</div>
<!-- ============ TESTO ============ -->
<div class="tab-panel" data-tab="testo">
<section class="span2">
<label>Testo scorrevole</label>
<input type="text" id="ticker-text" class="textfield" placeholder="Es. NOME DJ · EVENTO" />
<div class="row">
<label class="chk"><input type="checkbox" id="ticker-on" /> Mostra</label>
<select id="ticker-pos">
<option value="bottom">Basso</option>
<option value="top">Alto</option>
<option value="middle">Centro</option>
</select>
</div>
<label>Velocità testo <span id="ticker-speed-val">1.0×</span></label>
<input type="range" id="ticker-speed" min="0.2" max="4" step="0.1" value="1" />
</section>
</div>
<!-- ============ REGISTRA ============ -->
<div class="tab-panel" data-tab="registra">
<section class="span2">
<label>Registrazione output → MP4</label>
<div class="rec-status">
<span id="rec-dot" class="off"></span>
<span id="rec-label">Pronto</span>
<span id="rec-time">00:00</span>
</div>
<label>Formato</label>
<select id="rec-aspect">
<option value="1920x1080">16:9 orizzontale (1920×1080)</option>
<option value="1080x1920">9:16 verticale (1080×1920)</option>
<option value="1080x1080">1:1 quadrato (1080×1080)</option>
<option value="1440x1080">4:3 (1440×1080)</option>
<option value="1080x1440">3:4 verticale (1080×1440)</option>
<option value="2560x1080">21:9 cinema (2560×1080)</option>
</select>
<button id="btn-rec" class="wide">🔴 Avvia registrazione</button>
<button id="btn-rec-folder" class="wide">📁 Apri cartella registrazioni</button>
<div class="hint-mini">Registra ciò che vedi sull'output + l'audio (file o input live). Salvataggio in <b>Filmati ▸ DJ Visualizer</b>. La conversione in MP4 avviene allo stop.</div>
</section>
</div>
<!-- ============ SCHERMO ============ -->
<div class="tab-panel" data-tab="schermo">
<section class="span2">
<label>Schermo di output</label>
<select id="display-select"></select>
<div class="row">
<button id="btn-display">📺 Manda al monitor</button>
<button id="btn-fullscreen">⛶ Fullscreen</button>
</div>
</section>
</div>
</main>
<footer id="hints">
<kbd>1</kbd>–<kbd>9</kbd> effetti in sequenza · <kbd>F</kbd> fullscreen · <kbd>O</kbd> aggiungi brani ·
<kbd>← →</kbd> immagini · <kbd>Spazio</kbd> play/pausa · tasti rapidi personalizzabili
</footer>
<script src="effects.js"></script>
<script src="control.js"></script>
</body>
</html>