• Stars
    star
    4,389
  • Rank 9,309 (Top 0.2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created about 4 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Slick, declarative command line video editing & API

Discord NPM version Build status PayPal

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, audio 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.

demo

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

Features

  • 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
  • Overlay transparent images or even videos with alpha channel
  • Show different sub-clips for parts of a clips duration (B-roll)
  • Picture-in-picture
  • Vignette
  • Preserve/mix multiple audio sources
  • Automatic audio crossfading
  • Automatic audio ducking and normalization

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
  • Create news stories
  • Create an animated 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)
  • Create a podcast with multiple mixed tracks

See examples

Requirements

Installing

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' \
  clip1.mov \
  clip2.mov \
  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 user friendly JSON format):

editly my-spec.json5 --fast --keep-source-audio --out output.gif

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

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

import editly from 'editly';

// See editSpec documentation
await editly(editSpec)

Edit spec

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

{
  outPath,
  width,
  height,
  fps,
  allowRemoteRequests: false,
  defaults: {
    duration: 4,
    transition: {
      duration: 0.5,
      name: 'random',
      audioOutCurve: 'tri',
      audioInCurve: 'tri',
    },
    layer: {
      fontPath,
      // ...more layer defaults
    },
    layerType: {
      'fill-color': {
        color: '#ff6666',
      }
      // ...more per-layer-type defaults
    },
  },
  clips: [
    {
      transition,
      duration,
      layers: [
        {
          type,
          // ...more layer-specific options
        }
        // ...more layers
      ],
    }
    // ...more clips
  ],
  audioFilePath,
  loopAudio: false,
  keepSourceAudio: false,
  clipsAudioVolume: 1,
  outputVolume: 1,
  audioTracks: [
    {
      path,
      mixVolume: 1,
      cutFrom: 0,
      cutTo,
      start: 0,
    },
    // ...more audio tracks
  ],
  audioNorm: {
    enable: false,
    gaussSize: 5,
    maxGain: 30,
  }

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

Parameters

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
customOutputArgs Specify custom output codec/format arguments for ffmpeg (See example) auto (h264)
allowRemoteRequests --allow-remote-requests Allow remote URLs as paths false
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
defaults.transition.name --transition-name Default transition type. See Transition types random
defaults.transition.audioOutCurve Default fade out curve in audio cross fades tri
defaults.transition.audioInCurve Default fade in curve in audio cross fades tri
clips[] List of clip objects that will be played in sequence. Each clip can have one or more layers.
clips[].duration Clip duration. See defaults.duration. If unset, the clip duration will be that of the first video layer. 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 (final layer on top)
clips[].layers[].type Layer type, see below
clips[].layers[].start What time into the clip should this layer start sec
clips[].layers[].stop What time into the clip should this layer stop sec
audioTracks[] List of arbitrary audio tracks. See audio tracks. []
audioFilePath --audio-file-path Set an audio track for the whole video. See also audio tracks
loopAudio --loop-audio Loop the audio track if it is shorter than video? false
keepSourceAudio --keep-source-audio Keep source audio from clips? false
clipsAudioVolume Volume of audio from clips relative to audioTracks. See audio tracks. 1
outputVolume --output-volume Adjust output volume (final stage). See example 1 e.g. 0.5 or 10dB
audioNorm.enable Enable audio normalization? See audio normalization. false
audioNorm.gaussSize Audio normalization gauss size. See audio normalization. 5
audioNorm.maxGain Audio normalization max gain. See audio normalization. 30

Transition types

transition.name can be any of gl-transitions, or any of the following: directional-left, directional-right, directional-up, directional-down, random or dummy.

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. If the layer has audio, it will be kept (and mixed with other audio layers if present.)

Parameter Description Default
path Path to video file
resizeMode See Resize modes
cutFrom Time value to cut from 0 sec
cutTo Time value to cut to end of video sec
width Width relative to screen width 1 0 to 1
height Height relative to screen height 1 0 to 1
left X-position relative to screen width 0 0 to 1
top Y-position relative to screen height 0 0 to 1
originX X anchor left left or right
originY Y anchor top top or bottom
mixVolume Relative volume when mixing this video's audio track with others 1

Layer type 'audio'

Audio layers will be mixed together. If cutFrom/cutTo is set, the resulting segment (cutTo-cutFrom) will be slowed/sped-up to fit clip.duration. The slow down/speed-up operation is limited to values between 0.5x and 100x.

Parameter Description Default
path Path to audio file
cutFrom Time value to cut from 0 sec
cutTo Time value to cut to clip.duration sec
mixVolume Relative volume when mixing this audio track with others 1

Layer type 'detached-audio'

This is a special case of audioTracks that makes it easier to start the audio relative to clips start times without having to calculate global start times.

detached-audio has the exact same properties as audioTracks, except start time is relative to the clip's start.

Example of detached audio tracks

Layer type 'image'

Full screen image

Parameter Description Default
path Path to image file
resizeMode See Resize modes

See also See Ken Burns parameters.

Layer type 'image-overlay'

Image overlay with a custom position and size on the screen. NOTE: If you want to use animated GIFs use video instead.

Parameter Description Default
path Path to image file
position See Position parameter
width Width (from 0 to 1) where 1 is screen width
height Height (from 0 to 1) where 1 is screen height

See also Ken Burns parameters.

Layer type 'title'

  • fontPath - See defaults.layer.fontPath
  • text - Title text to show, keep it short
  • textColor - default #ffffff
  • position - See Position parameter

See also Ken Burns parameters

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 'news-title'

  • fontPath - See defaults.layer.fontPath
  • text
  • textColor - default #ffffff
  • backgroundColor - default #d02a42
  • position - See Position parameter

Layer type 'slide-in-text'

  • fontPath - See defaults.layer.fontPath
  • text
  • fontSize
  • charSpacing
  • color
  • position - See Position parameter

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)

