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.

  1. Abre Cuenta y luego Reproductores de audio.
  2. 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.
  3. 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.

ValorQué es
listLos 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.
barSolo los controles. Para un artículo o una página de producto centrados en un episodio.
cardLa 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.
inlineUn botón de reproducción y un reloj, del tamaño justo para ir dentro de una frase en lugar de interrumpirla.
dockSe fija abajo de la ventana cuando alguien pulsa reproducir, para que los controles no se vayan al desplazarse. Se puede cerrar.
transcriptEl episodio como texto legible que sigue al audio. La línea que suena queda resaltada; pulsa cualquier línea para saltar ahí.
autoEl 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-playerObligatorio. El ID de tu reproductor.
data-obbo-uilist, bar, card, inline, dock, transcript o auto.
data-obbo-themelight u dark.
data-obbo-episodeEmpezar en un episodio concreto. Queda seleccionado, no se reproduce.
data-obbo-isolateRenderizar dentro de un shadow root, aislado de tu CSS.
data-obbo-localeIdioma 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-languageQué 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-autoadvanceReproducir 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-radius12px
--obbo-player-fontsystem 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-pLa raíz del reproductor. Lleva data-obbo-state.
.obbo-playBotón de reproducir y pausar.
.obbo-seekLa barra de búsqueda, un input de tipo range.
.obbo-title / .obbo-subTítulo del episodio y nombre del pódcast.
.obbo-artImagen de portada. Se oculta si el pódcast no tiene.
.obbo-list / .obbo-rowLista de episodios y sus filas. La fila en reproducción lleva aria-current.
.obbo-noteEl 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)

widgetIdObligatorio. El ID de tu reproductor.
localeIdioma de las etiquetas integradas. Por defecto en.
autoAdvanceContinuar con el siguiente episodio. Desactivado por defecto.
exclusivePausar 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.
mediaEl elemento de audio subyacente, por si necesitas algo que no hayamos previsto.

El estado

statusloading, ready, empty o error.
errorVacío, o blocked cuando el navegador se negó sin un toque, load_failed, o unavailable si el ID es incorrecto o está revocado.
episodesTodos los episodios del reproductor: título, descripción, número, fecha y duración.
episodeEl seleccionado. Seleccionado no significa en reproducción.
podcastTítulo, nombre de la empresa e imagen de portada.
playingSi el audio está sonando ahora mismo.
position / durationAmbos en segundos.
playableSi 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.versionConviene 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.mePara cargar el reproductor.
connect-src https://app.obbo.mePara obtener tu lista de episodios.
media-src https://app.obbo.me https://*.amazonaws.comPara 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

Ver todos los diseños funcionando

Añade un reproductor de pódcast a tu sitio