Giter Site home page Giter Site logo

muxinc / mux-node-sdk Goto Github PK

View Code? Open in Web Editor NEW
148.0 41.0 58.0 6.85 MB

Official Mux API wrapper for Node projects, supporting both Mux Data and Mux Video.

Home Page: https://mux.com/for/node

License: Apache License 2.0

JavaScript 1.61% TypeScript 97.54% Dockerfile 0.07% Shell 0.78%
mux video video-streaming video-processing video-analytics node

mux-node-sdk's Introduction

Mux Node API Library

NPM version

This library provides convenient access to the Mux REST API from server-side TypeScript or JavaScript.

Note

In February 2024 this SDK was updated to Version 8.0. For upgrading to 8.x see UPGRADE_8.x.md

The REST API documentation can be found on docs.mux.com. The full API of this library can be found in api.md.

Installation

npm install @mux/mux-node

Usage

The full API of this library can be found in api.md.

import Mux from '@mux/mux-node';

const mux = new Mux({
  tokenId: process.env['MUX_TOKEN_ID'], // This is the default and can be omitted
  tokenSecret: process.env['MUX_TOKEN_SECRET'], // This is the default and can be omitted
});

async function main() {
  const asset = await mux.video.assets.create({
    input: [{ url: 'https://storage.googleapis.com/muxdemofiles/mux-video-intro.mp4' }],
    playback_policy: ['public'],
  });

  console.log(asset.id);
}

main();

Request & Response types

This library includes TypeScript definitions for all request params and response fields. You may import and use them like so:

import Mux from '@mux/mux-node';

const mux = new Mux({
  tokenId: process.env['MUX_TOKEN_ID'], // This is the default and can be omitted
  tokenSecret: process.env['MUX_TOKEN_SECRET'], // This is the default and can be omitted
});

async function main() {
  const params: Mux.Video.AssetCreateParams = {
    input: [{ url: 'https://storage.googleapis.com/muxdemofiles/mux-video-intro.mp4' }],
    playback_policy: ['public'],
  };
  const asset: Mux.Video.Asset = await mux.video.assets.create(params);
}

main();

Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors.

JWT Helpers (API Reference)

You can use any JWT-compatible library, but we've included some light helpers in the SDK to make it easier to get up and running.

// Assuming you have your signing key specified in your environment variables:
// Signing token ID: process.env.MUX_SIGNING_KEY
// Signing token secret: process.env.MUX_PRIVATE_KEY

// Most simple request, defaults to type video and is valid for 7 days.
const token = mux.jwt.signPlaybackId('some-playback-id');
// https://stream.mux.com/some-playback-id.m3u8?token=${token}

// If you wanted to sign a thumbnail
const thumbParams = { time: 14, width: 100 };
const thumbToken = mux.jwt.signPlaybackId('some-playback-id', {
  type: 'thumbnail',
  params: thumbParams,
});
// https://image.mux.com/some-playback-id/thumbnail.jpg?token=${token}

// If you wanted to sign a gif
const gifToken = mux.jwt.signPlaybackId('some-playback-id', { type: 'gif' });
// https://image.mux.com/some-playback-id/animated.gif?token=${token}

// Here's an example for a storyboard
const storyboardToken = mux.jwt.signPlaybackId('some-playback-id', {
  type: 'storyboard',
});

// https://image.mux.com/some-playback-id/storyboard.jpg?token=${token}

// You can also use `signViewerCounts` to get a token
// used for requests to the Mux Engagement Counts API
// https://docs.mux.com/guides/see-how-many-people-are-watching
const statsToken = mux.jwt.signViewerCounts('some-live-stream-id', {
  type: 'live_stream',
});

// https://stats.mux.com/counts?token={statsToken}

Parsing Webhook payloads

To validate that the given payload was sent by Mux and parse the webhook payload for use in your application, you can use the mux.webhooks.unwrap utility method.

This method accepts a raw body string and a list of headers. As long as you have set your webhookSecret in the appropriate configuration property when instantiating the library, all webhooks will be verified for authenticity automatically.

The following example shows how you can handle a webhook using a Next.js app directory API route:

// app/api/mux/webhooks/route.ts
import { revalidatePath } from 'next/cache';
import { headers } from 'next/headers';

import Mux from '@mux/mux-node';

const mux = new Mux({
  webhookSecret: process.env.MUX_WEBHOOK_SECRET,
});

export async function POST(request: Request) {
  const headersList = headers();
  const body = await request.text();
  const event = mux.webhooks.unwrap(body, headersList);

  switch (event.type) {
    case 'video.live_stream.active':
    case 'video.live_stream.idle':
    case 'video.live_stream.disabled':
      /**
       * `event` is now understood to be one of the following types:
       *
       *   | Mux.Webhooks.VideoLiveStreamActiveWebhookEvent
       *   | Mux.Webhooks.VideoLiveStreamIdleWebhookEvent
       *   | Mux.Webhooks.VideoLiveStreamDisabledWebhookEvent
       */
      if (event.data.id === 'MySpecialTVLiveStreamID') {
        revalidatePath('/tv');
      }
      break;
    default:
      break;
  }

  return Response.json({ message: 'ok' });
}

Verifying Webhook Signatures

Verifying Webhook Signatures is optional but encouraged. Learn more in our Webhook Security Guide

/*
  If the header is valid, this function will not throw an error and will not return a value.
  If the header is invalid, this function will throw one of the following errors:
    - new Error(
      "The webhook secret must either be set using the env var, MUX_WEBHOOK_SECRET, on the client class, Mux({ webhookSecret: '123' }), or passed to this function",
    );
    - new Error('Could not find a mux-signature header');
    - new Error(
      'Webhook body must be passed as the raw JSON string sent from the server (do not parse it first).',
    );
    - new Error('Unable to extract timestamp and signatures from header')
    - new Error('No v1 signatures found');
    - new Error('No signatures found matching the expected signature for payload.')
    - new Error('Webhook timestamp is too old')
*/

