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

@genie-player/node

v0.1.3

Published

Upload videos, generate translated captions, and verify webhooks with the Genie Player Node.js SDK

Readme

Genie Player Node.js SDK

View @genie-player/node on npm

Upload videos, generate translated captions, and receive results through polling or signed webhooks from your Node.js backend.

Open Genie Dashboard · Documentation

Install

Requires Node.js 20 or later.

npm install @genie-player/node

Create a server API key in Dashboard → API keys for your project. Server API access is available on paid plans and active trials. Store the key in your server environment as GENIE_PLAYER_API_KEY; keep it out of browser code and logs.

Upload a video and receive captions

import { GeniePlayer } from "@genie-player/node";

const genie = new GeniePlayer({
  apiKey: process.env.GENIE_PLAYER_API_KEY!,
});

const { job, captions, captionUrls } = await genie.media.processAndDownload({
  file: "./lesson.mp4",
  targetLanguages: ["es", "ja"],
  videoType: "education",
});

console.log(job.id, job.status); // READY
console.log(job.reviewStatus); // pending: open job.reviewUrl and complete dashboard review
console.log(captions.es);       // undefined while review is pending
console.log(captionUrls.es);    // undefined while review is pending

processAndDownload uploads the video and waits for caption generation. New uploads return job.reviewStatus === "pending", job.publishable === false, job.reviewUrl, and empty captions/captionUrls. Complete review in the dashboard, then retrieve the job and download approved tracks. It throws if processing fails, is canceled, or exceeds the polling timeout.

Supported upload filenames include MP4, M4V, MOV, WebM, MKV, AVI, MPEG/MPG, and TS. Video contents are validated by the API. For a Blob, Uint8Array, or ArrayBuffer, also provide filename:

import { readFile } from "node:fs/promises";

await genie.media.processAndDownload({
  file: await readFile("./lesson.mp4"),
  filename: "lesson.mp4",
  targetLanguages: ["es"],
});

New SDK uploads require manual dashboard review before publication. Successful jobs retain a temporary review preview until approval, deletion, or 24 hours from upload. Keep your own video for playback and local preview recovery after expiry. Workspace owners and project admins can opt into batched review emails in Dashboard → Notifications.

Queue a job and check its status

const { job } = await genie.media.createAndTranslate({
  file: "./lesson.mp4",
  targetLanguages: ["es"],
});

const current = await genie.translationJobs.retrieve(job.id);
const completed = await genie.translationJobs.wait(job.id);
if (!completed.publishable) {
  console.log("Complete dashboard review:", completed.reviewUrl);
} else {
  const tracks = await genie.captions.list(completed.mediaId);
  const vtt = await genie.captions.downloadVtt(completed.mediaId, "es");
}

createAndTranslate returns after submitting the job. Use retrieve for a status snapshot, wait to await completion, or a webhook to receive the result asynchronously.

Completed caption tracks include short-lived downloadUrl links that work without an API key. Authenticated caption endpoints remain available through the SDK when those links expire.

Receive results through a webhook

In Dashboard → Webhooks, select your project, save an HTTPS receiver URL, and choose the events to receive. Copy the endpoint's signing secret into your receiver's environment as GENIE_ENDPOINT_WEBHOOK_SECRET.

Submit jobs with createAndTranslate and omit webhookUrl to use the project endpoint. New uploads emit translation_job.review_required (review link, no tracks), then translation_job.published after approval (approved tracks). Failed and canceled events remain available; translation_job.completed applies to historical jobs that did not require review. Send test delivers a webhook.test event without job or caption data.

Verify the untouched request body before using an event:

import { verifyGenieWebhook } from "@genie-player/node";

// rawBody: the original request bytes, before JSON parsing.
// headers: the incoming request headers, including Genie-Signature.
const event = verifyGenieWebhook(
  rawBody,
  headers,
  process.env.GENIE_ENDPOINT_WEBHOOK_SECRET!,
);

if (event.type === "translation_job.published") {
  for (const track of event.tracks ?? []) {
    if (!track.downloadUrl) continue;
    const response = await fetch(track.downloadUrl);
    if (!response.ok) throw new Error(`Caption download failed: ${response.status}`);
    const vtt = await response.text();
    // Store or process the WebVTT text.
  }
}

The verifier checks the signature and timestamp and throws WebhookSignatureError for invalid requests. Acknowledge accepted events promptly with a 2xx response, deduplicate by event.id, and process downloads in a background task. Delivery retries can send the same event more than once.

Use dashboard delivery history to inspect attempts and retry failed deliveries. When rotating the endpoint secret, update your receiver within the 24-hour transition period; signatures made with either secret verify during that period.

Override the endpoint for one job

An explicit webhookUrl replaces the project default for that job. It uses a separate signing secret, retrieved once during backend setup with await genie.webhooks.retrieveSigningSecret(). Store that secret securely and use it to verify callbacks to the explicit URL.

await genie.media.createAndTranslate({
  file: "./lesson.mp4",
  targetLanguages: ["es"],
  webhookUrl: "https://your-app.example/webhooks/genie",
});

Slack notifications

Pass a Slack incoming webhook URL as webhookUrl to receive a dashboard review link when generation finishes and caption download links after approval or an error notification on failure. Slack URLs are detected automatically. Use webhookType: "slack" for a Slack-compatible endpoint, or webhookType: "catalog" to request signed JSON. Slack notifications do not use the JSON signature verifier.

Configuration and errors

The client connects to https://api.genieplayer.com by default. Set baseUrl only when using a different Genie API environment. Configure timeoutMs and maxRetries on the client, and pass an AbortSignal to supported operations to cancel local requests or polling.

The timeoutMs option on processAndDownload covers polling; upload and caption downloads use their own request timeouts. Canceling a local request does not cancel a server job.

API errors extend GenieError and include status, code, and an optional requestId. Common processing codes include translation_failed, translation_canceled, and wait_timeout. The client rejects HTTP redirects to protect your API credentials.

API overview

| Method | Purpose | | --- | --- | | media.createAndTranslate(input) | Upload a video and queue processing | | media.processAndDownload(input) | Upload and wait for generation; return the review handoff or approved caption text | | media.delete(mediaId) | Delete media and its associated data | | translationJobs.retrieve(jobId) | Read the current job status | | translationJobs.wait(jobId, options?) | Wait for completion | | translationJobs.events(jobId, options?) | Iterate over job status snapshots | | captions.list(mediaId) | List caption tracks | | captions.retrieve(mediaId, language) | Retrieve structured caption cues | | captions.downloadVtt(mediaId, language) | Download WebVTT text | | usage.retrieve() | Read processing usage | | clientTokens.create(input) | Create a short-lived browser token | | webhooks.retrieveSigningSecret() | Retrieve the secret for explicit per-job callbacks |

CommonJS is also supported:

const { GeniePlayer, verifyGenieWebhook } = require("@genie-player/node");

Documentation · Dashboard · Support

License

MIT