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.
- 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.
- 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.
<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
| 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. |
<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 identificador | Qué hace |
|---|---|
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 | Idioma 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-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.
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 CSS | Valor 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-radius | 12px |
--obbo-player-font | Fuentes del sistema |
<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 identificador | Qué hace |
|---|---|
.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"] .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.
Cargando la muestra…
<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.
<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 identificador | Qué hace |
|---|---|
widgetId | Obligatorio. El ID de tu reproductor. |
locale | Idioma de las etiquetas integradas. Por defecto en. |
language | Idioma del audio solicitado. Usa el idioma de tu página; si no existe esa versión, se reproduce la grabación original. |
apiBase | Origen de la API pública. Por defecto https://app.obbo.me. Cámbialo solo para otro servidor de Obbo. |
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
| Ajuste o identificador | Qué 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. |
media | El elemento de audio subyacente, por si necesitas algo que no hayamos previsto. |
El estado
| Ajuste o identificador | Qué hace |
|---|---|
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
| Ajuste o identificador | Qué 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.version | Conviene 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.
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 identificador | Qué hace |
|---|---|
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. |
style-src | El 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-src | Permite 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