Have you ever wished for the ability to retrieve image or video file attributes
such as width, height, size, and mime type in Node without having
to resort to external libraries such as ffprobe
?
Yeah, me too! This is why leather
was created.
At the moment, the only package that does something similar is
image-size
and while it does work well, it does not handle video formats.
leather
uses streams to read image and video files in byte-sized chunks.
As soon attributes have been extracted, the stream will be closed. Some file
formats have a well-defined fixed position in which these attributes
can be found, in those cases, leather
skips any bytes before that
position and reads only the bytes needed to extract attributes directly.
However, sometimes the byte offset of these attributes may vary, in these
scenarios leather
makes a best-effort attempt to read as few bytes as
possible to get to the good stuff!
Before leather
, if you wanted to do something like this in Node
you would need to install image-size
to handle images and either
use ffprobe
directly or using some kind of wrapper package to
handle video files.
While I love ffprobe
for its capabilities, setting up a cross-platform
package requires some configuration. This package aims to solve that
by steering clear of any command-line tools which makes it more portable.
Stable Node versions from 14.18 and up are tested, Node 12.20 and up is supported.
Install the package locally using npm
:
npm install leather --save
Or using yarn
yarn add leather
After installing the package, it can be imported using commonjs:
const {readMediaAttributes} = require('leather');
Or using ES modules:
import {readMediaAttributes} from 'leather';
Then, it can be called on supported image and video formats:
console.log(readMediaAttributes('cat.jpg'));
// => {width: 200, height: 200, size: 40000, mime: 'image/jpeg'}
Starting from version 2.1.0, all readMediaAttributes
methods also accept Buffer
instances in addition to file paths:
const buffer = fs.readFileSync('cat.png');
console.log(readMediaAttributes(buffer));
// => {width: 200, height: 200, size: 40000, mime: 'image/jpeg'}
The width and height are pixel based. The size is the same as
fs.stat
.
If the width or height could not be extracted, they will default to 0
.
The mime type is also returned if found, otherwise undefined
.
If you are only using one or a few of the extractors, you can opt to require only the extractors you need, e.g. for jpg/jpeg using commonjs:
const {readFileSync} = require('fs');
const {readMediaAttributes} = require('leather/extractors/jpg');
console.log(readMediaAttributes('cat.jpg'));
console.log(readMediaAttributes(readFileSync('cat.jpg')));
// => {width: 200, height: 200, size: 40000, mime: 'image/jpeg'}
Or using ES modules:
import {readFileSync} from 'fs';
import {readMediaAttributes} from 'leather/extractors/jpg';
console.log(readMediaAttributes('cat.jpg'));
console.log(readMediaAttributes(readFileSync('cat.jpg')));
// => {width: 200, height: 200, size: 40000, mime: 'image/jpeg'}
All supported image and video formats can be found in the table below:
format | extractor | mime type |
---|---|---|
bmp | bmp | image/bmp |
dds | dds | image/vnd.ms-dds |
gif | gif | image/gif |
icns | icns | image/x-icns |
ico | ico | image/vnd.microsoft.icon |
cur | ico | image/vnd.microsoft.icon |
j2c | j2c | image/jp2 |
jp2 | j2c | image/jp2 |
jpg | jpg | image/jpeg |
ktx | ktx | image/ktx |
png | png | image/png |
apng | png | image/apng |
pfm | pnm | application/x-font-type1 |
pam | pnm | image/x-portable-arbitrarymap |
pbm | pnm | image/x-portable-bitmap |
pgm | pnm | image/x-portable-graymap |
ppm | pnm | image/x-portable-pixmap |
psd | psd | image/vnd.adobe.photoshop |
svg | svg | image/svg+xml |
tiff | tiff | image/tiff |
webp | webp | image/webp |
xpm | xpm | image/x-xpixmap |
xbm | xbm | image/x-xbitmap |
fit | fit | image/fits |
cel | cel | application/octet-stream |
hdr | hdr | image/vnd.radiance |
avi | avi | video/x-msvideo |
fli | fli | video/x-fli |
flc | fli | video/x-fli |
flv | flv | video/x-flv |
mng | png | video/x-mng |
mp4 | mp4 | video/mp4 |
m4v | mp4 | video/x-m4v |
mov | mp4 | video/quicktime |
ogv | ogv | video/ogg |
mkv | webm | video/x-matroska |
webm | webm | video/webm |
wmv | wmv | video/x-ms-wmv |
- https://www.npmjs.com/package/image-size
- http://www.fastgraph.com/help/avi_header_format.html
- http://www.fastgraph.com/help/flic_header_format.html
- https://docs.microsoft.com/en-us/previous-versions/ms779632(v=vs.85)
- https://en.wikipedia.org/wiki/List_of_file_signatures
- https://www.fileformat.info/format/tiff/egff.htm#TIFF.FO
- http://netpbm.sourceforge.net/doc/#formats
- https://www.garykessler.net/library/file_sigs.html
- https://github.com/sannies/mp4parser/blob/c869d076e9cd42aba5a3e35d88827610dec6ca15/examples/src/main/java/com/google/code/mp4parser/example/GetHeight.java
- https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html