Skip to content
Slick, declarative command line video editing
JavaScript GLSL
Branch: master
Clone or download

Latest commit

Latest commit d4bd8fe May 20, 2020


Type Name Latest commit message Commit time
Failed to load latest commit information.
.github add funding Apr 24, 2020
examples Make it easier to disable zoom direciton #31 May 2, 2020
shaders initial Apr 16, 2020
sources Make it easier to disable zoom direciton #31 May 2, 2020
.eslintrc initial Apr 16, 2020
.gitignore add output to igonre Apr 24, 2020
LICENSE Initial commit Apr 15, 2020 fix doc typos May 19, 2020
cli.js works Apr 29, 2020
colors.js initial Apr 16, 2020
glTransitions.js check for GL #29 Apr 30, 2020
index.js Add initial file exist checks #39 May 17, 2020
package.json 0.3.0 Apr 30, 2020
transitions.js default duration to 0 Apr 25, 2020
util.js allow settings ffmpegpath Apr 30, 2020

editly 🏄‍♀️


This GIF / YouTube was created with this command: "editly commonFeatures.json5". See more examples here.

Editly is a tool and framework for declarative NLE (non-linear video editing) using Node.js and ffmpeg. Editly allows you to easily and programmatically create a video from a set of clips, images and titles, with smooth transitions and music overlaid.

Editly has a simple CLI for quickly assembling a video from a set of clips or images, or you can use its more flexible JavaScript API.

Inspired by ffmpeg-concat, editly is much faster and doesn't require much storage because it uses streaming editing. Editly aims to be very extensible and feature rich with a pluggable interface for adding new dynamic content.


  • Edit videos with code! Declarative API with fun defaults
  • Create colorful videos with random colors generated from aesthetically pleasing palettes and random effects
  • Supports any input size, e.g. 4K video and DSLR photos
  • Can output to any dimensions and aspect ratio, e.g. Instagram post (1:1), Instagram story (9:16), YouTube (16:9), or any other dimensions you like.
  • Content is scaled and letterboxed automatically, even if the input aspect ratio is not the same and the framerate will be converted.
  • Speed up / slow down videos automatically to match the cutFrom/cutTo segment length with each clip's duration
  • Overlay text and subtitles on videos, images or backgrounds
  • Accepts custom HTML5 Canvas / Fabric.js JavaScript code for custom screens or dynamic overlays
  • Render custom GL shaders (for example from shadertoy)
  • Can output GIF

Use cases

  • Create a slideshow from a set of pictures with text overlay
  • Create a fast-paced trailer or promo video
  • Create a tutorial video with help text
  • Simply convert a video to a GIF
  • Resize video to any size or framerate and with automatic letterboxing/cropping (e.g. if you need to upload a video somewhere but the site complains Video must be 1337x1000 30fps)

See examples


Make sure you have ffmpeg and ffprobe installed and available in PATH


npm i -g editly

Usage: Command line video editor

Run editly --help for usage

Create a simple randomized video edit from videos, images and text with an audio track:

editly \
  title:'My video' \ \ \
  title:'My slideshow' \
  img1.jpg \
  img2.jpg \
  title:'THE END' \
  --fast \
  --audio-file-path /path/to/music.mp3

Or create an MP4 (or GIF) from a JSON or JSON5 edit spec (JSON5 is just a more friendly JSON format):

editly my-editly.json5 --fast --out output.gif

For examples of how to make a JSON edit spec, see below or

When you run with --fast or fast: true, it will render a much quicker low-resolution preview

Without --fast it will default to using the width, height and frame rate from the first input video. All other clips will be converted to these dimensions. You can of course override any or all of these parameters.

TIP: Use this tool in conjunction with LosslessCut

TIP: If you need catchy music for your video, have a look at this YouTube or the YouTube audio library. Then use youtube-dl to download the video, and then point --audio-file-path at the video file. Be sure to respect their license!

JavaScript library

const editly = require('editly');

// See editSpec documentation
await editly(editSpec)

Edit spec