/*
  `body` is the raw request body. It should be a string representation of a JSON object.
  `headers` is the value in request.headers
  `secret` is the signing secret for this configured webhook. You can find that in your webhooks dashboard
          (note that this secret is different than your API Secret Key)
*/

mux.webhooks.verifySignature(body, headers, secret);

Note that when passing in the payload (body) you want to pass in the raw un-parsed request body, not the parsed JSON. Here's an example if you are using express.

const Mux = require('@mux/mux-node');
const mux = new Mux();
const express = require('express');
const bodyParser = require('body-parser');

/**
 * You'll need to make sure this is externally accessible.  ngrok (https://ngrok.com/)
 * makes this really easy.
 */

const webhookSecret = process.env.WEBHOOK_SECRET;
const app = express();

app.post('/webhooks', bodyParser.raw({ type: 'application/json' }), async (req, res) => {
  try {
    // will raise an exception if the signature is invalid
    const isValidSignature = mux.webhooks.verifySignature(req.body, req.headers, webhookSecret);
    console.log('Success:', isValidSignature);
    // convert the raw req.body to JSON, which is originally Buffer (raw)
    const jsonFormattedBody = JSON.parse(req.body);
    // await doSomething();
    res.json({ received: true });
  } catch (err) {
    // On error, return the error message
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }
});

app.listen(3000, () => {
  console.log('Example app listening on port 3000!');
});

Handling errors

When the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of APIError will be thrown:

async function main() {
  const liveStream = await mux.video.liveStreams.create().catch(async (err) => {
    if (err instanceof Mux.APIError) {
      console.log(err.status); // 400
      console.log(err.name); // BadRequestError
      console.log(err.headers); // {server: 'nginx', ...}
    } else {
      throw err;
    }
  });
}

main();

Error codes are as followed:

Status Code Error Type
400 BadRequestError
401 AuthenticationError
403 PermissionDeniedError
404 NotFoundError
422 UnprocessableEntityError
429 RateLimitError
>=500 InternalServerError
N/A APIConnectionError

Retries

Certain errors will be automatically retried 2 times by default, with a short exponential backoff. Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, and >=500 Internal errors will all be retried by default.

You can use the maxRetries option to configure or disable this:

// Configure the default for all requests:
const mux = new Mux({
  maxRetries: 0, // default is 2
});

// Or, configure per-request:
await mux.video.assets.retrieve('t02rm...', {
  maxRetries: 5,
});

Timeouts

Requests time out after 1 minute by default. You can configure this with a timeout option:

// Configure the default for all requests:
const mux = new Mux({
  timeout: 20 * 1000, // 20 seconds (default is 1 minute)
});

// Override per-request:
await mux.video.assets.retrieve('t02rm...', {
  timeout: 5 * 1000,
});

On timeout, an APIConnectionTimeoutError is thrown.

Note that requests which time out will be retried twice by default.

Auto-pagination

List methods in the Mux API are paginated. You can use for await … of syntax to iterate through items across all pages:

async function fetchAllVideoDeliveryUsages(params) {
  const allVideoDeliveryUsages = [];
  // Automatically fetches more pages as needed.
  for await (const deliveryReport of mux.video.deliveryUsage.list()) {
    allVideoDeliveryUsages.push(deliveryReport);
  }
  return allVideoDeliveryUsages;
}

Alternatively, you can make request a single page at a time:

let page = await mux.video.deliveryUsage.list();
for (const deliveryReport of page.data) {
  console.log(deliveryReport);
}

// Convenience methods are provided for manually paginating:
while (page.hasNextPage()) {
  page = page.getNextPage();
  // ...
}

Advanced Usage

Accessing raw Response data (e.g., headers)

The "raw" Response returned by fetch() can be accessed through the .asResponse() method on the APIPromise type that all methods return.

You can also use the .withResponse() method to get the raw Response along with the parsed data.

const mux = new Mux();

const response = await mux.video.assets
  .create({
    input: [{ url: 'https://storage.googleapis.com/muxdemofiles/mux-video-intro.mp4' }],
    playback_policy: ['public'],
  })
  .asResponse();
console.log(response.headers.get('X-My-Header'));
console.log(response.statusText); // access the underlying Response object

const { data: asset, response: raw } = await mux.video.assets
  .create({
    input: [{ url: 'https://storage.googleapis.com/muxdemofiles/mux-video-intro.mp4' }],
    playback_policy: ['public'],
  })
  .withResponse();
console.log(raw.headers.get('X-My-Header'));
console.log(asset.id);

Making custom/undocumented requests

This library is typed for convenient access to the documented API. If you need to access undocumented endpoints, params, or response properties, the library can still be used.

Undocumented endpoints

To make requests to undocumented endpoints, you can use client.get, client.post, and other HTTP verbs. Options on the client, such as retries, will be respected when making these requests.

await client.post('/some/path', {
  body: { some_prop: 'foo' },
  query: { some_query_arg: 'bar' },
});

Undocumented params

To make requests using undocumented parameters, you may use // @ts-expect-error on the undocumented parameter. This library doesn't validate at runtime that the request matches the type, so any extra values you send will be sent as-is.

client.foo.create({
  foo: 'my_param',
  bar: 12,
  // @ts-expect-error baz is not yet public
  baz: 'undocumented option',
});

For requests with the GET verb, any extra params will be in the query, all other requests will send the extra param in the body.

