5.2 KiB
Diseño — la calidad de reproducción en el MediaPlayer
Estado: ESPECIFICADO, NO IMPLEMENTADO. Fecha: 2026-08-04. Decisión del usuario: escribir el contrato antes de tocar código.
Este documento existe porque la parte settings-button del morfo lleva
declarada desde el principio prometiendo «velocidad / calidad / pista», y al ir
a implementarla se descubrió que dos de los tres ejes ya no le corresponden y
el tercero no existe. Aquí queda por qué, y qué haría falta exactamente para
que existiera.
1. El hallazgo: la calidad no está en ninguna parte
Auditado el 2026-08-04 sobre el código, no sobre la memoria:
| Superficie | Campos de calidad |
|---|---|
MediaSnapshot (soma/components/media-player/media-provider.ts) |
0 de 14 |
MediaProvider (mismo fichero) |
0 de 9 miembros |
SoundMediaSnapshot / SoundMediaHandle (arts/sound/types.ts) |
0, espejo exacto |
Grep de quality|bitrate|resolution|level|representation sobre el puerto: cero
coincidencias. No es que esté a medias — es que el concepto no ha entrado nunca.
2. Por qué no es un descuido
La calidad no es intrínseca al <video>. Un <video src="pelicula.mp4"> no
tiene niveles: tiene un fichero. Los niveles aparecen cuando hay un manifiesto
(HLS o MPEG-DASH) y un motor que elige representación según ancho de banda.
Y este framework no vendoriza motores (regla de dependencia cero): hls.js o
dash.js los enchufa el consumidor por createProvider. Así que la lista de
calidades sólo puede venir del consumidor, nunca del componente.
Consecuencia: cualquier contrato de calidad que se escriba será, para el 90 % de los usos, una lista vacía. Eso no lo invalida, pero sí decide la forma — el control tiene que desaparecer, no salir vacío.
3. El contrato mínimo, si se abre
Nada especulativo: sólo lo que hace falta para poblar una lista y elegir.
3.1 MediaSnapshot — tres campos
/** Una representación que el motor ofrece. `id` es opaco: lo acuña el motor. */
interface MediaQuality {
id: string;
height?: number;
bitrate?: number;
/** Etiqueta ya legible («1080p»); si falta, la pinta el chrome desde height. */
label?: string;
}
qualities: readonly MediaQuality[]; // vacío = el medio no tiene niveles
qualityId: string | null; // la EFECTIVA ahora mismo; null = desconocida
qualityAuto: boolean; // true = manda el motor (ABR)
qualityId y qualityAuto son dos cosas distintas a propósito: en modo
automático el motor sigue reproduciendo alguna representación concreta, y un
menú honesto muestra «Auto (1080p)», no «Auto» a secas.
3.2 MediaProvider — un método
/** `null` devuelve el control al motor (auto). */
setQuality(id: string | null): void;
3.3 Los espejos de $arts/sound
SoundMediaSnapshot y SoundMediaHandle repiten la forma del puerto. Extender
uno solo deja al otro sin poder rellenarlo, así que van los dos o ninguno.
3.4 El morfo — aquí está el coste real
Fijar una calidad es un valor aplicado: commit.set, igual que
commit-set-rate. Eso obliga a:
- Un evento nuevo,
commit-set-quality. Rompe el test que fija los 11 eventos (morfo/components/media-player.test.ts) — es cambio de canon, no de implementación. - Decidir su
target. No hay partequality-button; anclaría ensettings-button. - Una regla en el pack de sema del componente.
- Textos:
qualityyauto.
⚠️ Y una trampa que ya nos mordió con la velocidad: el commit debe cabalgar el
RESULTADO, no el clic. Pedir 1080p no es haberlo conseguido — el motor puede
negarse o tardar. El commit tiene que salir cuando el snapshot refleje el cambio
de qualityId, igual que commit-set-rate cabalga ratechange.
4. La forma del control
Cuando qualities esté vacío el control no se pinta. Ni deshabilitado ni
vacío: ausente. Es la misma doctrina que el waveform sin picos — sin datos no se
inventa una forma. Un menú de ajustes con una entrada «Calidad ▸ (nada)» miente
sobre lo que el reproductor puede hacer.
Con eso, settings-button recupera su razón de ser: dos ejes reales (calidad +
pista de subtítulos) cuando hay motor, y ninguno cuando no lo hay.
5. Lo que queda fuera, y por qué
- Selector de pista de audio.
HTMLMediaElement.audioTracksno lo implementan ni Chrome ni Firefox. Saldría vacío en casi todos los navegadores. - Duplicar velocidad dentro de ajustes. Tiene su lista propia desde
ee51172d8(RateFloat). - Una tecla rápida para abrir ajustes. El provider declara 15 teclas y ninguna es ésta. Añadirla es cambio de contrato, no un detalle.
6. Estado de settings-button mientras tanto
Sigue declarado en el morfo y sin implementar, que es lo honesto: hoy sólo
podría contener una sección (la pista de subtítulos) y eso ya lo resuelve
<MediaPlayer.CaptionFloat>. Un engranaje con un solo cajón sería el
CaptionFloat disfrazado.
Se implementa cuando este documento deje de ser un plan.