obboÅbn arbejdsområde
Menu
Tilbage til afspillernes prøveside

Integrationsguide

Sæt en afspiller på dit websted

Lad besøgende lytte uden at forlade webstedet. Opret en lydafspiller i Obbo, indsæt koden på siden, og du er klar. Send guiden til den, der vedligeholder dit websted.

De første tre trin er nok for de fleste websteder. Styling og udviklerreference er valgfrit.

01Hent et afspiller-id

En afspiller er det, du indlejrer. Den peger på en hel podcast eller på bestemte afsnit, og den har et offentligt id, du indsætter i din HTML.

  1. Åbn Konto og derefter Lydafspillere.
  2. Opret en afspiller, giv den et navn til dit eget brug, og tilføj det, den skal spille: en hel podcast, ét afsnit eller flere afsnit i den rækkefølge, du vælger.
  3. Kopiér afspiller-id'et.
  4. Udgiv ændringerne, og hold afspilleren aktiveret. Besøgende ser ikke kladder.

Åbn dine lydafspillere

Id'et er ment til at være offentligt.Det står i din sides kildekode, hvor alle kan læse det, og det er fint. Det giver én ting: adgang til at afspille de afsnit, du lagde i den afspiller. Det er ikke en API-nøgle, det når intet andet på din konto, og deaktiverer du afspilleren, tilbagekaldes det alle steder på én gang.

Nye færdige afsnit vises automatisk, når afspilleren omfatter hele podcasten. Ændrer du de valgte afsnit eller indstillinger, skal ændringerne udgives. Indlejringskoden skal ikke udskiftes.

02Indsæt to linjer

Erstat YOUR_WIDGET_ID med dit afspiller-id. Sæt scriptet på siden og div'en dér, hvor afspilleren skal vises. I en hjemmesidebygger skal du bruge en HTML- eller indlejringsblok, der tillader scripts.

HTML
<script src="https://www.obbo.me/player/obboplayer.js" async></script>
<div data-obbo-player="YOUR_WIDGET_ID"></div>

Det er en komplet integration. Scriptet finder hvert element med attributten data-obbo-player og udfylder det, uanset om siden har én afspiller eller ti. Det gør ingen skade at indlæse scriptet to gange.

Lyd hentes først, når nogen trykker afspil.Afsnitsliste og cover hentes sammen med siden, men lyd hentes først, når en besøgende starter afspilningen. En sidevisning tæller ikke som en afspilning.

03Tjek din udgivne side

Gem og udgiv webstedet, og åbn siden som besøgende. Nogle redigeringsværktøjer kører ikke scripts i deres forhåndsvisning.

  • Podcasttitlen og færdige afsnit skal vises uden login til Obbo.
  • Tryk afspil, prøv søgebjælken, og sæt på pause. Lyden skal først starte, når du beder om det.
  • Tjek siden på både telefon og en bredere skærm. Mangler afspilleren, så kontrollér, at værktøjet tillader tilpasset HTML og eksterne scripts.

Du er klar.Du kan stoppe her. Læs kun videre, hvis du ønsker et andet layout, dit eget udtryk eller en særlig integration.

04Vælg et layout

Der er seks synlige layouts samt auto. Vælg med data-obbo-ui. Udelad det, eller brug auto for at følge afspillerens udgivne kompakt- eller listeindstilling.

Tilbage til afspillernes prøveside

VærdiHvad det er
listKnapperne med din afsnitsliste under. Til en hel podcast, eller når nogen kunne tænkes at ville et andet afsnit end det nyeste.
barKun knapperne. Til en artikel eller produktside bygget op om ét afsnit.
cardCoveret i fuld størrelse med knappen på kanten. Til sidebjælker og gitre, hvor en vandret bjælke ser påklistret ud.
inlineEn afspilningsknap og et ur i en størrelse, der passer ind i en sætning frem for at afbryde den.
dockSætter sig fast i bunden af vinduet, når nogen trykker afspil, så knapperne ikke forsvinder, når man ruller. Kan lukkes.
transcriptAfsnittet som læsbar tekst, der følger lyden. Den linje, der bliver sagt, fremhæves; klik på en linje for at springe dertil.
autoStandarden. Følger det layout, der er gemt på afspilleren.
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>

Alle attributter

Indstilling eller identifikatorHvad den gør
data-obbo-playerPåkrævet. Dit afspiller-id.
data-obbo-uilist, bar, card, inline, dock, transcript eller auto.
data-obbo-themelight eller dark.
data-obbo-episodeStart på et bestemt afsnit. Det bliver valgt, ikke afspillet.
data-obbo-isolateVis inde i en shadow root, adskilt fra din CSS.
data-obbo-localeSprog for afspillerens egne knapper: en, es, da eller ja. Afsnitstitler kommer fra din podcast under alle omstændigheder.
data-obbo-languageLydsprog: en, es, da, ja, de, fr, it, nl, sv, no eller pl. Bruger som standard sidens lang-attribut. Findes sproget ikke, afspilles originaloptagelsen.
data-obbo-autoadvanceSpil næste afsnit, når et slutter.

