BustPlay — クイックスタート
空のページから広告付きプレーヤーまで 5 分。以下はすべて現在のビルド (リポジトリのルートで npm run build)で動く実際の API であり、計画ではありません。
1. script タグでプレーヤー(1 分)
<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 または要素そのもの
sources: 'https://cdn.example/video.mp4', // 文字列または [{src, type}]
muted: true, // ブラウザの自動再生ポリシーに対応済み
});
BustPlayUI.createUI(player, { title: '動画タイトル' });
</script>
ファイルは packages/*/dist/ から取得します(npm 公開まで)。UMD グローバル: BustPlay (core)、BustPlayUI、BustPlayHls、BustPlayAds、 BustPlayAnalytics。
2. バンドラーで同じことを(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: '動画タイトル',
chapters: [{ t: 0, name: 'プロローグ' }, { t: 96, name: '第二章' }],
skin: 'studio', // studio | minimal | vertical
accent: '#5B8CFF', // 変数ひとつでホワイトラベル
});
インポートは SSR セーフ:createPlayer まで window に触れません。
3. HLS
import { attachHls, bindQualityMenu } from '@bustplay/hls';
const player = createPlayer({ container: 'player', sources: [] }); // ソースはアダプターが管理
const ui = createUI(player, { title: 'ライブ' });
const hls = await attachHls(player, 'https://cdn.example/stream.m3u8');
bindQualityMenu(hls, ui.menu); // 品質レベルは自動でメニューに表示
Safari はネイティブで再生。他のブラウザは hls.js を遅延読み込み: options.lib → ページ上のグローバル Hls → import('hls.js')。
4. 広告
import { createAdScheduler, breaksFromVmap } from '@bustplay/ads';
const scheduler = createAdScheduler(player, {
ui, // 「広告 1 / 2」カウンター、シーク禁止
breaks: [
{ offset: 'pre', tags: [TAG_A, TAG_B] }, // A が埋まらなければ B を試す
{ offset: { percent: 0.5 }, tags: [TAG_MID], pod: 2 },
{ offset: 'post', tags: [TAG_POST] },
],
consent: { gdpr: '1', gdprConsent: TCF_STRING }, // → マクロ {gdpr}/{gdpr_consent}
});
// コンテンツがちらつかないクリーンなプリロール:
await scheduler.runPreRoll();
void player.play();
// または VMAP からまるごと:
createAdScheduler(player, { ui, breaks: breaksFromVmap(vmapXml) });
5. 分析
import { createAnalytics } from '@bustplay/analytics';
createAnalytics(player, {
endpoint: 'https://stats.example.com/v1/events',
video: 'video-42', // 自社の動画 id。PII ではない
sampleRate: 1, // 収集するセッションの割合
});
イベント(TTFF 付き view_start、四分位、リバッファ、エラー、QoE 付き session_end) はバッチで送信され、タブを閉じても sendBeacon で届きます。受信側は services/stats(README はそちら)。
6. React と Web Component
import { BustPlayer } from '@bustplay/react';
import '@bustplay/ui/ui.css';
<BustPlayer sources="https://cdn.example/video.mp4" title="動画"
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="動画" muted></bust-play>
sources/src を変えるとプレーヤーが再生成されます。見た目(title、skin)は 生成時に適用。<bust-play> は Shadow DOM を使わないため、ページに ui.css が必要です。
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) }); // hls.js の EME
await attachDash(player, src, { protectionData: toDashProtectionData(drm) });
const off = enableFairPlay(player.media, drm.fairplay); // Safari ネイティブ HLS
Widevine/PlayReady は hls.js/dash.js が処理。ネイティブ経路の FairPlay は当方の EME 層が担当します(SPC/CKC は生バイト。サーバー差異は licenseBody / licenseResponse フックで)。実際の動作確認にはライセンスサーバーが必要です。
次のステップ
- ライブデモ:
apps/demo/index.html(npm run buildの後)。 - UI デザインシステム:
UI_DESIGN.md。 - ロードマップと正直な現状:
README.md§6。