Skip to content

feat: restore Node.js support via worker_threads#936

Open
JacobiusMakes wants to merge 1 commit intoffmpegwasm:mainfrom
JacobiusMakes:feat/nodejs-support
Open

feat: restore Node.js support via worker_threads#936
JacobiusMakes wants to merge 1 commit intoffmpegwasm:mainfrom
JacobiusMakes:feat/nodejs-support

Conversation

@JacobiusMakes
Copy link
Copy Markdown

Summary

Resolves #897 — restores Node.js support that was removed in v0.12.0.

With both fluent-ffmpeg (archived May 2025) and ffmpeg-kit (archived June 2025) now dead, there is no maintained way to use FFmpeg from Node.js without native binaries. This PR brings ffmpeg.wasm back to Node.js with a zero-change API — existing browser code works in Node.js by swapping the import.

What's included

  • node-classes.tsFFmpeg class using worker_threads.Worker instead of Web Workers. Same public API as the browser version.
  • node-worker.ts — Worker script using parentPort message passing. Mirrors the browser worker.ts exactly.
  • @ffmpeg/util/node — Node.js fetchFile() supporting local file paths (fs.readFile), URLs (fetch), Buffers, and base64 data URIs.
  • Updated empty.mts — Now re-exports the real Node.js implementation instead of throwing.
  • Integration testtests/node-ffmpeg.test.mjs

Design decisions

  • worker_threads over direct execution — Keeps transcoding off the main thread, preserving Node.js async behavior. The message-passing protocol is identical to Web Workers.
  • No new dependencies — Uses only Node.js built-ins (worker_threads, fs, url).
  • Backward compatible — The package.json exports field routes Node.js to the new implementation via the existing "node" condition. Browser builds are unchanged.

Usage

import { FFmpeg } from "@ffmpeg/ffmpeg";
import { fetchFile } from "@ffmpeg/util/node";

const ffmpeg = new FFmpeg();
await ffmpeg.load();
await ffmpeg.writeFile("input.mp4", await fetchFile("/path/to/video.mp4"));
await ffmpeg.exec(["-i", "input.mp4", "output.mp3"]);
const data = await ffmpeg.readFile("output.mp3");

Test plan

  • Verify node-classes.ts correctly spawns node-worker.ts via worker_threads
  • Test fetchFile with local paths, URLs, base64, and Buffers
  • Confirm browser builds are unaffected (exports field routing)
  • Run tests/node-ffmpeg.test.mjs with @ffmpeg/core installed
  • Verify terminate() cleanly shuts down the worker thread

🤖 Generated with Claude Code

Replace the error-throwing empty.mts stub with a full Node.js FFmpeg
implementation that mirrors the browser API using worker_threads.

New files:
- node-classes.ts: FFmpeg class using worker_threads.Worker
- node-worker.ts: Worker script using parentPort message passing
- util/node.ts: Node.js fetchFile (fs.readFile + fetch for URLs)
- tests/node-ffmpeg.test.mjs: Integration test for Node.js

The public API is identical to the browser version — existing code
works without changes, just swap the import. The worker_threads
approach keeps transcoding off the main thread, preserving Node.js
async behavior.

Resolves: ffmpegwasm#897

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@netlify
Copy link
Copy Markdown

netlify bot commented Mar 27, 2026

Deploy Preview for ffmpegwasm canceled.

Name Link
🔨 Latest commit 5ae1a4e
🔍 Latest deploy log https://app.netlify.com/projects/ffmpegwasm/deploys/69c5d0b34076a40008c4ec5f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Question]: Possible consideration for NodeJS support again due to alternatives going away?

1 participant