BustPlay
FR

BustPlay — démarrage rapide

Cinq minutes d’une page vide à un lecteur avec publicité. Tout ce qui suit est l’API réelle des builds actuels (npm run build à la racine du dépôt), pas des projets.

1. Lecteur par balise script (une minute)

<link rel="stylesheet" href="bustplay/ui.css">
<div id="player"></div>

<script src="bustplay/core.umd.cjs"></script>
<script src="bustplay/ui.umd.cjs"></script>
<script>
  const player = BustPlay.createPlayer({
    container: 'player',                       // id ou l’élément lui-même
    sources: 'https://cdn.example/video.mp4',  // chaîne ou [{src, type}]
    muted: true,                               // politiques d’autoplay des navigateurs gérées
  });
  BustPlayUI.createUI(player, { title: 'Titre de la vidéo' });
</script>

Les fichiers viennent de packages/*/dist/ (jusqu’à la publication npm). Globales UMD : BustPlay (core), BustPlayUI, BustPlayHls, BustPlayAds, BustPlayAnalytics.

2. La même chose avec un bundler (ESM)

import { createPlayer } from '@bustplay/core';
import { createUI } from '@bustplay/ui';
import '@bustplay/ui/ui.css';

const player = createPlayer({ container: 'player', sources: 'https://cdn.example/video.mp4' });
const ui = createUI(player, {
  title: 'Titre de la vidéo',
  chapters: [{ t: 0, name: 'Prologue' }, { t: 96, name: 'Chapitre deux' }],
  skin: 'studio',            // studio | minimal | vertical
  accent: '#5B8CFF',         // marque blanche avec une seule variable
});

L’import est compatible SSR : window n’est pas touché avant createPlayer.

3. HLS

import { attachHls, bindQualityMenu } from '@bustplay/hls';

const player = createPlayer({ container: 'player', sources: [] }); // l’adaptateur pilote la source
const ui = createUI(player, { title: 'Direct' });
const hls = await attachHls(player, 'https://cdn.example/stream.m3u8');
bindQualityMenu(hls, ui.menu); // les niveaux de qualité apparaissent d’eux-mêmes dans le menu

Safari lit nativement ; les autres navigateurs chargent hls.js paresseusement : options.lib → la globale Hls de la page → import('hls.js').

4. Publicité

import { createAdScheduler, breaksFromVmap } from '@bustplay/ads';

const scheduler = createAdScheduler(player, {
  ui,                                    // compteur « Publicité 1 sur 2 », recherche bloquée
  breaks: [
    { offset: 'pre',              tags: [TAG_A, TAG_B] }, // A n’a pas rempli — on essaie B
    { offset: { percent: 0.5 },   tags: [TAG_MID], pod: 2 },
    { offset: 'post',             tags: [TAG_POST] },
  ],
  consent: { gdpr: '1', gdprConsent: TCF_STRING },  // → macros {gdpr}/{gdpr_consent}
});

// Pre-roll propre sans flash du contenu :
await scheduler.runPreRoll();
void player.play();

// Ou entièrement depuis VMAP :
createAdScheduler(player, { ui, breaks: breaksFromVmap(vmapXml) });

5. Analytique

import { createAnalytics } from '@bustplay/analytics';

createAnalytics(player, {
  endpoint: 'https://stats.example.com/v1/events',
  video: 'video-42',       // votre id de vidéo, pas de PII
  sampleRate: 1,           // part des sessions collectées
});

Les événements (view_start avec TTFF, quartiles, rebuffer, erreurs, session_end avec QoE) partent par lots ; la fermeture de l’onglet est survécue via sendBeacon. Le côté réception est services/stats (README sur place).

6. React et Web Component

import { BustPlayer } from '@bustplay/react';
import '@bustplay/ui/ui.css';

<BustPlayer sources="https://cdn.example/video.mp4" title="Vidéo"
  onReady={({ player, ui }) => console.log(player.getState())} />
<script src="bustplay/element.umd.cjs"></script>
<script>BustPlayElement.define()</script>
<bust-play src="https://cdn.example/video.mp4" title="Vidéo" muted></bust-play>

Changer sources/src recrée le lecteur ; la cosmétique (title, skin) est appliquée à la création. <bust-play> n’a pas de Shadow DOM : il lui faut ui.css inclus dans la page.

7. DRM

import { toHlsDrmConfig, toDashProtectionData, enableFairPlay } from '@bustplay/drm';

const drm = {
  widevine:  { licenseUrl: 'https://lic.example/wv', headers: { 'X-Auth': token } },
  playready: { licenseUrl: 'https://lic.example/pr' },
  fairplay:  { licenseUrl: 'https://lic.example/fps', certificateUrl: 'https://lic.example/cert' },
};

await attachHls(player, src, { config: toHlsDrmConfig(drm) });          // EME de hls.js
await attachDash(player, src, { protectionData: toDashProtectionData(drm) });
const off = enableFairPlay(player.media, drm.fairplay);                  // HLS natif de Safari

Widevine/PlayReady sont gérés par hls.js/dash.js ; FairPlay sur le chemin natif est piloté par notre couche EME (SPC/CKC en octets bruts ; variantes serveur via les hooks licenseBody/licenseResponse). Un essai réel nécessite un serveur de licences.

Et ensuite