obboAbrir espacio de trabajo
Menú
Volver a la página de prueba de reproductores

Guía de integración

Añade un reproductor a tu sitio

Permite escuchar sin salir de tu web. Crea un reproductor de audio en Obbo, pega su código en tu página y listo. Si otra persona gestiona tu web, envíale esta guía.

Los tres primeros pasos bastan para la mayoría de las webs. El estilo y la referencia técnica son opcionales.

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.
  4. Publica los cambios y mantén el reproductor activado. Tus visitantes no ven los borradores.

Abrir tus reproductores de audio

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.

Los nuevos episodios terminados aparecen automáticamente si incluyes el pódcast completo. Si cambias los episodios elegidos o los ajustes, publica esos cambios. No necesitas sustituir el código.

02Pega dos líneas

Sustituye YOUR_WIDGET_ID por el ID de tu reproductor. Pon el script en la página y el div donde quieras mostrarlo. En un creador de webs, usa un bloque HTML o de inserción que admita scripts.

HTML
<script src="https://www.obbo.me/player/obboplayer.js" async></script>
<div data-obbo-player="YOUR_WIDGET_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.

El audio solo se descarga al pulsar reproducir.La lista de episodios y las portadas se cargan con la página, pero el audio solo se solicita cuando un visitante inicia la reproducción. Una visita no cuenta como reproducción.

03Comprueba la página publicada

Guarda y publica tu web y abre la página como visitante. Algunos editores no ejecutan scripts en la vista previa de edición.

  • El título y los episodios terminados deben aparecer sin iniciar sesión en Obbo.
  • Reproduce, prueba la barra de avance y pausa. El audio solo debe empezar cuando lo solicites.
  • Comprueba la página en un teléfono y en una pantalla más ancha. Si falta el reproductor, verifica que tu editor permita HTML personalizado y scripts externos.

Todo listo.Puedes terminar aquí. Consulta lo que sigue solo si quieres otro diseño, tu propia imagen de marca o una integración a medida.

04Elige un diseño

Hay seis diseños visibles, además de auto. Elige con data-obbo-ui. Omítelo o usa auto para seguir el ajuste compacto o de lista publicado en tu reproductor.

Volver a la página de prueba de reproductores

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.
HTML
<script src="https://www.obbo.me/player/obboplayer.js" async></script>
<div
  data-obbo-player="YOUR_WIDGET_ID"
  data-obbo-ui="list"
  data-obbo-theme="dark"
></div>

Todos los atributos

Ajuste o identificadorQué hace
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-languageIdioma del audio: en, es, da, ja, de, fr, it, nl, sv, no o pl. Usa el atributo lang de la página por defecto. Si no existe esa versión, reproduce la grabación original.
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.

05Que parezca de tu sitio

El reproductor se muestra en tu página, no en un iframe. Usa las variables para adaptar colores, bordes y fuente. El ejemplo incluye la clase que conecta tu HTML y CSS.

La forma rápida: nueve variables

Variable CSSValor predeterminado
--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-fontFuentes del sistema
HTML / CSS
<div class="my-player" data-obbo-player="YOUR_WIDGET_ID"></div>

<style>
  .my-player {
    --obbo-player-accent: #a1482e;
    --obbo-player-radius: 8px;
    --obbo-player-font: system-ui, sans-serif;
  }
</style>

La forma completa: nombres de clase

Las clases obbo- estables permiten personalizar los controles. Prefiere variables para la marca y clases para cambios detallados. data-obbo-state permite dar estilo a la carga y los errores. Mantén visibles los errores para que los visitantes sepan cuándo no se puede reproducir.

Ajuste o identificadorQué hace
.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.
CSS
.obbo-p[data-obbo-state="loading"] { opacity: 0.6; }
.obbo-p[data-obbo-state="error"] .obbo-note { font-weight: 700; }

Si tu CSS es agresivo, aíslalo.Añade data-obbo-isolate a un diseño dentro de la página para protegerlo de tu CSS. Las nueve variables siguen funcionando, pero las clases ya no llegan al interior. El diseño dock se añade al documento y no admite aislamiento shadow.

06Crea 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.

Ejemplo real de Momento. Estos controles personalizados usan el mismo motor que los diseños incluidos.

0:00

Cargando la muestra…

HTML / JavaScript
<script src="https://www.obbo.me/player/obboplayer.js" async></script>

<button id="play" type="button" disabled>Play</button>
<span id="time">0:00</span>

