Git Product home page Git Product logo

ffbinaries-node's Introduction

ffbinaries downloader

NPM Version NPM Downloads Build status Coveralls coverage

Downloads precompiled ffmpeg, ffprobe, ffplay and ffserver binaries from ffbinaries.com.

This module is cross-platform and can be used through CLI or as a Node module (i.e. as a build step or a part of app boot routine).

You can download whatever binaries you need during the build if you'd like to bundle the binaries with your distributable files or just download it on user's machine during initial setup process.

Usage

You can run it from your code or through CLI.

If output argument is specified the binary will be placed there. It will default to current working directory.

If platform argument is missing then the current platform will be automatically detected and binaries for it will be downloaded.

If components argument is missing then binaries of all available components will be downloaded (see Included components section).

CLI

When installed globally with npm i ffbinaries -g this module will register itself on command line interface.

Arguments

CLI uses the following syntax:

ffbinaries [components] [--platform] [--output] [--quiet] [--version]

Each flag can also be abbreviated in your scripts with -p, -o, -q and -v respectively.

Examples

Download all binaries for your platform

ffbinaries

Download all binaries for a specified platform

ffbinaries --platform=mac

Download only ffplay for 64-bit Windows, quiet output

ffbinaries ffplay --platform=win-64 --quiet

Download only ffmpeg and ffprobe, version 3.2 for 64-bit Linux, quiet output, save binaries in a specified directory

ffbinaries ffmpeg ffprobe -p=linux-64 -q -v=3.2 -o=/usr/local/bin

Additional commands

There are also ffbinaries help, ffbinaries versions and ffbinaries clearcache.

Programmatically

Methods

ffbinaries library exports the following methods:

  • downloadBinaries(platform, opts, callback) downloads and extracts the requested binaries.

    The opts parameter is an object that can contain these optional parameters:

    • destination: the path where the binaries will be downloaded to. If not provided it will default to ..
    • components: an array of string values that describes which components to download. If not provided it will default to all components available for the platform.
    • version: version of ffmpeg to download
    • force: ignore check for existing binaries in the destination and overwrite them if necessary
    • quiet: suppress verbose logs
    • tickerFn: a progress-update function, triggered with percentage as argument at an interval until download is completed
    • tickerInterval: frequency at which the ticker progress updates are issued (in ms; defaults to 1000)
  • getVersionData(version, callback) fetches the full data set without downloading any binaries.

  • listVersions(callback) returns the list of available versions from the API

  • listPlatforms() returns the list of available platforms

  • detectPlatform() returns the platform code of the machine as detected by the module.

  • resolvePlatform(input) resolves input to a platform code (matches aliases).

  • getBinaryFilename(component, platform) resolves a filename of a binary for a given platform (appends ".exe" in Windows).

  • locateBinariesSync(components, opts) looks for binaries already existing in the system. Returns object with located binaries, their paths and versions.

    opts parameter is an object that can specify these additional options:

    • paths to provide locations to check in first
    • ensureExecutable will set executable flag on the file if it's missing
  • clearCache() purges local cache

Examples

Download all binaries for your platform

var ffbinaries = require('ffbinaries');

ffbinaries.downloadBinaries(function () {
  console.log('Downloaded all binaries for current platform.');
});

Note: you don't need to check for existence of the binaries in the destination folder. ffbinaries will check if the binaries exist first and it will not attempt to re-download them unless you specify {force: true}.

Download only ffmpeg and ffprobe, version 3.2 for 64-bit Linux, quiet output, save binaries in a specified location

var ffbinaries = require('ffbinaries');
var dest = __dirname + '/binaries';

ffbinaries.downloadBinaries(['ffmpeg', 'ffprobe'], {platform: 'linux-64', quiet: true, destination: dest}, function () {
  console.log('Downloaded ffplay and ffprobe binaries for linux-64 to ' + dest + '.');
});

See more examples.

Platforms

The following platform codes are available:

windows-32 (aliases: win, windows, win-32), windows-64 (alias: win-64)

linux-32 (alias: linux), linux-64, linux-armhf (alias: linux-arm), linux-armel

osx-64 (aliases: mac, osx, mac-64)

You can use aliases as your platform code argument in both CLI and programmatically.

Included components