Flere afspillere på én side er fint.De deler én enkelt forespørgsel efter din afsnitsliste, og starter man én, sættes de andre på pause, så en besøgende aldrig ender med to stemmer på én gang.

05Få den til at ligne dit websted

Afspilleren vises på din side, ikke i en iframe. Brug variablerne til farver, hjørner og skrifttype. Eksemplet indeholder klassen, der forbinder HTML og CSS.

Den hurtige måde: ni variabler

CSS-variabelStandardværdi
--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-fontSystemets skrifttyper
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>

Den grundige måde: klassenavne

Faste obbo--klasser giver adgang til knapperne. Brug helst variabler til dit udtryk og klasser til detaljer. data-obbo-state bruges til indlæsnings- og fejltilstande. Behold fejlbeskeder synlige, så besøgende ved, når afspilning ikke er mulig.

Indstilling eller identifikatorHvad den gør
.obbo-pAfspillerens rod. Har data-obbo-state.
.obbo-playAfspil- og pauseknap.
.obbo-seekSøgebjælken, et input af typen range.
.obbo-title / .obbo-subAfsnitstitel og podcastnavn.
.obbo-artCoverbillede. Skjules, hvis podcasten ikke har et.
.obbo-list / .obbo-rowAfsnitsliste og dens rækker. Den spillende række har aria-current.
.obbo-noteBeskeden ved indlæsning, tom og fejl.
CSS
.obbo-p[data-obbo-state="loading"] { opacity: 0.6; }
.obbo-p[data-obbo-state="error"] .obbo-note { font-weight: 700; }

Er din CSS aggressiv, så luk den ude.Tilføj data-obbo-isolate til et layout på siden for at beskytte det mod din CSS. De ni variabler virker stadig, men klasser når ikke ind. Dock-layoutet sættes på dokumentet og understøtter ikke shadow-isolation.

06Byg din egen afspiller

Spring layoutene helt over. createPlayer giver dig afsnitsdata, afspilning og position; du skriver markuppet. Lytning bliver stadig talt med, og udløbne lydlinks henter sig stadig, uden at nogen af delene er dit problem. Knapperne herunder kører koden, der står nedenunder.

Levende eksempel fra Momento. Knapperne bruger samme afspilningsmotor som de færdige layouts.

0:00

Indlæser eksemplet…

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>

Hold knappen deaktiveret, indtil status er ready.På iOS er tilladelsen til at afspille lyd bundet til det tryk, der bad om den. Et tryk, afspilleren endnu ikke kan handle på, er spildt, og din besøgende skal trykke igen.

07Udskriften, der følger med

Udskriftslayoutet lægger hele afsnittet på din side som tekst og holder det i takt med lyden. Hvert Obbo-afsnit bliver skrevet ud med tidsmarkering pr. sætning som en del af produktionen, så du skal ikke forberede noget.

  • Den linje, der bliver sagt, fremhæves og ruller sig selv frem. Ruller du selv, holder den op med at følge med, og en knap fører dig tilbage — den slås ikke med dig om rullebjælken.
  • Klikker man på en linje, spilles der derfra, og det gør afsnittet citerbart: en læser kan finde den sætning, de vil have, og høre den sagt.
  • Udskriften kan markeres og læses af hjælpeteknologi efter indlæsning. Behold vigtig tekst i sidens egen HTML, når søgesynlighed betyder noget; JavaScript-genereret tekst bliver ikke nødvendigvis indekseret.
HTML
<script src="https://www.obbo.me/player/obboplayer.js" async></script>
<div data-obbo-player="YOUR_WIDGET_ID" data-obbo-ui="transcript"></div>

Bruger den tilgængelige udskrift for hvert afsnit.Færdige udskrifter leveres af indlejrings-API'et. Mangler en udskrift, virker lyden stadig, og afspilleren forklarer det. Prøvesiden har et fungerende læs-med-eksempel.

08API-reference

Obbo.createPlayer(options)

Indstilling eller identifikatorHvad den gør
widgetIdPåkrævet. Dit afspiller-id.
localeSprog for indbyggede etiketter. Standard er en.
languageDet ønskede lydsprog. Brug sidens sprog; manglende sprogversioner afspilles som originaloptagelsen.
apiBaseDen offentlige API-adresse. Standard er https://app.obbo.me. Skift kun ved brug af en anden Obbo-server.
autoAdvanceFortsæt til næste afsnit. Slået fra som standard.
exclusiveSæt andre afspillere på siden på pause, når denne starter. Slået til som standard.

Afspilleren