Arbitrary audio tracks

audioTracks property can optionally contain a list of objects which specify audio tracks that can be started at arbitrary times in the final video. These tracks will be mixed together (mixVolume specifying a relative number for how loud each track is compared to the other tracks). Because audio from clips will be mixed separately from audioTracks, clipsAudioVolume specifies the volume of the combined audio from clips relative to the volume of each of the audio tracks from audioTracks.

Parameter Description Default
audioTracks[].path File path for this track
audioTracks[].mixVolume Relative volume for this track 1
audioTracks[].cutFrom Time value to cut source file from 0 sec
audioTracks[].cutTo Time value to cut source file to sec
audioTracks[].start How many seconds into video to start this audio track 0 sec

The difference between audioTracks and Layer type 'audio' is that audioTracks will continue to play across multiple clips and can start and stop whenever needed.

See audioTracks example

See also Layer type 'detached-audio'.

Audio normalization

You can enable audio normalization of the final output audio. This is useful if you want to achieve Audio Ducking (e.g. automatically lower volume of all other tracks when voice-over speaks).

audioNorm parameters are documented here.

Example of audio ducking

Resize modes

resizeMode - How to fit image to screen. Can be one of:

  • contain - All the video will be contained within the frame and letterboxed
  • contain-blur - Like contain, but with a blurred copy as the letterbox
  • cover - Video be cropped to cover the whole screen (aspect ratio preserved)
  • stretch - Video will be stretched to cover the whole screen (aspect ratio ignored).

Default contain-blur.

See:

Position parameter

Certain layers support the position parameter

position can be one of either:

  • top, bottom center, top-left, top-right, center-left, center-right, bottom-left, bottom-right
  • An object { x, y, originX = 'left', originY = 'top' }, where { x: 0, y: 0 } is the upper left corner of the screen, and { x: 1, y: 1 } is the lower right corner, x is relative to video width, y to video height. originX and originY are optional, and specify the position's origin (anchor position) of the object.

See position.json5

Ken Burns parameters

Parameter Description Default
zoomDirection Zoom direction for Ken Burns effect: in, out, left, right or null to disable
zoomAmount Zoom amount for Ken Burns effect 0.1

Docker

This should help you use editly as a containerized CLI, without worrying about getting all the right versions of dependencies on your system.

$ git clone https://github.com/mifi/editly.git
$ cd editly/examples
$ git clone https://github.com/mifi/editly-assets.git assets
$ cd ..
$ docker-compose up
$ docker-compose run editly bash -c "cd examples && editly audio1.json5 --out /outputs/audio1.mp4"
$ docker cp editly:/outputs/audio1.mp4 .

Troubleshooting

  • 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

Donate 🙏

This project is maintained by me alone. The project will always remain free and open source, but if it's useful for you, consider supporting me. :) It will give me extra motivation to improve it.