If you want to explicitly send an extra argument, you can do so with the query, body, and headers request options.

Undocumented properties

To access undocumented response properties, you may access the response object with // @ts-expect-error on the response object, or cast the response object to the requisite type. Like the request params, we do not validate or strip extra properties from the response from the API.

Customizing the fetch client

By default, this library uses node-fetch in Node, and expects a global fetch function in other environments.

If you would prefer to use a global, web-standards-compliant fetch function even in a Node environment, (for example, if you are running Node with --experimental-fetch or using NextJS which polyfills with undici), add the following import before your first import from "Mux":

// Tell TypeScript and the package to use the global web fetch instead of node-fetch.
// Note, despite the name, this does not add any polyfills, but expects them to be provided if needed.
import '@mux/mux-node/shims/web';
import Mux from '@mux/mux-node';

To do the inverse, add import "@mux/mux-node/shims/node" (which does import polyfills). This can also be useful if you are getting the wrong TypeScript types for Response (more details).

Logging and middleware

You may also provide a custom fetch function when instantiating the client, which can be used to inspect or alter the Request or Response before/after each request:

import { fetch } from 'undici'; // as one example
import Mux from '@mux/mux-node';

const client = new Mux({
  fetch: async (url: RequestInfo, init?: RequestInit): Promise<Response> => {
    console.log('About to make a request', url, init);
    const response = await fetch(url, init);
    console.log('Got response', response);
    return response;
  },
});

Note that if given a DEBUG=true environment variable, this library will log all requests and responses automatically. This is intended for debugging purposes only and may change in the future without notice.

Configuring an HTTP(S) Agent (e.g., for proxies)

By default, this library uses a stable agent for all http/https requests to reuse TCP connections, eliminating many TCP & TLS handshakes and shaving around 100ms off most requests.

If you would like to disable or customize this behavior, for example to use the API behind a proxy, you can pass an httpAgent which is used for all requests (be they http or https), for example:

import http from 'http';
import { HttpsProxyAgent } from 'https-proxy-agent';

// Configure the default for all requests:
const mux = new Mux({
  httpAgent: new HttpsProxyAgent(process.env.PROXY_URL),
});

// Override per-request:
await mux.video.assets.retrieve('t02rm...', {
  httpAgent: new http.Agent({ keepAlive: false }),
});

Semantic versioning

This package generally follows SemVer conventions, though certain backwards-incompatible changes may be released as minor versions:

  1. Changes that only affect static types, without breaking runtime behavior.
  2. Changes to library internals which are technically public but not intended or documented for external use. (Please open a GitHub issue to let us know if you are relying on such internals).
  3. Changes that we do not expect to impact the vast majority of users in practice.

We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.

We are keen for your feedback; please open an issue with questions, bugs, or suggestions.

Requirements

TypeScript >= 4.5 is supported.

The following runtimes are supported:

  • Node.js 18 LTS or later (non-EOL) versions.
  • Deno v1.28.0 or higher, using import Mux from "npm:@mux/mux-node".
  • Bun 1.0 or later.
  • Cloudflare Workers.
  • Vercel Edge Runtime.
  • Jest 28 or greater with the "node" environment ("jsdom" is not supported at this time).
  • Nitro v2.6 or greater.

Note that React Native is not supported at this time.

If you are interested in other runtime environments, please open or upvote an issue on GitHub.

mux-node-sdk's People

Contributors

alexdechaves avatar aminamos avatar davekiss avatar decepulis avatar dependabot[bot] avatar dylanjha avatar ebeloded avatar erikpena avatar eropple avatar fedetibaldo avatar iamkhushbajwa avatar iamvajid avatar jacob-israel-turner avatar jacquimanzi avatar jannikst avatar jaredsmith avatar jsanford8 avatar kevmo314 avatar luwes avatar mbrendel avatar mmcc avatar mmvsk avatar nemo avatar philcluff avatar radmen avatar reimertz avatar robertcraigie avatar snyk-bot avatar stainless-app[bot] avatar yukukotani avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mux-node-sdk's Issues

can't resolve `fs` in node_modules/@mux/mux-node/src/utils

Hi folks,
I'm trying to extend our CMS to integrate with Mux by creating a custom field that will allow an author to create a video asset.

I'm creating a custom JavaScript component in VueJS and I'm looking to take the public URL from the author and then client-side, generate the new video asset.

I have a JS method

        generateNewAsset() {
            console.log('kick off the new asset generation')
            const muxClient = new Mux(process.env.MIX_MUX_ACCESS_TOKEN, process.env.MIX_MUX_SECRET_KEY)
            console.log(muxClient)
        }

but running into

ERROR in ./node_modules/@mux/mux-node/src/utils/jwt.js
Module not found: Error: Can't resolve 'fs' in '/Users/stevengrant/Sites/ghijk/node_modules/@mux/mux-node/src/utils'
 @ ./node_modules/@mux/mux-node/src/utils/jwt.js 6:11-24
 @ ./node_modules/@mux/mux-node/src/mux.js

is this because the Node SDK is for server-side JS rather than client-side?

Any advice appreciated.

Deprecated api field: low_latency instead of latency_mode

Hello!

Small issue using 5.0.0-rc.5
According to the api documentation, this package types currently exposes outdated fields for livestreams creation.

We currently have to use these params in mux.LiveStreams.create method

low_latency: true,
playback_policy: 'public',
new_asset_settings: {
  playback_policy: 'public',
},

while it should probably be

latency_mode: 'low',
playback_policy: 'public',
new_asset_settings: {
  playback_policy: 'public',
},

I don't have much time right now to make a PR, so feel free to fix it before I do ;D

