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 🙏

© 2024 – Pkg Stats / Ryan Hefner

plugin-adaptive-bitrate-videos

v1.0.5

Published

Payload plugin for automatic adaptive bitrate process of videos.

Downloads

396

Readme

Payload Adaptive Bitrate Videos Plugin

This plugin extends Payload CMS to provide Adaptive Bitrate (ABR) streaming capabilities for uploaded video files. It automatically processes video uploads, creates segment playlists for multiple resolution versions, generates HLS manifests, and updates the collection with the master manifest file location.

Features

  • Automatic video processing on upload
  • Multiple resolution transcoding (144p to 4K, define custom sizes/bitrates)
  • HLS playlist and master manifest generation
  • Flexible storage integration (Local, AWS S3, Google Cloud Storage, Azure Blob Storage)

Installation

yarn add plugin-adaptive-bitrate-videos  or  npm install plugin-adaptive-bitrate-videos

Usage

Add this package into your dependencies executing this code in your command line:

yarn add plugin-adaptive-bitrate-videos

Now install this plugin within your Payload as follows:

//payload.config.ts
import { buildConfig } from 'payload/config'
import path from 'path'
import { adaptiveBirateVideos } from 'plugin-adaptive-bitrate-videos`'

export default buildConfig({
  serverUrl: 'https://example.com' // Must be set to use pluggin
  plugins: [
    adaptiveBirateVideos({
      collections: {
        'my-collection-slug': {keepOrginal: true}
      }
    })
  ]
  // The rest of your config goes here
})

See Payload config options for documentation on setting serverUrl in Payload config.

Cloud Storage Plugin

This plugin can be used with the Payload Cloud Storage Plugin to store you segments and manifest files. cloudStorage is CollectionOptions object from Payload Cloud Plugin Collection specific options.

//payload.config.ts
import { buildConfig } from 'payload/config'
import path from 'path'
import { adaptiveBirateVideos } from 'plugin-adaptive-bitrate-videos'
import { gcsAdapter } from '@payloadcms/plugin-cloud-storage/gcs'

const adapter = gcsAdapter({
  options: {
    // you can choose any method for authentication, and authorization which is being provided by `@google-cloud/storage`
    keyFilename: './gcs-credentials.json',
    //OR
    credentials: JSON.parse(process.env.GCS_CREDENTIALS || '{}'), // this env variable will have stringify version of your credentials.json file
  },
  bucket: process.env.GCS_BUCKET,
})
// Now you can pass this adapter to the plugin

export default buildConfig({
  serverUrl: 'https://example.com' // Must be set to use plugin
  plugins: [
    adaptiveBirateVideos({
      collections: {
        // The collection users upload source videos to
        'my-collection-slug': {keepOriginal: true}
      }
    }),
    cloudStorage({ // Cloud storage plugin must come after plugin
      collections: {
        // The collection users upload source videos to
        'my-collection-slug': {
          // see docs for the adapter you want to use
          adapter: adapter,
        },
        // the output collection created by the plugin
        'segments': { // Required name 'segments' unless overridden in segmentsOverride
          adapter: adapter,
        },
      },
    }),
  ]
  // The rest of your config goes here
})

Custom Sizes And Bitrates

If not resolutions array is provide, the plugin will use the default resolutions and bit rates. size specifies the pixel size of the short side of the video so the aspect ratio of any input video is maintained.

For Example: if you input a 4k 16:9 video (The standard landscape video aspect ratio), the plugin will change the video's height to and allow the width to proportionally change.

For the 1080 output the resulting video will be 1080p x 1920p, the standard 1080p pixel size.

The principle is followed for square and portrait videos.

Note: The plugin will only output segments for resolutions that are less than or equal to the short side of the video. Meaning no upscaling is conducted. Example: a 1080p video will only produce output segments at resolutions that are specifed less than or eqaul to 1080.

//payload.config.ts
import { buildConfig } from 'payload/config'
import path from 'path'
import { adaptiveBirateVideos } from 'plugin-adaptive-bitrate-videos`'

export default buildConfig({
  serverUrl: 'https://example.com' // Must be set to use pluggin
  plugins: [
    adaptiveBirateVideos({
      collections: {
        'my-collection-slug':{
          keepOriginal: true,
          resolutions: [
            {
              size: 1080 // pixel size
              bitrate: 4000 // kilobits per second
            },
            // ...more custom resolutions
          ]
        }
      }
    })
  ]
  // The rest of your config goes here
})

