Guía de integración
Añade un reproductor a tu sitio
Una etiqueta de script te da un reproductor que funciona. El mismo script te da una API de JavaScript, así que si ninguno de los diseños listos encaja con el tuyo, puedes crear el tuyo propio y seguir teniendo reproducción, datos de episodios y estadísticas de escucha. Sin compilación, sin framework, sin paquete npm.
01Consigue un ID de reproductor
Un reproductor es lo que insertas. Apunta a un pódcast completo o a episodios concretos, y tiene un ID público que pegas en tu HTML.
- Abre Cuenta y luego Reproductores de audio.
- Crea un reproductor, ponle un nombre para tu propia referencia y añade lo que debe reproducir: un pódcast completo, un episodio o varios en el orden que elijas.
- Copia el ID del reproductor.
El ID es público a propósito.Está en el código de tu página, donde cualquiera puede leerlo, y no pasa nada. Concede una sola cosa: permiso para reproducir los episodios que pusiste en ese reproductor. No es una clave de API, no llega a nada más de tu cuenta y desactivar el reproductor lo revoca en todas partes a la vez.
Si añades un episodio más adelante, aparece de inmediato en todas las inserciones de ese reproductor. No hay que volver a pegar nada.
02Pega dos líneas
Pon el script en cualquier parte de la página, y el div donde quieras el reproductor.
<script src="https://www.obbo.me/player/obboplayer.js" async></script>
<div data-obbo-player="YOUR_PLAYER_ID"></div>Eso es una integración completa. El script busca todos los elementos con el atributo data-obbo-player y los rellena, tanto si la página tiene un reproductor como diez. Cargar el script dos veces no causa problemas.
No se descarga nada hasta que alguien pulsa reproducir.El reproductor obtiene su lista de episodios al cargar, pero no se pide ningún audio hasta que una visita inicia uno de verdad. Poner un reproductor en una página no le cuesta nada a tus visitas y nunca registra una reproducción que no ocurrió.
03Elige un diseño
Hay siete incluidos. Elige uno con data-obbo-ui; si lo omites, se usa el que seleccionaste al crear el reproductor, así que puedes cambiar de idea sin editar ninguna página.
| Valor | Qué es |
|---|---|
| list | Los controles con tu lista de episodios debajo. Para un pódcast completo, o cuando alguien pueda querer un episodio que no sea el más reciente. |
| bar | Solo los controles. Para un artículo o una página de producto centrados en un episodio. |
| card | La portada a tamaño completo con el botón en su borde. Para barras laterales y rejillas, donde una barra horizontal parece pegada con cinta. |
| inline | Un botón de reproducción y un reloj, del tamaño justo para ir dentro de una frase en lugar de interrumpirla. |
| dock | Se fija abajo de la ventana cuando alguien pulsa reproducir, para que los controles no se vayan al desplazarse. Se puede cerrar. |
| transcript | El episodio como texto legible que sigue al audio. La línea que suena queda resaltada; pulsa cualquier línea para saltar ahí. |
| auto | El valor por defecto. Sigue el diseño guardado con el reproductor. |
<div data-obbo-player="YOUR_PLAYER_ID"
data-obbo-ui="list"
data-obbo-theme="dark"></div>Todos los atributos
| data-obbo-player | Obligatorio. El ID de tu reproductor. |
| data-obbo-ui | list, bar, card, inline, dock, transcript o auto. |
| data-obbo-theme | light u dark. |
| data-obbo-episode | Empezar en un episodio concreto. Queda seleccionado, no se reproduce. |
| data-obbo-isolate | Renderizar dentro de un shadow root, aislado de tu CSS. |
| data-obbo-locale | Idioma de los botones del reproductor: en, es, da o ja. Los títulos de los episodios vienen de tu pódcast en cualquier caso. |
| data-obbo-language | Qué idioma del audio se reproduce: en, es, da o ja. Por defecto usa el lang de tu propia página y reproduce el original cuando un episodio no existe en ese idioma. |
| data-obbo-autoadvance | Reproducir el siguiente episodio cuando termine uno. |
Varios reproductores en una página no son problema.Comparten una sola petición de tu lista de episodios, y al iniciar uno se pausan los demás, así que una visita nunca acaba con dos voces a la vez.
04Que parezca de tu sitio
El reproductor se renderiza en el DOM de tu propia página, no en un marco aislado. Tu hoja de estilos lo alcanza y hereda tus tipografías.
La forma rápida: nueve variables
| --obbo-player-bg | #ffffff |
| --obbo-player-fg | #1c2733 |
| --obbo-player-muted | #66768a |
| --obbo-player-accent | #2f6fed |
| --obbo-player-accent-fg | #ffffff |
| --obbo-player-border | #e3e8ef |
| --obbo-player-row-hover | #f4f6f9 |
| --obbo-player-radius | 12px |
| --obbo-player-font | system stack |
.my-player {
--obbo-player-accent: #e5484d;
--obbo-player-radius: 4px;
--obbo-player-font: 'Söhne', system-ui, sans-serif;
}
@media (prefers-color-scheme: dark) {
.my-player {
--obbo-player-bg: #181d24;
--obbo-player-fg: #f2f5f8;
}
}La forma completa: nombres de clase
Cada elemento lleva una clase obbo- estable, y todas las reglas que enviamos son de una sola clase, así que tu regla gana sin necesidad de !important. La raíz también lleva data-obbo-state, lo que te permite dar estilo a las fases de carga y error sin conocer nuestro funcionamiento interno.
| .obbo-p | La raíz del reproductor. Lleva data-obbo-state. |
| .obbo-play | Botón de reproducir y pausar. |
| .obbo-seek | La barra de búsqueda, un input de tipo range. |
| .obbo-title / .obbo-sub | Título del episodio y nombre del pódcast. |
| .obbo-art | Imagen de portada. Se oculta si el pódcast no tiene. |
| .obbo-list / .obbo-row | Lista de episodios y sus filas. La fila en reproducción lleva aria-current. |
| .obbo-note | El mensaje de carga, vacío y error. |
.obbo-p[data-obbo-state="loading"] { opacity: 0.6; }
.obbo-p[data-obbo-state="error"] { display: none; }Si tu CSS es agresivo, aíslalo.Un reset de framework potente puede alcanzar al reproductor. Añade data-obbo-isolate y se renderizará en un shadow root: inmune a tu hoja de estilos, aunque las nueve variables siguen pasando, así que conservas los controles de color y solo pierdes los de clase.
05Crea tu propio reproductor
Prescinde por completo de los diseños. createPlayer te da datos de episodios, reproducción y posición; tú escribes el marcado. La escucha se sigue contando y los enlaces de audio caducados se siguen recuperando, sin que ninguna de las dos cosas sea asunto tuyo. Los controles de abajo están ejecutando el código que aparece debajo.
<button id="play" disabled>Play</button>
<span id="title"></span>
<div id="track"><div id="fill"></div></div>
<script>
var player = Obbo.createPlayer({ widgetId: 'YOUR_PLAYER_ID' });
player.subscribe(function (state) {
play.disabled = state.status !== 'ready';
play.textContent = state.playing ? 'Pause' : 'Play';
title.textContent = state.episode ? state.episode.title : '';
fill.style.width = (state.position / state.duration * 100) + '%';
});
play.onclick = function () { player.toggle(); };
</script>Mantén el botón desactivado hasta que status sea ready.En iOS, el permiso para reproducir audio va ligado al toque que lo pidió. Un toque que el reproductor todavía no puede atender se gasta para nada, y tu visita tiene que volver a tocar.
06La transcripción sincronizada
El diseño de transcripción pone el episodio completo en tu página como texto, y lo mantiene al paso del audio. Cada episodio de Obbo se transcribe con marcas de tiempo por frase durante la producción, así que no tienes que preparar nada.
- La línea que suena queda resaltada y se desplaza sola hasta quedar a la vista. Si te desplazas tú, deja de seguir el audio y aparece un botón para volver: no te disputará la barra de desplazamiento.
- Al pulsar cualquier línea se reproduce desde ahí, lo que hace el episodio citable: quien lee puede encontrar la frase que quiere y oírla dicha.
- El texto es texto real dentro de tu página, así que los buscadores lo indexan y los lectores de pantalla lo leen. Un episodio que de otro modo sería una caja de audio opaca se convierte en contenido sobre tu tema.
<div data-obbo-player="YOUR_PLAYER_ID"
data-obbo-ui="transcript"></div>Todavía no está activado.Las transcripciones se generan para todos los episodios, pero aún no se publican en la API de inserción, así que por ahora este diseño muestra el reproductor con un aviso en lugar del texto. Se rellenará solo cuando activemos el campo: no habrá que cambiar nada en tu página.
07Referencia de la API
Obbo.createPlayer(options)
| widgetId | Obligatorio. El ID de tu reproductor. |
| locale | Idioma de las etiquetas integradas. Por defecto en. |
| autoAdvance | Continuar con el siguiente episodio. Desactivado por defecto. |
| exclusive | Pausar los demás reproductores de la página al iniciar este. Activado por defecto. |
El reproductor
| subscribe(fn) | Llama a tu función con el estado completo en cada cambio, y una vez de inmediato. Devuelve una función para cancelar la suscripción. |
| getState() | El estado actual, si prefieres consultarlo en vez de suscribirte. |
| play(episodeId?) | Empezar a reproducir, cambiando antes de episodio si quieres. |
| pause() / toggle() | Lo evidente. |
| select(episodeId) | Cambiar de episodio sin reproducir. No hace ninguna petición. |
| seek(seconds) | Saltar a una posición, en segundos. |
| setRate(rate) | Velocidad de reproducción, de 0,75 a 2. |
| next() / previous() | Avanzar por la lista de episodios. |
| reload() | Volver a obtener la lista de episodios. |
| destroy() | Detener y desconectar. Llámalo cuando tu componente se desmonte. |
| media | El elemento de audio subyacente, por si necesitas algo que no hayamos previsto. |
El estado
| status | loading, ready, empty o error. |
| error | Vacío, o blocked cuando el navegador se negó sin un toque, load_failed, o unavailable si el ID es incorrecto o está revocado. |
| episodes | Todos los episodios del reproductor: título, descripción, número, fecha y duración. |
| episode | El seleccionado. Seleccionado no significa en reproducción. |
| podcast | Título, nombre de la empresa e imagen de portada. |
| playing | Si el audio está sonando ahora mismo. |
| position / duration | Ambos en segundos. |
| playable | Si el episodio seleccionado se puede reproducir. |
También en Obbo
| Obbo.formatTime(s) | Convierte 65 en 1:05, igual que los diseños integrados. |
| Obbo.ui.list(el, player, opts) | Montar tú mismo un diseño integrado. Devuelve un objeto con destroy. |
| Obbo.mount(root?) | Buscar elementos de reproductor y montarlos. Llámalo si añades marcado dinámicamente. |
| Obbo.unmountElement(el) | Desmontar uno. |
| Obbo.version | Conviene indicarlo al reportar un problema. |
08React, Vue y compañía
No confíes en el escaneo automático. Un framework que vuelva a renderizar el contenedor borrará el marcado del reproductor y dejará atrás sus escuchadores de eventos. Móntalo tú y desmóntalo al desmontar, en un elemento en el que nunca rendericen nada.
function Player({ widgetId }) {
const host = useRef(null);
useEffect(() => {
const player = Obbo.createPlayer({ widgetId });
const ui = Obbo.ui.list(host.current, player);
return () => { ui.destroy(); player.destroy(); };
}, [widgetId]);
return <div ref={host} />;
}Carga el script una vez, en el head del documento o mediante un pequeño cargador, antes de que se ejecute el efecto. Lo mismo vale para onMounted y onUnmounted de Vue, y para onMount de Svelte.
09Content-Security-Policy
Si tu sitio envía una cabecera Content-Security-Policy, necesita tres directivas.
| script-src https://www.obbo.me | Para cargar el reproductor. |
| connect-src https://app.obbo.me | Para obtener tu lista de episodios. |
| media-src https://app.obbo.me https://*.amazonaws.com | Para transmitir el audio. |
media-src es la que se olvida.El audio se sirve desde un almacenamiento en un host distinto al de la API. Si la omites, el reproductor parece perfectamente sano, justo hasta que alguien pulsa reproducir.
10Qué se contabiliza
La escucha en tu sitio aparece en tus estadísticas de Obbo: cuántas veces se cargó el reproductor, cuántas reproducciones empezaron y cuánto se escuchó realmente.
- Tus visitas nunca se identifican. Sin cuenta, sin inicio de sesión, y el reproductor no pone ninguna cookie. Los informes se atribuyen a ti como propietario, no a quien escucha.
- Una visita no es una reproducción. Nada cuenta como reproducción hasta que el audio empieza de verdad.
- El tiempo de escucha se mide, no se supone. Adelantar no cuenta como haber escuchado lo que te saltaste.
11Cuando no funciona
No aparece nada
Comprueba que el elemento tiene data-obbo-player con tu ID y que la etiqueta de script está en la página. Si añadiste el marcado después de cargar la página, llama a Obbo.mount() una vez después.
Dice que el reproductor no está disponible
El ID es incorrecto o el reproductor está desactivado en tu cuenta. Ambos dan el mismo mensaje a propósito.
Dice que no hay episodios
El reproductor está vacío, o sus episodios todavía se están produciendo. Solo se sirven los episodios terminados.
Se ve bien pero no suena
Casi siempre falta media-src en tu Content-Security-Policy. Si no, revisa state.error: blocked significa que el navegador quería un toque real primero, algo que ocurre cuando la reproducción se dispara por algo que no es un clic.
Se ve mal
El CSS de tu página está alcanzándolo, que suele ser la idea pero a veces no. Añade data-obbo-isolate para aislarlo.
¿Sigues atascado?Envíanos la dirección de la página, el ID de tu reproductor y el valor de Obbo.version a hello@obbo.me