npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mebius-io/web

v0.6.1

Published

Mebius Client SDK for the web — live streaming, simple API.

Readme

@mebius-io/web

SDK web Mebius untuk live streaming — install, ikuti docs, hit API.

npm version license

Requirements

  • Browser modern dengan WebRTC (Chrome, Edge, Firefox, Safari terbaru).
  • HTTPS wajib di production. localhost boleh 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/web

Package 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 — works

Via 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 appSecret di 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 via file://.
  • HTTPS: WebRTC butuh secure context di production.
  • Autoplay: browser memblok autoplay dengan suara. Mulai playback setelah interaksi user, atau set muted dulu lalu unmute via setVolume.

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 react

Versioning & 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