Mac Linux Windows
ffmpeg v v v
ffprobe v v v
ffserver v v
ffplay v v* v

(* Only linux-32 and linux-64 builds of ffplay 3.2 are currently available)

Source of binaries

The API providing data to the module is located at ffbinaries.com. The code is located in ffbinaries-api repo.

The binaries are hosted on GitHub as releases of ffbinaries-prebuilt repo.

Changelog

History of changes can be found in changelog.md file.

Contributing

If you'd like to contribute to this project have a look at contributing.md file for more information.

Reporting issues

If you're experiencing issues please update to the newest version and run ffbinaries clearcache.

If that doesn't resolve it simply raise an issue on GitHub.

Make sure to include the information about which version you're using, platform, the exact commands you're trying to execute and the output.

ffbinaries-node's People

Contributors

aaronjamt avatar agmcleod avatar aredfox avatar dudewheresmycode avatar jeongukjae avatar kevingodell avatar shpingalet007 avatar vot avatar zeevl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

ffbinaries-node's Issues

Download zip fow windows contains __MACOSX folder

Not sure if this is the right place to report this, but anyway, here goes:

Since the 8th of January there is a new version downloadable at https://ffbinaries.com/

Now, when our downloader lib (running on Windows) gets the latest version, the zip file also contains a folder which apparently seems to be for OSX systems:

image

Apart from it not making any sense, it also breaks the unzipper of the downloader lib, because it appears that it is running without creating subfolders when necessary.

As a workaround we now create the sub-folder and the file correctly unzips. However, to avoid future support issues it may make sense to package the windows version on its own.

Issue creating bin directory in electron asar package

Hi there. I ran into an issue where the package tries to create the bin folder: https://github.com/vot/ffbinaries-node/blob/master/ffbinaries-lib.js#L25, so it can ensure there is a destination to use here: https://github.com/vot/ffbinaries-node/blob/master/ffbinaries-lib.js#L303. Since I am using an asar package, it's not able to create a directory within the package itself. So i get a ENOTDIR error.

In my case i am specifying a destination to ffbinaries.downloadFiles, so I'm wondering if creating the bin directory should be invoked at function call time, instead of initialization time.

Anyways thanks for this package, it's been awesome for a small audio tool i've been wanting to make.

Replacing the request module

Hello.

The request module has been deprecated so I have made a fork that replaces it with axios.
All tests are passing and during the practical use no issues were spotted.
So I wanted to know whether or not you'd allow such a change to your original module so that I would know should I open a pull request or not?

Support changing cache directory

Hi, guys.

Thank you for maintaining this awesome package!

I tried to use this package in an environment that it doesn't have write access to home directory ( Lambda function on Localstack), and got this error.

"ENOENT: no such file or directory, mkdir '/home/sbx_user1051/.ffbinaries-cache'

I have write access to /tmp directory, so changed LOCAL_CACHE_DIR manually then it worked.

Can it support changing cache directory officially?

for example, like

import { setCacheDir, downloadBinaries } from 'ffbinaries'

setCacheDir('/tmp/.ffbinaries')
downloadBinaries(["ffmpeg"])

Or, just for my usecase, it is enough to set through environment variables like FFBINARIES_CACHE_DIR="/tmp/.ffbinaries".

use case for .clearCache()

I was testing deployment with your module because I am including it with my rtsp-cam-tester node app. I was testing various configurations and came across an error, which could very well be my fault. When my app loads, I called .clearCache() which did not throw an error. Later, when my app did some checking to see if ffmpeg is available and initiates a download via your module, it throws an error

internal/streams/legacy.js:59
      throw er; // Unhandled stream error in pipe.
      ^

Error: ENOENT: no such file or directory, open '/Users/kevinGodell/.ffbinaries-cache/ffmpeg-3.4-osx-64.zip.part'

So it seems that the cache was cleared, but when trying to download a fresh copy, it tried to look for the cache and did not find it. Otherwise, great module. Thanks. I don't really need this fixed. I just came across it when doing some testing that would not occur in production for me.

P.S. The main reason I am using your module vs the other ffmpeg modules is that yours gives me the control I needed to install only if i needed to. I found it impossible to package ffmpeg with my app when using "pkg."

Better error handling - Use of process.exit

Hi, thank you very much for this and related packages. It's great and easy to use.