Indstilling eller identifikatorHvad den gør
subscribe(fn)Kalder din funktion med hele tilstanden ved hver ændring, og én gang med det samme. Returnerer en funktion, der afmelder.
getState()Den aktuelle tilstand, hvis du hellere vil hente end abonnere.
play(episodeId?)Begynd at afspille, eventuelt med et skift af afsnit først.
pause() / toggle()Det indlysende.
select(episodeId)Skift afsnit uden at afspille. Koster ingen forespørgsel.
seek(seconds)Spring til en position, i sekunder.
setRate(rate)Afspilningshastighed, fra 0,75 til 2.
next() / previous()Bevæg dig gennem afsnitslisten.
reload()Hent afsnitslisten igen.
destroy()Stop og kobl fra. Kald den, når din komponent fjernes.
mediaDet underliggende lydelement, til noget vi ikke har tænkt på.

Tilstanden

Indstilling eller identifikatorHvad den gør
statusloading, ready, empty eller error.
errorTom, eller blocked når browseren nægtede uden et tryk, load_failed, eller unavailable ved et forkert eller tilbagekaldt id.
episodesAlle afsnit i afspilleren: titel, beskrivelse, nummer, dato og længde.
episodeDet valgte. Valgt betyder ikke, at det spiller.
podcastTitel, firmanavn og coverbillede.
playingOm der spiller lyd lige nu.
position / durationBegge i sekunder.
playableOm det valgte afsnit overhovedet kan afspilles.

Også på Obbo

Indstilling eller identifikatorHvad den gør
Obbo.formatTime(s)Laver 65 om til 1:05, ligesom de indbyggede layouts gør.
Obbo.ui.list(el, player, opts)Montér selv et indbygget layout. Returnerer et objekt med destroy.
Obbo.mount(root?)Find afspillerelementer og montér dem. Kald den, hvis du tilføjer markup dynamisk.
Obbo.unmountElement(el)Fjern én.
Obbo.versionVærd at oplyse i en fejlrapport.

09React, Vue og resten

Stol ikke på den automatiske scanning. Et framework, der gentegner beholderen, sletter afspillerens markup og efterlader dens event-lyttere. Montér den selv, og fjern den ved unmount, i et element du aldrig selv tegner i.

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>}
  </>;
}

Eksemplet venter på SDK'et, aflyser sene monteringer og fjerner både layout og afspiller ved oprydning. Giv sidens sprog som locale. Brug samme livscyklus i Vue eller Svelte. Inline-eksempler kan kræve en CSP-nonce eller en ekstern JavaScript-fil efter sidens politik.

10Content-Security-Policy

Sender siden Content-Security-Policy, så gennemgå direktiverne med udvikleren. Tilføj værterne til den eksisterende politik; rækkerne er ikke en komplet politik til indsætning.

Indstilling eller identifikatorHvad den gør
script-src https://www.obbo.meFor at indlæse afspilleren.
connect-src https://app.obbo.meFor at hente din afsnitsliste.
media-src https://app.obbo.me https://*.amazonaws.comFor at streame selve lyden.
style-srcSDK'et indsætter et inline-stylesheet. Politikken skal tillade det; bundlen understøtter ikke en stylesheet-nonce. Gennemgå kravet med udvikleren i stedet for at slå CSP fra.
img-srcTillad værten for podcastens cover, ofte S3. Brug den faktiske billedadresse til at begrænse listen over tilladte værter.

media-src er den, folk glemmer.Lyd leveres fra lagring på en anden vært end API'et. Udelader du den, ser afspilleren helt rask ud, lige indtil nogen trykker afspil.

11Hvad der tælles

Lytning på dit websted dukker op i din Obbo-statistik: hvor mange gange afspilleren blev indlæst, hvor mange afspilninger der startede, og hvor meget der faktisk blev hørt.

  • Dine besøgende bliver aldrig identificeret. Ingen konto, intet login, og afspilleren sætter ingen cookie. Rapporter tilskrives dig som ejer, ikke den, der lytter.
  • Et sidevisning er ikke en afspilning. Intet tæller som afspilning, før lyden rent faktisk starter.
  • Lyttetid måles, den antages ikke. At spole frem tæller ikke som at have hørt det, du sprang over.

12Når det ikke virker

Der kommer slet ikke noget frem

Tjek, at elementet har data-obbo-player med dit id, og at script-tagget er på siden. Tilføjede du markuppet, efter siden var indlæst, så kald Obbo.mount() én gang bagefter.

Der står, at afspilleren ikke er tilgængelig

Id'et er forkert, eller afspilleren er deaktiveret på din konto. Begge dele giver med vilje den samme besked.

Der står, at der ingen afsnit er

Afspilleren er tom, eller dens afsnit er stadig under produktion. Kun færdige afsnit leveres.

Den ser rigtig ud, men vil ikke spille

Næsten altid manglende media-src i din Content-Security-Policy. Ellers tjek state.error: blocked betyder, at browseren først ville have et rigtigt tryk, hvilket sker, når afspilning udløses af noget andet end et klik.

Den ser forkert ud

Din sides CSS når ind i den, hvilket som regel er meningen, men af og til ikke er. Tilføj data-obbo-isolate for at lukke den ude.

Stadig i tvivl?Send os sidens adresse, dit afspiller-id og værdien af Obbo.version på hello@obbo.me

Tilbage til afspillernes prøveside
Sæt en podcastafspiller på dit websted