Der Tonversatz ist ein Regler, abgetrennt unter den Spuren
Drei Anläufe, und du hattest jedes Mal recht. **Er gehört ins Tonmenü** — aber sichtbar nicht zu den Spuren. Jetzt trennt ihn ein Strich ab, darüber steht „TONVERSATZ — Ohne Versatz" als Überschrift, darunter ein Regler. Drei Mittel, und jedes einzelne würde schon sagen, dass das keine Sprache ist. **Ein Regler statt Auswahlpunkten.** Feste Stufen hiessen: für jeden Wert ein Eintrag, und die standen zwischen den Sprachen wie weitere Sprachen. Gezogen wird von −3 bis +3 Sekunden in Hundertern; die Mitte ist als Strich markiert, sonst trifft man die Null nur zufällig. Gerechnet wird erst beim Loslassen, nicht beim Ziehen — jede Änderung baut den Strom neu auf, und das tut man nicht zwanzigmal beim Hinschieben. Daneben „Zurücksetzen", sobald etwas eingestellt ist. **Und der Lautsprecher ist zurück.** Hier stand ein eigenes Zeichen, damit er nicht zweimal in der Leiste auftaucht — links Stummschalten, rechts die Tonspur. Die Wellenform erkannte aber niemand als „Ton". Zwei Lautsprecher sind das kleinere Übel, zumal der linke beim Stummschalten durchgestrichen wird und damit anders aussieht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
dc9d1cea85
commit
2f7768136b
@@ -96,8 +96,6 @@ export const icons = {
|
||||
* löst keinen Alarm aus. */
|
||||
fahne: rahmen('<path d="M6 21V4"/><path d="M6 4.8h11.6l-2.5 4 2.5 4H6"/>'),
|
||||
|
||||
/** Tonversatz — zwei Pfeile, die auseinandergehen. */
|
||||
versatz: rahmen('<path d="M3 12h18"/><path d="M7 8l-4 4 4 4"/><path d="M17 8l4 4-4 4"/>'),
|
||||
} as const;
|
||||
|
||||
export type IconName = keyof typeof icons;
|
||||
|
||||
+73
-29
@@ -85,13 +85,12 @@ export function geraeteprofil(): {
|
||||
/** Wie oft der Stand zum Server geht. */
|
||||
const MELDEABSTAND = 10_000;
|
||||
|
||||
/** Die Stufen des Tonversatzes in Millisekunden.
|
||||
*
|
||||
* **Nicht jeder Hunderter von −5000 bis +5000.** Das wären einhunderteins
|
||||
* Einträge für etwas, das man im Jahr dreimal braucht. Diese elf decken ab,
|
||||
* was vorkommt — und wer mehr braucht, hat keine Einstellung zu wenig,
|
||||
* sondern eine kaputte Datei. */
|
||||
const VERSAETZE = [-1000, -500, -300, -200, -100, 0, 100, 200, 300, 500, 1000];
|
||||
/** In welchen Schritten der Regler einrastet. */
|
||||
const VERSATZSCHRITT = 100;
|
||||
|
||||
/** Wie weit in beide Richtungen. Darüber hinaus ist es kein Versatz mehr,
|
||||
* sondern eine kaputte Datei. */
|
||||
const VERSATZGRENZE = 3000;
|
||||
|
||||
/** Wo gemerkte Tonversätze liegen — je Datei, in diesem Browser.
|
||||
*
|
||||
@@ -372,10 +371,58 @@ export function spieler(anfrage: Spieleranfrage): void {
|
||||
* acht Strahlen sah aus wie eine Sonne — niemand vermutete die Bildqualität
|
||||
* dahinter. Jetzt: Wellenform für den Ton, CC-Kasten für die Untertitel,
|
||||
* Schieberegler für die Qualität. */
|
||||
const tonmenue = menue('tonspur', 'Tonspur');
|
||||
// **Der Lautsprecher, nicht die Wellenform.** Hier stand einmal ein eigenes
|
||||
// Zeichen, damit er nicht zweimal in der Leiste auftaucht — links für
|
||||
// Stummschalten, rechts für die Tonspur. Die Wellenform erkannte aber
|
||||
// niemand als „Ton"; zwei Lautsprecher sind das kleinere Übel, zumal der
|
||||
// linke beim Stummschalten durchgestrichen wird und damit anders aussieht.
|
||||
const tonmenue = menue('ton', 'Ton');
|
||||
const textmenue = menue('untertitel', 'Untertitel');
|
||||
const stufenmenue = menue('regler', 'Qualität');
|
||||
const versatzmenue = menue('versatz', 'Tonversatz');
|
||||
|
||||
/* ---------- Der Tonversatz, abgetrennt im Tonmenü ---------- */
|
||||
|
||||
// **Ein Regler, keine Liste.** Feste Stufen hiessen: für jeden Wert ein
|
||||
// Eintrag, und die standen zwischen den Sprachen wie weitere Sprachen.
|
||||
// Hier wird gezogen, und zwar erst beim Loslassen — jede Änderung baut den
|
||||
// Strom neu auf, und das tut man nicht zwanzigmal beim Hinschieben.
|
||||
const versatzkopf = document.createElement('div');
|
||||
versatzkopf.className = 'pl-fusstitel';
|
||||
|
||||
const versatzregler = document.createElement('input');
|
||||
versatzregler.type = 'range';
|
||||
versatzregler.className = 'pl-laut pl-versatz';
|
||||
versatzregler.min = String(-VERSATZGRENZE);
|
||||
versatzregler.max = String(VERSATZGRENZE);
|
||||
versatzregler.step = String(VERSATZSCHRITT);
|
||||
versatzregler.setAttribute('aria-label', 'Tonversatz in Millisekunden');
|
||||
|
||||
const versatzzurueck = knopf('Zurücksetzen', 'pl-punkt');
|
||||
|
||||
function versatzstand(): void {
|
||||
versatzkopf.textContent = `Tonversatz — ${versatzWort(tonversatz)}`;
|
||||
versatzregler.value = String(tonversatz);
|
||||
versatzregler.setAttribute('aria-valuetext', versatzWort(tonversatz));
|
||||
versatzzurueck.classList.toggle('hidden', tonversatz === 0);
|
||||
}
|
||||
|
||||
function versatzSetzen(ms: number): void {
|
||||
tonversatz = Math.max(-VERSATZGRENZE, Math.min(VERSATZGRENZE, Math.round(ms / VERSATZSCHRITT) * VERSATZSCHRITT));
|
||||
versatzMerken(anfrage.dateiId, tonversatz);
|
||||
versatzstand();
|
||||
void stromAufbauen(filmzeit());
|
||||
}
|
||||
|
||||
// Beim Ziehen nur die Zahl mitlaufen lassen, beim Loslassen rechnen.
|
||||
versatzregler.oninput = () => {
|
||||
versatzkopf.textContent = `Tonversatz — ${versatzWort(Number(versatzregler.value))}`;
|
||||
};
|
||||
versatzregler.onchange = () => versatzSetzen(Number(versatzregler.value));
|
||||
versatzregler.onclick = e => e.stopPropagation();
|
||||
versatzzurueck.onclick = e => { e.stopPropagation(); versatzSetzen(0); };
|
||||
|
||||
tonmenue.fuss.append(versatzkopf, versatzregler, versatzzurueck);
|
||||
|
||||
|
||||
const links = document.createElement('div');
|
||||
links.className = 'pl-gruppe';
|
||||
@@ -383,8 +430,7 @@ export function spieler(anfrage: Spieleranfrage): void {
|
||||
|
||||
const rechts = document.createElement('div');
|
||||
rechts.className = 'pl-gruppe';
|
||||
rechts.append(
|
||||
rest, tonmenue.knopf, versatzmenue.knopf, textmenue.knopf, stufenmenue.knopf, vollbild);
|
||||
rechts.append(rest, tonmenue.knopf, textmenue.knopf, stufenmenue.knopf, vollbild);
|
||||
|
||||
const unten = document.createElement('div');
|
||||
unten.className = 'pl-unten';
|
||||
@@ -653,23 +699,9 @@ export function spieler(anfrage: Spieleranfrage): void {
|
||||
|
||||
tonmenue.setzen(spuren);
|
||||
|
||||
// **Der Versatz hat ein eigenes Menü.** Er stand vorher unter den
|
||||
// Tonspuren, und dort las er sich wie eine: „Später (+100 ms)" sah aus
|
||||
// wie der Name einer Spur. Eine Einstellung gehört nicht in eine Liste
|
||||
// von Inhalten.
|
||||
//
|
||||
// Feste Stufen statt zweier Tasten, wie bei der Qualität: so zeigt der
|
||||
// Haken, wo man steht, und man trifft einen Wert, statt sich
|
||||
// hinzutasten — jeder Schritt baut den Strom neu auf.
|
||||
versatzmenue.setzen(VERSAETZE.map(ms => ({
|
||||
text: versatzWort(ms),
|
||||
gewaehlt: ms === tonversatz,
|
||||
tun: () => {
|
||||
tonversatz = ms;
|
||||
versatzMerken(anfrage.dateiId, ms);
|
||||
void stromAufbauen(filmzeit());
|
||||
},
|
||||
})));
|
||||
// Ohne Tonspur gibt es nichts zu verschieben.
|
||||
tonmenue.fuss.classList.toggle('hidden', toene.length === 0);
|
||||
versatzstand();
|
||||
|
||||
const texte = auskunft?.subtitleStreams ?? [];
|
||||
textmenue.setzen(
|
||||
@@ -914,7 +946,7 @@ export function spieler(anfrage: Spieleranfrage): void {
|
||||
|
||||
/** Ein kleines Menü, das über der Leiste aufgeht. */
|
||||
function menue(bild: keyof typeof icons, titel: string): {
|
||||
knopf: HTMLElement; setzen: (punkte: Wahl[]) => void;
|
||||
knopf: HTMLElement; fuss: HTMLElement; setzen: (punkte: Wahl[]) => void;
|
||||
} {
|
||||
const huelle = document.createElement('div');
|
||||
huelle.className = 'pl-menue';
|
||||
@@ -934,10 +966,20 @@ export function spieler(anfrage: Spieleranfrage): void {
|
||||
|
||||
const liste = document.createElement('div');
|
||||
liste.className = 'pl-liste';
|
||||
|
||||
// **Ein abgetrennter Fuss für das, was keine Auswahl ist.**
|
||||
// Eine Einstellung zwischen Inhalten sieht aus wie ein Inhalt — der
|
||||
// Tonversatz stand als „Später (+100 ms)" zwischen den Sprachen und las
|
||||
// sich wie eine. Hier ist er durch einen Strich und eine Überschrift
|
||||
// sichtbar etwas anderes.
|
||||
const fuss = document.createElement('div');
|
||||
fuss.className = 'pl-fuss hidden';
|
||||
huelle.append(ausloeser, liste);
|
||||
liste.appendChild(fuss);
|
||||
|
||||
return {
|
||||
knopf: huelle,
|
||||
fuss,
|
||||
setzen: punkte => {
|
||||
liste.innerHTML = '';
|
||||
punkte.forEach(p => {
|
||||
@@ -950,6 +992,8 @@ export function spieler(anfrage: Spieleranfrage): void {
|
||||
};
|
||||
liste.appendChild(b);
|
||||
});
|
||||
// Der Fuss gehört nicht zur Auswahl und wird deshalb wieder angehängt.
|
||||
liste.appendChild(fuss);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -897,6 +897,29 @@ textarea.feld {
|
||||
}
|
||||
.pl-menue.auf .pl-liste { display: flex; }
|
||||
|
||||
/* **Der Fuss ist sichtbar etwas anderes als die Liste darüber.**
|
||||
Eine Einstellung zwischen Inhalten sieht aus wie ein Inhalt — der
|
||||
Tonversatz stand als Eintrag zwischen den Sprachen und las sich wie eine.
|
||||
Ein Strich, eine Überschrift, ein Regler: drei Mittel, und jedes einzelne
|
||||
würde es schon sagen. */
|
||||
.pl-fuss {
|
||||
margin-top: 6px; padding: 8px 8px 6px;
|
||||
border-top: 1px solid var(--line);
|
||||
display: flex; flex-direction: column; gap: 6px;
|
||||
}
|
||||
.pl-fusstitel {
|
||||
font-size: 11px; font-weight: 600; letter-spacing: .04em;
|
||||
text-transform: uppercase; color: var(--text-muted);
|
||||
}
|
||||
/* Breiter als der Lautstärkeregler — hier wird genau gezielt, nicht gewischt. */
|
||||
.pl-versatz { width: 100%; }
|
||||
/* Die Mitte markieren: ohne sie trifft man die Null nur durch Zufall. */
|
||||
.pl-versatz::-webkit-slider-runnable-track {
|
||||
background:
|
||||
linear-gradient(rgba(255, 255, 255, .55), rgba(255, 255, 255, .55)) 50% / 2px 10px no-repeat,
|
||||
rgba(255, 255, 255, .28);
|
||||
}
|
||||
|
||||
.pl-punkt {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
background: none; border: 0; color: var(--text);
|
||||
|
||||
Reference in New Issue
Block a user