<script>
  addEventListener('load', function () {
    var player = Obbo.createPlayer({ widgetId: 'YOUR_WIDGET_ID' });
    var button = document.getElementById('play');
    var time = document.getElementById('time');

    player.subscribe(function (state) {
      button.disabled = state.status !== 'ready' || !state.playable;
      button.textContent = state.playing ? 'Pause' : 'Play';
      time.textContent = Obbo.formatTime(state.position);
    });

    button.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.

07La 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.
  • La transcripción es texto seleccionable que las tecnologías de asistencia pueden leer tras cargarlo. Conserva el contenido escrito esencial en el HTML si importa aparecer en buscadores: no se garantiza la indexación del texto generado con JavaScript.
HTML
<script src="https://www.obbo.me/player/obboplayer.js" async></script>
<div data-obbo-player="YOUR_WIDGET_ID" data-obbo-ui="transcript"></div>

Usa la transcripción disponible de cada episodio.La API de inserción sirve las transcripciones terminadas. Si falta una, el audio sigue funcionando y el reproductor lo indica. Puedes probar un ejemplo sincronizado en la página de diseños.

08Referencia de la API

Obbo.createPlayer(options)

Ajuste o identificadorQué hace
widgetIdObligatorio. El ID de tu reproductor.
localeIdioma de las etiquetas integradas. Por defecto en.
languageIdioma del audio solicitado. Usa el idioma de tu página; si no existe esa versión, se reproduce la grabación original.
apiBaseOrigen de la API pública. Por defecto https://app.obbo.me. Cámbialo solo para otro servidor de Obbo.
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

Ajuste o identificadorQué hace
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

Ajuste o identificadorQué hace
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

Ajuste o identificadorQué hace
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.

09React, 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.

React
import { useEffect, useRef, useState } from 'react';

let sdkPromise;
function loadPlayer() {
  if (window.Obbo) return Promise.resolve(window.Obbo);
  if (sdkPromise) return sdkPromise;
  sdkPromise = new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = 'https://www.obbo.me/player/obboplayer.js';
    script.async = true;
    script.onload = () => {
      if (window.Obbo) resolve(window.Obbo);
      else {
        sdkPromise = null;
        script.remove();
        reject(new Error('Player SDK unavailable'));
      }
    };
    script.onerror = () => {
      sdkPromise = null;
      script.remove();
      reject(new Error('Player SDK could not load'));
    };
    document.head.appendChild(script);
  });
  return sdkPromise;
}

export function Player({ widgetId, locale = 'en' }) {
  const host = useRef(null);
  const [failed, setFailed] = useState(false);
  const [attempt, setAttempt] = useState(0);

  useEffect(() => {
    let cancelled = false;
    let cleanup;
    loadPlayer().then((Obbo) => {
      if (cancelled) return;
      const player = Obbo.createPlayer({ widgetId, locale, language: locale });
      const ui = Obbo.ui.list(host.current, player, { locale });
      cleanup = () => { ui.destroy(); player.destroy(); };
    }).catch((error) => {
      if (!cancelled) {
        console.error('Player failed to load', error);
        setFailed(true);
      }
    });
    return () => { cancelled = true; cleanup?.(); };
  }, [widgetId, locale, attempt]);

  return <>
    <div ref={host} />
    {failed && <p role="alert">
      The player could not load.
      <button type="button" onClick={() => {
        setFailed(false);
        setAttempt((value) => value + 1);
      }}>Try again</button>
    </p>}
  </>;
}

Este ejemplo espera al SDK, cancela montajes tardíos y destruye el diseño y el reproductor al limpiar. Pasa el idioma de tu web como locale. Aplica el mismo ciclo en Vue o Svelte. Los ejemplos en línea pueden necesitar un nonce CSP o un archivo JavaScript externo según tu política.

10Content-Security-Policy

Si tu web envía Content-Security-Policy, revisa estas directivas con tu desarrollador. Añade los hosts necesarios a tu política; estas filas no son una política completa para pegar.

Ajuste o identificadorQué hace
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.
style-srcEl SDK inyecta una hoja de estilos en línea. Tu política debe permitirla; el paquete actual no admite un nonce de estilos. Revísalo con tu desarrollador en lugar de desactivar CSP.
img-srcPermite el host de la portada, normalmente S3. Usa la URL real para limitar la lista de hosts permitidos.

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.

11Qué 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.

12Cuando 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

Volver a la página de prueba de reproductores
Añade un reproductor de pódcast a tu sitio