Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ffmpeg-extract-frames

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ffmpeg-extract-frames - npm Package Compare versions

Comparing version 1.0.0 to 2.0.0

.editorconfig

78

index.js

@@ -5,31 +5,73 @@ 'use strict'

const path = require('path')
const probe = require('ffmpeg-probe')
const noop = () => { }
module.exports = (opts) => {
module.exports = async (opts) => {
const {
log = noop,
// required
input,
output,
// optional
timestamps,
offsets,
folder,
filename
fps,
numFrames
} = opts
if (!timestamps && !offsets) {
throw new Error('missing required screenshot timestamps or offsets')
}
if (!input) throw new Error('missing required input')
if (!output) throw new Error('missing required output')
const framePattern = path.join(folder, filename)
const outputPath = path.parse(output)
return new Promise((resolve, reject) => {
ffmpeg(input)
.on('start', (cmd) => log({ cmd }))
.on('end', () => resolve(framePattern))
.on('error', (err) => reject(err))
.screenshots({
folder,
filename,
timestamps: timestamps || offsets.map((offset) => offset / 1000)
})
})
const cmd = ffmpeg(input)
.on('start', (cmd) => log({ cmd }))
if (timestamps || offsets) {
const folder = outputPath.dir
const filename = outputPath.base
return new Promise((resolve, reject) => {
cmd
.on('end', () => resolve(output))
.on('error', (err) => reject(err))
.screenshots({
folder,
filename,
timestamps: timestamps || offsets.map((offset) => offset / 1000)
})
})
} else {
if (fps) {
cmd.outputOptions([
'-r', Math.max(1, fps | 0)
])
} else if (numFrames) {
const info = await probe(input)
const numFramesTotal = parseInt(info.streams[0].nb_frames)
const nthFrame = (numFramesTotal / numFrames) | 0
cmd.outputOptions([
'-vsync', 'vfr',
'-vf', `select=not(mod(n\\,${nthFrame}))`
])
}
if (outputPath.ext === '.raw') {
cmd.outputOptions([
'-pix_fmt', 'rgba'
])
}
return new Promise((resolve, reject) => {
cmd
.on('end', () => resolve(output))
.on('error', (err) => reject(err))
.output(output)
.run()
})
}
}

@@ -5,2 +5,3 @@ 'use strict'

const path = require('path')
const rmfr = require('rmfr')
const sharp = require('sharp')

@@ -14,11 +15,35 @@ const tempy = require('tempy')

test('jpg + offsets', async (t) => {
test('default (all frames) => jpg', async (t) => {
const folder = tempy.directory()
const filename = 'test-%d.jpg'
const output = path.join(folder, filename)
await extractFrames({
log: console.log,
input,
output
})
for (let i = 1; i <= 100; ++i) {
const file = output.replace('%d', i)
const image = await sharp(file).metadata()
t.deepEqual(image.width, 640)
t.deepEqual(image.height, 360)
t.deepEqual(image.channels, 3)
t.deepEqual(image.format, 'jpeg')
}
await rmfr(folder)
})
test('offsets => jpg', async (t) => {
const folder = tempy.directory()
const filename = 'test-%i.jpg'
const output = path.join(folder, filename)
const filePattern = await extractFrames({
await extractFrames({
log: console.log,
input,
folder,
filename,
output,
offsets: [

@@ -32,3 +57,3 @@ 0,

for (let i = 1; i <= 3; ++i) {
const file = filePattern.replace('%i', i)
const file = output.replace('%i', i)
const image = await sharp(file).metadata()

@@ -41,13 +66,15 @@

}
await rmfr(folder)
})
test('png + timestamps', async (t) => {
test('timestamps => png', async (t) => {
const folder = tempy.directory()
const filename = 'test-%i.png'
const output = path.join(folder, filename)
const filePattern = await extractFrames({
await extractFrames({
log: console.log,
input,
folder,
filename,
output,
timestamps: [

@@ -62,3 +89,3 @@ '0%',

for (let i = 1; i <= 4; ++i) {
const file = filePattern.replace('%i', i)
const file = output.replace('%i', i)
const image = await sharp(file).metadata()

@@ -71,2 +98,54 @@

}
await rmfr(folder)
})
test('fps => png', async (t) => {
const folder = tempy.directory()
const filename = 'test-%d.png'
const output = path.join(folder, filename)
await extractFrames({
log: console.log,
input,
output,
fps: 2
})
for (let i = 1; i <= 10; ++i) {
const file = output.replace('%d', i)
const image = await sharp(file).metadata()
t.deepEqual(image.width, 640)
t.deepEqual(image.height, 360)
t.deepEqual(image.channels, 3)
t.deepEqual(image.format, 'png')
}
await rmfr(folder)
})
test('numFrames => jpg', async (t) => {
const folder = tempy.directory()
const filename = 'test-%d.jpg'
const output = path.join(folder, filename)
await extractFrames({
log: console.log,
input,
output,
numFrames: 7
})
for (let i = 1; i <= 7; ++i) {
const file = output.replace('%d', i)
const image = await sharp(file).metadata()
t.deepEqual(image.width, 640)
t.deepEqual(image.height, 360)
t.deepEqual(image.channels, 3)
t.deepEqual(image.format, 'jpeg')
}
await rmfr(folder)
})
{
"name": "ffmpeg-extract-frames",
"version": "1.0.0",
"description": "Extracts screenshots from a video.",
"version": "2.0.0",
"description": "Extracts frames from a video.",
"main": "index.js",

@@ -19,2 +19,3 @@ "repository": "transitive-bullshit/ffmpeg-extract-frames",

"ava": "^0.25.0",
"rmfr": "^2.0.0",
"sharp": "^0.20.1",

@@ -25,4 +26,5 @@ "standard": "^11.0.0",

"dependencies": {
"ffmpeg-probe": "^1.0.1",
"fluent-ffmpeg": "^2.1.2"
}
}
# ffmpeg-extract-frames
> Extracts screenshots from a video using [fluent-ffmpeg](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg).
> Extracts frames from a video using [fluent-ffmpeg](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg).

@@ -21,6 +21,5 @@ [![NPM](https://img.shields.io/npm/v/ffmpeg-extract-frames.svg)](https://www.npmjs.com/package/ffmpeg-extract-frames) [![Build Status](https://travis-ci.org/transitive-bullshit/ffmpeg-extract-frames.svg?branch=master)](https://travis-ci.org/transitive-bullshit/ffmpeg-extract-frames) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)

// extract 3 frames at 1s, 2s, and 3.5s respectively
const filePattern = await extractFrames({
await extractFrames({
input: 'media/1.mp4',
folder: '.',
filename: 'screenshot-%i.jpg',
output: './screenshot-%i.jpg',
offsets: [

@@ -34,2 +33,6 @@ 1000,

// filePattern = './screenshot-%i.jpg'
// generated screenshots:
// `./screenshot-1.jpg
// `./screenshot-2.jpg
// `./screenshot-3.jpg
```

@@ -43,2 +46,4 @@

There are several options for specifying which frames to extract, namely `timestamps`, `offsets`, `fps`, and `numFrames`. The default behavior if you don't specify any of these options is to extract *all* frames from the input.
#### options

@@ -49,17 +54,17 @@

Type: `String`
**Required**
Path or URL to a video file.
##### folder
##### output
Type: `String`
**Required**
Output directory.
Output file pattern.
##### filename
Note that for `timestamps` or `offsets`, the pattern should include a `%i` or `%s` ([details](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg#screenshotsoptions-dirname-generate-thumbnails)).
Type: `String`
For any other call, you should use the `%d` format specifier. I know this is confusing, but it's how [fluent-ffmpeg](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg) works under the hood.
Output file pattern including a `%i`
##### offsets

@@ -71,4 +76,2 @@

Note: you must pass either `offsets` or `timestamps`, with `timestamps` taking precedence.
##### timestamps

@@ -80,4 +83,14 @@

Note: you must pass either `offsets` or `timestamps`, with `timestamps` taking precedence.
##### fps
Type: `Number`
Frames per second to output.
##### numFrames
Type: `Number`
Output a specific number of frames. The input video's frames will be skipped such that only this number of frames are output.
##### log

@@ -92,4 +105,5 @@

- [ffmpeg-extract-frame](https://github.com/transitive-bullshit/ffmpeg-extract-frame) extracts a single frame from a video.
- [fluent-ffmpeg](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg)
- [ffmpeg-extract-frame](https://github.com/transitive-bullshit/ffmpeg-extract-frame) - Extracts a single frame from a video.
- [ffmpeg-generate-video-preview](https://github.com/transitive-bullshit/ffmpeg-generate-video-preview) - Generates an attractive image strip or GIF preview from a video.
- [fluent-ffmpeg](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg) - A fluent API to [FFmpeg](http://ffmpeg.org/).

@@ -96,0 +110,0 @@ ## License

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc