libflac bindings to node.js with easy to use API
npm install flac-bindingsNodejs bindings to libFLAC
!Node-API v9
!Node CI

``
$ npm install flac-bindings
$ yarn add flac-bindings
`
This is a pure ESM package. If you get an error like require() of ES Module, then read this gist. You may also need to update to the latest version of supported node.js versions as ESM packages can be imported in CJS under certain circumstancies.
The library has some native code that binds the JS code to the flac library. Depending on your platform, an already-compiled library is available for you. The following logic applies:
- If your CPU is amd64/x86_64 and the OS is Linux/glibc, Linux/musl, macOS or Windows, and node version is in the N-API compatibility table for v8, then the prebuild version will download.arm64
- If your CPU is /aarch64 and the OS is Linux/glibc, Linux/musl or macOS, and node version is in the aformentioned compatibility table for v8, then the prebuild version will download.pkg-config
- If you have and libFLAC development package installed (apt install libflac-dev, pacman -S flac, apk add flac-dev, brew install flac...), then it will use this library and only compile the binding code. Requires you to also have Cmake installed.libogg
- In any other case, it will download and libFLAC source code and compile both libraries plus the binding code. Requires you to also have Cmake and git installed.
See How to compile section for more information.
For use it, include with
`javascript
// ESM import (Streams and native API alias)
import {
api,
FileDecoder,
StreamDecoder,
FileEncoder,
StreamEncoder,
} from 'flac-bindings';
// ESM import for native API
import {
Encoder,
Decoder,
format,
metadata,
metadata0,
SimpleIterator,
Chain,
Iterator,
fns,
} from 'flac-bindings/api';
`
> Note: _this library has its own TypeScript typings, so it's possible to use it in a TS project and have the right types_
> Note: _this library is written in ES Modules, and cannot be imported from CommonJS modules - see this_
Here's an example of using flac-bindings to encode some raw PCM data coming from process.stdin to a FLAC file that gets piped to process.stdout:
`js
import { StreamEncoder } from 'flac-bindings';
// create the Encoder instance
const encoder = new StreamEncoder({
channels: 2, // 2 channels (left and right)
bitsPerSample: 16, // 16-bit samples
samplerate: 44100, // 44,100 Hz sample rate
compressionLevel: 7,
});
// raw PCM data from stdin gets piped into the encoder
process.stdin.pipe(encoder);
// the generated FLAC file gets piped to stdout
encoder.pipe(process.stdout);
`
See examples for more examples. See the tests directory for even more examples using advanced API.
The module is be divided in various sections:
- StreamEncoder - a stream.Transform class for encoding raw PCM streamsstream.Writable
- FileEncoder - a class for encoding raw PCM streams into a filestream.Transform
- StreamDecoder - a class for decoding FLAC into a PCM streamstream.Readable
- FileDecoder - a class for decoding FLAC file into a PCM streamapi
- - the native bindings, easy to use from JS sideStreamEncoder
- format - includes only the functions and some types
- Encoder - the APIStreamDecoder
- Decoder - the APIStreamMetadata
- metadata - includes the classes and their methods
- metadata0 - metadata level 0 APIs
- SimpleIterator - metadata level 1 iterator class
- Chain - metadata level 2 Chain class
- Iterator - metadata level 2 Iterator class
The package includes typings that could help you :)
All memory is managed by the library. But there are some methods that give you references to objects that can be destroyed before the JS object. These methods are documented with such special behaviour.
Almost every function/method expects his parameters in his right type (as in the FLAC documentation). If it not, an JS exception will be thrown, or in the worst scenario, a crash (_report an issue if this happens_). So, pay attention on the types of the functions (the typings are just to help you ๐).
Callbacks don't follow exactly the same signature that shows in Encoder and Decoder sections (from the FLAC documentation). They don't need some of the parameters as in JS there are other ways to get the encoder/decoder instance and some context. The init functions don't receive any private data.
There are asynchronous functions and methods for IO bound tasks. The syncrhonous API will be faster, but will block node. If you are writing an server or expect high concurrency, use the asynchronous API.
You need node version that supports v8 N-API (see compatibility table), which is supported in node v14.17.0/v16.0.0 or higher. Recommended use of BigInt when possible to have numbers be represented without truncation (Number can only store 53 bit integers! ๐คจ).
> Note: Buffers from Encoder, Decoder and IO Callbacks (metadata level 2) have a strict lifetime: buffers are ensured to be valid inside the callback itself, if the buffer must be used outside the callback, make a copy.
When using StreamEncoder, StreamDecoder, FileEncoder or FileDecoder, and something does not work properly, you can enable verbose/debug logs by defining the environment variable DEBUG=flac:* (see debug package for more information). Each class has its own namespace, so you can enable debug logs only for some of them. See below the list of namespaces:
- StreamEncoder: flac:encoder:streamFileEncoder
- : flac:encoder:fileStreamDecoder
- : flac:decoder:streamFileDecoder
- : flac:decoder:filepost-install
- The script: flac:build
> !! These logs can be useful when creating a new issue.
You can also try to debug the native code by setting up a test JS file and launching the debugger with the node executable and arguments the script itself.
In case you need to compile or want to, ensure to install the optional peer dependencies! These are optional because they are not required in general terms as the pre-compiled code is enought for most cases.
To compile the bindings you need Cmake installed in your system and accessible from the terminal, and the C and C++ compilers as well. On Windows, the compilers can be installed easily with npm install --global --production windows-build-tools. Don't forget git. It is mandatory!
There are some options to use when compiling. The build tries to use an already installed compatible dev package of libflac (apt install libflac-dev, pacman -S flac, apk add flac-dev, brew install flac...), but with FLAC_BINDINGS_USE_FLAC_SOURCES will force to download the sources and compile everything from there.
> Supported libFLAC versions are 1.3.x and 1.4.x (binary versions 10 and 12).
Then, you just need to recompile the package with: npm rebuild flac-bindings. If you are inside this repo tree, then run npm run install.
For more advanced commands for compilation inside the repo tree, see below:
`shCompile (debug version)
-p -> If desired, tell cmake to run with parallel jobs (faster)
npx cmake-js build --debug -p 4
How to run the tests
With a dev environment, and being able to compile the project, ensure to have installed the
flac CLI (apt install flac, pacman -S flac, apk add flac, brew install flac...) and present in the $PATH. It is recommended to have installed the FLAC dev package. Also ensure to have installed Cmake and available in the $PATH.The recommended steps are:
`sh
Do not run tests with sanitizers enabled, it's tricky to make it work
npx cmake-js configure --debug
npx cmake-js build --debug -p 4
npm testTo run tests with coverage (requires lcov to be installed)
scripts/coverage.sh rebuild # first time
script/coverage.sh # next times
`Happy
npm test` runs :)See the wiki for the documentation.