Files
micarrsim/apps/dataset-builder/index.html
T

218 lines
14 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="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="micarrsim 음향 장면 및 ground truth 생성기" />
<title>Dataset Builder · micarrsim</title>
<link rel="stylesheet" href="/packages/ui/app-shell.css" />
<link rel="stylesheet" href="/apps/dataset-builder/styles.css" />
</head>
<body>
<div class="app-shell builder-shell">
<header class="app-header builder-header">
<a class="app-brand" href="/">
<strong>micarrsim</strong>
<span>Dataset Builder</span>
</a>
<nav class="builder-workflow" id="builder-workflow" aria-label="Scene 제작 순서">
<ol>
<li data-workflow-step="input"><span>1</span>입력</li>
<li data-workflow-step="edit"><span>2</span>배치·편집</li>
<li data-workflow-step="validate"><span>3</span>검증</li>
<li data-workflow-step="save"><span>4</span>저장</li>
</ol>
</nav>
<div class="header-actions">
<button class="button button--ghost" id="preview-button" type="button">▶ 미리 듣기</button>
<button class="button button--primary" id="export-button" type="button">Scene JSON 저장</button>
<details class="header-more">
<summary class="button button--ghost" aria-label="추가 작업">더보기</summary>
<div class="header-more__menu">
<button class="button button--ghost" id="wav-button" type="button" title="공간정보 없이 모든 음원을 합친 mono 확인용 WAV입니다.">Preview WAV 저장</button>
<a class="button button--ghost" href="/apps/acoustic-camera/">Acoustic Camera 열기 →</a>
</div>
</details>
</div>
</header>
<main class="builder-layout" id="builder-layout" data-split-layout>
<section class="scene-workspace" id="builder-workspace" aria-label="장면 편집 화면">
<div class="workspace-heading">
<div>
<p class="eyebrow">01 · 입력과 배치</p>
<h1 id="workspace-title">음향 장면</h1>
</div>
<div class="workspace-tools">
<label class="button button--ghost file-button">
Scene 불러오기
<input id="scene-input" type="file" accept="application/json,.json" />
</label>
<label class="button button--ghost file-button">
배경 이미지
<input id="image-input" type="file" accept="image/*" />
</label>
<button class="button button--danger is-hidden" id="remove-image-button" type="button">이미지 해제</button>
<label class="button button--ghost file-button" title="Scene을 다시 열었을 때 원본 파일을 SHA-256으로 재연결합니다.">
원본 재연결
<input id="audio-input" type="file" accept="audio/*,.wav,.flac,.mp3,.ogg,.m4a" multiple />
</label>
</div>
</div>
<div class="canvas-card">
<canvas id="scene-canvas" aria-label="이미지 평면과 음원 ground truth"></canvas>
<div class="canvas-empty" id="canvas-empty">
<strong>음원을 선택하고 canvas를 클릭해 위치를 지정하세요.</strong>
<span>배경 이미지는 선택 사항입니다.</span>
</div>
<div class="canvas-badge" id="canvas-badge">x −0.60…0.60 m · y −0.45…0.45 m</div>
</div>
<div class="source-strip-heading">
<div>
<p class="eyebrow">02 · 음원 편집</p>
<h2>음원과 이동 경로</h2>
<p>카드를 선택한 뒤 canvas를 클릭하면 현재 위치 또는 선택한 경로점이 이동합니다.</p>
</div>
<div class="source-actions">
<button class="button button--ghost" id="add-source-button" type="button">+ 합성 음원</button>
<label class="button button--primary file-button">
+ 오디오 파일 음원
<input id="audio-source-input" type="file" accept="audio/*,.wav,.flac,.mp3,.ogg,.m4a" multiple />
</label>
</div>
</div>
<div class="source-strip" id="source-list" aria-label="음원 목록"></div>
<section class="asset-shelf">
<div>
<h2>연결된 원본 파일</h2>
<details class="asset-help">
<summary>파일 연결 도움말</summary>
<p>원본은 업로드되지 않고 브라우저에서만 처리됩니다. Scene을 다시 열었다면 위의 <strong>원본 재연결</strong>에서 같은 파일을 선택하세요. PCM WAV를 권장합니다.</p>
</details>
</div>
<div class="asset-list" id="asset-list"></div>
</section>
</section>
<div
class="split-handle"
id="builder-split-handle"
role="separator"
tabindex="0"
aria-label="장면 설정 패널 너비 조절"
aria-controls="builder-controls"
aria-orientation="vertical"
data-split-resizer
data-storage-key="micarrsim.builder.control-panel-width"
title="드래그하거나 방향키로 너비 조절 · Enter/더블클릭으로 초기화"
></div>
<aside class="control-panel" id="builder-controls" data-split-panel aria-label="장면 파라미터">
<div class="runtime-line">
<span class="status-chip status-chip--neutral" data-runtime-status>런타임 확인 중…</span>
<span class="save-state" id="save-state">기본 장면</span>
</div>
<section class="validation-card" aria-live="polite">
<div class="validation-dot" id="validation-dot"></div>
<div><strong id="validation-title">검증 대기</strong><p id="validation-message">장면을 준비하고 있습니다.</p></div>
</section>
<section class="control-section control-section--primary" id="source-editor-section">
<div class="section-title"><span>02</span><h2>선택 음원 편집</h2></div>
<div id="no-source-message" class="inline-note">음원을 선택하세요.</div>
<div id="source-fields">
<label class="field field--wide"><span>이름</span><input id="source-name" type="text" maxlength="120" /></label>
<div class="field-grid field-grid--three">
<label class="field"><span>x (m)</span><input id="source-x" type="number" step="0.01" /></label>
<label class="field"><span>y (m)</span><input id="source-y" type="number" step="0.01" /></label>
<label class="field"><span>거리 z (m)</span><input id="source-z" type="number" min="0.01" step="0.1" /></label>
</div>
<div class="field-grid field-grid--three">
<label class="field"><span>Gain (dB)</span><input id="source-gain" type="number" min="-120" max="24" step="1" /></label>
<label class="field"><span>시작 (s)</span><input id="source-start" type="number" min="0" step="0.01" /></label>
<label class="field"><span>길이 (s)</span><input id="source-duration" type="number" min="0.01" step="0.01" /></label>
</div>
<section class="trajectory-editor" aria-label="음원 이동 경로">
<label class="check-field trajectory-toggle"><input id="source-motion" type="checkbox" /><span>시간에 따라 음원 이동</span></label>
<p class="section-note">켜면 현재 위치부터 Scene 끝까지의 기본 경로가 만들어집니다.</p>
<div id="trajectory-fields" class="is-hidden">
<label class="field field--wide trajectory-preview">
<span>경로 미리보기 · <output id="preview-time-value" for="preview-time">0.00 s</output></span>
<input id="preview-time" type="range" min="0" max="1" step="0.01" value="0" />
</label>
<p class="section-note">경로점을 선택하고 canvas를 클릭해 x/y를 옮기세요.</p>
<div class="trajectory-list" id="trajectory-list"></div>
<button class="button button--ghost button--full" id="add-keyframe-button" type="button">+ 경로점 추가</button>
</div>
</section>
<label class="field field--wide"><span>신호 종류</span><select id="source-type"><option value="tone">Tone</option><option value="noise">Noise</option><option value="asset">Audio asset</option></select></label>
<div id="tone-fields"><label class="field field--wide"><span>주파수 (Hz)</span><input id="tone-frequency" type="number" min="1" step="1" /></label></div>
<div id="noise-fields"><label class="field field--wide"><span>Noise color</span><select id="noise-color"><option value="white">White</option><option value="pink">Pink</option></select></label></div>
<div id="asset-fields">
<label class="field field--wide"><span>Audio asset</span><select id="source-asset"></select></label>
<div class="field-grid">
<label class="field"><span>Channel</span><input id="source-channel" type="number" min="0" max="255" step="1" /></label>
<label class="check-field"><input id="source-loop" type="checkbox" /><span>짧은 파일 반복</span></label>
</div>
</div>
<button class="button button--danger button--full" id="remove-source-button" type="button">선택 음원 삭제</button>
</div>
</section>
<section class="control-section">
<div class="section-title"><span>설정</span><h2>장면 기본값</h2></div>
<label class="field field--wide">
<span>이름</span>
<input id="scene-name" type="text" maxlength="120" />
</label>
<label class="field field--wide">
<span>Scene ID</span>
<input id="scene-id" type="text" maxlength="120" pattern="[a-z0-9][a-z0-9._-]*" />
</label>
<label class="field field--wide"><span>길이 (s)</span><input id="scene-duration" type="number" min="0.05" max="300" step="0.05" /></label>
<details class="inline-disclosure">
<summary>고급 음향·믹스 설정</summary>
<div class="field-grid">
<label class="field"><span>Sample rate</span><input id="sample-rate" type="number" min="8000" max="192000" step="1" /></label>
<label class="field"><span>음속 (m/s)</span><input id="speed-of-sound" type="number" min="250" max="400" step="0.1" /></label>
<label class="field"><span>Seed</span><input id="scene-seed" type="number" min="0" max="4294967295" step="1" /></label>
<label class="field"><span>Mix 정규화</span><select id="mix-normalization"><option value="none">없음</option><option value="peak">Peak</option></select></label>
<label class="field"><span>Target peak</span><input id="target-peak" type="number" min="0.01" max="1" step="0.01" /></label>
</div>
</details>
</section>
<details class="control-section disclosure-section">
<summary class="section-summary"><span>범위</span><strong>표시 평면</strong><small>고급</small></summary>
<div class="field-grid field-grid--compact">
<label class="field"><span>x min</span><input id="plane-x-min" type="number" step="0.05" /></label>
<label class="field"><span>x max</span><input id="plane-x-max" type="number" step="0.05" /></label>
<label class="field"><span>y min</span><input id="plane-y-min" type="number" step="0.05" /></label>
<label class="field"><span>y max</span><input id="plane-y-max" type="number" step="0.05" /></label>
<label class="field"><span>plane z (m)</span><input id="plane-z" type="number" min="0.01" step="0.1" /></label>
</div>
<p class="section-note">x/y는 canvas 범위이며 배경이 있으면 image plane으로 저장됩니다.</p>
</details>
<details class="control-section disclosure-section">
<summary class="section-summary"><span>배경음</span><strong>Ambient</strong><small>선택 사항</small></summary>
<label class="field field--wide"><span>종류</span><select id="ambient-type"><option value="none">없음</option><option value="white">White noise</option><option value="pink">Pink noise</option><option value="asset">Audio asset</option></select></label>
<label class="field field--wide" id="ambient-asset-field"><span>Audio asset</span><select id="ambient-asset"></select></label>
<div class="field-grid" id="ambient-asset-options">
<label class="field"><span>Channel</span><input id="ambient-channel" type="number" min="0" max="255" step="1" /></label>
<label class="check-field"><input id="ambient-loop" type="checkbox" /><span>짧은 파일 반복</span></label>
</div>
<label class="field field--wide"><span>Gain (dB)</span><input id="ambient-gain" type="number" min="-120" max="24" step="1" /></label>
</details>
</aside>
</main>
</div>
<script type="module" src="/packages/ui/runtime-status.js"></script>
<script type="module" src="/apps/dataset-builder/main.js"></script>
</body>
</html>