Have a great day

TypeScript types

Hey, looking forward to using Mux in my project. It would be great if TypeScript typings could either be provided with the module, or in an @types/@mux/mux-node package. You've done a great job with the JSDoc comments, hopefully there's an easy way to generate them from those.

invalid parameter when adding a token to a m3u8 url

Hello!
I am using "@mux/mux-node": "^3.1.0"

I am able to get a livestream and an assets video playback id just fine, but when I add a token query parameters has shown in the documentation

const token = Mux.JWT.sign('some-playback-id');
// https://stream.mux.com/some-playback-id.m3u8?token=${token}

(request then looks like this ```https://stream.mux.com/jqSQn4Vq3SmbRxGj9cZLEFJB7Eb00015jbYa3EY9dQE.m3u8?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlptZ....``

I get a the following error

{error: {messages: ["Invalid Parameters"], type: "invalid_parameters"}}

Mux with dotenv Error

Hi, I have a question about dotenv process on Mux.

I initialized a Video from new Mux. Previously, I hard coded 2 params with plain string. It worked successfully.

const { Video } = new Mux(
"my_token_id",
  "my_token_secret"
);

However, when I installed dotenv, added token_id and token_secret into .env file, and changed the code like following

// TODO : Not hard coded
const { Video } = new Mux(
  process.env.MUX_TOKEN_ID,
  process.env.MUX_TOKEN_SECRET
);

It popped up an error like below.
image

I printed the variables which turned out to be undefined.

However, in the same project, dotenv worked for other dependency like firestore.
image

How do I handle this error? Thanks a lot.

error : Mux is not a constructor

version : ^5.0.0-rc.5
error : Mux is not a constructor

import Mux from '@mux/mux-node';

const { Video } = new Mux(process.env.MUX_TOKEN_ID, process.env.MUX_TOKEN_SECRET);

Retrieve an Asset. [Video.Assets.get() Issue]

Hi,

I tried to retrieve an asset by asset_id. And I wanted to get several properties of that asset, like asset.playback_ids[0].id.

I was expecting no errors on asset.playback_ids[0].id. But it popped up like this.
image

So I try to print what happened in asset. When I print the asset in the console, I got that the asset is an object of Promise. I checked the source code for get method. It says it returns a resolved promise. Does it mean I am supposed to get a fulfilled promise, which means I can directly use asset.playback_ids[0].id ?

How do I handle this error? The codes are shown below.

  const [isUploading, setIsUploading] = useState(false);
  const [isPreparing, setIsPreparing] = useState(false);
  const [uploadId, setUploadId] = useState(null);
  const [progress, setProgress] = useState(null);
  const [errorMessage, setErrorMessage] = useState("");
  const inputRef = useRef(null);

  const [title, setTitle] = useState("");
  const [description, setDescription] = useState("");
  const [tags, setTags] = useState("");

  const { data, error } = useSwr(
    () => (isPreparing ? `/api/upload/${uploadId}` : null),
    fetcher,
    { refreshInterval: 5000 }
  );

  const getAsset = async () => {
    const asset = await Video.Assets.get(upload.asset_id);
    return asset;
  };

  const upload = data && data.upload;
  useEffect(() => {
    if (upload && upload.asset_id) {
      const colRef = collection(db, "Videos");
      // query from mux about duration, thumb_url, vid_url
      // asset's type is promise
      const asset = getAsset();

      asset.then(() => {
        console.log("asset: " + asset);
        addDoc(colRef, {
          description: description,
          tags: tags.split(","),
          title: title,
          duration: asset.duration,
          thumb_url: `https://image.mux.com/{asset.playback_ids[0].id}/thumbnail.{png|jpg}`,
          vid_asset_id: upload.asset_id,
          vid_playback_id: asset.playback_ids[0].id,
          vid_url: `https://stream.mux.com/{asset.playback_ids[0].id}.m3u8`, // playback url  : "https://stream.mux.com/{PLAYBACK_ID}.m3u8"
          vid_tier: "free",
          created_at: serverTimestamp()
        });
      });
    }
  }, [upload]);

TypeError: The superclass is not a constructor.

Code:

import Mux from '@mux/mux-node'

const { Video } = new Mux(token, secret)

Environment: VueJS (3.1.4), Vite (2.4.1)

Problem: The previous code always gives this error "TypeError: The superclass is not a constructor."

Does not work with Vite/Sveltekit

Error only occurs when running npm run build:

> Using @sveltejs/adapter-netlify
> Named export 'Webhooks' not found. The requested module '@mux/mux-node' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@mux/mux-node';
const { Webhooks } = pkg;

file:///Users/ben/dev/mux-node-esm-issue/.svelte-kit/output/server/app.js:4
import { Webhooks } from "@mux/mux-node";
         ^^^^^^^^
