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

vod-ssai

v1.0.8

Published

Server-guided ad insertion (SGAI) proof of concept: Eyevinn sgai-ad-proxy, VAST bridge, HLS.js + IMA player, Docker Compose stack

Readme

SSAI / SGAI proof of concept

npm package

Install and use from Node.js or run the bundled Docker stack via CLI:

npm install vod-ssai

For frontend-only integration (lightweight player embed helpers + static index.html), use:

import { createPlayerUrl, mountPlayer } from "vod-ssai/player-sdk";

React integration

  1. Copy the player HTML once during setup/build:
mkdir -p public/player
cp node_modules/vod-ssai/player-sdk/index.html public/player/index.html
  1. Use helper API:
import { createPlayerUrl } from "vod-ssai/player-sdk";

export function SgaiPlayerFrame({ videoId, apiBase }) {
  const src = createPlayerUrl({
    playerPath: "/player/index.html",
    videoId,
    apiBase,
  });
  return (
    <iframe
      title="SSAI Player"
      src={src}
      allow="autoplay; fullscreen; picture-in-picture"
      style={{ width: "100%", aspectRatio: "16/9", border: 0 }}
    />
  );
}

Angular integration

  1. Add asset copy in angular.json:
{
  "glob": "index.html",
  "input": "node_modules/vod-ssai/player-sdk",
  "output": "/player"
}
  1. Component usage:
import { Component } from "@angular/core";
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
import { createPlayerUrl } from "vod-ssai/player-sdk";

@Component({
  selector: "app-player-frame",
  template: `<iframe [src]="src" allow="autoplay; fullscreen; picture-in-picture"></iframe>`,
})
export class PlayerFrameComponent {
  src: SafeResourceUrl;
  constructor(private sanitizer: DomSanitizer) {
    const url = createPlayerUrl({
      playerPath: "/player/index.html",
      videoId: "VIDEO_UUID",
      apiBase: "https://YOUR-SERVER.COM",
    });
    this.src = this.sanitizer.bypassSecurityTrustResourceUrl(url);
  }
}
import {
  packageRoot,
  DEFAULT_URLS,
  DEFAULT_PORTS,
  getPaths,
  runDockerCompose,
} from "vod-ssai";

console.log(DEFAULT_URLS.player);
await runDockerCompose(["up", "--build", "-d"]);
npx vod-ssai compose up --build -d
npx vod-ssai root
npx vod-ssai urls

You still need Docker, generated hls-out/ under the package directory (see scripts), and a browser at the player URL.

Publish: log in with npm login, set "name" in package.json (use a scoped name if vod-ssai is taken), optionally add "repository" / "homepage", then run npm publish (public scoped packages: npm publish --access public).


This repository demonstrates server-guided ad insertion (SGAI) using Eyevinn sgai-ad-proxy: a VAST-backed proxy that rewrites your HLS manifest with interstitial breaks, plus a small HLS.js + Google IMA player that plays the stitched stream from a same-origin URL.

What you get in Docker

| Piece | Role | |--------|------| | hls-nginx | Serves generated VoD HLS (hls-out/) on host :8000 | | vast-bridge | Minimal VAST 4.x HTTP service for the proxy (:8080); optional JSON hook to an ad decision API | | sgai-ad-proxy | Rewrites master.m3u8 with SGAI interstitials (:3333) | | sgai-player | Static player + reverse proxy so the browser hits :8090 (avoids CORS on interstitial requests) |

There is no separate “ad database” or bidding service in this compose: the POC is intentionally small so you can focus on manifest behavior and the player.


Quick start

chmod +x scripts/*.sh
./scripts/generate-hls-docker.sh    # FFmpeg in Docker; outputs ./hls-out
docker compose up --build -d

Open http://127.0.0.1:8090/player/ in Chrome or Firefox (HLS.js with interstitials). Use the Ad tag dropdown to try Google sample VAST/VMAP, Eyevinn’s test ad, or same-origin URLs under /vast-proxy/ (proxied to vast-bridge).

Stop: docker compose down

More detail (Helm sketch, host ffmpeg, CLI notes): see POC.md.


SaaS console (per-video ad count + IMA)

Use docker-compose.saas.yml: config API, /admin UI, and three SGAI presets (1 / 2 / 5 mid-roll slots). See deployment/saas/README.md.


AWS (EC2 + S3 + CloudFront)

VoD can stay packaged as HLS in S3; sgai-ad-proxy pulls the master playlist URL over HTTPS (no re-encode required for hosting). EC2 runs the Docker stack that serves the player and proxy.

  • Guide: deployment/aws/README.md
  • Compose: docker-compose.aws.yml with .env.aws from deployment/aws/env.example (CDN_ORIGIN = CloudFront hostname only; manifest paths such as videos/video1/master.m3u8 come from the SaaS console or player URL)
  • Upload HLS to S3: ./scripts/sync-hls-to-s3.sh s3://YOUR_BUCKET/videos/video1/ (or any prefix that matches manifest_path in the console)

Why OpenAdServer is not in this docker-compose.yml

OpenAdServer (and similar forks) is a full ad stack: API service, PostgreSQL, Redis, often optional Nginx/Prometheus—its own docker-compose.yml with fixed ports and healthchecks.

We do not vendor that stack here for several practical reasons:

  1. Port conflicts with this POC
    This repo already maps host :8000 to hls-nginx (your VoD origin). Typical OpenAdServer compose maps :8000 to the ad-server container. Running both “as-is” on one machine collides unless you remap ports everywhere.

  2. Different responsibility
    sgai-ad-proxy speaks VAST XML to decide what to stitch. OpenAdServer (today) is oriented around JSON APIs (e.g. POST /api/v1/ad/request), not a drop-in VAST server for the proxy. This repo’s vast-bridge already bridges that gap: it emits VAST and optionally calls OPENADS_URL for targeting.

  3. Operational weight
    Pulling Postgres + Redis + migrations + seed data into this compose would turn a manifest/player POC into a multi-team platform install: longer boot, more failure modes, and harder CI for anyone who only wants SGAI behavior.

  4. Upstream owns the contract
    OpenAdServer’s Docker layout, env vars, and init scripts change with the fork. Embedding a copy here would duplicate maintenance and drift from the project you actually run.

Recommended pattern: run OpenAdServer from its repository (or your fork), then point this stack at it only when you need it:

# Example: OpenAdServer listening on host :8000
export OPENADS_URL=http://host.docker.internal:8000
docker compose up -d

vast-bridge will see OPENADS_URL and can use JSON responses when they include a usable video URL on the creative; otherwise it keeps using DEFAULT_MEDIA_M3U8 for the VAST MediaFile.


URLs (defaults)

| URL | Meaning | |-----|--------| | http://127.0.0.1:8000/hls-out/master.m3u8 | Raw VoD (no SGAI) | | http://127.0.0.1:3333/hls-out/master.m3u8 | SGAI-rewritten manifest | | http://127.0.0.1:8090/player/ | Player (use this to see interstitials) | | http://127.0.0.1:8080/vast / .../api/vast | VAST bridge (direct) |

If 8080 is taken on your machine, change the vast-bridge port mapping in docker-compose.yml and update the sgai-ad-proxy command VAST URL accordingly.


License

Third-party components (sgai-ad-proxy, HLS.js, IMA SDK, OpenAdServer) follow their respective licenses. This POC’s glue code is provided as-is for experimentation.