I have only one issue with way errors are handled, because in case there is no internet (or some other error occurres) in listVersions and getVersionData functions, process.exit(1) is used. It makes it impossible for gracefully handling these errors programatically. I'm creating Electron app and without using child process or somehow overriding process.exit method it's not possible to keep the application from exiting.

I'm happy to create PR myself if I know it's going to be merged.

ffbinaries.com is down

Hi,

Seems like ffbinaries.com is down right now
It would be a good idea to enable proper caching on cloudflare?
Our app build depends on this to work...

I'm getting `Couldn't connect...` error message, diving deeper tells me the error is `certificate has expired`

Without changing anything on my end, I'm running my code again after a few months and getting Couldn't connect to ffbinaries.com API. Check your Internet connection.

I looked into what's reporting this, it's this line:

return callback(errorMsgs.connectionIssues);

Logging the err variable from there gives me:

"Error: certificate has expired
    at TLSSocket.onConnectSecure (_tls_wrap.js:1331:34)
    at TLSSocket.emit (events.js:210:5)
    at TLSSocket._finishInit (_tls_wrap.js:804:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:618:12)"

Which doesn't make any sense to me since I can access the url fine from Chrome/Postman. I'm getting the latest version of ffmpeg and ffprobe, and I've checked the url, it's correct. The url it's requesting is "https://ffbinaries.com/api/v1/latest"

Maybe the redirect has something to do with it? Anyway, I replaced the request function with fetch and it does work without issue, so maybe you could fix it that way.

This is what I cooked up real quick:

    fetch(API_URL + url).then(r => r.text().then(body => {

            var parsed;

            try {
                parsed = JSON.parse(body.toString());
            } catch (e) {
                return callback(errorMsgs.parsingVersionData);
            }

            RUNTIME_CACHE[version] = parsed;
            return callback(null, parsed);
        }).catch(e => console.warn('json err', e))
    ).catch(e => console.warn("fetch err", e))

No proper error checks here though.

I'm using node 16.20.0

Errors when using the API

First things first: thank you for your brilliant effort of making this available!

I am trying to get this running for a small electron app that I make for a friend of mine. I would like it to install ffmpeg on the first startup.

I am on OS X, node v6.9.1.

I couldn't get ffbinaries-node to download anything in my project, so I thought I test your examples.

When trying to run your examples, I get the following problems:

01-basic-usage.js

> node examples/01-basic-usage.js

Directories
 LOCAL_CACHE_DIR: /Users/caillou/.ffbinaries-cache
 CWD: /Users/caillou/tmp/ffbinaries-node
------------------------------------
Getting version data: latest
------------------------------------
Downloading binaries for osx-64:
err No versionUrls!
data undefined

02-listing-versions.js

> node examples/02-listing-versions.js

error Couldn't get valid data.

03-get-version-metadata.js

> cd examples
> node 03-get-version-metadata.js
Getting version data: 3.2
------------------------------------
error Couldn't get valid data.

Do you know what I am doing wrong?

Binaries for windows are failing

I am trying to use ffprobe to parse my files for processing but they return a file error, same goes for ffmpeg.
When i overwrite the executables with my regular ffmpeg it works like it's supposed to.

The executables downloaded by this package are half the size of my ffmpeg executables.

ffbinaries-node ffmpeg.exe: 67,081,216 bytes
ffbinaries-node ffprobe.exe: 6,993,152 bytes

Official ffmpeg.exe: 94,240,768 bytes
Official ffprobe.exe: 94,134,272 bytes

Source: https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2021-04-21-12-38/ffmpeg-n4.4-5-ge3fb0f0c88-win64-gpl-4.4.zip

The results from the linux executables are as expected.

Problem in running using github actions

Here the error which I get:

Error: ENOENT: no such file or directory, rename '/home/runner/.ffbinaries-cache/ffmpeg-4.4.1-linux-64.zip.part' -> '/home/runner/.ffbinaries-cache/ffmpeg-4.4.1-linux-64.zip'
at Object.renameSync (node:fs:1030:3)
at Request._callback (/home/runner/work/minigames/minigames/node_modules/ffbinaries/ffbinaries-lib.js:287:15)
at Request.self.callback (/home/runner/work/minigames/minigames/node_modules/request/request.js:185:22)
at Request.emit (node:events:513:28)
at Request.emit (node:domain:552:15)
at Request. (/home/runner/work/minigames/minigames/node_modules/request/request.js:1154:10)
at Request.emit (node:events:525:35)
at Request.emit (node:domain:552:15)
at IncomingMessage. (/home/runner/work/minigames/minigames/node_modules/request/request.js:1076:12)
at Object.onceWrapper (node:events:627:28)

Download progress

Is it currently possible to provide a download progress callback in the downloadFiles method? Just want to make sure I didn't miss something in the docs, before I hack around on it.

path must be a string or Buffer

When using the API, I get following error - below the error is the gulp-task I use.
Using Windows 7 (64bit) - node 7.0.0 - ffbinaries 0.1.5

Error:

SCHELPEY@AKDGPORT6348 C:\Dev\Repos\Kdg.Xtl4
> gulp build --prod
[14:37:39] Using gulpfile C:\Dev\Repos\Kdg.Xtl4\gulpfile.js
[14:37:39] Starting 'build'...
[14:37:39] Starting 'build:clean'...
[14:37:39] Finished 'build:clean' after 33 ms
[14:37:39] Starting 'copy:data'...
[14:37:39] Starting 'copy:ffmpeg'...
Trying to download FFMPEG for windows-64 to C:\Dev\Repos\Kdg.Xtl4\app\lib\ffmpeg...
Directories
 LOCAL_CACHE_DIR: C:\Users\SCHELPEY/.ffbinaries-cache
 CWD: C:\Dev\Repos\Kdg.Xtl4
------------------------------------
[14:37:39] 'copy:ffmpeg' errored after 868 μs
[14:37:39] TypeError: path must be a string or Buffer
    at Object.fs.mkdirSync (fs.js:846:18)
    at _ensureDirSync (C:\Dev\Repos\Kdg.Xtl4\node_modules\ffbinaries\ffbinaries-lib.js:20:9)
    at Object.downloadFiles (C:\Dev\Repos\Kdg.Xtl4\node_modules\ffbinaries\ffbinaries-lib.js:274:3)
    at Gulp.<anonymous> (C:\Dev\Repos\Kdg.Xtl4\gulp\tasks\copy\copy.ffmpeg.js:15:31)
    at module.exports (C:\Dev\Repos\Kdg.Xtl4\node_modules\orchestrator\lib\runTask.js:34:7)
    at Gulp.Orchestrator._runTask (C:\Dev\Repos\Kdg.Xtl4\node_modules\orchestrator\index.js:273:3)
    at Gulp.Orchestrator._runStep (C:\Dev\Repos\Kdg.Xtl4\node_modules\orchestrator\index.js:214:10)
    at Gulp.Orchestrator.start (C:\Dev\Repos\Kdg.Xtl4\node_modules\orchestrator\index.js:134:8)
    at runNextSet (C:\Dev\Repos\Kdg.Xtl4\node_modules\run-sequence\index.js:86:16)
    at Gulp.onTaskEnd (C:\Dev\Repos\Kdg.Xtl4\node_modules\run-sequence\index.js:75:5)
[14:37:39] 'build' errored after 50 ms
[14:37:39] TypeError in plugin 'run-sequence(copy:ffmpeg)'
Message:
    path must be a string or Buffer
Stack:
TypeError: path must be a string or Buffer
    at Object.fs.mkdirSync (fs.js:846:18)
    at _ensureDirSync (C:\Dev\Repos\Kdg.Xtl4\node_modules\ffbinaries\ffbinaries-lib.js:20:9)
    at Object.downloadFiles (C:\Dev\Repos\Kdg.Xtl4\node_modules\ffbinaries\ffbinaries-lib.js:274:3)
    at Gulp.<anonymous> (C:\Dev\Repos\Kdg.Xtl4\gulp\tasks\copy\copy.ffmpeg.js:15:31)
    at module.exports (C:\Dev\Repos\Kdg.Xtl4\node_modules\orchestrator\lib\runTask.js:34:7)
    at Gulp.Orchestrator._runTask (C:\Dev\Repos\Kdg.Xtl4\node_modules\orchestrator\index.js:273:3)
    at Gulp.Orchestrator._runStep (C:\Dev\Repos\Kdg.Xtl4\node_modules\orchestrator\index.js:214:10)
    at Gulp.Orchestrator.start (C:\Dev\Repos\Kdg.Xtl4\node_modules\orchestrator\index.js:134:8)
    at runNextSet (C:\Dev\Repos\Kdg.Xtl4\node_modules\run-sequence\index.js:86:16)
    at Gulp.onTaskEnd (C:\Dev\Repos\Kdg.Xtl4\node_modules\run-sequence\index.js:75:5)
[14:37:39] Finished 'copy:data' after 68 ms

Gulp Task:

The gulp task is seperated, inside plugins is ffbinaries named as ffmpeg. It spits out the correct platform for me, as you can see in the logs above. The outputfolder gets generated ok as well. I think the error resides somewhere in downloadFiles but I'm a bit lost.. Will try this on linux as well and report when I know more.

module.exports = (gulp, plugins) => {
    return () => {
        const platform = plugins.ffmpeg.detectPlatform();
        const outputFolder = plugins.path.resolve(plugins.path.join(plugins.config.paths.dest.lib, 'ffmpeg', '\\'));
        console.log(`Trying to download FFMPEG for ${platform} to ${outputFolder}...`);
        return plugins.ffmpeg.downloadFiles(platform, outputFolder.toString(), () => {
            console.log('Downloaded binaries for ' + platform + ' to ' + outputFolder + '.');
        });
    };
};

Binaries not downloading?

Found this module while looking for a way to convert mp4 to mp3, and it seemed useful. But I can't seem to get it to actually download anything?

var ffbinariesPlatform = ffbinaries.detectPlatform();

createDirectory('./ffbinaries'); // Creates directory
 
ffbinaries.downloadFiles(ffbinariesPlatform, {destination:'./ffbinaries'}, () => {
  	console.log('Done');
});

This seems to work, as it does log Done as expected. But nothing is saved to the ffbinaries folder. The folder exists, and no errors are thrown. Just doesn't seem to want to download the binaries there (or anywhere).

execSync write error when checking version

I just ran into an unusual situation, but did come up with a remedy for it. I was playing with deploying my ffmpeg-streamer app on a remote ubuntu server and ran into a little trouble.

I made a respawn app to keep track of ffmepg-streamer which will respawn it 10 seconds after if it exits due to crashing or somebody pressing the x button on it. Works surprisingly well and only took about 5 minutes to make. After running the process in the command line and sending it to the background with a trailing & (./respawn-linux-x64 ./ffmpeg-streamer-linux-x64 3000 &) and exiting the ssh terminal, it seemed that some permissions were lost and execSync could no longer check the version. Returned some type of cryptic EIO i/o write error.

I dug deep and tried many options with various versions of child processes such as execFileSync and spawnSync. The problem seems to originate from execSync and execFileSync using a shell, while spawnSync does not.

For line 412, I propose to make a small change which seems a little cleaner than the try catch:

    // check version
    if (result.found && result.isExecutable) {
      var stdout = childProcess.spawnSync(result.path, ['-version']).stdout;
      // if stdout.length === 0, then we must have stderr instead
      if (stdout.length) {
        result.version = stdout.toString().split(' ')[2];
      }
    }

spawnSync actually returns an object with properties such as output, stdout, stderr, etc. I just check stdout.length to make sure it is filled with something other than an empty buffer array of length 0. Verified this works for me on windows, mac, and ubuntu 17.

If this looks good to you, I could just make a PR. Let me know. Thanks.

feature request ffbinaries.findBinary()

I was just thinking about how i am using your module. Before starting a download of ffmpeg, I first check to see if there is a copy in the current directory(and check if it is executable). If not found there, I run a command to see if it is in PATH by calling ffmpeg -version and parsing the output to get the version number. If not found there, I then use your module to install fresh copy.

It could be a good addition if you incorporated that utility function to check for existence of binary.

const binary = ffbinaries.findBinary('ffmpeg');

//returns null if not found in the usual location, current dir, home dir, PATH, ...
if (binary) {
    console.log(binary.path, binary.version, ...etc)
}

I kinda do this starting about here. I also have to check process.pkg because I am packaging it into executable using nodejs module "pkg" and it does not give the correct running cwd when using process.cwd().

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.