editor.py aktualisiert

This commit is contained in:
2026-09-29 08:19:42 +02:00
parent e342736a80
commit aac7ebf0f9
+36 -4
View File
@@ -213,6 +213,7 @@ h1 { margin:0 0 6px; font-size:28px; }
.wave-wrap { position:relative; width:100%; height:240px; background:#0b0b0b; border-radius:6px; overflow:hidden; user-select:none; touch-action:none; }
.wave-wrap img { width:100%; height:100%; object-fit:fill; display:block; opacity:.9; }
.selection { position:absolute; top:0; bottom:0; background:rgba(80,150,255,.16); border-left:2px solid #fff; border-right:2px solid #fff; pointer-events:none; }
.playhead { position:absolute; top:0; bottom:0; width:2px; margin-left:-1px; background:#ffcc33; box-shadow:0 0 5px #000; z-index:4; pointer-events:none; }
.handle { position:absolute; top:0; bottom:0; width:18px; margin-left:-9px; cursor:ew-resize; z-index:3; touch-action:none; }
.handle::after { content:""; position:absolute; left:7px; top:0; bottom:0; width:4px; background:#fff; border-radius:2px; box-shadow:0 0 5px #000; }
.time-row { display:flex; justify-content:space-between; margin-top:8px; color:#aaa; font-size:14px; }
@@ -253,6 +254,7 @@ button:disabled { opacity:.45; cursor:not-allowed; }
<div class="wave-wrap" id="wave">
<img src="{{ waveform_url }}" alt="Wellenform">
<div class="selection" id="selection"></div>
<div class="playhead" id="playhead"></div>
<div class="handle" id="startHandle" title="Anfang verschieben"></div>
<div class="handle" id="endHandle" title="Ende verschieben"></div>
</div>
@@ -267,9 +269,13 @@ button:disabled { opacity:.45; cursor:not-allowed; }
<div class="controls">
<button onclick="jump(-10)">⏮ 10 s</button>
<button onclick="jump(-1)">⏪ 1 s</button>
<button onclick="jump(1)">1 s ⏩</button>
<button onclick="jump(10)">10 s ⏭</button>
<button onclick="playSelection()">▶ Auswahl abspielen</button>
<button onclick="playFromStart()">▶ Ab Auswahlstart</button>
<button onclick="setStartAtCurrent()">⏱ Anfang = Position</button>
<button onclick="setEndAtCurrent()">⏱ Ende = Position</button>
<span class="position" id="position">00:00:00</span>
</div>
@@ -283,7 +289,7 @@ button:disabled { opacity:.45; cursor:not-allowed; }
<button class="primary" id="trimButton" onclick="trim()">✂ Fertige Aufnahme erstellen</button>
<a class="button" href="{{ audio_url }}" download>Original herunterladen</a>
</div>
<div class="info">Die erste Version der Aufnahme wird als Original auf dem Server behalten. Weitere Schnitte sind möglich und können jederzeit auf das Original zurückgesetzt werden.</div>
<div class="info">Die Originalaufnahme bleibt unverändert. Aus dem gewählten Bereich wird eine fertige Aufnahme im separaten Ausgabeordner erstellt.</div>
<div id="message" class="message"></div>
</div>
</div>
@@ -297,6 +303,7 @@ const wave = document.getElementById('wave');
const startHandle = document.getElementById('startHandle');
const endHandle = document.getElementById('endHandle');
const selection = document.getElementById('selection');
const playhead = document.getElementById('playhead');
const audio = document.getElementById('audio');
function fmt(sec) {
@@ -320,6 +327,11 @@ function render() {
document.getElementById('startValue').textContent = fmt(start);
document.getElementById('endValue').textContent = fmt(end);
document.getElementById('keepValue').textContent = fmt(end-start);
renderPlayhead();
}
function renderPlayhead() {
const t = Math.max(0, Math.min(duration, audio.currentTime || 0));
playhead.style.left = ((t/duration)*100)+'%';
}
function beginDrag(which, e) {
e.preventDefault();
@@ -343,11 +355,31 @@ wave.addEventListener('pointerdown', e => {
});
audio.addEventListener('timeupdate', () => {
document.getElementById('position').textContent=fmt(audio.currentTime);
renderPlayhead();
if (audio.currentTime >= end && !audio.paused) audio.pause();
});
function jump(sec) { audio.currentTime=Math.max(0,Math.min(duration,audio.currentTime+sec)); }
function playFromStart() { audio.currentTime=start; audio.play(); }
function playSelection() { audio.currentTime=start; audio.play(); }
audio.addEventListener('seeking', renderPlayhead);
function jump(sec) { audio.currentTime=Math.max(0,Math.min(duration,audio.currentTime+sec)); renderPlayhead(); }
function playFromStart() { audio.currentTime=start; renderPlayhead(); audio.play(); }
function playSelection() { audio.currentTime=start; renderPlayhead(); audio.play(); }
function setStartAtCurrent() {
const t = Math.max(0, Math.min(duration, audio.currentTime || 0));
if (t >= end - 0.5) {
msg('Der Anfang muss mindestens 0,5 s vor dem Ende liegen.', false);
return;
}
start = t;
render();
}
function setEndAtCurrent() {
const t = Math.max(0, Math.min(duration, audio.currentTime || 0));
if (t <= start + 0.5) {
msg('Das Ende muss mindestens 0,5 s nach dem Anfang liegen.', false);
return;
}
end = t;
render();
}
function msg(text, ok) {
const el=document.getElementById('message'); el.textContent=text; el.className='message '+(ok?'ok':'error');
}