Paypal

Thanks

This package would not exist without the support and help from all the contributors and sponsors!

Special thanks to:

See also

Videos made by you

Submit a PR if you want to share your videos or project created with editly here.


Made with ❤️ in 🇳🇴

More apps by mifi.no

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

More Repositories

1

lossless-cut

The swiss army knife of lossless video/audio editing
JavaScript
19,775
star
2

instauto

Instagram bot / automation library written in Javascript for Node.js
JavaScript
735
star
3

SimpleInstaBot

Simple Instagram bot GUI
JavaScript
532
star
4

ezshare

Easily share files, folders and clipboard over LAN - Like Google Drive but without internet
JavaScript
458
star
5

react-lottie-player

Fully declarative React Lottie player
JavaScript
445
star
6

hls-vod

HTTP Live Streaming with on-the-fly encoding of any video file for Web/Apple TV/iPhone/iPad/iPod
JavaScript
264
star
7

cognito-backup

CLI for backing up AWS Cogntito User Pools
JavaScript
141
star
8

reactive-video

Create videos using React!
JavaScript
118
star
9

dynamodump

Node CLI for backing up and restoring schema+data from DynamoDB tables
JavaScript
115
star
10

stacktracify

CLI to make unreadable production stack traces readable using source maps
JavaScript
111
star
11

in-app-subscription-example

Example of implementing auto-renewing in-app subscriptions for Android & iOS using React Native / Node.js
JavaScript
96
star
12

ical-expander

ICS / iCal / iCalendar parser / expander
JavaScript
63
star
13

commonify

Recursively publish ESM packages as CommonJS!
JavaScript
31
star
14

libxcomfort

Open source library for controlling Moeller XComfort devices through the USB/RS232 dongle
C
31
star
15

build-electron

Use ES modules in Electron
JavaScript
25
star
16

telldus-api

Node.js interface for Telldus Live and Telldus Local API
JavaScript
18
star
17

mjml-dynamic

Dynamic JSON content for MJML templates
TypeScript
16
star
18

VideoGrader

JavaScript
14
star
19

lossless-cut-fixtures

Test fixtures (videos) for manual testing of LosslessCut
13
star
20

cordova-xml

Edit cordova config.xml from the command line or via API
JavaScript
7
star
21

file2kodi

Plays a local file on Kodi/XBMC
JavaScript
5
star
22

ffmpeg-builds

FFMPEG static builds for use with LosslessCut
4
star
23

s3fuse

Simple and stable Node.js implementation of read-only S3 file system
JavaScript
4
star
24

rpi-touch-ui

Basic control of a Raspberry Pi with a touch screen
JavaScript
4
star
25

telldus-local-auth

Node CLI for assisting set up of local auth for Telldus Live local devices
JavaScript
4
star
26

fork-worker

Makes it easier to fork off a separate Node.js job
JavaScript
4
star
27

sleekboard

Sleekboard is a slick on-screen-keyboard built on Cairo and X11
Shell
3
star
28

cloudwatch-winston

Robust and simple Winston transport for AWS CloudWatch Logs
JavaScript
2
star
29

form-encode-object

Convert a deep object structure to be sent as urlencoded or form data (PHP style).
JavaScript
2
star
30

facetracker

C
2
star
31

digital-media-frame

Making a digital media frame running on Linux with Chromium
CSS
2
star
32

scripts

Some handy scripts
Shell
2
star
33

jquery-joystick

jQuery Joystick
JavaScript
2
star
34

google-photos-timestamp-fix

Attempt to write a script that automatically sets the correct timestamp for videos uploaded to google photos, see: https://productforums.google.com/forum/#!topic/photos/oj96JZK14Fs
JavaScript
1
star
35

mifi

mifi npm package
1
star
36

chrome-to-xbmc

Chrome plugin for detecting video streams on pages and sending them to XBMC
1
star
37

restplass-alerts

Service that polls finn.no restplass and gives notifications when something changes for the better
JavaScript
1
star
38

mifi.no

JavaScript
1
star
39

editly-assets

Assets for editly examples
GLSL
1
star
40

github-action-push-static

Example GitHub Action workflow that will automatically push all files in a specified directory to a different GitHub repo
JavaScript
1
star
41

xbmc-vsxu

VSXu visualization for XBMC
C
1
star