Conditionally Enabling/Disabling

The proper way to conditionally enable/disable this plugin is to use the enabled property.

//payload.config.ts
adaptiveBirateVideos({
  enabled: process.env.MY_CONDITION === 'true',
  collections: {
    'media': {keepOrginal: true}
  }
}),

If the code is included in any way in your config but conditionally disabled in another fashion, you may run into issues such as Webpack Build Error: Can't Resolve 'fs' and 'stream' or similar because the plugin must be run at all times in order to properly extend the webpack config.

Segments Collection Override

Override anything on the segments collection by sending a Payload Collection Config to the segmentsOverrides property.

// payload.config.ts
adaptiveBirateVideos({
  // ...
  segmentOverrides: {
    slug: "contact-forms",
    access: {
      read: () => true,
      update: () => false,
    },
    fields: [
    {
      name: "custom-field",
      type: "text"
    }]
  }
})

Custom Segment Length

Optionally set the length of the segments the source video will be divided into. Default length is 2 seconds. The property takes in an number representing seconds.

// payload.config.ts
adaptiveBirateVideos({
  // ...
  segmentLength: 5 //seconds. Default is 2 seconds.
})

Plugin options

This plugin is configurable to work across many different Payload collections. A * denotes that the property is required.

| Option | Type | Description | | ------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | collections* | Records<string,CollectionOptions> | Object with keys set to the slug of collections you want to enable the plugin for, and values set to collection-specific options. | | enabled | boolean | Conditionally enable/disable plugin. Default: true. | | segmentsOverrides | PayloadCollectionConfig | Object that overrides the default collection used to store reference to the output segments. Default: SegmentOverrideDefault |

Collection-specific options:

| Option | Type | Description | | --------------- | ------------------- | ---------------------------------------------------------------------------------------------- | | keepOriginal* | boolean | Conditionally set to keep the original source file after processing. | | resolutions | Array<Resolution> | Set custom resolutions for the plugin to output segment videos to. Default: ResolutionsDefault | | segmentLength | number | Set the output segment length in seconds for each resolution output. Default: 2 |

SegmentOverrideDefault

const SegmentOverrideDefault = {
  slug: "segments",
  labels: { singular: 'ABR Segment', plural: 'ABR Segments' },
  access: {
    read: () => true,
    update: () => false,
  },
  upload: true,
  fields: []
}

ResolutionsDefault

const DefaultResolutions = [
    { size: 144, bitrate: 150 },
    { size: 240, bitrate: 250 },
    { size: 360, bitrate: 500 },
    { size: 480, bitrate: 1000 },
    { size: 720, bitrate: 1500 },
    { size: 1080, bitrate: 4000 },
    { size: 1440, bitrate: 6000 },
    { size: 2160, bitrate: 10000 },

]

Example Front-end Usage

Any video player that can play .m3u8 files can be used. Here is a simple example using the react-hls-video-player. View docs for react-hls-video-player here.

import React, { useRef, useState } from 'react';
import ReactHlsPlayer from 'react-hls-video-player';

const SimpleHlsPlayer = () => {
  const playerRef = useRef(null);
  const [isPlaying, setIsPlaying] = useState(false);

  const handlePlay = () => {
    setIsPlaying(true);
  };

  const handlePause = () => {
    setIsPlaying(false);
  };

  return (
    <div className="w-full max-w-2xl mx-auto">
      <ReactHlsPlayer
        id="videoElement"
        playerRef={playerRef}
        src="https://example.com/path/to/your/manifest.m3u8"
        className="w-full aspect-video"
        autoPlay={false}
        controls={true}
        onPlay={handlePlay}
        onPause={handlePause}
        muted
        playsInline
      />
      <div className="mt-4 text-center">
        <p>Player status: {isPlaying ? 'Playing' : 'Paused'}</p>
      </div>
    </div>
  );
};

export default SimpleHlsPlayer;

Memory Considerations

To run the this plugin, you will need to run your Payload server on a machine that can comfortably storage 2x the max video upload size.

This is required because the source video needs to be temporally stored and the output segments need to be temporally stored before being saved in your final destination.

See Payload Documentation on settingupload limits here.

Questions

Please open an issue on this repo with any questions or issues about using this plugin.