SyntaxError: Named export 'Webhooks' not found. The requested module '@mux/mux-node' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@mux/mux-node';
const { Webhooks } = pkg;

    at ModuleJob._instantiate (internal/modules/esm/module_job.js:97:21)
    at async ModuleJob.run (internal/modules/esm/module_job.js:142:20)
    at async Loader.import (internal/modules/esm/loader.js:182:24)
    at async prerender (file:///Users/ben/dev/mux-node-esm-issue/node_modules/@sveltejs/kit/dist/chunks/index6.js:80:14)
    at async Object.prerender (file:///Users/ben/dev/mux-node-esm-issue/node_modules/@sveltejs/kit/dist/chunks/index6.js:312:5)
    at async adapt (file:///Users/ben/dev/mux-node-esm-issue/node_modules/@sveltejs/adapter-netlify/index.js:34:4)
    at async adapt (file:///Users/ben/dev/mux-node-esm-issue/node_modules/@sveltejs/kit/dist/chunks/index6.js:338:2)
    at async file:///Users/ben/dev/mux-node-esm-issue/node_modules/@sveltejs/kit/dist/cli.js:887:5

adapter-netlify / SvelteKit are not recognising @mux/mux-node as an ESM package. This could be due to "type": "module" not being present in the package.json. Could also be that "main": "src/index.js" needs to be replaced with "exports": "src/index.js"

EDIT: Repro repo: https://github.com/benwoodward/mux-node-esm-issue (Run npm run build to see the error`)

JWT.sign expiration property is not well documented

We have been using the JWT utility to sign our secure URL tokens. Recently our thumbnails started disappearing. It turned out that expiration was not set in an expected format.

By reading this document, I assumed that expiration property is the same as exp on the JWT token, so I've been setting it to the UNIX epoch value of desired expiration date.

There was no errors during signing, so I didn't expect things to go awry.

After digging, I found that expiration on JWT.sign is passed to expiresIn on jsonwebtoken. expiresIn is clearly a better name and wouldn't have caused the issue.

May I suggest renaming the property to expiresIn to avoid this confusion for others and maybe add some JSDocs for the prop.

expiresIn in jsonwebtoken accepts value in vercel/ms format, which can be a number representing seconds, or a string. A string can be a number with units: "7d", "3h", etc. If a string is a number without units then it is considered to be ms. This is what happened in my case - I was providing stringified UNIX timestamp, which was turned into ms duration.

PS. I know that reference doc highlights that the default value is '7d' and if as much was mentioned in the docs or JSDocs, the problem could have been averted.

Mux is not a constructor

Hi all,
I am trying to implement this package in our API but I'm struggling to get it set up.
I am using the latest 5.0.0-rc.5 package and I see that there was a recent PR that should fix the issue but I'm stilling having problems (#144).

The code I am using is below:
const Mux = require('@mux/mux-node'); const accessToken = 'myaccesstoken'; const secret = 'mysecret'; const { Video } = new Mux(accessToken, secret);

And we are receiving the following error:
const { Video } = new Mux(accessToken, secret); ^ TypeError: Mux is not a constructor at Object.<anonymous>

I'm using Node.js v17.5.0.
If anyone could help that would be greatly appreciated.
Thanks!

Callback support

Currently, we support ES6 promises, but it would be nice to also allow for callback support.

Clipping length error

Hello,

When I try to clip an asset, i get this error:
Effective clip duration of $TIME too short, minimum clip duration is 5.000 seconds

but my input is
[{ url: ..., start_time: 0.4, end_time: 5.43, }];
so the length is 5.03

and the error is:
[invalid_parameters]:
Effective clip duration of 4.730 too short, minimum clip duration is 5.000 seconds

After some tests, it looks like there is an offset of 0.3s:

Start: 0.37
End: 5.43
length = 5.06
=> error: 4.760 (5.06 - 4.76 = 0.3)

Start: 0.33
End: 5.43
length = 5.1
=> error: 4.800 (5.1 - 4.8 = 0.3)

Start: 0.3
End: 5.43
length = 5.13
=> error: 4.830 (5.13 - 4.83 = 0.3)

Start: 0.27
End: 5.43
length = 5.16
=> error: 4.860 (5.16 - 4.86 = 0.3)

Expose JWT and Webhooks objects on instance

Hello! First of all, thanks for building the Node SDK! It's been very valuable for our team.

Would the team be ok with attaching the JWT and Webhooks objects to the mux instance? Currently, they're only available on the top-level class. It's fine, but was a little confusing when I was initially looking for the JWT object, as everything else we use has been on the instance itself. Seems like it would be a simple change - simply attach them within the constructor at initialization time, like we already do with Video and Data.

If the team would be ok with this, I'd be happy to put together a PR with the changes!

Incorrect typescript typings for 'Mux.JWT.sign()'

Currently the typings look like this:

export declare interface JWTOptions {
  keyId: string;
  keySecret: string;
  type: string;
  params?: any;
}

export declare class JWT {
  static sign(playbackId: string, options: JWTOptions): string;
}

All of the usage examples in the ReadMe (https://github.com/muxinc/mux-node-sdk#jwt-helpers-api-reference) cause typescript errors because:

  • the JWTOptions are not optional in the signature of the sign method
  • the keyId and the keySecret are not optional in the JWTOptions type

In addition JWTOptions do not contain the expiration parameter.

Suggested types:

export declare interface JWTOptions {
  type: string;
  keyId?: string;
  keySecret?: string;
  expiration?: string;
  params?: any;
}

export declare class JWT {
  static sign(playbackId: string, options?: JWTOptions): string;
}

`Video.Assets.create` doesn't just return asset anymore

I have the following code:

const asset = await Video.Assets.create({
  input: videoUrl,
  playback_policy: 'public',
})
console.info(asset)

While the type definition clearly indicates that Video.Assets.create would resolve to an asset object that looks like this:

{
  "status": "preparing",
  "playback_ids": [
    {
      "policy": "public",
      "id": "OHWwY9L00OoSNAQ7MrtDH00Gal4S01z7wyeszVLIThmbh00"
    }
  ],
  "mp4_support": "none",
  "master_access": "none",
  "id": "H4I300fePrcZs6lJ009m2vyeiLtojQ7u7FESR3CRf3tZY",
  "created_at": "1632108478"
}

Now it resolves to an object that looks like a HTTP response:

{
  "status": 201,
  "statusText": "Created",
  "headers": {
    ...
  },
  "config": {
    ...
  },
  "request": {
    ...
  },
  "data": {
    "data": {
      "status": "preparing",
      "playback_ids": [
        {
          "policy": "public",
          "id": "OHWwY9L00OoSNAQ7MrtDH00Gal4S01z7wyeszVLIThmbh00"
        }
      ],
      "mp4_support": "none",
      "master_access": "none",
      "id": "H4I300fePrcZs6lJ009m2vyeiLtojQ7u7FESR3CRf3tZY",
      "created_at": "1632108478"
    }
  }
}

I'm using @mux/mux-node v3.2.3.

Property SigningKeys does not exist on type Video

Looks like a small typing problem, in /node_modules/@mux/mux-node/types/mux.d.ts shows that the SigningKey isn't part of the typing for Video

export declare class Video extends Base {
  Assets: Assets;
  LiveStreams: LiveStreams;
  Uploads: Uploads;
  Metrics: Metrics;
}

But in /node_modules/@mux/mux-node/src/video/video.js SigningKeys is in the class defintion.

Direct Upload response changed without notice

So out of the blue, the structure of the response got updated for the direct upload endpoint.
No type changes are pushed or warnings were given. So I'm not sure if this change was intentional ?

The response object went from data: {...} to data: data: {...} on the direct upload endpoint.

image

Errors thrown are not instance of `Error` class

Though it may not be a major issue in integrating with mux, it would be nice if the errors thrown out from sdk are instances of native Error class. It means a lot to the developer experience

How to get the storage bucket for my mux file

Hi, I use mux for video streaming and have been running direct uploads from the client browsers to Mux using Upchunk until recently when I decided to revamp the flow.

So now, I upload to a Google Storage bucket before using Mux PULL-BASED approach to create an asset with a reference to the file on GCS as input. And it works really seamless.

// Create an asset
const asset = await Video.Assets.create({
  input: 'https://storage.googleapis.com/muxdemofiles/mux-video-intro.mp4',
});

Now I am trying to sync my files from Mux to my GCS bucket but don't want to use Google storage transfer service. I'm hoping that I can get a handle for my files on Mux storage bucket, GCS or S3, and use GCP's gsutil to copy the files to my storage bucket. Something like the this:

gsutil -h "Content-Type:video/mp4" -m cp gs://stream.mux.com/file-uuid/high.mp4 gs://mux-migration/video-files/-6mERHzSS-

Allow webhook creation via API

Any chance you could support creation of a Webhook via a new API given client id & secret?

Or perhaps an API to verify that a webhook exists for the given client?

Vulnerabilities in diverse dependencies

I ran yarn audit --level moderate in the package and a few vulnerabilities were found

───────────────┬──────────────────────────────────────────────────────────────┐
│ high          │ Remote Code Execution                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ serialize-javascript                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=3.1.0                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ mocha                                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ mocha > serialize-javascript                                 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://www.npmjs.com/advisories/1548                        │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ high          │ Server-Side Request Forgery                                  │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ axios                                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=0.21.1                                                     │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ axios                                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ axios                                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://www.npmjs.com/advisories/1594                        │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ moderate      │ Prototype Pollution                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ just-extend                                                  │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=4.0.0                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ sinon                                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ sinon > nise > just-extend                                   │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://www.npmjs.com/advisories/780                         │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ high          │ Insufficient Entropy                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ cryptiles                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=3.1.3 <4.0.0 || >=4.1.2                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ esdoc                                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ esdoc > ice-cap > cheerio > jsdom > request > hawk >         │
│               │ cryptiles                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://www.npmjs.com/advisories/720                         │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ high          │ Insufficient Entropy                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ cryptiles                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=3.1.3 <4.0.0 || >=4.1.2                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ esdoc-standard-plugin                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ esdoc-standard-plugin > esdoc-publish-html-plugin > ice-cap  │
│               │ > cheerio > jsdom > request > hawk > cryptiles               │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://www.npmjs.com/advisories/720                         │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ high          │ Insufficient Entropy                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ cryptiles                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=4.1.2                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ esdoc                                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ esdoc > ice-cap > cheerio > jsdom > request > hawk >         │
│               │ cryptiles                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://www.npmjs.com/advisories/1464                        │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ high          │ Insufficient Entropy                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ cryptiles                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=4.1.2                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ esdoc-standard-plugin                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ esdoc-standard-plugin > esdoc-publish-html-plugin > ice-cap  │
│               │ > cheerio > jsdom > request > hawk > cryptiles               │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://www.npmjs.com/advisories/1464                        │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ moderate      │ Regular Expression Denial of Service                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ marked                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=0.6.2                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ esdoc                                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ esdoc > marked                                               │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://www.npmjs.com/advisories/812                         │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ moderate      │ Regular Expression Denial of Service                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ marked                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=0.6.2                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ esdoc-standard-plugin                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ esdoc-standard-plugin > esdoc-publish-html-plugin > marked   │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://www.npmjs.com/advisories/812                         │
└───────────────┴──────────────────────────────────────────────────────────────┘

I believe that the highest priority would be to update axios since it's not a devDependency.

This is related to the MR #88

Firebase Deploy Error: "Mux is not a constructor"

I'm having an issue when trying to deploy code with the newest Mux version (3.0.2 -- using typescript types). Note: previous Mux versions (before Typescript support worked fine)

I'm deploying my code to Firebase's cloud functions via the firebase deploy --only functions command.

The code is able to build correctly without errors, but Firebase's deploy command will throw the following:

Error: Error occurred while parsing your function triggers.

TypeError: Mux is not a constructor
    at Object.<anonymous> (/mnt/l/projects/my_fb_project/backend/functions/lib/index.js:44:57)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Module.require (internal/modules/cjs/loader.js:692:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at /mnt/l/projects/my_fb_project/backend/functions/node_modules/firebase-tools/lib/triggerParser.js:15:15
    at Object.<anonymous> (/mnt/l/projects/my_fb_project/backend/functions/node_modules/firebase-tools/lib/triggerParser.js:53:3)

Best practices for tracking duplicate webhooks

I was wondering if there's an accepted way to handle duplicate hooks, currently I'm hashing the response data & storing that in Redis & checking against it to see if I've already handled a hook.

I'm just confused as there seems to be no identifier to say "these hooks were meant to do this action on this object" that we can use to check for duplicates, since each webhook/attempt has a unique identifier.

e.g. a video.asset.errored has happened twice in the same day on the same object - so they're not duplicate hooks, but have duplicate data. Maybe I'm missing something here - thanks in advance for any pointers.

Type of CreateAssetParams.input should not be required

CreateAssetParams interface requires 'input' to be defined.

This would break the example of direct upload in Mux Docs.

 const upload = await Video.Uploads.create({
    // Set the CORS origin to your application.
    cors_origin: 'https://your-app.com',

    // Specify the settings used to create the new Asset after
    // the upload is complete
    new_asset_settings: { // <- this is CreateAssetParams without input
      passthrough: id,
      playback_policy: 'public',
    }
  });

Property 'DeliveryUsage' does not exist on type 'Video'

Property 'DeliveryUsage' does not exist on type 'Video'

I get the above error when I try to get the delivery usage for a video by doing

const { Video } = new Mux(accessToken, secret);

Video.DeliveryUsage.list({timeframe: [startTime, endTime]}); // <--- linter picks the Error here

Missing `status` parameter for list live streams API

Summary

The list method from LiveStream has a ListParams interface, which doesn't include certain params mentioned in the Mux API docs

SDK interface:

export interface ListLiveStreamParams {
limit?: number;
page?: number;
live_stream_id?: string;
upload_id?: string;
}

From docs:
Screenshot 2022-05-03 at 10 45 16

Use case

TS compiler gives an error for use cases where live streams need to be filtered by status, since the parameters interface doesn't contain this key

The workaround that I'm doing at the moment is by asserting the whole object to ListParams, but it's not type-safe, or at least I could define a union for status and compose another interface on top of that but wouldn't be tied to the SDK

VideoAPI.LiveStreams.list({ status } as ListParams)

Expected behavior

Introduce status union type as a parameter for Live Stream filtering

No signatures found matching the expected signature for payload

Hello,

Mux webhook signature validation does not appear to be working for my Node/express service, or it's possible I am making a mistake somewhere! I am following the webhook validation guide on Mux GitHub for Node SDK. Here is my controller that Mux is successfully invoking in the development environment.

const { Webhooks } = Mux
const webhook = asyncHandler(async (req: Request, res: Response) => {
  try {
    console.log(`Mux Signature is ${req.headers['mux-signature']}`)
    console.log(`Mux body is ${JSON.stringify(req.body)}`)
    console.log(`MUX_WEBHOOK_SECRET is ${MUX_WEBHOOK_SECRET}`)
    const sig = req.headers['mux-signature'] as string
    Webhooks.verifyHeader(req.body, sig, MUX_WEBHOOK_SECRET)
    const jsonFormattedBody = JSON.parse(req.body)
    if (jsonFormattedBody.type === 'video.asset.ready') {
      await VideoModel.findOneAndUpdate(req.body.data.passthrough, { assetId: req.body.data.id })
    }
  } catch (err: any) {
    return res.status(400).send(`Webhook Error: ${err.message}`)
  }
  return res.status(200).json({ success: true, data: {} })
})
export { webhook }

Here is the server output

Mux Signature is t=1652463851,v1=af3d5ae111b82be67addcc5f8b559ea22ac38f5cbde9a9557e5f878c7db9c424

MUX_WEBHOOK_SECRET is <>

Mux body is {"type":"video.upload.created","request_id":null,"object":{"type":"upload","id":"i024lBXuvCcaaTyOx6m5f4jFsnRaurpvSVvV3tHDkIjg"},"id":"4821381f-1caa-475e-a12f-923e3209249e","environment":{"name":"Development","id":"fodthr"},"data":{"url":"https://storage.googleapis.com/video-storage-us-east1-uploads/i024lBXuvCcaaTyOx6m5f4jFsnRaurpvSVvV3tHDkIjg?Expires=1652466970&GoogleAccessId=direct-uploads-writer-prod%40mux-cloud.iam.gserviceaccount.com&Signature=ZqZvwIAtPZVe82q4BZ6I0uU6Y7RSZM3nwxX79akZ7aO88nV8qh4u8CXv3rLCeb4JpZgz2RlH0hzlHRgP%2B482eVGPkkVOJsae9gSjwt2oW5hof3zOaZaosbb9xtw3D0ru5Fgf2H1BauYcdKCQT8cWXG2QAvjMkQHjuMe7af7oCEh66kadWf1%2FJcaajsEUWpa1xtromKNjU3xBijHnbhatYbZvpKo3CwUJawB%2FleoK4VFGGOycy5fJazmhsCge%2F1REmxOmqJNPifmKANio2laOhjjn%2F8J5zkouaVQqXPCpCn1%2BP7aK%2BZtS3y817r1mbeC9UsROqeAsWYwVoZm5TrGrvw%3D%3D&upload_id=ADPycduPCfUilP-wNV37M7d6vh27oLhe8dWlk8z_XDTrCjIyjX8fbPPrulcmVwzDCVIP_9S5Oqc4AeKOsRD-yA9ybohjgg","timeout":3600,"status":"waiting","new_asset_settings":{"playback_policies":["public"],"passthrough":"5fa96044-3b80-4bc2-bb10-93eb863de173"},"id":"i024lBXuvCcaaTyOx6m5f4jFsnRaurpvSVvV3tHDkIjg"},"created_at":"2022-05-13T17:36:11.000000Z","attempts":[{"webhook_id":24494,"response_status_code":400,"response_headers":{"x-powered-by":"Express","vary":"Origin","ngrok-trace-id":"287a6d40cd33981fdef9fa911f77c0c8","etag":"W/\"4f-DkfDr22GwbEWIl8UeufGfjqzZqA\"","date":"Fri, 13 May 2022 17:36:11 GMT","content-type":"text/html; charset=utf-8","content-length":"79","access-control-allow-credentials":"true"},"response_body":"Webhook Error: No signatures found matching the expected signature for payload.","max_attempts":30,"id":"3be4550f-95af-4d9d-8483-5dd75df1c731","created_at":"2022-05-13T17:36:11.000000Z","address":"https://0a1d-2600-1700-23d2-3200-9c75-d8fd-e17b-6ba7.ngrok.io/api/v1/mux"},{"webhook_id":24494,"response_status_code":400,"response_headers":{"x-powered-by":"Express","vary":"Origin","ngrok-trace-id":"e9a9417c413cd6381db2783284b70478","etag":"W/\"4f-DkfDr22GwbEWIl8UeufGfjqzZqA\"","date":"Fri, 13 May 2022 17:38:11 GMT","content-type":"text/html; charset=utf-8","content-length":"79","access-control-allow-credentials":"true"},"response_body":"Webhook Error: No signatures found matching the expected signature for payload.","max_attempts":30,"id":"0fa168cb-910d-42ee-ab2f-b99fce2b2faa","created_at":"2022-05-13T17:38:11.000000Z","address":"https://0a1d-2600-1700-23d2-3200-9c75-d8fd-e17b-6ba7.ngrok.io/api/v1/mux"},{"webhook_id":24494,"response_status_code":400,"response_headers":{"x-powered-by":"Express","vary":"Origin","ngrok-trace-id":"3cd8e0f17ebe84f696f10425b7d988ea","etag":"W/\"4f-DkfDr22GwbEWIl8UeufGfjqzZqA\"","date":"Fri, 13 May 2022 17:40:11 GMT","content-type":"text/html; charset=utf-8","content-length":"79","access-control-allow-credentials":"true"},"response_body":"Webhook Error: No signatures found matching the expected signature for payload.","max_attempts":30,"id":"b53da5b3-51fe-4f4d-9e21-e4228218bf9e","created_at":"2022-05-13T17:40:11.000000Z","address":"https://0a1d-2600-1700-23d2-3200-9c75-d8fd-e17b-6ba7.ngrok.io/api/v1/mux"}],"accessor_source":null,"accessor":null}

My web server is returning a 400 Bad Request to Mux with the following error:

""Webhook Error: No signatures found matching the expected signature for payload.""

Do you have any tips for how to troubleshoot this further?

Thank you.

Maximum number of filters for the requested metric is 0

Trying to use filters when on the 'Starter' MUX data tier returns the following error:

maximum number of filters for the requested metric is 0

        const data = await mux.connection.Data.Metrics.breakdown('views', {
          group_by: 'video_id',
          timeframe: [start.toString(), end.toString()],
          measurement: 'count',
          filters: [`video_id:${primary._id}`]
        });

Is this because of the pricing tier not having filters? I know this isn't the repo to raise since it's an issue with the internal API, but having something that at-least hints to the fact that a higher tier is required for filtering would be useful.

image

Env file in NPM package

Hey folks,

I've noticed that the npm package holds .env-dylan file with MUX tokens. It's not in the repo so I guess it got there during the packaging. Should it be there? :)

Steps to reproduce:

$ npm i @mux/mux-node
$ ls -lah node_modules/@mux/mux-node/
total 48K
drwxr-xr-x 3 radmen radmen 4,0K 04-30 10:53 .
drwxr-xr-x 3 radmen radmen 4,0K 04-30 10:53 ..
-rw-r--r-- 1 radmen radmen 2,1K 1985-10-26  CHANGELOG.md
-rw-r--r-- 1 radmen radmen  143 1985-10-26  .env-dylan
-rw-r--r-- 1 radmen radmen 1,2K 1985-10-26  .esdoc.json
-rw-r--r-- 1 radmen radmen 1,1K 1985-10-26  LICENSE
-rw-r--r-- 1 radmen radmen 2,4K 04-30 10:53 package.json
-rw-r--r-- 1 radmen radmen 8,8K 1985-10-26  README.md
drwxr-xr-x 6 radmen radmen 4,0K 04-30 10:53 src
-rw-r--r-- 1 radmen radmen  267 1985-10-26  .travis.yml

[Feature Request] Add /video/v1/live-streams/$id/events to library

This request is to add the /video/v1/live-streams/$id/events API to the the library. This endpoint can be curled today, but is not part of the node library.

Example curl (requies passing token):

curl https://api.mux.com/video/v1/live-streams/$id/events?limit=10 \
  -X GET \
  -u {MUX_TOKEN_ID}:{MUX_TOKEN_SECRET}

[Bug] Type is wrong for Asset type

On the Asset interface, the max_stored_resolution? is defined as 'Audio-only' | 'SD' | 'HD' | 'FHD' | 'UHD'. In practice, the Mux API returns Audio only (no -).

I think the fix for this would just be to change the definition in Asset.ts to reflect what's being returned from your API in practice, but I wanted to open as an issue first to confirm that this is in fact a bug.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.