Edit specs are JavaScript / JSON objects describing the whole edit operation with the following structure:

  defaults: {
    duration: 4,
    transition: {
      duration: 0.5,
      name: 'random',
    layer: {
      // ...more layer defaults
  clips: [
      layers: [
          // ...more layer-specific options
        // ...more layers
    // ...more clips

  // Testing options:
  enableFfmpegLog: false,
  verbose: false,
  fast: false,


Parameter CLI equivalent Description Default
outPath --out Output path (mp4, mkv), can also be a .gif
width --width Width which all media will be converted to 640
height --height Height which all media will be converted to auto based on width and aspect ratio of first video
fps --fps FPS which all videos will be converted to First video FPS or 25
audioFilePath --audio-file-path Set an audio track to the whole output video
fast --fast, -f Fast mode (low resolution and FPS, useful for getting a quick preview) false
defaults.layer.fontPath --font-path Set default font to a .ttf System font
defaults.layer.* Set any layer parameter that all layers will inherit
defaults.duration --clip-duration Set default clip duration for clips that don't have an own duration 4 sec
defaults.transition An object { name, duration } describing the default transition. Set to null to disable transitions
defaults.transition.duration --transition-duration Default transition duration 0.5 sec --transition-name Default transition type. See Transition types random
clips[] List of clip objects that will be concatenated in sequence
clips[].duration Clip duration. See defaults.duration defaults.duration
clips[].transition Specify transition at the end of this clip. See defaults.transition defaults.transition
clips[].layers[] List of layers within the current clip that will be overlaid in their natural order (last layer on top)
clips[].layers[].type Layer type, see below

Transition types can be any of gl-transitions, or any of the following: directional-left, directional-right, directional-up, directional-down and random.

Layer types

See examples and commonFeatures.json5

Layer type 'video'

For video layers, if parent clip.duration is specified, the video will be slowed/sped-up to match clip.duration. If cutFrom/cutTo is set, the resulting segment (cutTo-cutFrom) will be slowed/sped-up to fit clip.duration.

Parameter Description Default
path Path to video file
resizeMode One of cover, contain, stretch contain
cutFrom Time value to cut from 0 sec
cutTo Time value to cut from end of video sec
backgroundColor Background of letterboxing #000000

Layer type 'image'

Parameter Description Default
path Path to image file
zoomDirection Zoom direction for Ken Burns effect: in, out or null to disable in
zoomAmount Zoom amount for Ken Burns effect 0.1

Layer type 'title'

  • fontPath - See defaults.layer.fontPath
  • text - Title text to show, keep it short
  • textColor - default #ffffff
  • position - Vertical position: top, bottom or center

Layer type 'subtitle'

  • fontPath - See defaults.layer.fontPath
  • text - Subtitle text to show
  • textColor - default #ffffff

Layer type 'title-background'

Title with background

  • text - See type title
  • textColor - See type title
  • background - { type, ... } - See type radial-gradient, linear-gradient or fill-color
  • fontPath - See type title

Layer type 'fill-color', 'pause'

  • color - Color to fill background, default: randomize

Layer type 'radial-gradient'

  • colors - Array of two colors, default: randomize

Layer type 'linear-gradient'

  • colors - Array of two colors, default: randomize

Layer type 'rainbow-colors'


Layer type 'canvas'

See customCanvas.js

  • func - Custom JavaScript function

Layer type 'fabric'

See customFabric.js

  • func - Custom JavaScript function

Layer type 'gl'

Loads a GLSL shader. See gl.json5 and rainbow-colors.frag

  • fragmentPath
  • vertexPath (optional)


  • If you get Error: The specified module could not be found., try: npm un -g editly && npm i -g --build-from-source editly (see #15)
  • If you get an error about gl returning null, see Requirements.
  • If you get an error /bin/sh: pkg-config: command not found, try to use newest Node.js LTS version

See also


  • Keep source audio (See #1)

Made with ❤️ in 🇳🇴

More apps by

Follow me on GitHub, YouTube, IG, Twitter for more awesome content!

You can’t perform that action at this time.