Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <title>Sample Extractor</title> | |
| <link rel="stylesheet" href="/web/styles.css" /> | |
| </head> | |
| <body> | |
| <div id="globalDropOverlay" class="global-drop-overlay" aria-hidden="true"> | |
| <div> | |
| <strong>Drop audio to extract samples</strong> | |
| <span>The waveform appears immediately and processing starts automatically.</span> | |
| </div> | |
| </div> | |
| <div id="errorBanner" class="error-banner" role="alert" hidden> | |
| <div class="error-copy"> | |
| <strong id="errorTitle">Request failed</strong> | |
| <span id="errorMessage">Something went wrong.</span> | |
| <small id="errorDetail"></small> | |
| </div> | |
| <button id="dismissErrorButton" class="icon-button" type="button" aria-label="Dismiss error">×</button> | |
| </div> | |
| <div class="app-shell"> | |
| <header class="topbar"> | |
| <div class="brand"> | |
| <span class="brand-mark" aria-hidden="true"><i></i><i></i><i></i><i></i><i></i></span> | |
| <strong>Sample Extractor</strong> | |
| <span class="beta-pill">BETA</span> | |
| </div> | |
| <div id="dropzone" class="file-picker" title="Choose audio, or drop audio anywhere" role="button" tabindex="0"> | |
| <input id="fileInput" type="file" accept="audio/*,.wav,.mp3,.flac,.aiff,.ogg,.m4a,.aac" aria-label="Choose audio file" /> | |
| <button id="chooseAudioButton" class="file-picker-button" type="button">Choose audio</button> | |
| <span class="file-picker-copy"><span id="dropTitle">Drop audio anywhere</span><small id="dropMeta">Processing starts automatically</small></span> | |
| <span aria-hidden="true">⌄</span> | |
| </div> | |
| <div class="top-actions"> | |
| <div class="backend-pill" aria-live="polite"> | |
| <span class="status-dot" id="healthDot"></span> | |
| <span><strong id="healthText">Connecting</strong><small id="healthSubtext">FastAPI backend</small></span> | |
| </div> | |
| <button id="runButton" class="secondary-action" type="button" disabled>↻ Reprocess</button> | |
| <button id="exportAllButton" class="secondary-action" type="button" disabled>⇧ Export All</button> | |
| <button id="exportSelectedButton" class="primary-action" type="button" disabled>⇄ Export Selected <span id="selectedCountTop">(0)</span></button> | |
| </div> | |
| </header> | |
| <main class="main-grid"> | |
| <section class="canvas-pane" aria-label="Waveform and samples"> | |
| <section class="wave-panel" aria-label="Waveform overview"> | |
| <div class="wave-toolbar"> | |
| <div class="zoom-tools" aria-label="Waveform zoom controls"> | |
| <button id="zoomInspectButton" class="tool-button" type="button" title="Zoom with pinch or wheel">⌕</button> | |
| <button id="zoomOutButton" class="tool-button" type="button" title="Zoom out">−</button> | |
| <button id="zoomInButton" class="tool-button" type="button" title="Zoom in">+</button> | |
| <button id="zoomFitButton" class="tool-button fit" type="button" title="Fit waveform">Fit</button> | |
| </div> | |
| <div class="wave-status"> | |
| <strong id="waveTitle">Load audio</strong> | |
| <span id="waveProgressText">Drop a file anywhere. Extraction starts automatically.</span> | |
| </div> | |
| <time id="transportTime" class="top-time">0:00 / 0:00</time> | |
| </div> | |
| <canvas id="waveform" class="waveform" height="360"></canvas> | |
| <div class="transport-row" aria-label="Preview transport"> | |
| <button id="transportPlayButton" class="round-play" type="button" aria-label="Play preview">▶</button> | |
| <input id="transportSeek" class="transport-seek" type="range" min="0" max="1000" value="0" step="1" aria-label="Seek preview" /> | |
| <div class="preview-tabs" aria-label="Preview source"> | |
| <button id="previewSourceButton" class="preview-tab active" type="button" data-preview-mode="source">Source</button> | |
| <button id="previewStemButton" class="preview-tab" type="button" data-preview-mode="stem">Stem</button> | |
| <button id="previewReproductionButton" class="preview-tab" type="button" data-preview-mode="reproduction">Reproduced</button> | |
| </div> | |
| </div> | |
| <div class="hidden-audio-bank" aria-hidden="true"> | |
| <audio id="sourcePreview"></audio> | |
| <audio id="stemAudio"></audio> | |
| <audio id="reconAudio"></audio> | |
| <audio id="hitAudio"></audio> | |
| <audio id="sampleAudio"></audio> | |
| </div> | |
| </section> | |
| <section class="sample-board" aria-label="Extracted samples"> | |
| <div class="board-header"> | |
| <h2>Extracted Samples <span id="sampleCountLabel">(0)</span></h2> | |
| <span id="resultSummary">Drop audio. The app uploads, separates stems, tunes parameters, and deals sample cards.</span> | |
| </div> | |
| <div id="samplesGrid" class="sample-grid"></div> | |
| </section> | |
| </section> | |
| <aside class="settings-pane" aria-label="Settings"> | |
| <header class="settings-head"> | |
| <strong>Advanced Settings</strong> | |
| <button class="icon-button" type="button" aria-label="Hide settings">×</button> | |
| </header> | |
| <section class="settings-section simple-section"> | |
| <h3>Detection</h3> | |
| <label class="control-line">Stem | |
| <select id="stem"></select> | |
| </label> | |
| <label class="range-line">Sensitivity | |
| <span class="range-wrap"><input id="onset_delta" type="range" min="0.01" max="0.35" step="0.005" /><output id="sensitivityOutput">Auto</output></span> | |
| </label> | |
| <label class="range-line">Minimum interval | |
| <span class="range-wrap"><input id="min_gap" type="range" min="0.001" max="1" step="0.005" /><output id="minGapOutput">Auto</output></span> | |
| </label> | |
| <label class="range-line">Minimum amplitude | |
| <span class="range-wrap"><input id="energy_threshold_db" type="range" min="-100" max="0" step="1" /><output id="energyOutput">Auto</output></span> | |
| </label> | |
| </section> | |
| <section class="settings-section simple-section"> | |
| <h3>Grouping</h3> | |
| <label class="toggle-line"><span>Group Similar Hits</span><input id="groupSimilarToggle" type="checkbox" checked /></label> | |
| <label class="range-line">Max groups | |
| <span class="range-wrap"><input id="target_max" type="range" min="1" max="64" step="1" /><output id="targetMaxOutput">Auto</output></span> | |
| </label> | |
| <label class="range-line">Max group distance | |
| <span class="range-wrap"><input id="ncc_threshold" type="range" min="0" max="1" step="0.01" /><output id="nccOutput">Auto</output></span> | |
| </label> | |
| </section> | |
| <section class="settings-section simple-section"> | |
| <h3>Waveform</h3> | |
| <label class="control-line">Resolution | |
| <select id="waveformResolution"><option>High</option><option>Medium</option><option>Low</option></select> | |
| </label> | |
| <label class="control-line">Channels | |
| <select id="waveformChannels"><option>Left & Right</option><option>Mono</option></select> | |
| </label> | |
| </section> | |
| <details class="settings-section advanced-fold"> | |
| <summary>Expert pipeline controls</summary> | |
| <div class="expert-grid"> | |
| <label>Separation engine<select id="separation_backend"><option value="spleeter">Spleeter (default)</option><option value="demucs">Demucs</option><option value="none">No separation / full mix</option></select></label> | |
| <label>Spleeter model<select id="spleeter_model"></select></label> | |
| <label>Demucs model<select id="demucs_model"></select></label> | |
| <label>Clustering mode<select id="clustering_mode"><option value="batch_quality">batch quality</option><option value="online_preview">online preview</option></select></label> | |
| <label>Shifts<input id="demucs_shifts" type="number" min="0" max="8" step="1" /></label> | |
| <label>Overlap<input id="demucs_overlap" type="number" min="0" max="0.9" step="0.05" /></label> | |
| <label>Onset mode<select id="onset_mode"><option value="auto">auto / multiband</option><option value="percussive">percussive</option><option value="harmonic">harmonic</option><option value="broadband">broadband</option></select></label> | |
| <label>Pre-pad<input id="pre_pad" type="number" min="0" max="0.25" step="0.001" /></label> | |
| <label>Min duration<input id="min_dur" type="number" min="0.001" max="10" step="0.005" /></label> | |
| <label>Max duration<input id="max_dur" type="number" min="0.01" max="10" step="0.1" /></label> | |
| <label>Target min<input id="target_min" type="number" min="0" max="256" step="1" /></label> | |
| <label>Attack ms<input id="attack_ms" type="number" min="1" max="250" step="1" /></label> | |
| <label>Mel prefilter<input id="mel_threshold" type="number" min="0" max="1" step="0.01" /></label> | |
| <label>Linkage<select id="linkage"><option value="average">average</option><option value="complete">complete</option><option value="single">single</option></select></label> | |
| <label>MIDI grid<select id="subdivision"><option value="4">4th</option><option value="8">8th</option><option value="16">16th</option><option value="32">32nd</option><option value="64">64th</option></select></label> | |
| </div> | |
| <div class="toggles"> | |
| <label><input id="synthesize" type="checkbox" /> synthesize alternates</label> | |
| <label><input id="quantize_midi" type="checkbox" /> quantize MIDI</label> | |
| <label><input id="auto_tune" type="checkbox" checked /> automatic parameter tuning</label> | |
| <label><input id="use_disk_cache" type="checkbox" /> disk cache stems/source loads</label> | |
| <label><input id="allow_backend_fallback" type="checkbox" /> fallback to full mix if separation is unavailable</label> | |
| </div> | |
| <div class="preset-row"> | |
| <button id="usePreviewButton" class="secondary-action" type="button">Fast preview</button> | |
| <button id="useQualityButton" class="secondary-action" type="button">Best quality</button> | |
| <button id="clearCacheButton" class="secondary-action" type="button">Clear cache</button> | |
| </div> | |
| </details> | |
| <button id="resetUiButton" class="reset-button" type="button">Reset to Defaults</button> | |
| </aside> | |
| </main> | |
| <footer class="bottom-bar" aria-label="Selection and tools"> | |
| <div class="selection-count"><span class="checked-box">✓</span><strong id="selectedCountBottom">0 Selected</strong></div> | |
| <div class="bottom-zoom"><button class="tool-button" type="button" data-zoom-command="out">⌕ −</button><input class="mini-slider" type="range" min="1" max="64" value="1" /><button class="tool-button" type="button" data-zoom-command="in">+</button></div> | |
| <div class="bottom-actions"><button id="selectAllSamplesButton" class="secondary-action" type="button">☑ Select All</button><button id="clearSelectionButton" class="secondary-action" type="button">🗑 Clear</button><button id="openToolsButton" class="help-button" type="button">?</button></div> | |
| </footer> | |
| <section id="toolsDrawer" class="tools-drawer" aria-label="Review tools" hidden> | |
| <div class="drawer-grid"> | |
| <article> | |
| <h3>Pipeline</h3> | |
| <span id="jobPill" class="job-pill">idle</span> | |
| <div id="stageList" class="stage-list"></div> | |
| <pre id="logs" class="logs" aria-live="polite"></pre> | |
| </article> | |
| <article> | |
| <h3>Exports</h3> | |
| <div id="downloads" class="downloads compact-downloads"></div> | |
| <div id="editedDownloads" class="downloads edited-downloads"></div> | |
| <button id="exportStateButton" class="secondary-action" type="button" disabled>Export edited pack</button> | |
| </article> | |
| <article> | |
| <h3>Selection</h3> | |
| <p id="selectedHitMeta">Click an onset marker or hit row to audition the detected slice.</p> | |
| <p id="selectedSampleMeta">Click a sample card to hear the representative sample.</p> | |
| <div id="supervisionSummary" class="state-summary">No interactive state loaded.</div> | |
| </article> | |
| <article> | |
| <h3>Run history</h3> | |
| <button id="refreshHistoryButton" class="secondary-action" type="button">Refresh history</button> | |
| <div id="historyList" class="history-list"></div> | |
| </article> | |
| </div> | |
| <details class="drawer-advanced"> | |
| <summary>Review & edit state</summary> | |
| <div class="supervision-actions"> | |
| <button id="refreshStateButton" class="secondary-action" type="button">Refresh state</button> | |
| <button id="forceOnsetButton" class="secondary-action" type="button" disabled>Add-onset mode off</button> | |
| <button id="undoButton" class="secondary-action" type="button" disabled>Undo edit</button> | |
| </div> | |
| <div class="supervision-tools"> | |
| <label>Target cluster<select id="targetClusterSelect"></select></label> | |
| <button id="moveHitButton" class="secondary-action" type="button" disabled>Move selected hit</button> | |
| <button id="pullHitButton" class="secondary-action" type="button" disabled>Pull into new cluster</button> | |
| <button id="acceptHitButton" class="secondary-action" type="button" disabled>Accept hit</button> | |
| <button id="favoriteHitButton" class="secondary-action" type="button" disabled>Favorite</button> | |
| <button id="suppressHitButton" class="secondary-action danger" type="button" disabled>Suppress</button> | |
| <button id="restoreHitButton" class="secondary-action" type="button" disabled>Restore</button> | |
| <button id="lockClusterButton" class="secondary-action" type="button" disabled>Lock cluster</button> | |
| <button id="explainClusterButton" class="secondary-action" type="button" disabled>Explain</button> | |
| </div> | |
| <div class="supervision-grid"> | |
| <article><h4>Outlier-first review queue</h4><div id="reviewQueue" class="compact-list"></div></article> | |
| <article><h4>Cluster board</h4><div id="clusterBoard" class="compact-list"></div></article> | |
| <article><h4>Suggestion inbox</h4><div id="suggestionInbox" class="compact-list"></div></article> | |
| <article><h4>Constraint / event log</h4><div id="stateLog" class="compact-list"></div></article> | |
| </div> | |
| <pre id="clusterExplanation" class="explanation empty">Select a cluster and click Explain.</pre> | |
| </details> | |
| <details class="drawer-advanced"> | |
| <summary>Raw tables</summary> | |
| <div class="result-columns"> | |
| <section><h3>Representative samples</h3><div class="table-wrap"><table id="samplesTable"><thead><tr><th>Audition</th><th>Sample</th><th>Class</th><th>Hits</th><th>Score</th><th>Duration</th><th>First hit</th><th>File</th></tr></thead><tbody></tbody></table></div></section> | |
| <section><h3>Detected hit review</h3><div class="table-wrap hit-table-wrap"><table id="hitsTable"><thead><tr><th>Audition</th><th>#</th><th>Label</th><th>Cluster</th><th>Confidence</th><th>Flags</th><th>Onset</th><th>Duration</th><th>Energy</th><th>File</th></tr></thead><tbody></tbody></table></div></section> | |
| </div> | |
| </details> | |
| </section> | |
| </div> | |
| <script type="module" src="/web/app.js"></script> | |
| </body> | |
| </html> | |