@mebius-io/web
v0.6.1
Published
Mebius Client SDK for the web — live streaming, simple API.
Maintainers
Readme
@mebius-io/web
SDK web Mebius untuk live streaming — install, ikuti docs, hit API.
Requirements
- Browser modern dengan WebRTC (Chrome, Edge, Firefox, Safari terbaru).
- HTTPS wajib di production.
localhostboleh dipakai untuk development. - Node 20+ hanya untuk build tooling (bukan runtime SDK).
Install
Package sudah live di npm registry (public). Install seperti biasa:
npm i @mebius-io/web
# atau: pnpm add @mebius-io/web / yarn add @mebius-io/webPackage berisi dist/ (ESM + CJS + UMD + types) dan menarik dependency runtime
playback-nya otomatis. Tidak perlu build di sisi consumer.
const { Mebius } = require("@mebius-io/web"); // CJS — works
import { Mebius } from "@mebius-io/web"; // ESM — worksVia CDN (UMD global Mebius):
<script src="https://unpkg.com/@mebius-io/web/dist/index.global.js"></script>
<script>
Mebius.Mebius.init({ appId: "app_123", gateway: "https://gateway.mebius.io" });
</script>Butuh install offline / tanpa registry? Lihat Distribusi via tarball.
Single-file drop-in (PHP / plain HTML, no build)
For PHP or any plain-HTML project: download ONE self-contained file and add a
<script> tag — no npm, no bundler. The scale engine is bundled in; zero
external deps. Mebius becomes a global.
<script src="mebius.min.js"></script>
<script>
Mebius.init({ appId: "app_123", gateway: "https://gateway.mebius.io" });
const client = Mebius.connect({ token, deliveries }); // dari backend kamu
</script>File + full PHP example: standalone/. Raw download:
https://raw.githubusercontent.com/russimobiledroidx/mebius-web-sdk/v0.4.6/packages/web/standalone/mebius.min.js
The drop-in file is not part of the npm package — files ships only dist — so it
is fetched from the tag, and the tag must match the version you installed. For a
page with a build step, or one that can use an import map, prefer the ESM path:
https://esm.sh/@mebius-io/[email protected].
Quick Start
a. Auth
Token di-mint dari backend kamu, JANGAN embed
appSecretdi client. Backend menukar (appId + appSecret) jadi JWT short-lived; client cuma terima string token-nya.
b. Init + connect
import { Mebius } from "@mebius-io/web";
Mebius.init({ appId: "app_123", gateway: "https://gateway.mebius.io" });
const token = await fetch("/api/mebius-token").then((r) => r.text());
const client = Mebius.connect({ token });
client.on("connected", () => console.log("Mebius connected"));
client.on("error", (err) => {
if (err.code === "TOKEN_EXPIRED") {
// refresh token dari backend, lalu connect ulang
}
});c. Broadcast
const broadcaster = client.createBroadcaster({ video: true, audio: true });
broadcaster.on("started", ({ streamId }) => console.log("live:", streamId));
broadcaster.on("stats", (s) => console.log(s.bitrateKbps, "kbps"));
await broadcaster.start("my-stream");
broadcaster.attachPreview("#preview"); // preview lokal (web convenience)
// kontrol
broadcaster.setMicEnabled(false);
broadcaster.setCameraEnabled(true);
await broadcaster.switchCamera();
// stop
await broadcaster.stop();d. Watch
const player = client.createPlayer(); // mode default "auto"
player.on("playing", ({ streamId }) => console.log("playing", streamId));
player.on("buffering", () => console.log("buffering..."));
player.on("ended", () => console.log("ended"));
await player.play("my-stream", "#viewer"); // <video id="viewer">
player.setVolume(0.8);
await player.stop();Mode playback
| Mode | Kapan dipakai |
| --- | --- |
| "auto" (default) | Rekomendasi. Mebius pilih rute per penonton, dan pindah sendiri kalau rute yang dipakai berhenti mengirim frame. |
| "low-latency" | Interaktif dua arah (mis. co-broadcast), delay sub-detik. Browser saja. |
| "balanced" | Delay rendah tapi tetap skala besar. Butuh browser dengan Media Source (bukan Safari iOS). |
| "scale" | Audiens paling besar, delay paling tinggi, jalan di semua platform termasuk Safari iOS. |
Ganti mode kapan saja dengan membuat player baru.
Menonton lawan bicara (createMonitor)
Kalau kamu menonton stream yang sedang kamu ajak interaksi (sisi lain dari co-broadcast), delay satu-dua detik membuat interaksinya terasa rusak:
const monitor = client.createMonitor();
await monitor.play(opponentStreamId, "#opponent");Sama seperti player biasa, hanya budget delay-nya beda. Monitor mulai dari rute real-time dan pindah sendiri kalau rute itu tidak mengirim frame dalam 8 detik — logika yang sebelumnya harus ditulis ulang di setiap aplikasi, dan kalau salah hasilnya frame hitam di depan penonton live.
deliveries
Mebius.connect() menerima deliveries yang dikirim backend bareng token:
const { token, deliveries } = await (await fetch("/api/mebius-token")).json();
const client = Mebius.connect({ token, deliveries });Teruskan apa adanya — isinya opaque dan Mebius yang mengurutkan serta memilih. Opsional: tanpa itu playback tetap jalan, tapi setiap penonton dilayani dari origin Mebius, bukan edge terdekat.
beaconToken / beaconUrl — quality di dashboard
Response token juga membawa dua field opsional. Teruskan keduanya dan SDK melaporkan kualitas stream ini (bitrate, fps, rtt, jeda first-frame) tiap ~15 detik:
const { token, deliveries, beaconToken, beaconUrl } = await (await fetch("/api/mebius-token")).json();
const client = Mebius.connect({ token, deliveries, beaconToken, beaconUrl });Itu yang mengisi Quality → Publish / Play di dashboard Mebius, dan yang jadi dasar hitung viewer minutes — laporan sisi penonton adalah satu-satunya sumber data itu, karena cuma client yang bisa melihat pengalaman penonton sebenarnya.
Aman di browser: kredensialnya terikat klaim bertanda tangan ke satu stream dan satu project, jadi tak bisa dipakai menulis telemetri milik stream lain. SDK tidak pernah tahu tenant-mu — informasi itu ada di dalam klaim, bukan di kode client.
Tanpa dua field itu stream tetap jalan normal; kamu hanya tidak melihat data
kualitasnya. Tambahkan userId di connect() kalau ingin laporan itu ikut membawa
id pengguna versimu.
Integrasi per framework
Vanilla JS
ESM:
import { Mebius } from "@mebius-io/web";
Mebius.init({ appId, gateway });
const client = Mebius.connect({ token });UMD <script>:
<script src="https://unpkg.com/@mebius-io/web/dist/index.global.js"></script>
<script>
const { Mebius } = window.Mebius;
Mebius.init({ appId, gateway });
</script>React
Pakai @mebius-io/react (hooks tipis di atas package ini):
import { useMebius, usePlayer } from "@mebius-io/react";
function Watch({ token, streamId }) {
const { client } = useMebius({ appId, gateway, token });
const { videoRef, play } = usePlayer(client, {});
return <video ref={videoRef} onClick={() => play(streamId)} autoPlay />;
}Next.js
"use client";
import dynamic from "next/dynamic";
// SDK butuh WebRTC browser → jangan render di server.
const Watch = dynamic(() => import("../components/Watch"), { ssr: false });
export default function Page() {
return <Watch />;
}Vue 3 (Composition API)
import { onMounted, onUnmounted, ref } from "vue";
import { Mebius } from "@mebius-io/web";
export function useWatch(streamId: string) {
const video = ref<HTMLVideoElement>();
let player: ReturnType<ReturnType<typeof Mebius.connect>["createPlayer"]>;
onMounted(async () => {
Mebius.init({ appId, gateway });
const client = Mebius.connect({ token: await getToken() });
player = client.createPlayer();
await player.play(streamId, video.value!);
});
onUnmounted(() => player?.stop());
return { video };
}Vite
Tidak ada config khusus. ESM langsung jalan; engine playback per mode di-load
lazy hanya saat mode itu dipakai, jadi aplikasi yang cuma pakai "low-latency"
tidak membawa bundle mode lain.
API Reference
| Class | Method | Return | Keterangan |
|---|---|---|---|
| Mebius | init({ appId, gateway }) | void | Konfigurasi sekali di awal. |
| Mebius | connect({ token, deliveries? }) | MebiusClient | Buka koneksi. |
| MebiusClient | createBroadcaster({ video?, audio? }) | MebiusBroadcaster | |
| MebiusClient | createPlayer({ mode? }) | MebiusPlayer | mode: "auto" \| "low-latency" \| "balanced" \| "scale", default "auto" |
| MebiusClient | createMonitor() | MebiusPlayer | Player untuk stream yang kamu ajak interaksi. |
| MebiusClient | disconnect(reason?) | void | |
| MebiusBroadcaster | start(streamId) | Promise<void> | |
| MebiusBroadcaster | stop() | Promise<void> | |
| MebiusBroadcaster | switchCamera() | Promise<void> | |
| MebiusBroadcaster | setMicEnabled(bool) | void | |
| MebiusBroadcaster | setCameraEnabled(bool) | void | |
| MebiusBroadcaster | attachPreview(target) | void | Preview lokal (web). |
| MebiusPlayer | play(streamId, viewTarget) | Promise<void> | viewTarget: <video> atau selector. |
| MebiusPlayer | stop() | Promise<void> | |
| MebiusPlayer | setVolume(0..1) | void | |
Events
| Emitter | Event | Payload |
|---|---|---|
| client | connected | — |
| client | disconnected | { reason? } |
| client | error | MebiusError |
| broadcaster | started | { streamId } |
| broadcaster | stopped | — |
| broadcaster | stats | { bitrateKbps, framesPerSecond, rttMs? } |
| player | playing | { streamId } |
| player | buffering | — |
| player | ended | — |
| player | stats | { bitrateKbps, framesPerSecond, latencyMs? } |
client.on("connected", () => {});
client.on("error", (e) => console.warn(e.code, e.message));
broadcaster.on("stats", (s) => console.log(s.bitrateKbps));Error handling
Semua error adalah MebiusError dengan .code:
| Code | Arti | Recover |
|---|---|---|
| TOKEN_EXPIRED | Token habis masa berlaku | Mint token baru di backend, connect ulang. |
| PERMISSION_DENIED | Izin kamera/mic ditolak | Minta user mengizinkan, retry start(). |
| CONNECTION_FAILED | Gagal konek ke gateway | Cek jaringan/gateway, retry dengan backoff. |
| NOT_CONNECTED | Dipakai sebelum connect() | Pastikan connect() sukses dulu. |
| STREAM_NOT_FOUND | Stream tidak ada | Verifikasi streamId. |
client.on("error", (e) => {
switch (e.code) {
case "TOKEN_EXPIRED": return refreshAndReconnect();
case "PERMISSION_DENIED": return showPermissionHelp();
default: console.error(e);
}
});Troubleshooting
- Izin kamera/mic: browser hanya memberi izin di context aman (HTTPS atau
localhost). Pastikan halaman tidak dibuka viafile://. - HTTPS: WebRTC butuh secure context di production.
- Autoplay: browser memblok autoplay dengan suara. Mulai playback setelah
interaksi user, atau set
muteddulu lalu unmute viasetVolume.
Distribusi via tarball (offline / tanpa registry)
Package sudah live di npm (npm i @mebius-io/web). Bagian ini hanya untuk kasus
offline / air-gapped atau saat kamu sengaja tidak mau lewat registry.
# 1. Maintainer build + pack semua package sekaligus (di repo SDK):
pnpm pack:all
# -> mebius-web-0.1.0.tgz
# mebius-react-0.1.0.tgz
# mebius-react-native-0.1.0.tgz (di root repo)
# 2. Consumer install (copy .tgz ke project, lalu):
npm i ./mebius-web-0.1.0.tgz@mebius-io/web self-contained (tanpa workspace dep), jadi paling bersih untuk
install tarball standalone.
Cross-package dependency (react)
@mebius-io/react bergantung ke @mebius-io/web. Lewat npm registry ini otomatis
teratasi. Untuk tarball offline, workspace:* ditulis ulang jadi versi
konkret ("@mebius-io/web": "0.1.0"); install kedua tarball dalam satu perintah
agar dep-nya terpenuhi lokal:
npm i ./mebius-web-0.1.0.tgz ./mebius-react-0.1.0.tgz reactVersioning & changelog
SemVer. Public API stabil per major version; perubahan breaking pada kontrak = major bump serempak di semua platform Mebius. Lihat changeset di repo.
License
MIT
