Editly is a tool and framework for declarative NLE (non-linear video editing) using Node.js and ffmpeg. It allows you to **easily and programmatically** create a video from set of clips, images and titles, with smooth transitions between.
There is a simple command line for quickly assembling a video from a set of clips or images, or you can use it from Javascript!
Inspired by [ffmpeg-concat](https://github.com/transitive-bullshit/ffmpeg-concat). The problem with that project is that it is quite slow and uses an extreme amount of disk space, especially for HD/4K videos. This projects solves that by doing **streaming** editing, so it doesn't store any temporary files.
This GIF / YouTube was created with this command: "editly [commonFeatures.json5](https://github.com/mifi/editly/blob/master/examples/commonFeatures.json5)". See [more examples here](https://github.com/mifi/editly/tree/master/examples#examples).
**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 **set of clips, images and titles**, with smooth transitions between and music overlaid.
This GIF/youtube was created with this command: "editly [commonFeatures.json5](https://github.com/mifi/editly/blob/master/examples/commonFeatures.json5)"
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.
See [more examples here](https://github.com/mifi/editly/tree/master/examples#examples)
Inspired by [ffmpeg-concat](https://github.com/transitive-bullshit/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**.
## Features
## Features
- Edit videos with code! Declarative API with fun defaults
- Edit videos with code! Declarative API with fun defaults
- Create colorful videos with random colors generated from aesthetically pleasing pallettes and random effects
- Create colorful videos with random colors generated from aesthetically pleasing pallettes and random effects
- Supports any size like 4K video and DSLR photos
- Can output to any dimensions, like *Instagram post* (1:1), *Instagram story* (9:16), *YouTube* (16:9), or any other dimensions you like.
- Supports any input size like 4K video and DSLR photos
- Can output to any dimensions and aspect ratio, like *Instagram post* (1:1), *Instagram story* (9:16), *YouTube* (16:9), or any other dimensions you like.
- Content will be scaled and letterboxed automatically, even if input aspect ratio is not same, and framerate will be converted.
- Content will be scaled and letterboxed automatically, even if input aspect ratio is not same, and framerate will be converted.
- Speeds up / slow down videos automatically to match `cutFrom`/`cutTo` segment length with each clip's `duration`
- Speeds up / slow down videos automatically to match `cutFrom`/`cutTo` segment length with each clip's `duration`
- Overlay text and subtitles on videos, images or backgrounds
- Overlay text and subtitles on videos, images or backgrounds
- Accepts custom HTML5 Canvas / Fabric.js Javascript code for custom screens or dynamic overlays
- Accepts custom HTML5 Canvas / Fabric.js Javascript code for custom screens or dynamic overlays
- Render custom GL shaders (for example from [shadertoy](https://www.shadertoy.com/))
- Render custom GL shaders (for example from [shadertoy](https://www.shadertoy.com/))
- Output GIF
- Can output GIF
## Use cases
## Use cases
@ -31,7 +29,7 @@ See [more examples here](https://github.com/mifi/editly/tree/master/examples#exa
- Create a fast paced trailer or promo video
- Create a fast paced trailer or promo video
- Create a tutorial video with help text
- Create a tutorial video with help text
- Simply convert a video to a GIF
- Simply convert a video to a GIF
- Resize video to any size or framerate and with automatic letterbox/crop (e.g. if you need to upload a video somewhere and the site complains **video dimensions must be 1337x1000**
- Resize video to any size or framerate and with automatic letterbox/crop (e.g. if you need to upload a video somewhere but the site complains `Video must be 1337x1000 30fps`)
See [examples](https://github.com/mifi/editly/tree/master/examples)
See [examples](https://github.com/mifi/editly/tree/master/examples)
@ -90,7 +88,7 @@ await editly(editSpec)
## Edit spec
## Edit spec
Edit specs are Javascript / JSON ojects describing the whole edit operation.
Edit specs are Javascript / JSON ojects describing the whole edit operation with the following structure:
```js
```js
{
{
@ -136,27 +134,27 @@ Edit specs are Javascript / JSON ojects describing the whole edit operation.
`transition.name` can be any of [gl-transitions](https://gl-transitions.com/gallery), in addition to: `directional-left`, `directional-right`, `directional-up`, `directional-down` and `random`.
`transition.name` can be any of [gl-transitions](https://gl-transitions.com/gallery), or any of the following: `directional-left`, `directional-right`, `directional-up`, `directional-down` and `random`.
### Layer types
### Layer types
@ -164,14 +162,14 @@ See [examples](https://github.com/mifi/editly/tree/master/examples) and [commonF
#### Layer type 'video'
#### Layer type 'video'
For video layers, if parent `clip.duration` is specified, the video will be slowed/sped-up to match the `clip.duration`. If `cutFrom`/`cutTo` is set, the resulting segment will be slowed/sped-up to match the`clip.duration`.
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 | |
| Parameter | Description | Default | |
|-|-|-|-|
|-|-|-|-|
| `path` | Path to video file | | |
| `path` | Path to video file | | |
| `resizeMode` | One of `cover`, `contain`, `stretch` | | |
| `resizeMode` | One of `cover`, `contain`, `stretch` | `contain`| |
| `cutFrom` | Time value to cut from | `0` | sec |
| `cutFrom` | Time value to cut from | `0` | sec |
| `cutTo` | Time value to cut from | video duration | sec |
| `cutTo` | Time value to cut from | *end of video* | sec |
| `backgroundColor` | Background of letterboxing | `#000000` | |
| `backgroundColor` | Background of letterboxing | `#000000` | |