softchart / static /index.html
JacobLinCool's picture
Add BarScript (experimental preview) model + ura difficulty; vendored sc2 subpackage
d27cb1d verified
Raw
History Blame Contribute Delete
23.7 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="SoftChart turns music into playable, musical Taiko charts with an instant drum-mix audition.">
<meta name="theme-color" content="#f6f3ec">
<title>SoftChart — AI Taiko Chart Studio</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Ccircle cx='32' cy='32' r='25' fill='%23e14b3f'/%3E%3Ccircle cx='32' cy='32' r='18' fill='%23fff8ed'/%3E%3Ccircle cx='32' cy='32' r='9' fill='%23e14b3f'/%3E%3C/svg%3E">
<link rel="stylesheet" href="./static/app.css">
<script type="module" src="./static/app.js"></script>
</head>
<body>
<a class="skip-link" href="#main-content">Skip to main content</a>
<header class="site-header">
<a class="brand" href="./" aria-label="SoftChart home">
<svg class="brand-mark" viewBox="0 0 48 48" aria-hidden="true">
<circle cx="24" cy="24" r="20" fill="currentColor" opacity=".12"/>
<circle cx="24" cy="24" r="14.5" fill="none" stroke="currentColor" stroke-width="2.5"/>
<circle cx="24" cy="24" r="5.5" fill="currentColor"/>
<path d="M8.5 24h5M34.5 24h5" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/>
</svg>
<span>SoftChart</span>
<span class="brand-edition">STUDIO</span>
</a>
<div class="connection" id="connection" role="status" aria-live="polite">
<span class="connection-dot" aria-hidden="true"></span>
<span id="connection-label">Connecting</span>
</div>
</header>
<main id="main-content">
<section class="hero" aria-labelledby="hero-title">
<div class="hero-copy">
<h1 id="hero-title">Music in.<br><em>Taiko out.</em></h1>
<p class="hero-lede">Upload a track. Get a playable TJA. Hear it instantly.</p>
</div>
<ul class="hero-features" aria-label="Key features">
<li><strong>Beat-locked</strong></li>
<li><strong>Structure-aware</strong></li>
<li><strong>Instant audition</strong></li>
</ul>
</section>
<section class="studio-grid" aria-label="Taiko chart generation studio">
<form class="panel setup-panel" id="generate-form">
<div class="panel-heading">
<h2>Create</h2>
</div>
<div class="form-section">
<div class="label-row">
<label id="upload-label" for="file-input">Music</label>
<span class="field-hint">MP3, WAV, FLAC, OGG</span>
</div>
<input id="file-input" type="file" accept=".mp3,.wav,.flac,.ogg" tabindex="-1" aria-hidden="true">
<div class="dropzone" id="dropzone" role="button" tabindex="0" aria-labelledby="upload-label upload-help">
<svg class="upload-icon" viewBox="0 0 56 56" aria-hidden="true">
<circle cx="28" cy="28" r="27" fill="currentColor" opacity=".08"/>
<path d="M28 36V18m0 0-7 7m7-7 7 7M17 38.5h22" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span class="drop-title">Drop audio</span>
<span class="drop-subtitle" id="upload-help">or browse</span>
</div>
<div class="source-card" id="source-card" hidden>
<div class="source-info">
<span class="file-badge" aria-hidden="true"></span>
<span class="file-copy">
<strong id="file-name"></strong>
<span id="file-meta"></span>
</span>
<button type="button" class="icon-button" id="remove-file" aria-label="Remove music">
<svg viewBox="0 0 20 20" aria-hidden="true"><path d="m6 6 8 8m0-8-8 8"/></svg>
</button>
</div>
<audio id="source-audio" controls preload="metadata">Your browser does not support audio playback.</audio>
</div>
<p class="field-error" id="file-error" role="alert" hidden></p>
</div>
<div class="form-section split-rule">
<div class="field-group">
<div class="label-row">
<label for="model">Model</label>
</div>
<select id="model" class="model-select">
<optgroup label="v1.7 — richest patterns (recommended)">
<option value="v1.7" selected>v1.7 · 7.9M — best quality</option>
<option value="v1.7-small">v1.7-small · 3.6M</option>
<option value="v1.7-tiny">v1.7-tiny · 1.4M — fastest</option>
</optgroup>
<optgroup label="v1.6 — scaling ladder">
<option value="v1.6">v1.6 · 7.9M</option>
<option value="v1.6-small">v1.6-small · 3.6M</option>
<option value="v1.6-tiny">v1.6-tiny · 1.4M</option>
</optgroup>
<optgroup label="v1.5 — single model">
<option value="v1.5">v1.5 · 7.9M</option>
</optgroup>
<!-- BarScript is the experimental preview line, served from its
own release package. The group stays disabled and hidden
until /api/capabilities reports the package resolved; the
label below is a placeholder that app.js overwrites with the
group name the API returns. -->
<optgroup label="BarScript — EXPERIMENTAL PREVIEW, under evaluation" id="experimental-models" hidden disabled></optgroup>
</select>
<div class="model-notices" id="model-notices" hidden>
<strong id="model-notices-title">Known limitations</strong>
<ul id="model-notices-list"></ul>
</div>
</div>
<fieldset class="field-group">
<legend>Difficulty</legend>
<div class="course-selector">
<label><input type="radio" name="course" value="easy"><span><small>E</small>Easy</span></label>
<label><input type="radio" name="course" value="normal"><span><small>N</small>Normal</span></label>
<label><input type="radio" name="course" value="hard"><span><small>H</small>Hard</span></label>
<label><input type="radio" name="course" value="oni" checked><span><small>O</small>Oni</span></label>
<label><input type="radio" name="course" value="ura"><span><small>U</small>Ura</span></label>
</div>
</fieldset>
<div class="two-column-fields">
<div class="field-group">
<div class="label-row">
<label for="level">Star level</label>
<output class="value-output" id="level-output" for="level">★ 9</output>
</div>
<input class="range" id="level" type="range" min="1" max="10" value="9" step="1">
</div>
<div class="field-group">
<div class="label-row">
<label for="bpm">BPM</label>
</div>
<div class="input-with-unit">
<input id="bpm" type="number" min="0" max="400" step="0.1" inputmode="decimal" placeholder="AUTO">
</div>
</div>
</div>
</div>
<details class="advanced split-rule" id="advanced-settings">
<summary>
<span><strong>Advanced</strong></span>
<svg viewBox="0 0 20 20" aria-hidden="true"><path d="m6 8 4 4 4-4"/></svg>
</summary>
<div class="advanced-body">
<div class="toggle-list">
<label class="toggle-card compact">
<span><strong>Structure</strong></span>
<input id="auto-plan" type="checkbox" checked>
<span class="switch" aria-hidden="true"></span>
</label>
<label class="toggle-card compact">
<span><strong>Beat grid</strong></span>
<input id="use-beat" type="checkbox" checked>
<span class="switch" aria-hidden="true"></span>
</label>
<label class="toggle-card compact">
<span><strong>AI planner</strong></span>
<input id="use-planner" type="checkbox" checked>
<span class="switch" aria-hidden="true"></span>
</label>
</div>
<label class="toggle-card compact">
<span><strong>Creative sampling</strong></span>
<input id="sampling" type="checkbox">
<span class="switch" aria-hidden="true"></span>
</label>
<div class="parameter-grid" id="sampling-parameters" aria-disabled="true">
<div class="field-group">
<div class="label-row">
<label for="temperature">Variation</label>
<output class="value-output" id="temperature-output" for="temperature">0.80</output>
</div>
<input class="range" id="temperature" type="range" min="0.2" max="1.2" value="0.8" step="0.05" disabled>
</div>
<div class="field-group">
<div class="label-row">
<label for="top-p">Candidate range</label>
<output class="value-output" id="top-p-output" for="top-p">0.90</output>
</div>
<input class="range" id="top-p" type="range" min="0.5" max="1" value="0.9" step="0.01" disabled>
</div>
</div>
<div class="field-group drum-volume-field">
<div class="label-row">
<label for="drum-volume">Taiko preview volume</label>
<output class="value-output" id="drum-volume-output" for="drum-volume">80%</output>
</div>
<input class="range" id="drum-volume" type="range" min="0" max="1.5" value="0.8" step="0.05">
</div>
</div>
</details>
<button class="primary-button" id="generate-button" type="submit">
<span>Generate chart</span>
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14m-5-5 5 5-5 5"/></svg>
</button>
</form>
<div class="output-column">
<section class="panel process-panel" id="process-panel" aria-labelledby="process-title">
<div class="panel-heading">
<h2 id="process-title">Progress</h2>
<span class="status-chip is-idle" id="status-chip">Ready</span>
</div>
<div class="stage-canvas" id="stage-canvas">
<div class="stage-visual is-active" data-stage="loading" aria-hidden="true">
<svg viewBox="0 0 520 280">
<g class="loading-grid" stroke="currentColor" opacity=".07"><path d="M0 56h520M0 112h520M0 168h520M0 224h520M104 0v280M208 0v280M312 0v280M416 0v280"/></g>
<g transform="translate(260 140)">
<circle class="loading-orbit orbit-a" r="68" fill="none" stroke="currentColor" stroke-width="1.5" stroke-dasharray="10 12" opacity=".25"/>
<circle class="loading-orbit orbit-b" r="48" fill="none" stroke="currentColor" stroke-width="2" stroke-dasharray="3 9" opacity=".4"/>
<circle r="27" fill="currentColor" opacity=".1"/>
<circle class="loading-core" r="12" fill="currentColor"/>
<circle class="loading-dot dot-a" cx="0" cy="-68" r="5" fill="currentColor"/>
<circle class="loading-dot dot-b" cx="48" cy="0" r="4" fill="currentColor"/>
</g>
</svg>
</div>
<div class="stage-visual" data-stage="audio" aria-hidden="true">
<svg viewBox="0 0 520 280">
<path class="audio-line-back" d="M24 140C54 140 61 112 84 112s28 68 51 68 31-115 55-115 30 150 53 150 33-104 57-104 30 59 55 59 29-76 52-76 29 46 49 46h40" fill="none" stroke="currentColor" stroke-width="2" opacity=".14"/>
<path class="audio-line" pathLength="1" d="M24 140C54 140 61 112 84 112s28 68 51 68 31-115 55-115 30 150 53 150 33-104 57-104 30 59 55 59 29-76 52-76 29 46 49 46h40" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round"/>
<g class="audio-playhead"><path d="M0 48v184" stroke="currentColor" stroke-width="1.5" opacity=".45"/><circle cy="140" r="7" fill="currentColor"/></g>
<g fill="currentColor" opacity=".22"><circle cx="84" cy="112" r="4"/><circle cx="190" cy="65" r="4"/><circle cx="300" cy="111" r="4"/><circle cx="407" cy="94" r="4"/></g>
</svg>
</div>
<div class="stage-visual" data-stage="beat" aria-hidden="true">
<svg viewBox="0 0 520 280">
<path d="M72 205h376" stroke="currentColor" stroke-width="2" opacity=".14"/>
<g class="beat-ticks" stroke="currentColor" opacity=".26"><path d="M100 192v26M180 192v26M260 185v40M340 192v26M420 192v26"/></g>
<path class="beat-arc" d="M182 199a78 78 0 0 1 156 0" fill="none" stroke="currentColor" stroke-width="3" opacity=".18"/>
<g class="stage-anchor" transform="translate(260 199)">
<g class="metronome">
<path d="M0 0 54-118" stroke="currentColor" stroke-width="5" stroke-linecap="round"/>
<circle cx="54" cy="-118" r="10" fill="currentColor"/>
</g>
</g>
<g class="beat-pulses" fill="currentColor"><circle cx="100" cy="205" r="7"/><circle cx="180" cy="205" r="7"/><circle cx="260" cy="205" r="10"/><circle cx="340" cy="205" r="7"/><circle cx="420" cy="205" r="7"/></g>
</svg>
</div>
<div class="stage-visual" data-stage="plan" aria-hidden="true">
<svg viewBox="0 0 520 280">
<g class="plan-bars">
<rect x="42" y="166" width="45" height="60" rx="5"/>
<rect x="96" y="143" width="45" height="83" rx="5"/>
<rect x="150" y="153" width="45" height="73" rx="5"/>
<rect x="204" y="105" width="45" height="121" rx="5"/>
<rect x="258" y="127" width="45" height="99" rx="5"/>
<rect x="312" y="83" width="45" height="143" rx="5"/>
<rect x="366" y="53" width="45" height="173" rx="5" class="plan-climax"/>
<rect x="420" y="118" width="45" height="108" rx="5"/>
</g>
<path class="plan-path" d="M64 158 118 135l54 10 54-49 54 22 54-43 54-31 54 65" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<circle class="plan-cursor" cx="64" cy="158" r="7" fill="currentColor"/>
</svg>
</div>
<div class="stage-visual" data-stage="generate" aria-hidden="true">
<svg viewBox="0 0 520 280">
<path d="M20 94h480M20 186h480" stroke="currentColor" stroke-width="2" opacity=".13"/>
<path d="M20 140h480" stroke="currentColor" stroke-width="1.5" stroke-dasharray="5 10" opacity=".13"/>
<g class="note-stream">
<g class="note note-1"><circle r="20"/><circle r="11" fill="#fff8ed" opacity=".2"/></g>
<g class="note note-2"><circle r="20" class="ka"/><circle r="11" fill="#fff8ed" opacity=".2"/></g>
<g class="note note-3"><circle r="27"/><circle r="15" fill="#fff8ed" opacity=".2"/></g>
<g class="note note-4"><circle r="20" class="ka"/><circle r="11" fill="#fff8ed" opacity=".2"/></g>
<g class="note note-5"><circle r="20"/><circle r="11" fill="#fff8ed" opacity=".2"/></g>
</g>
<g class="stage-anchor" transform="translate(93 140)">
<g class="generate-gate"><circle r="42" fill="none" stroke="currentColor" stroke-width="2" opacity=".22"/><circle r="31" fill="none" stroke="currentColor" stroke-width="2" opacity=".38"/><path d="M0-49v98" stroke="currentColor" stroke-width="3"/></g>
</g>
</svg>
</div>
<div class="stage-visual" data-stage="export" aria-hidden="true">
<svg viewBox="0 0 520 280">
<g class="stage-anchor" transform="translate(175 34)">
<g class="export-sheet">
<path d="M8 0h126l42 42v189H8z" fill="currentColor" opacity=".08"/>
<path d="M134 0v42h42" fill="none" stroke="currentColor" stroke-width="2" opacity=".35"/>
<g class="export-lines" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M38 77h108M38 104h78M38 131h108M38 158h91"/></g>
<g class="export-dots" fill="currentColor"><circle cx="48" cy="194" r="8"/><circle cx="76" cy="194" r="8" class="ka"/><circle cx="104" cy="194" r="8"/><circle cx="132" cy="194" r="8" class="ka"/></g>
</g>
</g>
<path class="export-arrow" d="M366 91v105m0 0-20-20m20 20 20-20" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<div class="stage-visual" data-stage="mix" aria-hidden="true">
<svg viewBox="0 0 520 280">
<g class="mix-wave wave-top" fill="none" stroke="currentColor" stroke-width="3"><path d="M35 93c26 0 26-32 52-32s26 64 52 64 26-64 52-64 26 64 52 64 26-64 52-64 26 64 52 64 26-64 52-64 26 32 52 32h46"/></g>
<g class="mix-wave wave-bottom" fill="none" stroke="currentColor" stroke-width="3"><path d="M35 187c34 0 34-22 68-22s34 44 68 44 34-44 68-44 34 44 68 44 34-44 68-44 34 22 68 22h72"/></g>
<g class="stage-anchor" transform="translate(260 140)">
<g class="mix-drum"><circle r="48" fill="#fff8ed" stroke="currentColor" stroke-width="4"/><circle r="35" fill="currentColor" opacity=".12"/><circle r="13" fill="currentColor"/></g>
</g>
<g class="mix-spark" fill="currentColor"><circle cx="201" cy="119" r="5"/><circle cx="319" cy="161" r="5"/><circle cx="312" cy="100" r="3"/><circle cx="211" cy="177" r="3"/></g>
</svg>
</div>
<div class="stage-visual" data-stage="complete" aria-hidden="true">
<svg viewBox="0 0 520 280">
<g class="stage-anchor" transform="translate(260 140)">
<g class="complete-rings"><circle r="81" fill="none" stroke="currentColor" stroke-width="2" opacity=".12"/><circle r="64" fill="currentColor" opacity=".1"/><circle r="47" fill="currentColor"/></g>
</g>
<path class="complete-check" d="m235 140 17 17 35-38" fill="none" stroke="#fff8ed" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/>
<g class="confetti" fill="currentColor"><rect x="165" y="65" width="7" height="18" rx="3" transform="rotate(-35 168 74)"/><rect x="350" y="70" width="7" height="18" rx="3" transform="rotate(28 353 79)"/><circle cx="177" cy="201" r="6"/><circle cx="350" cy="207" r="5"/><path d="m387 139 12-7-1 14z"/><path d="m126 132 13-5-3 14z"/></g>
</svg>
</div>
</div>
<div class="process-copy">
<div class="process-title-row">
<div>
<p class="process-eyebrow" id="stage-eyebrow">STANDBY</p>
<h3 id="stage-title">Waiting for your music</h3>
</div>
<strong class="progress-number" id="progress-number">0%</strong>
</div>
<p class="sr-only" id="stage-detail">Upload a track to begin.</p>
<div class="progress-track" id="progress-track" role="progressbar" aria-label="Chart generation progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<span id="progress-bar"></span>
</div>
<div class="queue-row">
<span id="queue-label">Not started</span>
<button class="text-button" type="button" id="cancel-button" hidden>Cancel generation</button>
</div>
</div>
<div class="process-error" id="process-error" role="alert" hidden>
<strong>Generation incomplete</strong>
<span id="process-error-message"></span>
<button class="text-button" type="button" id="retry-button">Try again</button>
</div>
</section>
<section class="panel result-panel" id="result-panel" aria-labelledby="result-title" hidden>
<div class="panel-heading">
<h2 id="result-title">Ready</h2>
</div>
<div class="audition-card" id="audition-card">
<div class="audition-heading">
<span class="audition-icon" aria-hidden="true">
<svg viewBox="0 0 32 32"><circle cx="16" cy="16" r="12"/><path d="m13 10 9 6-9 6z"/></svg>
</span>
<span><strong>Taiko audition</strong></span>
</div>
<audio id="result-audio" controls preload="metadata">Your browser does not support audio playback.</audio>
</div>
<dl class="metrics-grid" id="metrics-grid" aria-label="Generation summary"></dl>
<div class="preview-block">
<div class="preview-tabs" role="tablist" aria-label="Preview type">
<button id="chart-tab" class="preview-tab is-active" type="button" role="tab" aria-selected="true" aria-controls="chart-preview">Chart preview</button>
<button id="plan-tab" class="preview-tab" type="button" role="tab" aria-selected="false" aria-controls="plan-preview" tabindex="-1">Song structure</button>
</div>
<div class="preview-frame">
<div id="chart-preview" role="tabpanel" aria-labelledby="chart-tab">
<img id="chart-image" alt="Preview of the generated Taiko chart">
<p class="preview-empty" id="chart-empty" hidden>No chart preview is available.</p>
</div>
<div id="plan-preview" role="tabpanel" aria-labelledby="plan-tab" hidden>
<img id="plan-image" alt="Song energy and chart section plan">
<p class="preview-empty" id="plan-empty" hidden>No song structure preview is available.</p>
</div>
</div>
</div>
<div class="download-group">
<a class="download-button primary-download" id="download-tja" href="#" download hidden>
<span><strong>Download TJA</strong></span>
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 4v11m0 0 4-4m-4 4-4-4M5 20h14"/></svg>
</a>
<a class="download-button" id="download-audio" href="#" download hidden>
<span><strong>Download audio</strong></span>
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 4v11m0 0 4-4m-4 4-4-4M5 20h14"/></svg>
</a>
</div>
<button class="secondary-button" id="new-chart-button" type="button">Create another chart</button>
</section>
</div>
</section>
</main>
<footer>
<span>SoftChart</span>
<a href="https://github.com/JacobLinCool/SoftChart" target="_blank" rel="noreferrer">GitHub <span aria-hidden="true"></span></a>
</footer>
<div class="sr-only" id="announcer" aria-live="assertive" aria-atomic="true"></div>
</body>
</html>