@shortkitsdk/web
v0.5.0
Published
ShortKit Web SDK — embeddable short-form video feed, player, and widget
Readme
@shortkitsdk/web
Embeddable short-form video feed, player, and widget for the web. Vanilla JS + JSDoc, ESM-first, optional hls.js peer dependency.
Install
npm install @shortkitsdk/web
# Optional — adds HLS support outside Safari
npm install hls.jsQuickstart
import { ShortKit } from '@shortkitsdk/web';
const sdk = new ShortKit({ apiKey: 'pk_live_…' });
await sdk.init();
const feed = sdk.createFeed(document.getElementById('feed'), {
config: { autoplay: true, muteOnStart: true },
});
await feed.init();Live streams
Live-stream items are first-class — any feed item with contentType: 'live_stream' automatically activates live behaviors (LIVE badge overlay, status polling, heartbeat-driven viewer count) across all four surfaces (FeedManager, EmbeddedFeedManager, SinglePlayer, WidgetManager).
Default LIVE badge (opt-in by default)
import { ShortKit } from '@shortkitsdk/web';
const sdk = new ShortKit({
apiKey: 'pk_live_…',
// liveOverlay defaults to 'default' — no config needed for the built-in badge
});Custom LIVE overlay
Provide a factory that returns { mount, update, destroy }. The factory is called per cell/tile.
const sdk = new ShortKit({
apiKey: 'pk_live_…',
liveOverlay: (player) => {
let el;
return {
mount(container, item) {
el = container;
el.innerHTML = `<div class="my-live-badge">LIVE · ${item.currentViewers}</div>`;
},
update(item) {
el.querySelector('.my-live-badge').textContent =
`LIVE · ${item.currentViewers}`;
},
destroy() {
// SDK clears `el`; cleanup any extra listeners here
},
};
},
});Disable the default overlay
new ShortKit({ apiKey: 'pk_live_…', liveOverlay: 'none' });Subscribe to live events
sdk.player.on('liveStatusChange', ({ playbackId, status, prevStatus }) => {
console.log(`Stream ${playbackId} transitioned ${prevStatus} → ${status}`);
});
sdk.player.on('viewerCountChange', ({ playbackId, currentViewers }) => {
console.log(`Stream ${playbackId} now has ${currentViewers} viewers`);
});
sdk.player.on('liveItemActivate', ({ playbackId, item }) => {
// Active live cell mounted — heartbeat sending began
});
sdk.player.on('liveItemDeactivate', ({ playbackId }) => {
// Active live cell torn down — heartbeat stopped
});Build a clip button
player.currentProgramDate() returns the wall-clock Date of the currently-playing live frame (from HLS PDT), or null for VOD or pre-manifest states. Use it to derive a server-side clip range.
async function clipLast30Seconds() {
const pdt = sdk.player.currentProgramDate();
if (!pdt) return; // VOD or pre-manifest
const item = sdk.player.currentItem;
const startedAt = new Date(item.startedAt);
const endSec = Math.floor((pdt - startedAt) / 1000);
const startSec = Math.max(0, endSec - 30);
// POST to your backend, which calls /v1/live-streams/{id}/clips with sk_
await fetch('/api/clips', {
method: 'POST',
body: JSON.stringify({
streamId: item.liveStreamId,
startSec,
endSec,
title: `Clip ${endSec - startSec}s @ ${new Date().toLocaleTimeString()}`,
}),
});
}