Skip to content

Convert / resize / transcode / down-sample photos & videos to be web-friendly

Notifications You must be signed in to change notification settings

thumbsup/downsize

Repository files navigation

thumbsup-downsize

Convert / resize / transcode / down-sample photos & videos to be web-friendly

This is one of the core modules of thumbsup.github.io.

NPM License Tests Dependencies Standard - JavaScript Style Guide

Setup

npm install thumbsup-downsize --save

This module requires the following binaries available in the system path, depending on the type of files you need to process:

To run the tests, you will also need

Usage

const downsize = require('thumbsup-downsize')

const options = { height: 100, width: 100 }
downsize.image('source.tiff', 'thumb.jpg', options, (err) => {
  console.log(err || 'Thumbnail created successfully')
})

API

.image

.image(source, target, options, callback)

Processes the image in source and creates a new image in target. The image is appropriately converted if needed based on the target file extension. You can specify the following options:

Image size
// proportionally resize the photo to a maximum height
opts = { height: 300 }

// proportionally resize the photo to a maximum width
opts = { width: 300 }

// resize and crop the photo to exactly height x width
// the image will not be distorted
opts = { height: 100, width: 100 }
Image quality
// quality between 0 and 100
opts = { quality: 80 }
Preserving metadata

By default, all metadata is removed from downsized images. This option will keep all EXIF / IPTC / XMP metadata in the target files.

When setting this option to true, images will no longer be auto-rotated.

opts = { keepMetadata: true }
Watermark

You can overlay a transparent watermark over the final image:

opts = {
  watermark: {
    file: 'path/watermark.png',  // transparent PNG
    position: 'NorthEast'        // position of the watermark
  }
}

The possible values for position are:

  • Repeat to repeat the watermark across the whole image
  • Center to position the watermark in the middle
  • NorthWest, North, NorthEast, West, East, SouthWest, South, SouthEast to position the watermark along the edge

watermark tiled

Note: watermarks are not compatible with cropped images. The watermark option will simply be ignored if both width and height are specified.

Post-processing

You can specify extra arguments that will be passed to GraphicsMagick. This only works with output arguments.

opts = {
  args: [
    '-unsharp 2 0.5 0.7 0',
    '-modulate 120'
  ]
}
GIF animation

By default, only the first frame of an animated GIF is exported. You can keep the entire animation by specifying:

opts = { animated: true }

This offloads the processing of the image to Gifsicle. Note that:

  • The destination file extension must be .gif
  • The only other supported parameters are width and height (e.g. no watermarks)
  • Cropping (specifying both width and height) is not supported and will throw an error

The flag is simply ignored if the source file is not a GIF.

.still

.still(source, target, options, callback)

Extract a single frame from the video in source, and writes the image to target. This method supports all the same options as .image(), with the addition of:

opts = {
  // take the screenshot at the very start of the video
  seek: 0
  // take the screenshot after N second (default = 1)
  seek: 1
  // take the screenshot in the middle of the video
  seek: -1
}

If seeking fails for any reason, the first frame is used instead.

.video

.video(source, target, options, callback)

Transcodes the video in source to a web-friendly format and lower bitrate, and writes it in target. You can specify the following options:

Format

The default export format is mp4. You can specify an export format by adding a format option:

opts = { format: 'mp4'  } // H264 encoder
opts = { format: 'webm' } // VP9 encoder

Note: encoding as webm is much slower.

Video quality

The default behaviour is to use CRF (constant rate factor) to control the output quality. The default value is 75%.

// value between 0 (worst) and 100 (best)
opts = { quality: 75 }

Notes:

  • the quality scale is not linear
  • you will most likely want a value between 50% and 90%
  • values over 90% can generate files larger than the original

Quality size ratio

Variable bitrate

Instead of CRF, you can specify a variable bitrate (a.k.a. average bitrate, or target bitrate) by using the bitrate option. Check the ffmpeg docmentation for more information. This is not compatible with the quality option.

opts = { bitrate: '1200k' }
HW acceleration

Enable VAAPI HW acceleration if supported on your platform (typically Intel/AMD chipsets). Requires intel-media-driver package to enable. This is not compatiable with the quality option and requires a bitrate setting. The default value is none.

// values 'vaapi' or 'none'
opts = { hwaccel: 'vaapi' }
Video FPS

The default export video FPS is 25. You can specify an explicit FPS by adding a framerate option:

opts = { framerate: 60 }
opts = { framerate: 0 }   // preserve the original source video's FPS
Preserving Metadata

By default, all metadata is removed from the target video. This option preserves the metadata.

opts = { keepMetadata: true }
Conversion progress

The .video() call returns an EventEmitter to follow the progress of the conversion, since it can take a long time.

const emitter = downsize.video(/* ... */)
emitter.on('progress', percent => console.log(`${percent}%`))

Contributing

Image/video resizing is hard to unit test. Instead, this repo contains an integration test suite made of many different resized files, covering different file formats and edge cases.

When submitting a change, make sure you run the build locally.

npm test

If you don't have all dependencies installed, you can also run the tests in Docker.

docker build -t downsize-test .

About

Convert / resize / transcode / down-sample photos & videos to be web-friendly

Resources

Stars

Watchers

Forks

Packages

No packages published