
Research
SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains
An emerging npm supply chain attack that infects repos, steals CI secrets, and targets developer AI toolchains for further compromise.
nodejs-ffmpeg
Advanced tools
A full-featured, cross-platform FFmpeg wrapper for Node.js with TypeScript support
npm install nodejs-ffmpeg
# or
yarn add nodejs-ffmpeg
# or
pnpm add nodejs-ffmpeg
import { convert, extractAudio, takeScreenshot } from "nodejs-ffmpeg";
// Convert video
await convert({
input: "input.mp4",
output: "output.webm",
videoCodec: "libvpx-vp9",
crf: 28,
onProgress: (p) => console.log(`${p.percent}%`),
});
// Extract audio
await extractAudio({
input: "video.mp4",
output: "audio.mp3",
format: "mp3",
bitrate: "192k",
});
// Take screenshot
await takeScreenshot({
input: "video.mp4",
output: "thumbnail.jpg",
time: 5,
width: 1280,
});
import { FFmpeg } from "nodejs-ffmpeg";
const result = await new FFmpeg()
.input("input.mp4")
.output("output.webm")
.videoCodec("libvpx-vp9")
.audioCodec("libopus")
.on("progress", (p) => console.log(`${p.percent}%`))
.run();
import { runCommand, runCommandString } from "nodejs-ffmpeg";
// Using array arguments
await runCommand({
args: ["-i", "input.mp4", "-vf", "scale=1280:-1", "-y", "output.mp4"],
onProgress: (p) => console.log(p.timemark),
});
// Using string command (like terminal)
await runCommandString('-i input.mp4 -vf "scale=1280:-1" -y output.mp4');
| Function | Description |
|---|---|
convert(options) | Generic conversion with 50+ options |
extractAudio(options) | Extract audio track (mp3, aac, opus, flac, wav) |
takeScreenshot(options) | Capture frame at specific time |
trim(options) | Cut video to time range (fast copy mode) |
compress(options) | Reduce file size with quality presets |
merge(options) | Combine video + audio files |
concat(options) | Join multiple videos |
toGif(options) | Create animated GIF |
addWatermark(options) | Overlay image with position/opacity |
changeSpeed(options) | Speed up/slow down with audio sync |
rotate(options) | Rotate 90/180/270 or flip |
runCommand(options) | Execute custom FFmpeg command |
await convert({
// Required
input: "input.mp4",
output: "output.mp4",
// Video Options
videoCodec: "libx264", // 'libx264', 'libx265', 'libvpx-vp9', 'copy'
videoBitrate: "2M", // Video bitrate
crf: 23, // Quality (0-51, lower = better)
preset: "fast", // 'ultrafast', 'fast', 'medium', 'slow'
fps: 30, // Frame rate
size: "1920x1080", // Resolution
scale: "1280:-1", // Scale filter
// Audio Options
audioCodec: "aac", // 'aac', 'libopus', 'libmp3lame', 'copy'
audioBitrate: "128k", // Audio bitrate
sampleRate: 44100, // Sample rate
channels: 2, // Audio channels
// Timing
seek: 10, // Start time (seconds)
duration: 60, // Duration (seconds)
// Filters
videoFilter: "scale=1280:-1,eq=brightness=0.1",
audioFilter: "volume=2",
// Stream Selection
noVideo: false, // Remove video
noAudio: false, // Remove audio
// General
overwrite: true, // Overwrite output
threads: 4, // Thread count
hwAccel: "cuda", // Hardware acceleration
// Callbacks
onProgress: (p) => {}, // Progress updates
onStart: (cmd) => {}, // Command started
});
import { FFprobe, getMetadata, getDuration } from "nodejs-ffmpeg";
// Quick helpers
const duration = await getDuration("video.mp4");
const metadata = await getMetadata("video.mp4");
// Full API
const ffprobe = new FFprobe();
const info = await ffprobe.getMetadata("video.mp4");
console.log(info.format.duration); // Duration in seconds
console.log(info.format.size); // File size
console.log(info.streams[0].codec_name); // Codec info
import { toMP4, toWebM, toHEVC, toHLS, toDASH } from "nodejs-ffmpeg";
// Convert to MP4 (H.264)
await toMP4("input.webm", "output.mp4", { quality: "medium" }).run();
// Convert to WebM (VP9)
await toWebM("input.mp4", "output.webm", { quality: "high" }).run();
// Convert to HEVC (H.265)
await toHEVC("input.mp4", "output.mp4", { crf: 28 }).run();
// Create HLS streaming output
await toHLS("input.mp4", "./hls/", { segmentDuration: 4 }).run();
// Create DASH streaming output
await toDASH("input.mp4", "./dash/", { segmentDuration: 4 }).run();
import {
downloadBinaries,
areBinariesDownloaded,
getFFmpegPath,
setFFmpegPath,
} from "nodejs-ffmpeg";
// Check if binaries exist
if (!areBinariesDownloaded()) {
await downloadBinaries({
onProgress: (p) => console.log(`${p.filename}: ${p.percent}%`),
});
}
// Use custom binary path
setFFmpegPath("/usr/local/bin/ffmpeg");
The examples/ directory contains comprehensive examples:
| Example | Description |
|---|---|
basic-conversion.ts | Simple video conversion |
object-api.ts | Object-based API usage |
custom-cli.ts | Custom FFmpeg commands |
probe-metadata.ts | FFprobe metadata extraction |
presets.ts | Built-in presets |
filters.ts | Video filters and effects |
effects.ts | Color, blur, rotation effects |
audio-processing.ts | Audio extraction and manipulation |
thumbnails.ts | Thumbnails and previews |
batch-processing.ts | Process multiple files |
streaming.ts | HLS/DASH streaming |
Run any example:
npx tsx examples/object-api.ts
MIT © 2024
FAQs
A full-featured, cross-platform FFmpeg wrapper for Node.js with TypeScript support
We found that nodejs-ffmpeg demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
An emerging npm supply chain attack that infects repos, steals CI secrets, and targets developer AI toolchains for further compromise.

Company News
Socket is proud to join the OpenJS Foundation as a Silver Member, deepening our commitment to the long-term health and security of the JavaScript ecosystem.

Security News
npm now links to Socket's security analysis on every package page. Here's what you'll find when you click through.