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

slideshow-video

v1.0.2

Published

NodeJS and FFmpeg powered automated creation of video slideshows from input images. Fully automatic, no manual editing required.

Downloads

62

Readme

documentation-page npm-version npm-downloads discord hit-count

ExamplesProject BoardReport BugRequest FeatureReleases


Table of Contents

About The Project

This tool uses ffmpeg to automatically create slideshow videos from images. Cross-platform support is ensured, and it comes bundled with ffmpeg and ffprobe binaries. The goal of this tool is to automate the creation of slideshow videos, so you don't have to manually tailor settings for every run.

  • Different image dimensions?
  • Different image counts?
  • Different audio durations?
  • Loop video if audio duration permits?
  • Loop audio if image count permits?

No problem, configure your settings once and let the tool do the rest.

The main inspiration for this tool is automated creation of videos from TikTok slideshows. With those you never know how many images there will be, what their dimensions will be, and how long the audio will be, etc. This tool can reliably and automatically create videos from them.
This is my first TypeScript project and npm package, feel free to tell me what I'm doing wrong or could be doing better.

Installation & Usage

Install the package from npm:

npm install slideshow-video

Then simply use it in your code:
(in reality you probably want to await, I just used .then() better compatibility (top level await is a bit iffy to setup))

Basic example with all default settings

import { createSlideshow } from 'slideshow-video';
// or in commonjs
// const { createSlideshow } = require('slideshow-video');

const images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
const audio = 'audio.mp3';

createSlideshow(images, audio).then(console.log);

Advanced example with options

Showcase of some of the available options, and ability to pass in image objects with specific options. See the documentation for more information about all the options.

const options = {
    imageOptions: {
        imageDuration: 5000,
        imageResizeDimensions: { width: 500 }
    },
    loopingOptions: {
        loopImages: 'auto',
        imageLoopThreshold: 'all',
    },
    transitionOptions: {
        imageTransition: 'smoothleft',
        loopTransition: 'fadeslow',
    },
    ffmpegOptions: {
        showFfmpegOutput: false,
        showFfmpegCommand: true,
        fps: 50,
        streamCopyAudio: true,
        videoCodec: 'libx264',
        x264Preset: 'ultrafast'
    },
    outputOptions: {
        outputBuffer: false,
        outputDir: '../my-out-folder'
    }
};

const imagesWithOptions = [
    {
        filePath: 'image1.jpg',
        duration: 1500,
        transitionDuration: 700
    },
    {
        buffer: Buffer.from(something),
        transition: 'circleclose'
    },
    {
        filePath: 'image3.jpg'
    }
];

createSlideshow(imagesWithOptions, audio, options).then(console.log);

Features

  • Automatic creation of a slideshow video from images
  • Add audio to the video
  • Local file paths or buffers
  • Automatic and configurable resizing of images
  • Configurable transitions between images
  • Global and/or per image configurable options
  • Automatically detect if image or audio looping is needed, configurable
  • Support for stream copying and concat muxing for very low system resource usage and fast encoding
  • Configurable FFmpeg options, output in any video format
  • Output to file or buffer

Documentation

Full documentation is hosted on the documentation site.

Documentation for the main function, createSlideshow, is also available below.

createSlideshow

createSlideshow(images, audio?, options?): Promise<Partial<SlideshowResponse>>

Brains of the operation, entrypoint to this whole package.

Takes in images, audio, and options from which it automatically creates a slideshow video.

If images are provided as an InputImage array, per image options can be specified. Per image options override options specified in the 3rd parameter. For example:

const images: InputImage[] = [
    {
        buffer: Buffer.from(myImage),
        duration: 5000
    },
    {
        filePath: 'image2.jpg',
        transition: 'dissolve',
        transitionDuration: 200
    },
    {
        filePath: '../../../documents/image3.png'
    }
];

const options: SlideshowOptions = {
    imageOptions: {
        imageDuration: 3500
    },
    transitionOptions: {
        transitionDuration: 500
    }
};

const response = await createSlideshow(images, './music/audio.mp3', options);

The three input images broken down:

First image, buffer input, overrides duration

  • Has a duration of 5000ms
  • 500ms transition (specified in options object) to the next image with the default transition (slideleft)

Second image, file path input, overrides transition and transition duration

  • Has a duration of 3500ms, specified in the options object
  • 200 ms transition to the next image with the dissolve transition

Third image, file path input, uses default options

  • Has a duration of 3500ms, specified in the options object
  • Will have no normal transition as it's the last image
  • Might have a 500ms loop transition (by default pixelize), if image and audio durations permit it
  • See remarks section for more about durations and looping

Remarks

Duration and looping

Possible total duration for one loop of images consist of the following:

Audio duration is simply just the duration of the audio.

Image Looping

Image looping is enabled by setting LoopingOptions.loopImages to "auto". It is set to "never" by default. "auto" means that the images will start looping if duration and threshold conditions are met.

For example:

| | Image 1 | Image 2 | Image 3 | Audio | |------------|:-------:|:-------:|:-----------------:|:------:| | Duration | 3.5 s | 4 sec | 3.5 sec | 21 sec | | Transition | 500 ms | 300 ms | 250 ms (if loop) | - |

So we have a total image duration of 11.8 sec + 250 ms loop transition (if a loop occurs) And a total audio duration of 21 sec.

We have no last image extra duration, and a default end of input threshold of 3.5 sec (last image's duration). And LoopingOptions.imageLoopThreshold is at its default value "all".

After the images have played once, 21 - 11.8 = 9.2 sec of audio is left.

Our imageLoopThreshold is set to "all", so all images will need to fit inside a loop for a loop to occur. We only have 9.2 sec of audio left, and full loop of images will take 12.05 sec, so no loop will be created? No, actually a loop will be created due to our end of input threshold being 3.5 sec. This means we are allowed 9.2 + 3.5 = 12.7 secs for a new loop.

Ok, new lets say our end of input threshold is set to 2000 (2 sec) instead. Now we only have 9.2 + 2 = 11.2 secs for a new loop. And a full loop of images will take 12.05 sec, so no loop will be created.

But let's also change our image loop threshold from "all" to 1. This means that only one image needs to fit inside a loop for a loop to occur. And our first image is 3.5 sec long, so a loop will be created. After the first image has been added to the loop looped, we have 11.2 - (3.5 + 0.25) = 7.45 secs left. The second image is 4 sec long, so it will also be inserted into the loop. Now we have 7.45 - (4 + 0.5) = 2.95 secs left. Inserting the third image would require 3.75 secs, so it will not be inserted into the second loop and the second loop, and whole slideshow, ends.

Now lets say we have a last image extra duration of 3 sec. This means that the last image of a full loop will be extended by 3 sec. And now we wouldn't again have space for the second image, so the second loop would only contain one image.

You can run this example as code from the examples folder.

npx ts-node examples/duration-looping.ts

Audio Looping

Audio looping works in a similar way to image looping, but it's a bit simpler. And of course, the logic is inverted in the sense that we are checking how much video duration time we have left for a new loop of the audio track. The end of input threshold is also considered, just as it was for image looping.

For audio looping, LoopingOptions.audioLoopThreshold, which defaults to 0, exists. It specifies the amount of milliseconds that need to fit inside a loop for an audio loop to occur. Alternatively it can be set to "all", which means that the whole audio track needs to fit into a loop for a loop to occur.

See

SlideshowOptions for more information about the options object
InputImage for more information about per image options

Parameters

| Name | Type | Description | | :------ | :------ | :------ | | images | string[] | Buffer[] | InputImage[] | Images to be used in the slideshow. Either a file path, buffer, or an InputImage | | audio? | string | Buffer | Audio to be used in the slideshow. Either a file path or buffer. Can be undefined, so the slideshow will have no audio | | options? | SlideshowOptions | Options object to configure the slideshow creation |

Returns

Promise<Partial<SlideshowResponse>>

A promise that resolves to a partial SlideshowResponse object. Available fields in the response object depend on what was specified in OutputOptions. By default, only a buffer of the resulting slideshow video is returned.

Examples

You can find examples about the usage of this library in the examples folder.
If you use this for something and want it to be shown here an example, I'd be glad to add it!

Optimization & System Requirements

Video encoding is a very CPU/memory intensive task. FFmpeg will suck back as much memory as it needs to complete its task. If memory runs out, FFmpeg probably gets killed by the OS. However, it's possible to use very little memory.

To optimize memory usage, consider the following:

  • Never run parallel slideshow creations
  • Don't use an unnecessarily high resolution
  • Transitions will use a lot of memory compared to not using them
  • Use 'libx264' or some other easy to encode codec
  • Use a fast x264 preset (if using x264)

Example memory usages with 26 images at 1284x1350 resolution, no image looping, audio loops once, ran on my local machine WSL2:

  • Transitions enabled, no resolution scaling, default x264 preset (medium)
    • 3.8 GB memory usage
  • Transitions enabled, no resolution scaling, ultrafast x264 preset
    • 3.24 GB memory usage
  • Transition enabled, scaled to 500px height, ultrafast x264 preset
    • 568 MB memory usage
  • Transitions disabled, no resolution scaling, ultrafast x264 preset
    • 420 MB memory usage
  • Transitions disabled, scaled to 500px height, ultrafast x264 preset
    • 283 MB memory usage

Support & Requests

Please report any issues you find on the issues page.
You can also join the discord server I just created to ask questions or request features or whatever.

Comparison with videoshow

videoshow is another npm package that generate slideshow videos.
It's very old, unmaintained, and didn't have some of the features I wanted, so I made this package.

Let's compare the two packages:
Yes, I'm obviously biased, but all the points are factual as far as I know

| Feature | slideshow-video | videoshow | Notes | |--------------------------------|:---------------:|:---------:|-----------------------------------------------------------------------------------------------------| | Currently maintained | ✅ | ❌ | | | Usable fully automatically | ✅ | ❌ | videoshow can't function if you don't control whatwill be passed into it (unless you get lucky) | | Included cross-platform FFmpeg | ✅ | ❌ | with videoshow, you have to install and configure ffmpeg manually | | Promise support | ✅ | ❌ | | | TypeScript support | ✅ | ❌ | | | Buffer support | ✅ | ❌ | | | Transitions | ✅ | 🟡 | Only one transition available vs 50 in slideshow-video | | Per image config | ✅ | ✅ | | | Support mixed image dimensions | ✅ | ❌ | In videoshow, all input images must have same the dimensions | | Image/audio looping | ✅ | ❌ | | | Configurable FFmpeg options | ✅ | ✅ | | | Output to buffer | ✅ | ❌ | | | CLI interface | ❌ | ✅ | Planned feature for slideshow-video | | Logo support | ❌ | ✅ | | | Subtitles support | ❌ | ✅ | | | Custom FFmpeg filters support | ❌ | ✅ | |