Web MIDI API: permisos y privacidad del dispositivo
Diseña Web MIDI con activación del usuario, permisos, cambios de puertos, mensajes acotados, metadatos mínimos y una alternativa fiable.
BotBrowser Team
Quieres la documentación estructurada de Plataforma?
Este artículo forma parte de la biblioteca editorial. Para pasos de configuración, material de referencia y actualizaciones continuas, entra en la sección de docs.
BotBrowser puede validar un flujo autorizado de Web MIDI cuando el navegador controlado expone navigator.requestMIDIAccess() y una acción declarada inicia la solicitud. No puede fabricar un instrumento físico, escoger un puerto por el usuario, conceder permisos fuera del navegador ni convertir el nombre del puerto en propiedad. El contrato útil es visible: solicitar, mostrar el resultado, validar cada mensaje, reconciliar cambios y conservar una ruta sin MIDI.
TL;DR
Web MIDI entrega acceso a puertos de entrada y salida después del permiso del navegador. No ofrece un inventario de hardware sin límites ni una identidad estable del instrumento. Detecta navigator.requestMIDIAccess, llama desde un control intencional, solicita solo lo necesario y trata MIDIAccess como una vista viva que puede cambiar. Escucha statechange, valida MIDIMessageEvent.data y libera listeners al desaparecer un puerto.
La especificación W3C Web MIDI define MIDIAccess, puertos, cambios de estado, eventos de mensajes y el acceso opcional a System Exclusive. MDN advierte que el soporte es limitado. BotBrowser puede registrar estados visibles de permisos y puertos, pero no prueba que un instrumento exista, pertenezca a alguien o produzca sonido.
Contenido
- El permiso es un límite de capacidad
- Solicita acceso desde una acción
- Trata los puertos como una sesión cambiante
- Acota los mensajes MIDI
- Minimiza metadatos y conserva una alternativa
- Tabla de resultados
- Prueba con BotBrowser
- Conclusión
El permiso es un límite de capacidad
navigator.requestMIDIAccess() solicita una capacidad gestionada por el navegador, no acceso a todos los dispositivos USB. Pueden ser necesarios contexto seguro, activación, permiso y soporte de plataforma. Un MIDIAccess resuelto significa que el navegador expuso la superficie; no significa que haya un puerto conectado o autorizado para una persona.
Solicita el alcance mínimo. Si solo necesitas notas y controles, usa { sysex: false }. System Exclusive puede contener comandos de fabricante y secuencias opacas más grandes; requiere una decisión separada y explicación clara. No actives sysex: true porque una biblioteca lo acepte. Web USB: acceso y límites de privacidad aplica la misma regla: permiso no es inventario.
Los nombres, fabricantes y versiones sirven para un selector visible, pero no prueban propiedad ni identifican un dispositivo estable. Guarda solo granted, denied, unsupported o no-port si la tarea lo necesita. No combines ese resultado con red, pantalla y perfil para crear una etiqueta persistente.
Solicita acceso desde una acción
Detecta la capacidad en el momento de uso. Un control “Conectar MIDI” puede estar desactivado si falta la API y habilitarse cuando la página puede explicar la acción. Llama desde clic o teclado, no al cargar, con un temporizador ni tras una petición de red.
async function connectMidi() {
if (!window.isSecureContext || !navigator.requestMIDIAccess) {
return showMidiState('unsupported');
}
setMidiState('requesting');
try {
const access = await navigator.requestMIDIAccess({ sysex: false });
attachMidiAccess(access);
renderPorts(access);
} catch (error) {
setMidiState(classifyMidiError(error));
showMidiFallback();
}
}
connectButton.addEventListener('click', connectMidi);
requesting evita dobles selectores y ofrece un estado accesible. Si la promesa falla, clasifica solo lo que la página sabe: NotAllowedError, falta de soporte o timeout local. No digas que un dispositivo nombrado negó el acceso. Restaura el control y ofrece un nuevo intento visible.
Web Bluetooth: permisos y privacidad del dispositivo muestra un selector comparable. MIDI y Bluetooth tienen protocolos distintos, pero ambos deben separar “la API existe”, “el navegador concedió acceso” y “hay un dispositivo utilizable”.
Trata los puertos como una sesión cambiante
MIDIAccess.inputs y MIDIAccess.outputs son mapas de puertos expuestos en ese momento. Escucha statechange cuando se conecta, desconecta o reconfigura un dispositivo y vuelve a dibujar el mapa completo. No acumules filas antiguas.
function attachMidiAccess(access) {
access.onstatechange = event => {
const port = event.port;
renderPorts(access);
if (port.state === 'disconnected') detachInput(port.id);
if (port.state === 'connected' && port.type === 'input') attachInput(port);
};
for (const input of access.inputs.values()) attachInput(input);
for (const output of access.outputs.values()) renderOutput(output);
}
Comprueba port.state y port.connection justo antes de usarlo y captura fallos de envío. Al desconectar una entrada, elimina el listener y borra el estado pendiente asociado. Usa port.id solo como clave corta de la sesión; no lo copies a un perfil ni lo conviertas en huella. La salida debe requerir selección explícita: send() no demuestra que se produjo audio ni que otra aplicación lo recibió.
Acota los mensajes MIDI
MIDIMessageEvent.data es una secuencia de bytes no confiable. Valida longitud, byte de estado, canal y rango de datos antes de actualizar el estado. La aplicación puede permitir menos mensajes que el protocolo completo.
const MAX_MIDI_BYTES = 3;
const allowedStatus = new Set([0x80, 0x90, 0xb0, 0xe0]);
function acceptMidiMessage(event) {
const bytes = [...event.data];
if (bytes.length < 2 || bytes.length > MAX_MIDI_BYTES) return;
const status = bytes[0] & 0xf0;
if (!allowedStatus.has(status) || bytes.slice(1).some(byte => byte > 0x7f)) return;
updateMusicState({ status, channel: bytes[0] & 0x0f, data: bytes.slice(1) });
}
El ejemplo ignora System Exclusive, realtime y mensajes de sistema. Activarlos debe ser un cambio deliberado con límites de tamaño y documentación del fabricante. No registres todos los bytes por defecto ni los trates como identidad. Limita eventos de alta frecuencia y conserva solo una captura diagnóstica breve cuando la persona la active.
Minimiza metadatos y conserva una alternativa
Una alternativa virtual, importación de archivo, atajos de teclado o vista de partitura mantiene la tarea útil sin MIDI. Debe explicar que el navegador no expuso un puerto, sin fingir que controla un instrumento. Mantén el modelo musical separado del adaptador: al desconectar, la edición continúa; al conectar otro puerto, exige selección explícita.
Un registro breve puede incluir resultado de soporte, permiso, tipo y estado del puerto, etiqueta local, contador de mensajes aceptados y fecha. No necesita fabricante completo, mapa de puertos, bytes crudos ni propiedades ajenas del navegador. Los nombres de puerto pueden revelar un modelo o estudio, así que define propósito y caducidad para los registros.
Tabla de resultados
| Resultado | Acción segura | No afirmar |
|---|---|---|
| API ausente o contexto inseguro | Mantener teclado virtual o archivo | Soporte universal |
| Permiso rechazado | Explicar y conservar tarea | Que un dispositivo nombrado negó |
| Acceso sin puertos | Mostrar guía y alternativa | Que no existen instrumentos físicos |
| Entrada conectada | Instalar listener validado | Que pertenece a una persona |
| Salida conectada | Exigir selección antes de enviar | Que se produjo o escuchó audio |
statechange desconecta | Quitar listener y marcar offline | Que volverá automáticamente |
| Bytes inválidos | Descartar y clasificar | Que el emisor está identificado |
| Se solicita SysEx | Pedir decisión separada | Que los datos son inocuos por defecto |
Prueba con BotBrowser
Un contexto controlado de BotBrowser puede ejecutar un botón determinista, alternativa sintética, validador acotado y registro visible de puertos. Registra presencia de API, resultado del permiso, conteos, eventos statechange y disponibilidad de la alternativa. unsupported, permission-denied y no-port son resultados válidos si no se afirma que sonó música. Funciones avanzadas de BotBrowser no garantizan un dispositivo MIDI en el runner.
{
"api": "requestMIDIAccess",
"permission": "unknown",
"ports": { "inputs": 0, "outputs": 0 },
"states": ["fallback"],
"messagesAccepted": 0,
"rawBytesRetained": false,
"physicalInstrument": "not-asserted"
}
Repite el fixture cambiando una sola variable: versión del navegador, contexto seguro, resultado de permiso, conexión o tipo de mensaje. Compara la primera divergencia visible sin convertir el resultado en una promesa para cada sistema o controlador.
Conclusión
Web MIDI es una capacidad del navegador, mediada por permiso y cambiante. Solicita desde una acción visible, usa el alcance mínimo, muestra un mapa vivo de puertos, valida mensajes y libera listeners al desconectar. BotBrowser puede repetir esas ramas visibles en contextos autorizados; no crea instrumentos, evita permisos, garantiza puertos ni infiere propiedad desde metadatos MIDI.
Fuentes públicas
Lectura siguiente
Compara Web Bluetooth: permisos y privacidad del dispositivo y Web USB: acceso al dispositivo y límites de privacidad.
Este artículo forma parte de la guía: Superficies de la plataforma web: mapa de revisión
Artículos Relacionados
Permisos y ciclo de vida de puertos con Web Serial API
PlataformaPermisos WebHID y límites de privacidad del dispositivo
PlataformaPresentation API: límites de pantalla y sesión
PlataformaWeb Share API: límites de permisos y respaldos seguros
PlataformaWindow Management API: límites entre varias pantallas
PlataformaDocument Picture-in-Picture: límites de permisos y ventanas
Lleva BotBrowser de la investigación a producción
Usa estas guías para entender el modelo y después avanzar hacia validación multiplataforma, contextos aislados y despliegue de navegador preparado para escalar.