editor.py aktualisiert
This commit is contained in:
@@ -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');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user