├── .gitignore ├── .prettierrc.json ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── lib ├── build │ ├── Lame.js │ ├── Lame.js.map │ ├── LameOptions.js │ ├── LameOptions.js.map │ ├── LameTypings.js │ └── LameTypings.js.map └── src │ ├── Lame.ts │ ├── LameOptions.ts │ └── LameTypings.ts ├── package-lock.json ├── package.json ├── temp ├── encoded │ └── .keep └── raw │ └── .keep ├── test ├── .keep ├── example.mp3 ├── example.wav ├── example.wav_LICENSE ├── notAWavFile.wav ├── notAnMp3File.mp3 ├── testpic.jpg └── tests.js ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | *.log 3 | npm-debug.log* 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # node-waf configuration 11 | .lock-wscript 12 | 13 | # Dependency directories 14 | node_modules 15 | 16 | # Lib dependencies 17 | bin/* 18 | 19 | # Optional npm cache directory 20 | .npm 21 | 22 | # Optional REPL history 23 | .node_repl_history 24 | 25 | # OS generated files 26 | .DS_Store* 27 | ehthumbs.db 28 | Icon? 29 | Thumbs.db 30 | 31 | # IDE 32 | .vscode/* 33 | .idea/* 34 | 35 | # Test 36 | test/encoded.mp3 -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2021, devowl.io GmbH and Jan Karres 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 6 | 7 | Source: http://opensource.org/licenses/ISC -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-lame 2 | 3 | node-lame Logo 4 | 5 | LAME is an open-source encoder that encodes and decodes audio to the MP3 file format. For all MP3 needs a Node.js wrapper of the full [LAME](http://lame.sourceforge.net/) command line. 6 | 7 | The encoder reads WAV-, MP1-, MP2- and MP3-format and encodes it into an MP3 file. The decoder reads MP3-format and decodes it into WAV. 8 | 9 | ## Requirements 10 | 11 | - Linux or MacOS (This package is NOT tested on Windows) 12 | - Lame Installed (View instructions below) 13 | - Node 12.20.\* or newer 14 | 15 | ## Installation 16 | 17 | You can install it with `npm`: 18 | 19 | ```bash 20 | $ npm install node-lame 21 | ``` 22 | 23 | If you have not installed [LAME](http://lame.sourceforge.net/) yet, please use the following instruction. 24 | 25 | ### Install on Debian 26 | 27 | ```bash 28 | $ sudo apt-get install lame 29 | ``` 30 | 31 | ### Install on MacOS with brew 32 | 33 | ```bash 34 | $ brew install lame 35 | ``` 36 | 37 | ### Install on Windows 38 | 39 | 1. Go to the the [Lame Download Page](https://lame.buanzo.org/#lamewindl) and download the EXE or ZIP file. 40 | 2. Navigate to the directory Lame was installed in (most commonly `C:\Program Files (x86)\Lame For Audacity`). 41 | 3. Add the directory to your [Environment Variables](https://www.java.com/en/download/help/path.xml). 42 | 43 | ## Examples 44 | 45 | ### Encode from file to file 46 | 47 | ```node 48 | const Lame = require("node-lame").Lame; 49 | 50 | const encoder = new Lame({ 51 | output: "./audio-files/demo.mp3", 52 | bitrate: 192, 53 | }).setFile("./audio-files/demo.wav"); 54 | 55 | encoder 56 | .encode() 57 | .then(() => { 58 | // Encoding finished 59 | }) 60 | .catch((error) => { 61 | // Something went wrong 62 | }); 63 | ``` 64 | 65 | ### Encode from file to buffer 66 | 67 | ```node 68 | const Lame = require("node-lame").Lame; 69 | 70 | const encoder = new Lame({ 71 | output: "buffer", 72 | bitrate: 192, 73 | }).setFile("./audio-files/demo.wav"); 74 | 75 | encoder 76 | .encode() 77 | .then(() => { 78 | // Encoding finished 79 | const buffer = encoder.getBuffer(); 80 | }) 81 | .catch((error) => { 82 | // Something went wrong 83 | }); 84 | ``` 85 | 86 | ### Encode from buffer to file 87 | 88 | ```node 89 | [...] 90 | 91 | const Lame = require("node-lame").Lame; 92 | 93 | const encoder = new Lame({ 94 | "output": "./audio-files/demo.mp3", 95 | "bitrate": 192 96 | }).setBuffer(audioFileBuffer); 97 | 98 | encoder.encode() 99 | .then(() => { 100 | // Encoding finished 101 | }) 102 | .catch((error) => { 103 | // Something went wrong 104 | }); 105 | ``` 106 | 107 | ### Encode from buffer to buffer 108 | 109 | ```node 110 | [...] 111 | 112 | const Lame = require("node-lame").Lame; 113 | 114 | const encoder = new Lame({ 115 | "output": "buffer", 116 | "bitrate": 192 117 | }).setBuffer(audioFileBuffer); 118 | 119 | encoder.encode() 120 | .then(() => { 121 | // Encoding finished 122 | const buffer = encoder.getBuffer(); 123 | }) 124 | .catch((error) => { 125 | // Something went wrong 126 | }); 127 | ``` 128 | 129 | ### Get status of encoder as object 130 | 131 | ```node 132 | const Lame = require("node-lame").Lame; 133 | 134 | const encoder = new Lame({ 135 | output: "buffer", 136 | bitrate: 192, 137 | }).setFile("./audio-files/demo.wav"); 138 | 139 | encoder 140 | .encode() 141 | .then(() => { 142 | // Encoding finished 143 | }) 144 | .catch((error) => { 145 | // Something went wrong 146 | }); 147 | 148 | const status = encoder.getStatus(); 149 | ``` 150 | 151 | ### Get status of encoder as EventEmitter 152 | 153 | ```node 154 | const Lame = require("node-lame").Lame; 155 | 156 | const encoder = new Lame({ 157 | output: "buffer", 158 | bitrate: 192, 159 | }).setFile("./audio-files/demo.wav"); 160 | 161 | const emitter = encoder.getEmitter(); 162 | 163 | emitter.on("progress", ([progress, eta]) => { 164 | // On progress of encoding. Progress in percent and estimated time of arrival as mm:ss 165 | }); 166 | 167 | emitter.on("finish", () => { 168 | // On finish 169 | }); 170 | 171 | emitter.on("error", (error) => { 172 | // On error 173 | }); 174 | 175 | encoder 176 | .encode() 177 | .then(() => { 178 | // Encoding finished 179 | }) 180 | .catch((error) => { 181 | // Something went wrong 182 | }); 183 | ``` 184 | 185 | ### Decode from file to file 186 | 187 | ```node 188 | const Lame = require("node-lame").Lame; 189 | 190 | const decoder = new Lame({ 191 | output: "./audio-files/demo.wav", 192 | }).setFile("./audio-files/demo.mp3"); 193 | 194 | decoder 195 | .decode() 196 | .then(() => { 197 | // Decoding finished 198 | }) 199 | .catch((error) => { 200 | // Something went wrong 201 | }); 202 | ``` 203 | 204 | ### Decode from file to buffer 205 | 206 | ```node 207 | const Lame = require("node-lame").Lame; 208 | 209 | const decoder = new Lame({ 210 | output: "buffer", 211 | }).setFile("./audio-files/demo.mp3"); 212 | 213 | decoder 214 | .decode() 215 | .then(() => { 216 | // Decoding finished 217 | const buffer = decoder.getBuffer(); 218 | }) 219 | .catch((error) => { 220 | // Something went wrong 221 | }); 222 | ``` 223 | 224 | ### Decode from buffer to file 225 | 226 | ```node 227 | [...] 228 | 229 | const Lame = require("node-lame").Lame; 230 | 231 | const decoder = new Lame({ 232 | "output": "./audio-files/demo.wav" 233 | }).setBuffer(mp3InputBuffer); 234 | 235 | decoder.decode() 236 | .then(() => { 237 | // Decoding finished 238 | }) 239 | .catch((error) => { 240 | // Something went wrong 241 | }); 242 | ``` 243 | 244 | ### Decode from buffer to buffer 245 | 246 | ```node 247 | [...] 248 | 249 | const Lame = require("node-lame").Lame; 250 | 251 | const decoder = new Lame({ 252 | "output": "buffer" 253 | }).setBuffer(mp3InputBuffer); 254 | 255 | decoder.decode() 256 | .then(() => { 257 | // Decoding finished 258 | const buffer = decoder.getBuffer(); 259 | }) 260 | .catch((error) => { 261 | // Something went wrong 262 | }); 263 | ``` 264 | 265 | ### Get status of decoder as object 266 | 267 | ```node 268 | const Lame = require("node-lame").Lame; 269 | 270 | const decoder = new Lame({ 271 | output: "buffer", 272 | }).setFile("./audio-files/demo.mp3"); 273 | 274 | decoder 275 | .encode() 276 | .then(() => { 277 | // Decoding finished 278 | }) 279 | .catch((error) => { 280 | // Something went wrong 281 | }); 282 | 283 | const status = decoder.getStatus(); 284 | ``` 285 | 286 | ### Get status of decoder as EventEmitter 287 | 288 | ```node 289 | const Lame = require("node-lame").Lame; 290 | 291 | const decoder = new Lame({ 292 | output: "buffer", 293 | }).setFile("./audio-files/demo.mp3"); 294 | 295 | const emitter = decoder.getEmitter(); 296 | 297 | emitter.on("progress", ([progress]) => { 298 | // On progress of decoder; in percent 299 | }); 300 | 301 | emitter.on("finish", () => { 302 | // On finish 303 | }); 304 | 305 | emitter.on("error", (error) => { 306 | // On error 307 | }); 308 | 309 | decoder 310 | .decode() 311 | .then(() => { 312 | // Decoding finished 313 | }) 314 | .catch((error) => { 315 | // Something went wrong 316 | }); 317 | ``` 318 | 319 | ## All options 320 | 321 | | Option | Description | Values | Default | 322 | | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | 323 | | output | Output filename | Path | 324 | | raw | Assume the input file is raw pcm. Sampling rate and mono/stereo/jstereo must be specified. For each stereo sample, LAME expects the input data to be ordered left channel first, then right channel. By default, LAME expects them to be signed integers with a bitwidth of 16. | boolean | `false` | 325 | | swap-bytes | Swap bytes in the input file or output file when using decoding. For sorting out little endian/big endian type problems. | boolean | `false` | 326 | | sfreq | Required only for raw PCM input files. Otherwise it will be determined from the header of the input file. LAME will automatically resample the input file to one of the supported MP3 samplerates if necessary. | `8`, `11.025`, `12`, `16`, `22.05`, `24`, `32`, `44.1`, `48` | `undefined` | 327 | | bitwidth | Required only for raw PCM input files. Otherwise it will be determined from the header of the input file. | `8`, `16`, `24`, `32` | `16` | 328 | | signed | Required only for raw PCM input files. Instructs LAME that the samples from the input are signed. | boolean | `false`; `true` for 16, 24 and 32 bits raw pcm data | 329 | | unsigned | Required only for raw PCM input files and only available at bitwidth 8. Instructs LAME that the samples from the input are unsigned (the default for 8 bits raw pcm data, where 0x80 is zero). | boolean | `undefined` | 330 | | little-endian | Required only for raw PCM input files. Instructs LAME that the samples from the input are in little-endian form. | boolean | `undefined` | 331 | | big-endian | Required only for raw PCM input files. Instructs LAME that the samples from the input are in big-endian form. | boolean | `undefined` | 332 | | mp2Input | Assume the input file is a MPEG Layer II (ie MP2) file. If the filename ends in ".mp2" LAME will assume it is a MPEG Layer II file. | boolean | `undefined` | 333 | | mp3Input | Assume the input file is a MP3 file. Useful for downsampling from one mp3 to another. | boolean | `undefined` | 334 | | mode | Details see [LAME man page](https://linux.die.net/man/1/lame). | `s` simple stereo, `j` joint stereo, `f` forced MS stereo, `d` dual mono, `m` mono, `l` left channel only, `r` right channel only | `j` or `s` (see details) | 335 | | to-mono | Mix the stereo input file to mono and encode as mono. The downmix is calculated as the sum of the left and right channel, attenuated by 6 dB. | boolean | `false` | 336 | | channel-different-block-sizes | Allows the left and right channels to use different block size types. | boolean | `false` | 337 | | freeformat | Produces a free format bitstream. With this option, you can use `bitrate` with any bitrate higher than 8 kbps. | `FreeAmp` up to 440 kbps, `in_mpg123` up to 560 kbps, `l3dec` up to 310 kbps, `LAME` up to 560 kbps, `MAD` up to 640 kbps | `undefined` | 338 | | disable-info-tag | Disable writing of the INFO Tag on encoding. | boolean | `false` | 339 | | comp | Instead of choosing bitrate, using this option, user can choose compression ratio to achieve. | number | `undefined` | 340 | | scale | Scales input volume by n. This just multiplies the PCM data (after it has been converted to floating point) by n. | number | `1` | 341 | | scale-l | Same as `scale`, but for left channel only. | number | `undefined` | 342 | | scale-r | Same as `scale`, but for right channel only. | number | `undefined` | 343 | | replaygain-fast | Compute ReplayGain fast but slightly inaccurately. Details see [LAME man page](https://linux.die.net/man/1/lame). | boolean | `false` | 344 | | replaygain-accurate | Compute ReplayGain more accurately and find the peak sample. Details see [LAME man page](https://linux.die.net/man/1/lame). | boolean | `false` | 345 | | no-replaygain | Disable ReplayGain analysis. By default ReplayGain analysis is enabled. Details see [LAME man page](https://linux.die.net/man/1/lame). | boolean | `false` | 346 | | clip-detect | Clipping detection. | boolean | `false` | 347 | | preset | Use one of the built-in presets. Details see [LAME man page](https://linux.die.net/man/1/lame). | `medium`, `standard`, `extreme` or `insane` | `undefined` | 348 | | noasm | Disable specific assembly optimizations. Quality will not increase, only speed will be reduced. | `mmx`, `3dnow` or `sse` | `undefined` (probably depending on OS) | 349 | | quality | Bitrate is of course the main influence on quality. The higher the bitrate, the higher the quality. But for a given bitrate, we have a choice of algorithms to determine the best scalefactors and Huffman encoding (noise shaping). | `0` (best) to `9` (worst) | `5` | 350 | | bitrate | For MPEG-1 (sampling frequencies of 32, 44.1 and 48 kHz): n = `32`, `40`, `48`, `56`, `64`, `80`, `96`, `112`, `128`, `160`, `192`, `224`, `256`, `320`; For MPEG-2 (sampling frequencies of 16, 22.05 and 24 kHz): n = `8`, `16`, `24`, `32`, `40`, `48`, `56`, `64`, `80`, `96`, `112`, `128`, `144`, `160`; For MPEG-2.5 (sampling frequencies of 8, 11.025 and 12 kHz): n = `8`, `16`, `24`, `32`, `40`, `48`, `56`, `64` | See description | `128` for MPEG1 and `64` for MPEG2 | 351 | | force-bitrate | Strictly enforce the `bitrate` option. This is mainly for use with hardware players that do not support low bitrate mp3. | boolean | `false` | 352 | | cbr | Enforce use of constant bitrate. | boolean | `false` | 353 | | abr | ABR (average bitrate) options. Turns on encoding with a targeted average bitrate of n kbits, allowing to use frames of different sizes. | `8` to `310` | `undefined` | 354 | | vbr | Use variable bitrate. | boolean | `false` | 355 | | vbr-quality | Enable `vbr` and specifies the value of VBR quality. | `0` (best) to `9` (worst) | `4` | 356 | | ignore-noise-in-sfb21 | LAME ignore noise in sfb21, like in CBR. | boolean | `false` | 357 | | emp | All this does is set a flag in the MP3 header bitstream. If you have a PCM input file where one of the above types of (obsolete) emphasis has been applied, you can set this flag in LAME. Then the mp3 decoder should de-emphasize the output during playback, although most decoders ignore this flag. | `n` none, `5` 0/15 microseconds, `c` citt j.17 | `n` | 358 | | mark-as-copyrighted | Mark the encoded file as being copyrighted. | boolean | `false` | 359 | | mark-as-copy | Mark the encoded file as being a copy. | boolean | `false` | 360 | | crc-error-protection | Turn on CRC error protection.It will add a cyclic redundancy check (CRC) code in each frame, allowing to detect transmission errors that could occur on the MP3 stream. | boolean | `false` | 361 | | nores | Disable the bit reservoir. Each frame will then become independent from previous ones, but the quality will be lower. | boolean | `false` | 362 | | strictly-enforce-ISO | With this option, LAME will enforce the 7680 bit limitation on total frame size. | boolean | `false` | 363 | | lowpass | Set a lowpass filtering frequency in kHz. Frequencies specified one will be cutoff. | number | `undefined` | 364 | | lowpass-width | Set the width of the lowpass filter in percent. | number | `15` | 365 | | highpass | Set an highpass filtering frequency in kHz. | number | `undefined` | 366 | | highpass-width | Set the width of the highpass filter in percent. | number | `15` | 367 | | resample | Output sampling frequency (for encoding). If not specified, LAME will automatically resample the input when using high compression ratios. | `8`, `11.025`, `12`, `16`, `22.05`, `24`, `32`, `44.1`, `48` | `undefined` | 368 | | meta | Meta data for MP3. | Object | `undefined` | 369 | 370 | _Meta options_ 371 | 372 | | Option | Description | Values | Default | 373 | | ----------------- | ----------------------------------------------------------------------------- | ------- | ----------- | 374 | | title | Set title tag (max 30 chars for version 1 tag). | String | `undefined` | 375 | | artist | Set artist tag (max 30 chars for version 1 tag). | String | `undefined` | 376 | | album | Set album tag (max 30 chars for version 1 tag). | String | `undefined` | 377 | | year | Set year tag. | String | `undefined` | 378 | | comment | Set user-defined text (max 30 chars for v1 tag, 28 for v1.1). | String | `undefined` | 379 | | track | Set track tag, with or without number of total tracks. | String | `undefined` | 380 | | genre | Set genre tag (max 30 chars for version 1 tag). | String | `undefined` | 381 | | artwork | Set album artwork image (path to jpeg/png/gif file, v2.3 tag). | String | `undefined` | 382 | | add-id3v2 | Force addition of version 2 tag. | boolean | `false` | 383 | | id3v1-only | Add only a version 1 tag. | boolean | `false` | 384 | | id3v2-only | Add only a version 2 tag. | boolean | `false` | 385 | | id3v2-latin1 | Add meta options in ISO-8859-1 text encoding. | boolean | `false` | 386 | | id3v2-utf16 | Add meta options in unicode text encoding. | boolean | `false` | 387 | | space-id3v1 | Pad version 1 tag with spaces instead of nulls. | boolean | `false` | 388 | | pad-id3v2 | Same as `pad-id3v2-size` value `128` | boolean | `false` | 389 | | pad-id3v2-size | Adds version 2 tag, pad with extra "num" bytes. | number | `undefined` | 390 | | ignore-tag-errors | Ignore errors in values passed for tags, use defaults in case an error occurs | boolean | `false` | 391 | | genre-list | Print alphabetically sorted ID3 genre list and exit | string | `undefined` | 392 | 393 | Option description text from [LAME man page](https://linux.die.net/man/1/lame). Based on LAME version [3.99.5](https://sourceforge.net/projects/lame/files/lame/3.99/) from Feb 28, 2012. 394 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from "events"; 2 | 3 | declare namespace Options { 4 | type sfreq = 8 | 11.025 | 12 | 16 | 22.05 | 24 | 32 | 44.1 | 48; 5 | type bitwidth = 8 | 16 | 24 | 32; 6 | type mode = "s" | "j" | "f" | "d" | "m" | "l" | "r"; 7 | type freeformat = "FreeAmp" | "in_mpg123" | "l3dec" | "LAME" | "MAD"; 8 | type preset = "medium" | "standard" | "extreme" | "insane"; 9 | type noasm = "mmx" | "3dnow" | "sse"; 10 | type quality = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; 11 | type bitrate = 12 | | 8 13 | | 16 14 | | 24 15 | | 32 16 | | 40 17 | | 48 18 | | 56 19 | | 64 20 | | 80 21 | | 96 22 | | 112 23 | | 128 24 | | 144 25 | | 160 26 | | 192 27 | | 224 28 | | 256 29 | | 320; 30 | type emp = "n" | 5 | "c"; 31 | type resample = 8 | 11.025 | 12 | 16 | 22.05 | 24 | 32 | 44.1 | 48; 32 | 33 | interface meta { 34 | title?: string; 35 | artist?: string; 36 | album?: string; 37 | year?: string; 38 | comment?: string; 39 | track?: string; 40 | genre?: string; 41 | artwork?: string; 42 | 43 | "add-id3v2"?: boolean; 44 | "id3v1-only"?: boolean; 45 | "id3v2-only"?: boolean; 46 | "id3v2-latin1"?: boolean; 47 | "id3v2-utf16"?: boolean; 48 | "space-id3v1"?: boolean; 49 | "pad-id3v2-size"?: number; 50 | "genre-list"?: string; 51 | "ignore-tag-errors"?: boolean; 52 | } 53 | } 54 | 55 | declare interface Options { 56 | output: string | "buffer"; 57 | raw?: boolean; 58 | "swap-bytes"?: boolean; 59 | sfreq?: Options.sfreq; 60 | bitwidth?: Options.bitwidth; 61 | signed?: boolean; 62 | unsigned?: boolean; 63 | "little-endian"?: boolean; 64 | "big-endian"?: boolean; 65 | mp2Input?: boolean; 66 | mp3Input?: boolean; 67 | mode?: Options.mode; 68 | "to-mono"?: boolean; 69 | "channel-different-block-sizes"?: boolean; 70 | freeformat?: Options.freeformat; 71 | "disable-info-tag"?: boolean; 72 | comp?: number; 73 | scale?: number; 74 | "scale-l"?: number; 75 | "scale-r"?: number; 76 | "replaygain-fast"?: boolean; 77 | "replaygain-accurate"?: boolean; 78 | "no-replaygain"?: boolean; 79 | "clip-detect"?: boolean; 80 | preset?: Options.preset; 81 | noasm?: Options.noasm; 82 | quality?: Options.quality; 83 | bitrate?: Options.bitrate; 84 | "force-bitrate"?: boolean; 85 | cbr?: boolean; 86 | abr?: number; 87 | vbr?: boolean; 88 | "vbr-quality"?: number; 89 | "ignore-noise-in-sfb21"?: boolean; 90 | emp?: Options.emp; 91 | "mark-as-copyrighted"?: boolean; 92 | "mark-as-copy"?: boolean; 93 | "crc-error-protection"?: boolean; 94 | nores?: boolean; 95 | "strictly-enforce-ISO"?: boolean; 96 | lowpass?: number; 97 | "lowpass-width"?: number; 98 | highpass?: number; 99 | "highpass-width"?: number; 100 | resample?: Options.resample; 101 | meta?: Options.meta; 102 | } 103 | 104 | declare interface LameStatus { 105 | started: boolean; 106 | finished: boolean; 107 | progress: number; 108 | eta: string; 109 | } 110 | 111 | declare class Lame { 112 | constructor(options: Options); 113 | 114 | public setFile(path: string): Lame; 115 | public setBuffer(file: Buffer): Lame; 116 | public getFile(): string; 117 | public getBuffer(): Buffer; 118 | public getEmitter(): EventEmitter; 119 | public getStatus(): LameStatus; 120 | 121 | public encode(): Promise; 122 | public decode(): Promise; 123 | private progress(type: "encode" | "decode"): Promise; 124 | private execProgress( 125 | inputFilePath: string, 126 | args: string[], 127 | type: "encode" | "decode" 128 | ); 129 | private tempFilePathGenerator(type: "raw" | "encoded"): string; 130 | private removeTempFilesOnError(); 131 | } 132 | 133 | export { Lame }; 134 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Jan Karres (https://jankarres.com/) 3 | */ 4 | 5 | "use strict"; 6 | 7 | module.exports = require('./lib/build/Lame'); 8 | -------------------------------------------------------------------------------- /lib/build/Lame.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.Lame = void 0; 4 | const LameOptions_1 = require("./LameOptions"); 5 | const fs_1 = require("fs"); 6 | const util_1 = require("util"); 7 | const child_process_1 = require("child_process"); 8 | const events_1 = require("events"); 9 | /** 10 | * Wrapper for Lame for Node 11 | * 12 | * @class Lame 13 | */ 14 | class Lame { 15 | /** 16 | * Creates an instance of Lame and set all options 17 | * @param {Options} options 18 | */ 19 | constructor(options) { 20 | this.status = { 21 | started: false, 22 | finished: false, 23 | progress: undefined, 24 | eta: undefined 25 | }; 26 | this.emitter = new events_1.EventEmitter(); 27 | this.options = options; 28 | this.args = new LameOptions_1.LameOptions(this.options).getArguments(); 29 | } 30 | /** 31 | * Set file path of audio to decode/encode 32 | * 33 | * @param {string} filePath 34 | */ 35 | setFile(path) { 36 | if (!fs_1.existsSync(path)) { 37 | throw new Error("Audio file (path) does not exist"); 38 | } 39 | this.filePath = path; 40 | this.fileBuffer = undefined; 41 | return this; 42 | } 43 | /** 44 | * Set file buffer of audio to decode/encode 45 | * 46 | * @param {Buffer} file 47 | */ 48 | setBuffer(file) { 49 | if (!util_1.isBuffer(file)) { 50 | throw new Error("Audio file (buffer) dose not exist"); 51 | } 52 | this.fileBuffer = file; 53 | this.filePath = undefined; 54 | return this; 55 | } 56 | /** 57 | * Get decoded/encoded file path 58 | * 59 | * @returns {string} Path of decoded/encoded file 60 | */ 61 | getFile() { 62 | if (this.progressedFilePath == undefined) { 63 | throw new Error("Audio is not yet decoded/encoded"); 64 | } 65 | return this.progressedFilePath; 66 | } 67 | /** 68 | * Get decoded/encoded file as buffer 69 | * 70 | * @returns {Buffer} decoded/Encoded file 71 | */ 72 | getBuffer() { 73 | if (this.progressedBuffer == undefined) { 74 | throw new Error("Audio is not yet decoded/encoded"); 75 | } 76 | return this.progressedBuffer; 77 | } 78 | /** 79 | * Get event emitter 80 | * 81 | * @returns {EventEmitter} 82 | */ 83 | getEmitter() { 84 | return this.emitter; 85 | } 86 | /** 87 | * Get status of converter 88 | * 89 | * @returns {LameStatus} 90 | */ 91 | getStatus() { 92 | return this.status; 93 | } 94 | /** 95 | * Encode audio file by Lame 96 | * 97 | * @return {Promise} 98 | */ 99 | encode() { 100 | return this.progress("encode"); 101 | } 102 | /** 103 | * Decode audio file by Lame 104 | * 105 | * @return {Promise} 106 | */ 107 | decode() { 108 | return this.progress("decode"); 109 | } 110 | /** 111 | * Decode/Encode audio file by Lame 112 | * 113 | * @return {Promise} 114 | */ 115 | progress(type) { 116 | if (this.filePath == undefined && this.fileBuffer == undefined) { 117 | throw new Error("Audio file to encode is not set"); 118 | } 119 | // Set decode flag to progress a MP3 to WAV decode 120 | const args = this.args; 121 | if (type == "decode") { 122 | args.push("--decode"); 123 | } 124 | if (this.fileBuffer != undefined) { 125 | // File buffer is set; write it as temp file 126 | this.fileBufferTempFilePath = this.tempFilePathGenerator("raw", type); 127 | return new Promise((resolve, reject) => { 128 | fs_1.writeFile(this.fileBufferTempFilePath, this.fileBuffer, err => { 129 | if (err) { 130 | reject(err); 131 | return; 132 | } 133 | resolve(this.fileBufferTempFilePath); 134 | }); 135 | }) 136 | .then((file) => { 137 | return this.execProgress(file, args, type); 138 | }) 139 | .catch((error) => { 140 | this.removeTempFilesOnError(); 141 | throw error; 142 | }); 143 | } 144 | else { 145 | // File path is set 146 | return this.execProgress(this.filePath, args, type).catch((error) => { 147 | this.removeTempFilesOnError(); 148 | throw error; 149 | }); 150 | } 151 | } 152 | /** 153 | * Execute decoding/encoding via spawn Lame 154 | * 155 | * @private 156 | * @param {string} inputFilePath Path of input file 157 | */ 158 | execProgress(inputFilePath, args, type) { 159 | // Add output settings args 160 | args.push("--disptime"); 161 | args.push("1"); 162 | // Add output file to args, if not undefined in options 163 | if (this.options.output == "buffer") { 164 | const tempOutPath = this.tempFilePathGenerator("encoded", type); 165 | args.unshift(`${tempOutPath}`); 166 | // Set decode/encoded file path 167 | this.progressedBufferTempFilePath = tempOutPath; 168 | } 169 | else { 170 | // Set decode/encoded file path 171 | this.progressedFilePath = this.options.output; 172 | args.unshift(this.progressedFilePath); 173 | } 174 | // Add input file to args 175 | args.unshift(inputFilePath); 176 | // Spawn instance of encoder and hook output methods 177 | this.status.started = true; 178 | this.status.finished = false; 179 | this.status.progress = 0; 180 | this.status.eta = undefined; 181 | /** 182 | * Handles output of stdout (and stderr) 183 | * Parses data from output into object 184 | * 185 | * @param {(String | Buffer)} data 186 | */ 187 | const progressStdout = (data) => { 188 | data = data.toString().trim(); 189 | // Every output of Lame comes as "stderr". Deciding if it is an error or valid data by regex 190 | if (data.length > 6) { 191 | if (type == "encode" && 192 | data.search("Writing LAME Tag...done") > -1) { 193 | // processing done 194 | this.status.finished = true; 195 | this.status.progress = 100; 196 | this.status.eta = "00:00"; 197 | this.emitter.emit("finish"); 198 | this.emitter.emit("progress", [ 199 | this.status.progress, 200 | this.status.eta 201 | ]); 202 | } 203 | else if (type == "encode" && 204 | data.search(/\((( [0-9])|([0-9]{2})|(100))%\)\|/) > -1) { 205 | // status of processing 206 | const progressMatch = data.match(/\((( [0-9])|([0-9]{2})|(100))%\)\|/); 207 | const etaMatch = data.match(/[0-9]{1,2}:[0-9][0-9] /); 208 | const progress = String(progressMatch[1]); 209 | let eta = null; 210 | if (etaMatch != null) { 211 | eta = etaMatch[0].trim(); 212 | } 213 | if (progress != null && 214 | Number(progress) > this.status.progress) { 215 | this.status.progress = Number(progress); 216 | } 217 | if (eta != null) { 218 | this.status.eta = eta; 219 | } 220 | this.emitter.emit("progress", [ 221 | this.status.progress, 222 | this.status.eta 223 | ]); 224 | } 225 | else if (type == "decode" && 226 | data.search(/[0-9]{1,10}\/[0-9]{1,10}/) > -1) { 227 | const progressMatch = data.match(/[0-9]{1,10}\/[0-9]{1,10}/); 228 | const progressAbsolute = progressMatch[0].split("/"); 229 | const progress = Math.floor((Number(progressAbsolute[0]) / 230 | Number(progressAbsolute[1])) * 231 | 100); 232 | if (!isNaN(progress) && 233 | Number(progress) > this.status.progress) { 234 | this.status.progress = Number(progress); 235 | } 236 | this.emitter.emit("progress", [ 237 | this.status.progress, 238 | this.status.eta 239 | ]); 240 | } 241 | else if (data.search(/^lame: /) > -1 || 242 | data.search(/^Warning: /) > -1 || 243 | data.search(/Error /) > -1) { 244 | // Unexpected output => error 245 | if (data.search(/^lame: /) == -1) { 246 | this.emitter.emit("error", new Error("lame: " + data)); 247 | } 248 | else { 249 | this.emitter.emit("error", new Error(String(data))); 250 | } 251 | } 252 | } 253 | }; 254 | const progressOnClose = code => { 255 | if (code == 0) { 256 | if (!this.status.finished) { 257 | this.emitter.emit("finish"); 258 | } 259 | this.status.finished = true; 260 | this.status.progress = 100; 261 | this.status.eta = "00:00"; 262 | } 263 | if (code === 255) { 264 | this.emitter.emit("error", new Error("Unexpected termination of the process, possibly directly after the start. Please check if the input and/or output does not exist.")); 265 | } 266 | }; 267 | /** 268 | * Handles error throw of Lame instance 269 | * 270 | * @param {Error} error 271 | */ 272 | const progressError = (error) => { 273 | this.emitter.emit("error", error); 274 | }; 275 | const instance = child_process_1.spawn("lame", args); 276 | instance.stdout.on("data", progressStdout); 277 | instance.stderr.on("data", progressStdout); // Most output, even non-errors, are on stderr 278 | instance.on("close", progressOnClose); 279 | instance.on("error", progressError); 280 | // Return promise of finish encoding progress 281 | return new Promise((resolve, reject) => { 282 | this.emitter.on("finish", () => { 283 | // If input was buffer, remove temp file 284 | if (this.fileBufferTempFilePath != undefined) { 285 | fs_1.unlinkSync(this.fileBufferTempFilePath); 286 | } 287 | // If output should be a buffer, load decoded/encoded audio file in object and remove temp file 288 | if (this.options.output == "buffer") { 289 | fs_1.readFile(this.progressedBufferTempFilePath, null, (error, data) => { 290 | // Remove temp decoded/encoded file 291 | fs_1.unlinkSync(this.progressedBufferTempFilePath); 292 | if (error) { 293 | reject(error); 294 | return; 295 | } 296 | this.progressedBuffer = Buffer.from(data); 297 | this.progressedBufferTempFilePath = undefined; 298 | resolve(this); 299 | }); 300 | } 301 | else { 302 | resolve(this); 303 | } 304 | }); 305 | this.emitter.on("error", error => { 306 | reject(error); 307 | }); 308 | }); 309 | } 310 | /** 311 | * Generate temp file path 312 | * 313 | * @param {("raw" | "encoded")} type 314 | * @returns {string} Path 315 | */ 316 | tempFilePathGenerator(type, progressType) { 317 | const prefix = `${__dirname}/../.`; 318 | let path = `${prefix}./temp/${type}/`; 319 | let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 320 | for (let i = 0; i < 32; i++) { 321 | path += possible.charAt(Math.floor(Math.random() * possible.length)); 322 | } 323 | if (type == "raw" && progressType == "decode") { 324 | path += `.mp3`; 325 | } 326 | if (!fs_1.existsSync(`${prefix}./temp/${path}`)) { 327 | return path; 328 | } 329 | else { 330 | return this.tempFilePathGenerator(type, progressType); 331 | } 332 | } 333 | /** 334 | * Remove temp files, if error occurred 335 | */ 336 | removeTempFilesOnError() { 337 | if (this.fileBufferTempFilePath != undefined && fs_1.existsSync(this.fileBufferTempFilePath)) { 338 | fs_1.unlinkSync(this.fileBufferTempFilePath); 339 | } 340 | if (this.progressedBufferTempFilePath != undefined && fs_1.existsSync(this.progressedBufferTempFilePath)) { 341 | fs_1.unlinkSync(this.progressedBufferTempFilePath); 342 | } 343 | } 344 | } 345 | exports.Lame = Lame; 346 | //# sourceMappingURL=Lame.js.map -------------------------------------------------------------------------------- /lib/build/Lame.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Lame.js","sourceRoot":"","sources":["../src/Lame.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /lib/build/LameOptions.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.LameOptions = void 0; 4 | /** 5 | * All options of node-lame; build argument array for binary 6 | * 7 | * @class LameOptions 8 | */ 9 | class LameOptions { 10 | /** 11 | * Validate all options and build argument array for binary 12 | * @param {Object} options 13 | */ 14 | constructor(options) { 15 | this.args = []; 16 | // Output is required 17 | if (options["output"] == undefined) { 18 | throw new Error("lame: Invalid option: 'output' is required"); 19 | } 20 | // Save options as arguments 21 | for (const key in options) { 22 | const value = options[key]; 23 | let arg; 24 | switch (key) { 25 | case "output": 26 | arg = this.output(value); 27 | break; 28 | case "raw": 29 | arg = this.raw(value); 30 | break; 31 | case "swap-bytes": 32 | arg = this.swapBytes(value); 33 | break; 34 | case "sfreq": 35 | arg = this.sfreq(value); 36 | break; 37 | case "bitwidth": 38 | arg = this.bitwidth(value); 39 | break; 40 | case "signed": 41 | arg = this.signed(value); 42 | break; 43 | case "unsigned": 44 | arg = this.unsigned(value); 45 | break; 46 | case "little-endian": 47 | arg = this.littleEndian(value); 48 | break; 49 | case "big-endian": 50 | arg = this.bigEndian(value); 51 | break; 52 | case "mp2Input": 53 | arg = this.mp2Input(value); 54 | break; 55 | case "mp3Input": 56 | arg = this.mp3Input(value); 57 | break; 58 | case "mode": 59 | arg = this.mode(value); 60 | break; 61 | case "to-mono": 62 | arg = this.toMono(value); 63 | break; 64 | case "channel-different-block-sizes": 65 | arg = this.channelDifferentBlockSize(value); 66 | break; 67 | case "freeformat": 68 | arg = this.freeformat(value); 69 | break; 70 | case "disable-info-tag": 71 | arg = this.disableInfoTag(value); 72 | break; 73 | case "comp": 74 | arg = this.comp(value); 75 | break; 76 | case "scale": 77 | arg = this.scale(value); 78 | break; 79 | case "scale-l": 80 | arg = this.scaleL(value); 81 | break; 82 | case "scale-r": 83 | arg = this.scaleR(value); 84 | break; 85 | case "replaygain-fast": 86 | arg = this.replaygainFast(value); 87 | break; 88 | case "replaygain-accurate": 89 | arg = this.replaygainAccurate(value); 90 | break; 91 | case "no-replaygain": 92 | arg = this.noreplaygain(value); 93 | break; 94 | case "clip-detect": 95 | arg = this.clipDetect(value); 96 | break; 97 | case "preset": 98 | arg = this.preset(value); 99 | break; 100 | case "noasm": 101 | arg = this.noasm(value); 102 | break; 103 | case "quality": 104 | arg = this.quality(value); 105 | break; 106 | case "bitrate": 107 | arg = this.bitrate(value); 108 | break; 109 | case "force-bitrate": 110 | arg = this.forceBitrate(value); 111 | break; 112 | case "cbr": 113 | arg = this.cbr(value); 114 | break; 115 | case "abr": 116 | arg = this.abr(value); 117 | break; 118 | case "vbr": 119 | arg = this.vbr(value); 120 | break; 121 | case "vbr-quality": 122 | arg = this.vbrQuality(value); 123 | break; 124 | case "ignore-noise-in-sfb21": 125 | arg = this.ignoreNoiseInSfb21(value); 126 | break; 127 | case "emp": 128 | arg = this.emp(value); 129 | break; 130 | case "mark-as-copyrighted": 131 | arg = this.markAsCopyrighted(value); 132 | break; 133 | case "mark-as-copy": 134 | arg = this.markAsCopy(value); 135 | break; 136 | case "crc-error-protection": 137 | arg = this.crcErrorProtection(value); 138 | break; 139 | case "nores": 140 | arg = this.nores(value); 141 | break; 142 | case "strictly-enforce-ISO": 143 | arg = this.strictlyEnforceIso(value); 144 | break; 145 | case "lowpass": 146 | arg = this.lowpass(value); 147 | break; 148 | case "lowpass-width": 149 | arg = this.lowpassWidth(value); 150 | break; 151 | case "highpass": 152 | arg = this.highpass(value); 153 | break; 154 | case "highpass-width": 155 | arg = this.highpassWidth(value); 156 | break; 157 | case "resample": 158 | arg = this.resample(value); 159 | break; 160 | case "meta": 161 | arg = this.meta(value); 162 | break; 163 | default: 164 | throw new Error("Unknown parameter " + key); 165 | } 166 | if (arg != undefined) { 167 | for (const i in arg) { 168 | this.args.push(arg[i]); 169 | } 170 | } 171 | } 172 | } 173 | /** 174 | * Get all arguments for binary 175 | */ 176 | getArguments() { 177 | return this.args; 178 | } 179 | output(value) { 180 | return undefined; // Handled in Lame class, because of fixed position (2nd parameter) 181 | } 182 | raw(value) { 183 | if (value == true) { 184 | return [`-r`]; 185 | } 186 | else { 187 | return undefined; 188 | } 189 | } 190 | swapBytes(value) { 191 | if (value == true) { 192 | return [`-x`]; 193 | } 194 | else { 195 | return undefined; 196 | } 197 | } 198 | sfreq(value) { 199 | if (value == 8 || 200 | value == 11.025 || 201 | value == 12 || 202 | value == 16 || 203 | value == 22.05 || 204 | value == 24 || 205 | value == 32 || 206 | value == 44.1 || 207 | value == 48) { 208 | return [`-s`, value]; 209 | } 210 | else { 211 | throw new Error("lame: Invalid option: 'sfreq' is not in range of 8, 11.025, 12, 16, 22.05, 24, 32, 44.1 or 48."); 212 | } 213 | } 214 | bitwidth(value) { 215 | if (value == 8 || value == 16 || value == 24 || value == 32) { 216 | return [`--bitwidth`, value]; 217 | } 218 | else { 219 | throw new Error("lame: Invalid option: 'sfreq' is not in range of 8, 16, 24 or 32."); 220 | } 221 | } 222 | signed(value) { 223 | if (value == true) { 224 | return [`--signed`]; 225 | } 226 | else { 227 | return undefined; 228 | } 229 | } 230 | unsigned(value) { 231 | if (value == true) { 232 | return [`--unsigned`]; 233 | } 234 | else { 235 | return undefined; 236 | } 237 | } 238 | littleEndian(value) { 239 | if (value == true) { 240 | return [`--little-endian`]; 241 | } 242 | else { 243 | return undefined; 244 | } 245 | } 246 | bigEndian(value) { 247 | if (value == true) { 248 | return [`--big-endian`]; 249 | } 250 | else { 251 | return undefined; 252 | } 253 | } 254 | mp2Input(value) { 255 | if (value == true) { 256 | return [`--mp2input`]; 257 | } 258 | else { 259 | return undefined; 260 | } 261 | } 262 | mp3Input(value) { 263 | if (value == true) { 264 | return [`--mp3input`]; 265 | } 266 | else { 267 | return undefined; 268 | } 269 | } 270 | mode(value) { 271 | if (value == "s" || 272 | value == "j" || 273 | value == "f" || 274 | value == "d" || 275 | value == "m" || 276 | value == "l" || 277 | value == "r") { 278 | return [`-m`, value]; 279 | } 280 | else { 281 | throw new Error("lame: Invalid option: 'mode' is not in range of 's', 'j', 'f', 'd', 'm', 'l' or 'r'."); 282 | } 283 | } 284 | toMono(value) { 285 | if (value == true) { 286 | return [`-a`]; 287 | } 288 | else { 289 | return undefined; 290 | } 291 | } 292 | channelDifferentBlockSize(value) { 293 | if (value == true) { 294 | return [`-d`]; 295 | } 296 | else { 297 | return undefined; 298 | } 299 | } 300 | freeformat(value) { 301 | if (value == "FreeAmp" || 302 | value == "in_mpg123" || 303 | value == "l3dec" || 304 | value == "LAME" || 305 | value == "MAD") { 306 | return [`--freeformat`, value]; 307 | } 308 | else { 309 | throw new Error("lame: Invalid option: 'mode' is not in range of 'FreeAmp', 'in_mpg123', 'l3dec', 'LAME', 'MAD'."); 310 | } 311 | } 312 | disableInfoTag(value) { 313 | if (value == true) { 314 | return [`-t`]; 315 | } 316 | else { 317 | return undefined; 318 | } 319 | } 320 | comp(value) { 321 | return [`--comp`, value]; 322 | } 323 | scale(value) { 324 | return [`--scale`, value]; 325 | } 326 | scaleL(value) { 327 | return [`--scale-l`, value]; 328 | } 329 | scaleR(value) { 330 | return [`--scale-r`, value]; 331 | } 332 | replaygainFast(value) { 333 | if (value == true) { 334 | return [`--replaygain-fast`]; 335 | } 336 | else { 337 | return undefined; 338 | } 339 | } 340 | replaygainAccurate(value) { 341 | if (value == true) { 342 | return [`--replaygain-accurate`]; 343 | } 344 | else { 345 | return undefined; 346 | } 347 | } 348 | noreplaygain(value) { 349 | if (value == true) { 350 | return [`--noreplaygain`]; 351 | } 352 | else { 353 | return undefined; 354 | } 355 | } 356 | clipDetect(value) { 357 | if (value == true) { 358 | return [`--clipdetect`]; 359 | } 360 | else { 361 | return undefined; 362 | } 363 | } 364 | preset(value) { 365 | if (value == "medium" || 366 | value == "standard" || 367 | value == "extreme" || 368 | value == "insane") { 369 | return [`--preset`, value]; 370 | } 371 | else { 372 | throw new Error("lame: Invalid option: 'mode' is not in range of 'medium', 'standard', 'extreme' or 'insane'."); 373 | } 374 | } 375 | noasm(value) { 376 | if (value == "mmx" || value == "3dnow" || value == "sse") { 377 | return [`--noasm`, value]; 378 | } 379 | else { 380 | throw new Error("lame: Invalid option: 'noasm' is not in range of 'mmx', '3dnow' or 'sse'."); 381 | } 382 | } 383 | quality(value) { 384 | if (value >= 0 && value <= 9) { 385 | return [`-q`, value]; 386 | } 387 | else { 388 | throw new Error("lame: Invalid option: 'quality' is not in range of 0 to 9."); 389 | } 390 | } 391 | bitrate(value) { 392 | if (value == 8 || 393 | value == 16 || 394 | value == 24 || 395 | value == 32 || 396 | value == 40 || 397 | value == 48 || 398 | value == 56 || 399 | value == 64 || 400 | value == 80 || 401 | value == 96 || 402 | value == 112 || 403 | value == 128 || 404 | value == 144 || 405 | value == 160 || 406 | value == 192 || 407 | value == 224 || 408 | value == 256 || 409 | value == 320) { 410 | return [`-b`, value]; 411 | } 412 | else { 413 | throw new Error("lame: Invalid option: 'bitrate' is not in range of 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 192, 224, 256 or 320."); 414 | } 415 | } 416 | forceBitrate(value) { 417 | if (value == true) { 418 | return [`-F`]; 419 | } 420 | else { 421 | return undefined; 422 | } 423 | } 424 | cbr(value) { 425 | if (value == true) { 426 | return [`--cbr`]; 427 | } 428 | else { 429 | return undefined; 430 | } 431 | } 432 | abr(value) { 433 | if (value >= 8 && value <= 310) { 434 | return [`--abr`, value]; 435 | } 436 | else { 437 | throw new Error("lame: Invalid option: 'abr' is not in range of 8 to 310."); 438 | } 439 | } 440 | vbr(value) { 441 | if (value == true) { 442 | return [`-v`]; 443 | } 444 | else { 445 | return undefined; 446 | } 447 | } 448 | vbrQuality(value) { 449 | if (value >= 0 && value <= 9) { 450 | return [`-V`, value]; 451 | } 452 | else { 453 | throw new Error("lame: Invalid option: 'vbrQuality' is not in range of 0 to 9."); 454 | } 455 | } 456 | ignoreNoiseInSfb21(value) { 457 | if (value == true) { 458 | return [`-Y`]; 459 | } 460 | else { 461 | return undefined; 462 | } 463 | } 464 | emp(value) { 465 | if (value == "n" || value == 5 || value == "c") { 466 | return [`-e`, value]; 467 | } 468 | else { 469 | throw new Error("lame: Invalid option: 'emp' is not in range of 'n', 5 or 'c'."); 470 | } 471 | } 472 | markAsCopyrighted(value) { 473 | if (value == true) { 474 | return [`-c`]; 475 | } 476 | else { 477 | return undefined; 478 | } 479 | } 480 | markAsCopy(value) { 481 | if (value == true) { 482 | return [`-o`]; 483 | } 484 | else { 485 | return undefined; 486 | } 487 | } 488 | crcErrorProtection(value) { 489 | if (value == true) { 490 | return [`-p`]; 491 | } 492 | else { 493 | return undefined; 494 | } 495 | } 496 | nores(value) { 497 | if (value == true) { 498 | return [`--nores`]; 499 | } 500 | else { 501 | return undefined; 502 | } 503 | } 504 | strictlyEnforceIso(value) { 505 | if (value == true) { 506 | return [`--strictly-enforce-ISO`]; 507 | } 508 | else { 509 | return undefined; 510 | } 511 | } 512 | lowpass(value) { 513 | return [`--lowpass`, value]; 514 | } 515 | lowpassWidth(value) { 516 | return [`--lowpass-width`, value]; 517 | } 518 | highpass(value) { 519 | return [`--highpass`, value]; 520 | } 521 | highpassWidth(value) { 522 | return [`--highpass-width`, value]; 523 | } 524 | resample(value) { 525 | if (value == 8 || 526 | value == 11.025 || 527 | value == 12 || 528 | value == 16 || 529 | value == 22.05 || 530 | value == 24 || 531 | value == 32 || 532 | value == 44.1 || 533 | value == 48) { 534 | return [`--resample`, value]; 535 | } 536 | else { 537 | throw new Error("lame: Invalid option: 'resample' is not in range of 8, 11.025, 12, 16, 22.05, 24, 32, 44.1 or 48."); 538 | } 539 | } 540 | meta(metaObj) { 541 | for (const key in metaObj) { 542 | const value = metaObj[key]; 543 | if (key == "title" || 544 | key == "artist" || 545 | key == "album" || 546 | key == "year" || 547 | key == "comment" || 548 | key == "track" || 549 | key == "genre" || 550 | key == "artwork" || 551 | key == "genre-list" || 552 | key == "pad-id3v2-size") { 553 | let arg0; 554 | if (key == "title") { 555 | arg0 = `--tt`; 556 | } 557 | else if (key == "artist") { 558 | arg0 = `--ta`; 559 | } 560 | else if (key == "album") { 561 | arg0 = `--tl`; 562 | } 563 | else if (key == "year") { 564 | arg0 = `--ty`; 565 | } 566 | else if (key == "comment") { 567 | arg0 = `--tc`; 568 | } 569 | else if (key == "track") { 570 | arg0 = `--tn`; 571 | } 572 | else if (key == "genre") { 573 | arg0 = `--tg`; 574 | } 575 | else if (key == "artwork") { 576 | arg0 = `--ti`; 577 | } 578 | else if (key == "genre-list") { 579 | arg0 = `--genre-list`; 580 | } 581 | else if (key == "pad-id3v2-size") { 582 | arg0 = `--pad-id3v2-size`; 583 | } 584 | else { 585 | throw new Error(`lame: Invalid option: 'meta' unknown property '${key}'`); 586 | } 587 | const arg1 = `${value}`; 588 | this.args.push(arg0); 589 | this.args.push(arg1); 590 | } 591 | else if (key == "add-id3v2" || 592 | key == "id3v1-only" || 593 | key == "id3v2-only" || 594 | key == "id3v2-latin1" || 595 | key == "id3v2-utf16" || 596 | key == "space-id3v1" || 597 | key == "pad-id3v2" || 598 | key == "ignore-tag-errors") { 599 | this.args.push(`--${key}`); 600 | } 601 | else { 602 | throw new Error(`lame: Invalid option: 'meta' unknown property '${key}'`); 603 | } 604 | } 605 | return undefined; 606 | } 607 | } 608 | exports.LameOptions = LameOptions; 609 | //# sourceMappingURL=LameOptions.js.map -------------------------------------------------------------------------------- /lib/build/LameOptions.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"LameOptions.js","sourceRoot":"","sources":["../src/LameOptions.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /lib/build/LameTypings.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=LameTypings.js.map -------------------------------------------------------------------------------- /lib/build/LameTypings.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"LameTypings.js","sourceRoot":"","sources":["../src/LameTypings.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /lib/src/Lame.ts: -------------------------------------------------------------------------------- 1 | import { LameStatus, Options } from "./LameTypings"; 2 | import { LameOptions } from "./LameOptions"; 3 | import { 4 | existsSync as fsExistsSync, 5 | readFile as fsReadFile, 6 | writeFile as fsWriteFile, 7 | unlinkSync as fsUnlinkSync 8 | } from "fs"; 9 | import { isBuffer as utilIsBuffer } from "util"; 10 | import { spawn } from "child_process"; 11 | import { EventEmitter } from "events"; 12 | 13 | /** 14 | * Wrapper for Lame for Node 15 | * 16 | * @class Lame 17 | */ 18 | class Lame { 19 | private status: LameStatus = { 20 | started: false, 21 | finished: false, 22 | progress: undefined, 23 | eta: undefined 24 | }; 25 | private emitter: EventEmitter = new EventEmitter(); 26 | 27 | private options: Options; 28 | private args: string[]; 29 | 30 | private filePath: string; 31 | private fileBuffer: Buffer; 32 | private fileBufferTempFilePath: string; 33 | 34 | private progressedFilePath: string; 35 | private progressedBuffer: Buffer; 36 | private progressedBufferTempFilePath: string; 37 | 38 | /** 39 | * Creates an instance of Lame and set all options 40 | * @param {Options} options 41 | */ 42 | constructor(options: Options) { 43 | this.options = options; 44 | this.args = new LameOptions(this.options).getArguments(); 45 | } 46 | 47 | /** 48 | * Set file path of audio to decode/encode 49 | * 50 | * @param {string} filePath 51 | */ 52 | public setFile(path: string): Lame { 53 | if (!fsExistsSync(path)) { 54 | throw new Error("Audio file (path) does not exist"); 55 | } 56 | 57 | this.filePath = path; 58 | this.fileBuffer = undefined; 59 | 60 | return this; 61 | } 62 | 63 | /** 64 | * Set file buffer of audio to decode/encode 65 | * 66 | * @param {Buffer} file 67 | */ 68 | public setBuffer(file: Buffer): Lame { 69 | if (!utilIsBuffer(file)) { 70 | throw new Error("Audio file (buffer) dose not exist"); 71 | } 72 | 73 | this.fileBuffer = file; 74 | this.filePath = undefined; 75 | 76 | return this; 77 | } 78 | 79 | /** 80 | * Get decoded/encoded file path 81 | * 82 | * @returns {string} Path of decoded/encoded file 83 | */ 84 | public getFile(): string { 85 | if (this.progressedFilePath == undefined) { 86 | throw new Error("Audio is not yet decoded/encoded"); 87 | } 88 | 89 | return this.progressedFilePath; 90 | } 91 | 92 | /** 93 | * Get decoded/encoded file as buffer 94 | * 95 | * @returns {Buffer} decoded/Encoded file 96 | */ 97 | public getBuffer(): Buffer { 98 | if (this.progressedBuffer == undefined) { 99 | throw new Error("Audio is not yet decoded/encoded"); 100 | } 101 | 102 | return this.progressedBuffer; 103 | } 104 | 105 | /** 106 | * Get event emitter 107 | * 108 | * @returns {EventEmitter} 109 | */ 110 | public getEmitter(): EventEmitter { 111 | return this.emitter; 112 | } 113 | 114 | /** 115 | * Get status of converter 116 | * 117 | * @returns {LameStatus} 118 | */ 119 | public getStatus(): LameStatus { 120 | return this.status; 121 | } 122 | 123 | /** 124 | * Encode audio file by Lame 125 | * 126 | * @return {Promise} 127 | */ 128 | public encode(): Promise { 129 | return this.progress("encode"); 130 | } 131 | 132 | /** 133 | * Decode audio file by Lame 134 | * 135 | * @return {Promise} 136 | */ 137 | public decode(): Promise { 138 | return this.progress("decode"); 139 | } 140 | 141 | /** 142 | * Decode/Encode audio file by Lame 143 | * 144 | * @return {Promise} 145 | */ 146 | private progress(type: "encode" | "decode"): Promise { 147 | if (this.filePath == undefined && this.fileBuffer == undefined) { 148 | throw new Error("Audio file to encode is not set"); 149 | } 150 | 151 | // Set decode flag to progress a MP3 to WAV decode 152 | const args = this.args; 153 | if (type == "decode") { 154 | args.push("--decode"); 155 | } 156 | 157 | if (this.fileBuffer != undefined) { 158 | // File buffer is set; write it as temp file 159 | this.fileBufferTempFilePath = this.tempFilePathGenerator( 160 | "raw", 161 | type 162 | ); 163 | 164 | return new Promise((resolve, reject) => { 165 | fsWriteFile( 166 | this.fileBufferTempFilePath, 167 | this.fileBuffer, 168 | err => { 169 | if (err) { 170 | reject(err); 171 | return; 172 | } 173 | 174 | resolve(this.fileBufferTempFilePath); 175 | } 176 | ); 177 | }) 178 | .then((file: string) => { 179 | return this.execProgress(file, args, type); 180 | }) 181 | .catch((error: Error) => { 182 | this.removeTempFilesOnError(); 183 | throw error; 184 | }); 185 | } else { 186 | // File path is set 187 | return this.execProgress(this.filePath, args, type).catch( 188 | (error: Error) => { 189 | this.removeTempFilesOnError(); 190 | throw error; 191 | } 192 | ); 193 | } 194 | } 195 | 196 | /** 197 | * Execute decoding/encoding via spawn Lame 198 | * 199 | * @private 200 | * @param {string} inputFilePath Path of input file 201 | */ 202 | private execProgress( 203 | inputFilePath: string, 204 | args: string[], 205 | type: "encode" | "decode" 206 | ) { 207 | // Add output settings args 208 | args.push("--disptime"); 209 | args.push("1"); 210 | 211 | // Add output file to args, if not undefined in options 212 | if (this.options.output == "buffer") { 213 | const tempOutPath = this.tempFilePathGenerator("encoded", type); 214 | args.unshift(`${tempOutPath}`); 215 | 216 | // Set decode/encoded file path 217 | this.progressedBufferTempFilePath = tempOutPath; 218 | } else { 219 | // Set decode/encoded file path 220 | this.progressedFilePath = this.options.output; 221 | args.unshift(this.progressedFilePath); 222 | } 223 | 224 | // Add input file to args 225 | args.unshift(inputFilePath); 226 | 227 | // Spawn instance of encoder and hook output methods 228 | this.status.started = true; 229 | this.status.finished = false; 230 | this.status.progress = 0; 231 | this.status.eta = undefined; 232 | 233 | /** 234 | * Handles output of stdout (and stderr) 235 | * Parses data from output into object 236 | * 237 | * @param {(String | Buffer)} data 238 | */ 239 | const progressStdout = (data: String | Buffer) => { 240 | data = data.toString().trim(); 241 | 242 | // Every output of Lame comes as "stderr". Deciding if it is an error or valid data by regex 243 | if (data.length > 6) { 244 | if ( 245 | type == "encode" && 246 | data.search("Writing LAME Tag...done") > -1 247 | ) { 248 | // processing done 249 | this.status.finished = true; 250 | this.status.progress = 100; 251 | this.status.eta = "00:00"; 252 | 253 | this.emitter.emit("finish"); 254 | this.emitter.emit("progress", [ 255 | this.status.progress, 256 | this.status.eta 257 | ]); 258 | } else if ( 259 | type == "encode" && 260 | data.search(/\((( [0-9])|([0-9]{2})|(100))%\)\|/) > -1 261 | ) { 262 | // status of processing 263 | const progressMatch = data.match( 264 | /\((( [0-9])|([0-9]{2})|(100))%\)\|/ 265 | ); 266 | const etaMatch = data.match(/[0-9]{1,2}:[0-9][0-9] /); 267 | 268 | const progress: string = String(progressMatch[1]); 269 | let eta: string = null; 270 | if (etaMatch != null) { 271 | eta = etaMatch[0].trim(); 272 | } 273 | 274 | if ( 275 | progress != null && 276 | Number(progress) > this.status.progress 277 | ) { 278 | this.status.progress = Number(progress); 279 | } 280 | 281 | if (eta != null) { 282 | this.status.eta = eta; 283 | } 284 | 285 | this.emitter.emit("progress", [ 286 | this.status.progress, 287 | this.status.eta 288 | ]); 289 | } else if ( 290 | type == "decode" && 291 | data.search(/[0-9]{1,10}\/[0-9]{1,10}/) > -1 292 | ) { 293 | const progressMatch = data.match( 294 | /[0-9]{1,10}\/[0-9]{1,10}/ 295 | ); 296 | const progressAbsolute = progressMatch[0].split("/"); 297 | const progress = Math.floor( 298 | (Number(progressAbsolute[0]) / 299 | Number(progressAbsolute[1])) * 300 | 100 301 | ); 302 | 303 | if ( 304 | !isNaN(progress) && 305 | Number(progress) > this.status.progress 306 | ) { 307 | this.status.progress = Number(progress); 308 | } 309 | 310 | this.emitter.emit("progress", [ 311 | this.status.progress, 312 | this.status.eta 313 | ]); 314 | } else if ( 315 | data.search(/^lame: /) > -1 || 316 | data.search(/^Warning: /) > -1 || 317 | data.search(/Error /) > -1 318 | ) { 319 | // Unexpected output => error 320 | if (data.search(/^lame: /) == -1) { 321 | this.emitter.emit("error", new Error("lame: " + data)); 322 | } else { 323 | this.emitter.emit("error", new Error(String(data))); 324 | } 325 | } 326 | } 327 | }; 328 | 329 | const progressOnClose = code => { 330 | if (code == 0) { 331 | if (!this.status.finished) { 332 | this.emitter.emit("finish"); 333 | } 334 | 335 | this.status.finished = true; 336 | this.status.progress = 100; 337 | this.status.eta = "00:00"; 338 | } 339 | 340 | if (code === 255) { 341 | this.emitter.emit("error", new Error("Unexpected termination of the process, possibly directly after the start. Please check if the input and/or output does not exist.")); 342 | } 343 | }; 344 | 345 | /** 346 | * Handles error throw of Lame instance 347 | * 348 | * @param {Error} error 349 | */ 350 | const progressError = (error: Error) => { 351 | this.emitter.emit("error", error); 352 | }; 353 | 354 | const instance = spawn("lame", args); 355 | instance.stdout.on("data", progressStdout); 356 | instance.stderr.on("data", progressStdout); // Most output, even non-errors, are on stderr 357 | instance.on("close", progressOnClose); 358 | instance.on("error", progressError); 359 | 360 | // Return promise of finish encoding progress 361 | return new Promise((resolve, reject) => { 362 | this.emitter.on("finish", () => { 363 | // If input was buffer, remove temp file 364 | if (this.fileBufferTempFilePath != undefined) { 365 | fsUnlinkSync(this.fileBufferTempFilePath); 366 | } 367 | 368 | // If output should be a buffer, load decoded/encoded audio file in object and remove temp file 369 | if (this.options.output == "buffer") { 370 | fsReadFile( 371 | this.progressedBufferTempFilePath, 372 | null, 373 | (error, data: string) => { 374 | // Remove temp decoded/encoded file 375 | fsUnlinkSync(this.progressedBufferTempFilePath); 376 | 377 | if (error) { 378 | reject(error); 379 | return; 380 | } 381 | 382 | this.progressedBuffer = Buffer.from(data); 383 | this.progressedBufferTempFilePath = undefined; 384 | 385 | resolve(this); 386 | } 387 | ); 388 | } else { 389 | resolve(this); 390 | } 391 | }); 392 | 393 | this.emitter.on("error", error => { 394 | reject(error); 395 | }); 396 | }); 397 | } 398 | 399 | /** 400 | * Generate temp file path 401 | * 402 | * @param {("raw" | "encoded")} type 403 | * @returns {string} Path 404 | */ 405 | private tempFilePathGenerator( 406 | type: "raw" | "encoded", 407 | progressType: "encode" | "decode" 408 | ): string { 409 | const prefix = `${__dirname}/../.`; 410 | let path = `${prefix}./temp/${type}/`; 411 | let possible = 412 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 413 | 414 | for (let i = 0; i < 32; i++) { 415 | path += possible.charAt( 416 | Math.floor(Math.random() * possible.length) 417 | ); 418 | } 419 | 420 | if (type == "raw" && progressType == "decode") { 421 | path += `.mp3`; 422 | } 423 | 424 | if (!fsExistsSync(`${prefix}./temp/${path}`)) { 425 | return path; 426 | } else { 427 | return this.tempFilePathGenerator(type, progressType); 428 | } 429 | } 430 | 431 | /** 432 | * Remove temp files, if error occurred 433 | */ 434 | private removeTempFilesOnError() { 435 | if (this.fileBufferTempFilePath != undefined && fsExistsSync(this.fileBufferTempFilePath)) { 436 | fsUnlinkSync(this.fileBufferTempFilePath); 437 | } 438 | 439 | if (this.progressedBufferTempFilePath != undefined && fsExistsSync(this.progressedBufferTempFilePath)) { 440 | fsUnlinkSync(this.progressedBufferTempFilePath); 441 | } 442 | } 443 | } 444 | 445 | export { Lame }; 446 | -------------------------------------------------------------------------------- /lib/src/LameOptions.ts: -------------------------------------------------------------------------------- 1 | import { Options } from "./LameTypings"; 2 | import * as fs from "fs"; 3 | 4 | /** 5 | * All options of node-lame; build argument array for binary 6 | * 7 | * @class LameOptions 8 | */ 9 | class LameOptions { 10 | private args = []; 11 | /** 12 | * Validate all options and build argument array for binary 13 | * @param {Object} options 14 | */ 15 | constructor(options: Options) { 16 | // Output is required 17 | if (options["output"] == undefined) { 18 | throw new Error("lame: Invalid option: 'output' is required"); 19 | } 20 | 21 | // Save options as arguments 22 | for (const key in options) { 23 | const value = options[key]; 24 | let arg; 25 | 26 | switch (key) { 27 | case "output": 28 | arg = this.output(value); 29 | break; 30 | case "raw": 31 | arg = this.raw(value); 32 | break; 33 | case "swap-bytes": 34 | arg = this.swapBytes(value); 35 | break; 36 | case "sfreq": 37 | arg = this.sfreq(value); 38 | break; 39 | case "bitwidth": 40 | arg = this.bitwidth(value); 41 | break; 42 | case "signed": 43 | arg = this.signed(value); 44 | break; 45 | case "unsigned": 46 | arg = this.unsigned(value); 47 | break; 48 | case "little-endian": 49 | arg = this.littleEndian(value); 50 | break; 51 | case "big-endian": 52 | arg = this.bigEndian(value); 53 | break; 54 | case "mp2Input": 55 | arg = this.mp2Input(value); 56 | break; 57 | case "mp3Input": 58 | arg = this.mp3Input(value); 59 | break; 60 | case "mode": 61 | arg = this.mode(value); 62 | break; 63 | case "to-mono": 64 | arg = this.toMono(value); 65 | break; 66 | case "channel-different-block-sizes": 67 | arg = this.channelDifferentBlockSize(value); 68 | break; 69 | case "freeformat": 70 | arg = this.freeformat(value); 71 | break; 72 | case "disable-info-tag": 73 | arg = this.disableInfoTag(value); 74 | break; 75 | case "comp": 76 | arg = this.comp(value); 77 | break; 78 | case "scale": 79 | arg = this.scale(value); 80 | break; 81 | case "scale-l": 82 | arg = this.scaleL(value); 83 | break; 84 | case "scale-r": 85 | arg = this.scaleR(value); 86 | break; 87 | case "replaygain-fast": 88 | arg = this.replaygainFast(value); 89 | break; 90 | case "replaygain-accurate": 91 | arg = this.replaygainAccurate(value); 92 | break; 93 | case "no-replaygain": 94 | arg = this.noreplaygain(value); 95 | break; 96 | case "clip-detect": 97 | arg = this.clipDetect(value); 98 | break; 99 | case "preset": 100 | arg = this.preset(value); 101 | break; 102 | case "noasm": 103 | arg = this.noasm(value); 104 | break; 105 | case "quality": 106 | arg = this.quality(value); 107 | break; 108 | case "bitrate": 109 | arg = this.bitrate(value); 110 | break; 111 | case "force-bitrate": 112 | arg = this.forceBitrate(value); 113 | break; 114 | case "cbr": 115 | arg = this.cbr(value); 116 | break; 117 | case "abr": 118 | arg = this.abr(value); 119 | break; 120 | case "vbr": 121 | arg = this.vbr(value); 122 | break; 123 | case "vbr-quality": 124 | arg = this.vbrQuality(value); 125 | break; 126 | case "ignore-noise-in-sfb21": 127 | arg = this.ignoreNoiseInSfb21(value); 128 | break; 129 | case "emp": 130 | arg = this.emp(value); 131 | break; 132 | case "mark-as-copyrighted": 133 | arg = this.markAsCopyrighted(value); 134 | break; 135 | case "mark-as-copy": 136 | arg = this.markAsCopy(value); 137 | break; 138 | case "crc-error-protection": 139 | arg = this.crcErrorProtection(value); 140 | break; 141 | case "nores": 142 | arg = this.nores(value); 143 | break; 144 | case "strictly-enforce-ISO": 145 | arg = this.strictlyEnforceIso(value); 146 | break; 147 | case "lowpass": 148 | arg = this.lowpass(value); 149 | break; 150 | case "lowpass-width": 151 | arg = this.lowpassWidth(value); 152 | break; 153 | case "highpass": 154 | arg = this.highpass(value); 155 | break; 156 | case "highpass-width": 157 | arg = this.highpassWidth(value); 158 | break; 159 | case "resample": 160 | arg = this.resample(value); 161 | break; 162 | case "meta": 163 | arg = this.meta(value); 164 | break; 165 | default: 166 | throw new Error("Unknown parameter " + key); 167 | } 168 | 169 | if (arg != undefined) { 170 | for (const i in arg) { 171 | this.args.push(arg[i]); 172 | } 173 | } 174 | } 175 | } 176 | 177 | /** 178 | * Get all arguments for binary 179 | */ 180 | public getArguments() { 181 | return this.args; 182 | } 183 | 184 | private output(value) { 185 | return undefined; // Handled in Lame class, because of fixed position (2nd parameter) 186 | } 187 | 188 | private raw(value) { 189 | if (value == true) { 190 | return [`-r`]; 191 | } else { 192 | return undefined; 193 | } 194 | } 195 | 196 | private swapBytes(value) { 197 | if (value == true) { 198 | return [`-x`]; 199 | } else { 200 | return undefined; 201 | } 202 | } 203 | 204 | private sfreq(value) { 205 | if ( 206 | value == 8 || 207 | value == 11.025 || 208 | value == 12 || 209 | value == 16 || 210 | value == 22.05 || 211 | value == 24 || 212 | value == 32 || 213 | value == 44.1 || 214 | value == 48 215 | ) { 216 | return [`-s`, value]; 217 | } else { 218 | throw new Error( 219 | "lame: Invalid option: 'sfreq' is not in range of 8, 11.025, 12, 16, 22.05, 24, 32, 44.1 or 48." 220 | ); 221 | } 222 | } 223 | 224 | private bitwidth(value) { 225 | if (value == 8 || value == 16 || value == 24 || value == 32) { 226 | return [`--bitwidth`, value]; 227 | } else { 228 | throw new Error( 229 | "lame: Invalid option: 'sfreq' is not in range of 8, 16, 24 or 32." 230 | ); 231 | } 232 | } 233 | 234 | private signed(value) { 235 | if (value == true) { 236 | return [`--signed`]; 237 | } else { 238 | return undefined; 239 | } 240 | } 241 | 242 | private unsigned(value) { 243 | if (value == true) { 244 | return [`--unsigned`]; 245 | } else { 246 | return undefined; 247 | } 248 | } 249 | 250 | private littleEndian(value) { 251 | if (value == true) { 252 | return [`--little-endian`]; 253 | } else { 254 | return undefined; 255 | } 256 | } 257 | 258 | private bigEndian(value) { 259 | if (value == true) { 260 | return [`--big-endian`]; 261 | } else { 262 | return undefined; 263 | } 264 | } 265 | 266 | private mp2Input(value) { 267 | if (value == true) { 268 | return [`--mp2input`]; 269 | } else { 270 | return undefined; 271 | } 272 | } 273 | 274 | private mp3Input(value) { 275 | if (value == true) { 276 | return [`--mp3input`]; 277 | } else { 278 | return undefined; 279 | } 280 | } 281 | 282 | private mode(value) { 283 | if ( 284 | value == "s" || 285 | value == "j" || 286 | value == "f" || 287 | value == "d" || 288 | value == "m" || 289 | value == "l" || 290 | value == "r" 291 | ) { 292 | return [`-m`, value]; 293 | } else { 294 | throw new Error( 295 | "lame: Invalid option: 'mode' is not in range of 's', 'j', 'f', 'd', 'm', 'l' or 'r'." 296 | ); 297 | } 298 | } 299 | 300 | private toMono(value) { 301 | if (value == true) { 302 | return [`-a`]; 303 | } else { 304 | return undefined; 305 | } 306 | } 307 | 308 | private channelDifferentBlockSize(value) { 309 | if (value == true) { 310 | return [`-d`]; 311 | } else { 312 | return undefined; 313 | } 314 | } 315 | 316 | private freeformat(value) { 317 | if ( 318 | value == "FreeAmp" || 319 | value == "in_mpg123" || 320 | value == "l3dec" || 321 | value == "LAME" || 322 | value == "MAD" 323 | ) { 324 | return [`--freeformat`, value]; 325 | } else { 326 | throw new Error( 327 | "lame: Invalid option: 'mode' is not in range of 'FreeAmp', 'in_mpg123', 'l3dec', 'LAME', 'MAD'." 328 | ); 329 | } 330 | } 331 | 332 | private disableInfoTag(value) { 333 | if (value == true) { 334 | return [`-t`]; 335 | } else { 336 | return undefined; 337 | } 338 | } 339 | 340 | private comp(value) { 341 | return [`--comp`, value]; 342 | } 343 | 344 | private scale(value) { 345 | return [`--scale`, value]; 346 | } 347 | 348 | private scaleL(value) { 349 | return [`--scale-l`, value]; 350 | } 351 | 352 | private scaleR(value) { 353 | return [`--scale-r`, value]; 354 | } 355 | 356 | private replaygainFast(value) { 357 | if (value == true) { 358 | return [`--replaygain-fast`]; 359 | } else { 360 | return undefined; 361 | } 362 | } 363 | 364 | private replaygainAccurate(value) { 365 | if (value == true) { 366 | return [`--replaygain-accurate`]; 367 | } else { 368 | return undefined; 369 | } 370 | } 371 | 372 | private noreplaygain(value) { 373 | if (value == true) { 374 | return [`--noreplaygain`]; 375 | } else { 376 | return undefined; 377 | } 378 | } 379 | 380 | private clipDetect(value) { 381 | if (value == true) { 382 | return [`--clipdetect`]; 383 | } else { 384 | return undefined; 385 | } 386 | } 387 | 388 | private preset(value) { 389 | if ( 390 | value == "medium" || 391 | value == "standard" || 392 | value == "extreme" || 393 | value == "insane" 394 | ) { 395 | return [`--preset`, value]; 396 | } else { 397 | throw new Error( 398 | "lame: Invalid option: 'mode' is not in range of 'medium', 'standard', 'extreme' or 'insane'." 399 | ); 400 | } 401 | } 402 | 403 | private noasm(value) { 404 | if (value == "mmx" || value == "3dnow" || value == "sse") { 405 | return [`--noasm`, value]; 406 | } else { 407 | throw new Error( 408 | "lame: Invalid option: 'noasm' is not in range of 'mmx', '3dnow' or 'sse'." 409 | ); 410 | } 411 | } 412 | 413 | private quality(value) { 414 | if (value >= 0 && value <= 9) { 415 | return [`-q`, value]; 416 | } else { 417 | throw new Error( 418 | "lame: Invalid option: 'quality' is not in range of 0 to 9." 419 | ); 420 | } 421 | } 422 | 423 | private bitrate(value) { 424 | if ( 425 | value == 8 || 426 | value == 16 || 427 | value == 24 || 428 | value == 32 || 429 | value == 40 || 430 | value == 48 || 431 | value == 56 || 432 | value == 64 || 433 | value == 80 || 434 | value == 96 || 435 | value == 112 || 436 | value == 128 || 437 | value == 144 || 438 | value == 160 || 439 | value == 192 || 440 | value == 224 || 441 | value == 256 || 442 | value == 320 443 | ) { 444 | return [`-b`, value]; 445 | } else { 446 | throw new Error( 447 | "lame: Invalid option: 'bitrate' is not in range of 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 192, 224, 256 or 320." 448 | ); 449 | } 450 | } 451 | 452 | private forceBitrate(value) { 453 | if (value == true) { 454 | return [`-F`]; 455 | } else { 456 | return undefined; 457 | } 458 | } 459 | 460 | private cbr(value) { 461 | if (value == true) { 462 | return [`--cbr`]; 463 | } else { 464 | return undefined; 465 | } 466 | } 467 | 468 | private abr(value) { 469 | if (value >= 8 && value <= 310) { 470 | return [`--abr`, value]; 471 | } else { 472 | throw new Error( 473 | "lame: Invalid option: 'abr' is not in range of 8 to 310." 474 | ); 475 | } 476 | } 477 | 478 | private vbr(value) { 479 | if (value == true) { 480 | return [`-v`]; 481 | } else { 482 | return undefined; 483 | } 484 | } 485 | 486 | private vbrQuality(value) { 487 | if (value >= 0 && value <= 9) { 488 | return [`-V`, value]; 489 | } else { 490 | throw new Error( 491 | "lame: Invalid option: 'vbrQuality' is not in range of 0 to 9." 492 | ); 493 | } 494 | } 495 | 496 | private ignoreNoiseInSfb21(value) { 497 | if (value == true) { 498 | return [`-Y`]; 499 | } else { 500 | return undefined; 501 | } 502 | } 503 | 504 | private emp(value) { 505 | if (value == "n" || value == 5 || value == "c") { 506 | return [`-e`, value]; 507 | } else { 508 | throw new Error( 509 | "lame: Invalid option: 'emp' is not in range of 'n', 5 or 'c'." 510 | ); 511 | } 512 | } 513 | 514 | private markAsCopyrighted(value) { 515 | if (value == true) { 516 | return [`-c`]; 517 | } else { 518 | return undefined; 519 | } 520 | } 521 | 522 | private markAsCopy(value) { 523 | if (value == true) { 524 | return [`-o`]; 525 | } else { 526 | return undefined; 527 | } 528 | } 529 | 530 | private crcErrorProtection(value) { 531 | if (value == true) { 532 | return [`-p`]; 533 | } else { 534 | return undefined; 535 | } 536 | } 537 | 538 | private nores(value) { 539 | if (value == true) { 540 | return [`--nores`]; 541 | } else { 542 | return undefined; 543 | } 544 | } 545 | 546 | private strictlyEnforceIso(value) { 547 | if (value == true) { 548 | return [`--strictly-enforce-ISO`]; 549 | } else { 550 | return undefined; 551 | } 552 | } 553 | 554 | private lowpass(value) { 555 | return [`--lowpass`, value]; 556 | } 557 | 558 | private lowpassWidth(value) { 559 | return [`--lowpass-width`, value]; 560 | } 561 | 562 | private highpass(value) { 563 | return [`--highpass`, value]; 564 | } 565 | 566 | private highpassWidth(value) { 567 | return [`--highpass-width`, value]; 568 | } 569 | 570 | private resample(value) { 571 | if ( 572 | value == 8 || 573 | value == 11.025 || 574 | value == 12 || 575 | value == 16 || 576 | value == 22.05 || 577 | value == 24 || 578 | value == 32 || 579 | value == 44.1 || 580 | value == 48 581 | ) { 582 | return [`--resample`, value]; 583 | } else { 584 | throw new Error( 585 | "lame: Invalid option: 'resample' is not in range of 8, 11.025, 12, 16, 22.05, 24, 32, 44.1 or 48." 586 | ); 587 | } 588 | } 589 | 590 | private meta(metaObj) { 591 | for (const key in metaObj) { 592 | const value = metaObj[key]; 593 | 594 | if ( 595 | key == "title" || 596 | key == "artist" || 597 | key == "album" || 598 | key == "year" || 599 | key == "comment" || 600 | key == "track" || 601 | key == "genre" || 602 | key == "artwork" || 603 | key == "genre-list" || 604 | key == "pad-id3v2-size" 605 | ) { 606 | let arg0; 607 | if (key == "title") { 608 | arg0 = `--tt`; 609 | } else if (key == "artist") { 610 | arg0 = `--ta`; 611 | } else if (key == "album") { 612 | arg0 = `--tl`; 613 | } else if (key == "year") { 614 | arg0 = `--ty`; 615 | } else if (key == "comment") { 616 | arg0 = `--tc`; 617 | } else if (key == "track") { 618 | arg0 = `--tn`; 619 | } else if (key == "genre") { 620 | arg0 = `--tg`; 621 | } else if (key == "artwork") { 622 | arg0 = `--ti`; 623 | } else if (key == "genre-list") { 624 | arg0 = `--genre-list`; 625 | } else if (key == "pad-id3v2-size") { 626 | arg0 = `--pad-id3v2-size`; 627 | } else { 628 | throw new Error( 629 | `lame: Invalid option: 'meta' unknown property '${key}'` 630 | ); 631 | } 632 | 633 | const arg1 = `${value}`; 634 | 635 | this.args.push(arg0); 636 | this.args.push(arg1); 637 | } else if ( 638 | key == "add-id3v2" || 639 | key == "id3v1-only" || 640 | key == "id3v2-only" || 641 | key == "id3v2-latin1" || 642 | key == "id3v2-utf16" || 643 | key == "space-id3v1" || 644 | key == "pad-id3v2" || 645 | key == "ignore-tag-errors" 646 | ) { 647 | this.args.push(`--${key}`); 648 | } else { 649 | throw new Error( 650 | `lame: Invalid option: 'meta' unknown property '${key}'` 651 | ); 652 | } 653 | } 654 | 655 | return undefined; 656 | } 657 | } 658 | 659 | export { LameOptions }; 660 | -------------------------------------------------------------------------------- /lib/src/LameTypings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Status data of lame instance 3 | * 4 | * @interface LameStatus 5 | */ 6 | interface LameStatus { 7 | started: boolean; 8 | finished: boolean; 9 | progress: number; 10 | eta: string; 11 | } 12 | 13 | /** 14 | * Raw options interface and types for Typescript definitions 15 | */ 16 | namespace Options { 17 | export type sfreq = 8 | 11.025 | 12 | 16 | 22.05 | 24 | 32 | 44.1 | 48; 18 | export type bitwidth = 8 | 16 | 24 | 32; 19 | export type mode = "s" | "j" | "f" | "d" | "m" | "l" | "r"; 20 | export type freeformat = "FreeAmp" | "in_mpg123" | "l3dec" | "LAME" | "MAD"; 21 | export type preset = "medium" | "standard" | "extreme" | "insane"; 22 | export type noasm = "mmx" | "3dnow" | "sse"; 23 | export type quality = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; 24 | export type bitrate = 25 | | 8 26 | | 16 27 | | 24 28 | | 32 29 | | 40 30 | | 48 31 | | 56 32 | | 64 33 | | 80 34 | | 96 35 | | 112 36 | | 128 37 | | 144 38 | | 160 39 | | 192 40 | | 224 41 | | 256 42 | | 320; 43 | export type emp = "n" | 5 | "c"; 44 | export type resample = 8 | 11.025 | 12 | 16 | 22.05 | 24 | 32 | 44.1 | 48; 45 | 46 | export interface meta { 47 | title?: string; 48 | artist?: string; 49 | album?: string; 50 | year?: string; 51 | comment?: string; 52 | track?: string; 53 | genre?: string; 54 | 55 | "add-id3v2"?: boolean; 56 | "id3v1-only"?: boolean; 57 | "id3v2-only"?: boolean; 58 | "id3v2-latin1"?: boolean; 59 | "id3v2-utf16"?: boolean; 60 | "space-id3v1"?: boolean; 61 | "pad-id3v2-size"?: number; 62 | "genre-list"?: string; 63 | "ignore-tag-errors"?: boolean; 64 | } 65 | } 66 | 67 | interface Options { 68 | output: string | "buffer"; 69 | raw?: boolean; 70 | "swap-bytes"?: boolean; 71 | sfreq?: Options.sfreq; 72 | bitwidth?: Options.bitwidth; 73 | signed?: boolean; 74 | unsigned?: boolean; 75 | "little-endian"?: boolean; 76 | "big-endian"?: boolean; 77 | mp2Input?: boolean; 78 | mp3Input?: boolean; 79 | mode?: Options.mode; 80 | "to-mono"?: boolean; 81 | "channel-different-block-sizes"?: boolean; 82 | freeformat?: Options.freeformat; 83 | "disable-info-tag"?: boolean; 84 | comp?: number; 85 | scale?: number; 86 | "scale-l"?: number; 87 | "scale-r"?: number; 88 | "replaygain-fast"?: boolean; 89 | "replaygain-accurate"?: boolean; 90 | "no-replaygain"?: boolean; 91 | "clip-detect"?: boolean; 92 | preset?: Options.preset; 93 | noasm?: Options.noasm; 94 | quality?: Options.quality; 95 | bitrate?: Options.bitrate; 96 | "force-bitrate"?: boolean; 97 | cbr?: boolean; 98 | abr?: number; 99 | vbr?: boolean; 100 | "vbr-quality"?: number; 101 | "ignore-noise-in-sfb21"?: boolean; 102 | emp?: Options.emp; 103 | "mark-as-copyrighted"?: boolean; 104 | "mark-as-copy"?: boolean; 105 | "crc-error-protection"?: boolean; 106 | nores?: boolean; 107 | "strictly-enforce-ISO"?: boolean; 108 | lowpass?: number; 109 | "lowpass-width"?: number; 110 | highpass?: number; 111 | "highpass-width"?: number; 112 | resample?: Options.resample; 113 | meta?: Options.meta; 114 | } 115 | 116 | export { LameStatus, Options }; 117 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-lame", 3 | "version": "1.3.2", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cspotcode/source-map-consumer": { 8 | "version": "0.8.0", 9 | "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", 10 | "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", 11 | "dev": true 12 | }, 13 | "@cspotcode/source-map-support": { 14 | "version": "0.6.1", 15 | "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz", 16 | "integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==", 17 | "dev": true, 18 | "requires": { 19 | "@cspotcode/source-map-consumer": "0.8.0" 20 | } 21 | }, 22 | "@tsconfig/node10": { 23 | "version": "1.0.8", 24 | "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", 25 | "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", 26 | "dev": true 27 | }, 28 | "@tsconfig/node12": { 29 | "version": "1.0.9", 30 | "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", 31 | "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", 32 | "dev": true 33 | }, 34 | "@tsconfig/node14": { 35 | "version": "1.0.1", 36 | "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", 37 | "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", 38 | "dev": true 39 | }, 40 | "@tsconfig/node16": { 41 | "version": "1.0.2", 42 | "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", 43 | "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", 44 | "dev": true 45 | }, 46 | "@types/chai": { 47 | "version": "4.2.21", 48 | "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.21.tgz", 49 | "integrity": "sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg==", 50 | "dev": true 51 | }, 52 | "@types/fs-extra": { 53 | "version": "9.0.12", 54 | "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.12.tgz", 55 | "integrity": "sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==", 56 | "dev": true, 57 | "requires": { 58 | "@types/node": "*" 59 | } 60 | }, 61 | "@types/mocha": { 62 | "version": "8.2.1", 63 | "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.1.tgz", 64 | "integrity": "sha512-NysN+bNqj6E0Hv4CTGWSlPzMW6vTKjDpOteycDkV4IWBsO+PU48JonrPzV9ODjiI2XrjmA05KInLgF5ivZ/YGQ==", 65 | "dev": true 66 | }, 67 | "@types/node": { 68 | "version": "14.17.10", 69 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.10.tgz", 70 | "integrity": "sha512-09x2d6kNBwjHgyh3jOUE2GE4DFoxDriDvWdu6mFhMP1ysynGYazt4ecZmJlL6/fe4Zi2vtYvTvtL7epjQQrBhA==", 71 | "dev": true 72 | }, 73 | "@ungap/promise-all-settled": { 74 | "version": "1.1.2", 75 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 76 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 77 | "dev": true 78 | }, 79 | "acorn": { 80 | "version": "8.4.1", 81 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", 82 | "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", 83 | "dev": true 84 | }, 85 | "acorn-walk": { 86 | "version": "8.1.1", 87 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz", 88 | "integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==", 89 | "dev": true 90 | }, 91 | "ansi-colors": { 92 | "version": "4.1.1", 93 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 94 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 95 | "dev": true 96 | }, 97 | "ansi-regex": { 98 | "version": "3.0.0", 99 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 100 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 101 | "dev": true 102 | }, 103 | "ansi-styles": { 104 | "version": "4.3.0", 105 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 106 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 107 | "dev": true, 108 | "requires": { 109 | "color-convert": "^2.0.1" 110 | } 111 | }, 112 | "anymatch": { 113 | "version": "3.1.2", 114 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 115 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 116 | "dev": true, 117 | "requires": { 118 | "normalize-path": "^3.0.0", 119 | "picomatch": "^2.0.4" 120 | } 121 | }, 122 | "arg": { 123 | "version": "4.1.3", 124 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", 125 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", 126 | "dev": true 127 | }, 128 | "argparse": { 129 | "version": "2.0.1", 130 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 131 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 132 | "dev": true 133 | }, 134 | "assertion-error": { 135 | "version": "1.1.0", 136 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 137 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 138 | "dev": true 139 | }, 140 | "balanced-match": { 141 | "version": "1.0.2", 142 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 143 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 144 | "dev": true 145 | }, 146 | "binary-extensions": { 147 | "version": "2.2.0", 148 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 149 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 150 | "dev": true 151 | }, 152 | "brace-expansion": { 153 | "version": "1.1.11", 154 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 155 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 156 | "dev": true, 157 | "requires": { 158 | "balanced-match": "^1.0.0", 159 | "concat-map": "0.0.1" 160 | } 161 | }, 162 | "braces": { 163 | "version": "3.0.3", 164 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 165 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 166 | "dev": true, 167 | "requires": { 168 | "fill-range": "^7.1.1" 169 | }, 170 | "dependencies": { 171 | "fill-range": { 172 | "version": "7.1.1", 173 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 174 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 175 | "dev": true, 176 | "requires": { 177 | "to-regex-range": "^5.0.1" 178 | } 179 | } 180 | } 181 | }, 182 | "browser-stdout": { 183 | "version": "1.3.1", 184 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 185 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 186 | "dev": true 187 | }, 188 | "camelcase": { 189 | "version": "6.2.0", 190 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", 191 | "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", 192 | "dev": true 193 | }, 194 | "chai": { 195 | "version": "4.3.4", 196 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", 197 | "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", 198 | "dev": true, 199 | "requires": { 200 | "assertion-error": "^1.1.0", 201 | "check-error": "^1.0.2", 202 | "deep-eql": "^3.0.1", 203 | "get-func-name": "^2.0.0", 204 | "pathval": "^1.1.1", 205 | "type-detect": "^4.0.5" 206 | } 207 | }, 208 | "chalk": { 209 | "version": "4.1.2", 210 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 211 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 212 | "dev": true, 213 | "requires": { 214 | "ansi-styles": "^4.1.0", 215 | "supports-color": "^7.1.0" 216 | }, 217 | "dependencies": { 218 | "supports-color": { 219 | "version": "7.2.0", 220 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 221 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 222 | "dev": true, 223 | "requires": { 224 | "has-flag": "^4.0.0" 225 | } 226 | } 227 | } 228 | }, 229 | "check-error": { 230 | "version": "1.0.2", 231 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 232 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 233 | "dev": true 234 | }, 235 | "chokidar": { 236 | "version": "3.5.1", 237 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", 238 | "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", 239 | "dev": true, 240 | "requires": { 241 | "anymatch": "~3.1.1", 242 | "braces": "~3.0.2", 243 | "fsevents": "~2.3.1", 244 | "glob-parent": "~5.1.0", 245 | "is-binary-path": "~2.1.0", 246 | "is-glob": "~4.0.1", 247 | "normalize-path": "~3.0.0", 248 | "readdirp": "~3.5.0" 249 | } 250 | }, 251 | "cliui": { 252 | "version": "7.0.4", 253 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 254 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 255 | "dev": true, 256 | "requires": { 257 | "string-width": "^4.2.0", 258 | "strip-ansi": "^6.0.0", 259 | "wrap-ansi": "^7.0.0" 260 | }, 261 | "dependencies": { 262 | "ansi-regex": { 263 | "version": "5.0.0", 264 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 265 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 266 | "dev": true 267 | }, 268 | "is-fullwidth-code-point": { 269 | "version": "3.0.0", 270 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 271 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 272 | "dev": true 273 | }, 274 | "string-width": { 275 | "version": "4.2.2", 276 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 277 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 278 | "dev": true, 279 | "requires": { 280 | "emoji-regex": "^8.0.0", 281 | "is-fullwidth-code-point": "^3.0.0", 282 | "strip-ansi": "^6.0.0" 283 | } 284 | }, 285 | "strip-ansi": { 286 | "version": "6.0.0", 287 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 288 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 289 | "dev": true, 290 | "requires": { 291 | "ansi-regex": "^5.0.0" 292 | } 293 | } 294 | } 295 | }, 296 | "color-convert": { 297 | "version": "2.0.1", 298 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 299 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 300 | "dev": true, 301 | "requires": { 302 | "color-name": "~1.1.4" 303 | } 304 | }, 305 | "color-name": { 306 | "version": "1.1.4", 307 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 308 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 309 | "dev": true 310 | }, 311 | "concat-map": { 312 | "version": "0.0.1", 313 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 314 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 315 | "dev": true 316 | }, 317 | "create-require": { 318 | "version": "1.1.1", 319 | "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", 320 | "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", 321 | "dev": true 322 | }, 323 | "debug": { 324 | "version": "4.3.1", 325 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 326 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 327 | "dev": true, 328 | "requires": { 329 | "ms": "2.1.2" 330 | }, 331 | "dependencies": { 332 | "ms": { 333 | "version": "2.1.2", 334 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 335 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 336 | "dev": true 337 | } 338 | } 339 | }, 340 | "decamelize": { 341 | "version": "4.0.0", 342 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 343 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 344 | "dev": true 345 | }, 346 | "deep-eql": { 347 | "version": "3.0.1", 348 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 349 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 350 | "dev": true, 351 | "requires": { 352 | "type-detect": "^4.0.0" 353 | } 354 | }, 355 | "diff": { 356 | "version": "5.0.0", 357 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 358 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 359 | "dev": true 360 | }, 361 | "emoji-regex": { 362 | "version": "8.0.0", 363 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 364 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 365 | "dev": true 366 | }, 367 | "escalade": { 368 | "version": "3.1.1", 369 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 370 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 371 | "dev": true 372 | }, 373 | "escape-string-regexp": { 374 | "version": "4.0.0", 375 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 376 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 377 | "dev": true 378 | }, 379 | "find-up": { 380 | "version": "5.0.0", 381 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 382 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 383 | "dev": true, 384 | "requires": { 385 | "locate-path": "^6.0.0", 386 | "path-exists": "^4.0.0" 387 | } 388 | }, 389 | "flat": { 390 | "version": "5.0.2", 391 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 392 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 393 | "dev": true 394 | }, 395 | "fs-extra": { 396 | "version": "10.0.0", 397 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", 398 | "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", 399 | "dev": true, 400 | "requires": { 401 | "graceful-fs": "^4.2.0", 402 | "jsonfile": "^6.0.1", 403 | "universalify": "^2.0.0" 404 | } 405 | }, 406 | "fs.realpath": { 407 | "version": "1.0.0", 408 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 409 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 410 | "dev": true 411 | }, 412 | "fsevents": { 413 | "version": "2.3.2", 414 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 415 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 416 | "dev": true, 417 | "optional": true 418 | }, 419 | "get-caller-file": { 420 | "version": "2.0.5", 421 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 422 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 423 | "dev": true 424 | }, 425 | "get-func-name": { 426 | "version": "2.0.0", 427 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 428 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 429 | "dev": true 430 | }, 431 | "glob": { 432 | "version": "7.1.6", 433 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 434 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 435 | "dev": true, 436 | "requires": { 437 | "fs.realpath": "^1.0.0", 438 | "inflight": "^1.0.4", 439 | "inherits": "2", 440 | "minimatch": "^3.0.4", 441 | "once": "^1.3.0", 442 | "path-is-absolute": "^1.0.0" 443 | } 444 | }, 445 | "glob-parent": { 446 | "version": "5.1.2", 447 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 448 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 449 | "dev": true, 450 | "requires": { 451 | "is-glob": "^4.0.1" 452 | } 453 | }, 454 | "graceful-fs": { 455 | "version": "4.2.8", 456 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", 457 | "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", 458 | "dev": true 459 | }, 460 | "growl": { 461 | "version": "1.10.5", 462 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 463 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 464 | "dev": true 465 | }, 466 | "has-flag": { 467 | "version": "4.0.0", 468 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 469 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 470 | "dev": true 471 | }, 472 | "he": { 473 | "version": "1.2.0", 474 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 475 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 476 | "dev": true 477 | }, 478 | "inflight": { 479 | "version": "1.0.6", 480 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 481 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 482 | "dev": true, 483 | "requires": { 484 | "once": "^1.3.0", 485 | "wrappy": "1" 486 | } 487 | }, 488 | "inherits": { 489 | "version": "2.0.4", 490 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 491 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 492 | "dev": true 493 | }, 494 | "is-binary-path": { 495 | "version": "2.1.0", 496 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 497 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 498 | "dev": true, 499 | "requires": { 500 | "binary-extensions": "^2.0.0" 501 | } 502 | }, 503 | "is-extglob": { 504 | "version": "2.1.1", 505 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 506 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 507 | "dev": true 508 | }, 509 | "is-fullwidth-code-point": { 510 | "version": "2.0.0", 511 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 512 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 513 | "dev": true 514 | }, 515 | "is-glob": { 516 | "version": "4.0.1", 517 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 518 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 519 | "dev": true, 520 | "requires": { 521 | "is-extglob": "^2.1.1" 522 | } 523 | }, 524 | "is-number": { 525 | "version": "7.0.0", 526 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 527 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 528 | "dev": true 529 | }, 530 | "is-plain-obj": { 531 | "version": "2.1.0", 532 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 533 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 534 | "dev": true 535 | }, 536 | "isexe": { 537 | "version": "2.0.0", 538 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 539 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 540 | "dev": true 541 | }, 542 | "js-yaml": { 543 | "version": "4.0.0", 544 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", 545 | "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", 546 | "dev": true, 547 | "requires": { 548 | "argparse": "^2.0.1" 549 | } 550 | }, 551 | "jsonfile": { 552 | "version": "6.1.0", 553 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 554 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 555 | "dev": true, 556 | "requires": { 557 | "graceful-fs": "^4.1.6", 558 | "universalify": "^2.0.0" 559 | } 560 | }, 561 | "locate-path": { 562 | "version": "6.0.0", 563 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 564 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 565 | "dev": true, 566 | "requires": { 567 | "p-locate": "^5.0.0" 568 | } 569 | }, 570 | "log-symbols": { 571 | "version": "4.0.0", 572 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", 573 | "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", 574 | "dev": true, 575 | "requires": { 576 | "chalk": "^4.0.0" 577 | } 578 | }, 579 | "make-error": { 580 | "version": "1.3.6", 581 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 582 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", 583 | "dev": true 584 | }, 585 | "minimatch": { 586 | "version": "3.0.4", 587 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 588 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 589 | "dev": true, 590 | "requires": { 591 | "brace-expansion": "^1.1.7" 592 | } 593 | }, 594 | "mocha": { 595 | "version": "8.4.0", 596 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", 597 | "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", 598 | "dev": true, 599 | "requires": { 600 | "@ungap/promise-all-settled": "1.1.2", 601 | "ansi-colors": "4.1.1", 602 | "browser-stdout": "1.3.1", 603 | "chokidar": "3.5.1", 604 | "debug": "4.3.1", 605 | "diff": "5.0.0", 606 | "escape-string-regexp": "4.0.0", 607 | "find-up": "5.0.0", 608 | "glob": "7.1.6", 609 | "growl": "1.10.5", 610 | "he": "1.2.0", 611 | "js-yaml": "4.0.0", 612 | "log-symbols": "4.0.0", 613 | "minimatch": "3.0.4", 614 | "ms": "2.1.3", 615 | "nanoid": "3.1.20", 616 | "serialize-javascript": "5.0.1", 617 | "strip-json-comments": "3.1.1", 618 | "supports-color": "8.1.1", 619 | "which": "2.0.2", 620 | "wide-align": "1.1.3", 621 | "workerpool": "6.1.0", 622 | "yargs": "16.2.0", 623 | "yargs-parser": "20.2.4", 624 | "yargs-unparser": "2.0.0" 625 | } 626 | }, 627 | "ms": { 628 | "version": "2.1.3", 629 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 630 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 631 | "dev": true 632 | }, 633 | "nanoid": { 634 | "version": "3.1.20", 635 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", 636 | "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", 637 | "dev": true 638 | }, 639 | "normalize-path": { 640 | "version": "3.0.0", 641 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 642 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 643 | "dev": true 644 | }, 645 | "once": { 646 | "version": "1.4.0", 647 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 648 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 649 | "dev": true, 650 | "requires": { 651 | "wrappy": "1" 652 | } 653 | }, 654 | "p-limit": { 655 | "version": "3.1.0", 656 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 657 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 658 | "dev": true, 659 | "requires": { 660 | "yocto-queue": "^0.1.0" 661 | } 662 | }, 663 | "p-locate": { 664 | "version": "5.0.0", 665 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 666 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 667 | "dev": true, 668 | "requires": { 669 | "p-limit": "^3.0.2" 670 | } 671 | }, 672 | "path-exists": { 673 | "version": "4.0.0", 674 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 675 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 676 | "dev": true 677 | }, 678 | "path-is-absolute": { 679 | "version": "1.0.1", 680 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 681 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 682 | "dev": true 683 | }, 684 | "pathval": { 685 | "version": "1.1.1", 686 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 687 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 688 | "dev": true 689 | }, 690 | "picomatch": { 691 | "version": "2.3.0", 692 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 693 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 694 | "dev": true 695 | }, 696 | "randombytes": { 697 | "version": "2.1.0", 698 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 699 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 700 | "dev": true, 701 | "requires": { 702 | "safe-buffer": "^5.1.0" 703 | } 704 | }, 705 | "readdirp": { 706 | "version": "3.5.0", 707 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", 708 | "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", 709 | "dev": true, 710 | "requires": { 711 | "picomatch": "^2.2.1" 712 | } 713 | }, 714 | "require-directory": { 715 | "version": "2.1.1", 716 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 717 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 718 | "dev": true 719 | }, 720 | "safe-buffer": { 721 | "version": "5.2.1", 722 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 723 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 724 | "dev": true 725 | }, 726 | "serialize-javascript": { 727 | "version": "5.0.1", 728 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", 729 | "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", 730 | "dev": true, 731 | "requires": { 732 | "randombytes": "^2.1.0" 733 | } 734 | }, 735 | "string-width": { 736 | "version": "2.1.1", 737 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 738 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 739 | "dev": true, 740 | "requires": { 741 | "is-fullwidth-code-point": "^2.0.0", 742 | "strip-ansi": "^4.0.0" 743 | } 744 | }, 745 | "strip-ansi": { 746 | "version": "4.0.0", 747 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 748 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 749 | "dev": true, 750 | "requires": { 751 | "ansi-regex": "^3.0.0" 752 | } 753 | }, 754 | "strip-json-comments": { 755 | "version": "3.1.1", 756 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 757 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 758 | "dev": true 759 | }, 760 | "supports-color": { 761 | "version": "8.1.1", 762 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 763 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 764 | "dev": true, 765 | "requires": { 766 | "has-flag": "^4.0.0" 767 | } 768 | }, 769 | "to-regex-range": { 770 | "version": "5.0.1", 771 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 772 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 773 | "dev": true, 774 | "requires": { 775 | "is-number": "^7.0.0" 776 | } 777 | }, 778 | "ts-node": { 779 | "version": "10.2.1", 780 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.1.tgz", 781 | "integrity": "sha512-hCnyOyuGmD5wHleOQX6NIjJtYVIO8bPP8F2acWkB4W06wdlkgyvJtubO/I9NkI88hCFECbsEgoLc0VNkYmcSfw==", 782 | "dev": true, 783 | "requires": { 784 | "@cspotcode/source-map-support": "0.6.1", 785 | "@tsconfig/node10": "^1.0.7", 786 | "@tsconfig/node12": "^1.0.7", 787 | "@tsconfig/node14": "^1.0.0", 788 | "@tsconfig/node16": "^1.0.2", 789 | "acorn": "^8.4.1", 790 | "acorn-walk": "^8.1.1", 791 | "arg": "^4.1.0", 792 | "create-require": "^1.1.0", 793 | "diff": "^4.0.1", 794 | "make-error": "^1.1.1", 795 | "yn": "3.1.1" 796 | }, 797 | "dependencies": { 798 | "diff": { 799 | "version": "4.0.2", 800 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 801 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 802 | "dev": true 803 | } 804 | } 805 | }, 806 | "type-detect": { 807 | "version": "4.0.8", 808 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 809 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 810 | "dev": true 811 | }, 812 | "typescript": { 813 | "version": "4.3.5", 814 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", 815 | "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", 816 | "dev": true 817 | }, 818 | "universalify": { 819 | "version": "2.0.0", 820 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", 821 | "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", 822 | "dev": true 823 | }, 824 | "which": { 825 | "version": "2.0.2", 826 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 827 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 828 | "dev": true, 829 | "requires": { 830 | "isexe": "^2.0.0" 831 | } 832 | }, 833 | "wide-align": { 834 | "version": "1.1.3", 835 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 836 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 837 | "dev": true, 838 | "requires": { 839 | "string-width": "^1.0.2 || 2" 840 | } 841 | }, 842 | "workerpool": { 843 | "version": "6.1.0", 844 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", 845 | "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", 846 | "dev": true 847 | }, 848 | "wrap-ansi": { 849 | "version": "7.0.0", 850 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 851 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 852 | "dev": true, 853 | "requires": { 854 | "ansi-styles": "^4.0.0", 855 | "string-width": "^4.1.0", 856 | "strip-ansi": "^6.0.0" 857 | }, 858 | "dependencies": { 859 | "ansi-regex": { 860 | "version": "5.0.0", 861 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 862 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 863 | "dev": true 864 | }, 865 | "is-fullwidth-code-point": { 866 | "version": "3.0.0", 867 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 868 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 869 | "dev": true 870 | }, 871 | "string-width": { 872 | "version": "4.2.2", 873 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 874 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 875 | "dev": true, 876 | "requires": { 877 | "emoji-regex": "^8.0.0", 878 | "is-fullwidth-code-point": "^3.0.0", 879 | "strip-ansi": "^6.0.0" 880 | } 881 | }, 882 | "strip-ansi": { 883 | "version": "6.0.0", 884 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 885 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 886 | "dev": true, 887 | "requires": { 888 | "ansi-regex": "^5.0.0" 889 | } 890 | } 891 | } 892 | }, 893 | "wrappy": { 894 | "version": "1.0.2", 895 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 896 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 897 | "dev": true 898 | }, 899 | "y18n": { 900 | "version": "5.0.8", 901 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 902 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 903 | "dev": true 904 | }, 905 | "yargs": { 906 | "version": "16.2.0", 907 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 908 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 909 | "dev": true, 910 | "requires": { 911 | "cliui": "^7.0.2", 912 | "escalade": "^3.1.1", 913 | "get-caller-file": "^2.0.5", 914 | "require-directory": "^2.1.1", 915 | "string-width": "^4.2.0", 916 | "y18n": "^5.0.5", 917 | "yargs-parser": "^20.2.2" 918 | }, 919 | "dependencies": { 920 | "ansi-regex": { 921 | "version": "5.0.0", 922 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 923 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 924 | "dev": true 925 | }, 926 | "is-fullwidth-code-point": { 927 | "version": "3.0.0", 928 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 929 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 930 | "dev": true 931 | }, 932 | "string-width": { 933 | "version": "4.2.2", 934 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 935 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 936 | "dev": true, 937 | "requires": { 938 | "emoji-regex": "^8.0.0", 939 | "is-fullwidth-code-point": "^3.0.0", 940 | "strip-ansi": "^6.0.0" 941 | } 942 | }, 943 | "strip-ansi": { 944 | "version": "6.0.0", 945 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 946 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 947 | "dev": true, 948 | "requires": { 949 | "ansi-regex": "^5.0.0" 950 | } 951 | } 952 | } 953 | }, 954 | "yargs-parser": { 955 | "version": "20.2.4", 956 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 957 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 958 | "dev": true 959 | }, 960 | "yargs-unparser": { 961 | "version": "2.0.0", 962 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 963 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 964 | "dev": true, 965 | "requires": { 966 | "camelcase": "^6.0.0", 967 | "decamelize": "^4.0.0", 968 | "flat": "^5.0.2", 969 | "is-plain-obj": "^2.1.0" 970 | } 971 | }, 972 | "yn": { 973 | "version": "3.1.1", 974 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", 975 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", 976 | "dev": true 977 | }, 978 | "yocto-queue": { 979 | "version": "0.1.0", 980 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 981 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 982 | "dev": true 983 | } 984 | } 985 | } 986 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-lame", 3 | "description": "LAME MP3 encoder for Node.js", 4 | "version": "1.3.2", 5 | "homepage": "https://github.com/devowlio/node-lame", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/devowlio/node-lame.git" 9 | }, 10 | "bugs": { 11 | "url": "https://github.com/devowlio/node-lame/issues" 12 | }, 13 | "author": { 14 | "name": "Jan Karres", 15 | "email": "jan.karres@devowl.io", 16 | "url": "https://jankarres.com/" 17 | }, 18 | "contributors": [ 19 | { 20 | "name": "devowl.io GmbH", 21 | "email": "mail@devowl.io" 22 | } 23 | ], 24 | "keywords": [ 25 | "mp3", 26 | "wav", 27 | "LAME", 28 | "MPEG-1", 29 | "MPEG-2", 30 | "encoder", 31 | "audio" 32 | ], 33 | "license": "ISC", 34 | "engines": { 35 | "node": ">=12.20" 36 | }, 37 | "scripts": { 38 | "build": "tsc", 39 | "test": "./node_modules/.bin/mocha" 40 | }, 41 | "files": [ 42 | "lib/build/", 43 | "temp/", 44 | "index.js", 45 | "index.d.ts", 46 | "README.md" 47 | ], 48 | "dependencies": {}, 49 | "devDependencies": { 50 | "@types/chai": "~4.2.21", 51 | "@types/fs-extra": "~9.0.12", 52 | "@types/mocha": "~8.2.1", 53 | "@types/node": "^14.10.1", 54 | "chai": "~4.3.4", 55 | "fs-extra": "~10.0.0", 56 | "mocha": "~8.4.0", 57 | "ts-node": "~10.2.1", 58 | "typescript": "~4.3.5" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /temp/encoded/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devowlio/node-lame/66ba6bd82f7dddabce1a26bad40a48bf61433940/temp/encoded/.keep -------------------------------------------------------------------------------- /temp/raw/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devowlio/node-lame/66ba6bd82f7dddabce1a26bad40a48bf61433940/temp/raw/.keep -------------------------------------------------------------------------------- /test/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devowlio/node-lame/66ba6bd82f7dddabce1a26bad40a48bf61433940/test/.keep -------------------------------------------------------------------------------- /test/example.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devowlio/node-lame/66ba6bd82f7dddabce1a26bad40a48bf61433940/test/example.mp3 -------------------------------------------------------------------------------- /test/example.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devowlio/node-lame/66ba6bd82f7dddabce1a26bad40a48bf61433940/test/example.wav -------------------------------------------------------------------------------- /test/example.wav_LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal (CC0 1.0), Public Domain Dedication 2 | See: https://creativecommons.org/publicdomain/zero/1.0/ 3 | 4 | Original file "Music Box.wav" by VSokorelos 5 | 6 | Source: https://www.freesound.org/people/VSokorelos/sounds/344219/ -------------------------------------------------------------------------------- /test/notAWavFile.wav: -------------------------------------------------------------------------------- 1 | not a wav file 2 | -------------------------------------------------------------------------------- /test/notAnMp3File.mp3: -------------------------------------------------------------------------------- 1 | not an mp3 file 2 | -------------------------------------------------------------------------------- /test/testpic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devowlio/node-lame/66ba6bd82f7dddabce1a26bad40a48bf61433940/test/testpic.jpg -------------------------------------------------------------------------------- /test/tests.js: -------------------------------------------------------------------------------- 1 | const testCase = require("mocha").describe; 2 | const assertions = require("mocha").it; 3 | const assert = require("chai").assert; 4 | const fs = require("fs"); 5 | const fsp = require("fs-extra"); 6 | 7 | const Lame = require("../index").Lame; 8 | 9 | testCase("Lame class", () => { 10 | const TEST_FILE_DURATION = 12; // Audio duration of the TEST_FILE in seconds 11 | const RESULT_DURATION_TOLERANCE = 1; // Max difference between TEST_FILE duration and converted file duration in seconds 12 | const EXPECTED_WAV_SIZE = 2142500; // Size of an correctly converted wav file in bytes 13 | const WAV_SIZE_TOLERANCE = 500; // Max difference between EXPECTED_WAV_SIZE and the actual size of the converted file 14 | 15 | testCase("Encode to .mp3", () => { 16 | const TEST_FILE = "./test/example.wav"; 17 | const OUTPUT_FILE = "./test/encoded.mp3"; 18 | 19 | /** 20 | * @testname Set invalid wav file 21 | * Try to convert a .wav file that contains invalid audio data 22 | */ 23 | assertions("Set invalid wav file", () => { 24 | let errorCaught = false; 25 | const targetBitrate = 128; 26 | 27 | const instance = new Lame({ 28 | output: OUTPUT_FILE, 29 | bitrate: targetBitrate 30 | }); 31 | 32 | instance.setFile("./test/notAWavFile.wav"); 33 | 34 | return instance.encode().catch(error => { 35 | errorCaught = true; 36 | 37 | const expected = 38 | "lame: Warning: unsupported audio format\nCan't init infile './test/notAWavFile.wav'"; 39 | const actual = error.message; 40 | 41 | assert.equal(actual, expected); 42 | assert.isTrue(errorCaught); 43 | }); 44 | }); 45 | 46 | /** 47 | * @testname Encode file to file 48 | * Convert a .wav file to a .mp3 file 49 | */ 50 | assertions("Encode file to file", () => { 51 | const targetBitrate = 128; 52 | 53 | const instance = new Lame({ 54 | output: OUTPUT_FILE, 55 | bitrate: targetBitrate 56 | }); 57 | 58 | instance.setFile(TEST_FILE); 59 | 60 | return instance.encode().then(() => { 61 | // Test expected file duration 62 | return fsp.stat(OUTPUT_FILE).then(stats => { 63 | const size = stats.size; 64 | const resultDuration = (size * 8) / (targetBitrate * 1000); 65 | fs.unlinkSync(OUTPUT_FILE); 66 | 67 | const isDurationWithinTolerance = 68 | TEST_FILE_DURATION - resultDuration < 69 | RESULT_DURATION_TOLERANCE && 70 | TEST_FILE_DURATION - resultDuration > 71 | -1 * RESULT_DURATION_TOLERANCE; 72 | assert.isTrue(isDurationWithinTolerance); 73 | }); 74 | }); 75 | }); 76 | 77 | /** 78 | * @testname Encode file to buffer 79 | * Convert a .wav file to a buffer 80 | */ 81 | assertions("Encode file to buffer", () => { 82 | const targetBitrate = 128; 83 | const output = "buffer"; 84 | 85 | const instance = new Lame({ 86 | output: output, 87 | bitrate: targetBitrate 88 | }); 89 | 90 | instance.setFile(TEST_FILE); 91 | 92 | return instance.encode().then(() => { 93 | // Test expected file duration 94 | const buffer = instance.getBuffer(); 95 | 96 | const size = buffer.byteLength; 97 | resultDuration = (size * 8) / (targetBitrate * 1000); 98 | 99 | const isDurationWithinTolerance = 100 | TEST_FILE_DURATION - resultDuration < 101 | RESULT_DURATION_TOLERANCE && 102 | TEST_FILE_DURATION - resultDuration > 103 | -1 * RESULT_DURATION_TOLERANCE; 104 | assert(isDurationWithinTolerance); 105 | }); 106 | }); 107 | 108 | /** 109 | * @testname Encode buffer to file 110 | * Read a .wav file into a buffer. Then convert the buffer to a .mp3 file. 111 | */ 112 | assertions("Encode buffer to file", () => { 113 | const targetBitrate = 128; 114 | 115 | return fsp.readFile(TEST_FILE).then(inputBuffer => { 116 | const instance = new Lame({ 117 | output: OUTPUT_FILE, 118 | bitrate: targetBitrate 119 | }); 120 | 121 | instance.setBuffer(inputBuffer); 122 | 123 | return instance.encode().then(() => { 124 | // Test expected file duration 125 | return fsp.stat(OUTPUT_FILE).then(stats => { 126 | const size = stats.size; 127 | const resultDuration = 128 | (size * 8) / (targetBitrate * 1000); 129 | fs.unlinkSync(OUTPUT_FILE); 130 | 131 | const isDurationWithinTolerance = 132 | TEST_FILE_DURATION - resultDuration < 133 | RESULT_DURATION_TOLERANCE && 134 | TEST_FILE_DURATION - resultDuration > 135 | -1 * RESULT_DURATION_TOLERANCE; 136 | assert.isTrue(isDurationWithinTolerance); 137 | }); 138 | }); 139 | }); 140 | }); 141 | 142 | /** 143 | * @testname Encode buffer to buffer 144 | * Read a .wav file into a buffer. Then convert the buffer to a buffer containing .mp3 data. 145 | */ 146 | assertions("Encode buffer to buffer", () => { 147 | const targetBitrate = 128; 148 | 149 | return fsp.readFile(TEST_FILE).then(inputBuffer => { 150 | const instance = new Lame({ 151 | output: "buffer", 152 | bitrate: targetBitrate 153 | }); 154 | instance.setBuffer(inputBuffer); 155 | 156 | return instance.encode().then(() => { 157 | // Test expected file duration 158 | const buffer = instance.getBuffer(); 159 | 160 | const size = buffer.byteLength; 161 | const resultDuration = (size * 8) / (targetBitrate * 1000); 162 | 163 | const isDurationWithinTolerance = 164 | TEST_FILE_DURATION - resultDuration < 165 | RESULT_DURATION_TOLERANCE && 166 | TEST_FILE_DURATION - resultDuration > 167 | -1 * RESULT_DURATION_TOLERANCE; 168 | assert.isTrue(isDurationWithinTolerance); 169 | }); 170 | }); 171 | }); 172 | }); 173 | 174 | testCase("Decode to .wav", () => { 175 | const TEST_FILE = "./test/example.mp3"; 176 | const OUTPUT_FILE = "./test/converted.wav"; 177 | 178 | /** 179 | * @testname Set invalid wav file 180 | * Try to convert a .mp3 file that contains invalid audio data 181 | */ 182 | assertions("Set invalid mp3 file", () => { 183 | let errorCaught = false; 184 | const targetBitrate = 128; 185 | 186 | const instance = new Lame({ 187 | output: OUTPUT_FILE, 188 | bitrate: targetBitrate 189 | }); 190 | 191 | instance.setFile("./test/notAnMp3File.mp3"); 192 | 193 | return instance.decode().catch(error => { 194 | errorCaught = true; 195 | 196 | const expected = 197 | "lame: Error reading headers in mp3 input file ./test/notAnMp3File.mp3.\nCan't init infile './test/notAnMp3File.mp3'"; 198 | const actual = error.message; 199 | 200 | assert.equal(actual, expected); 201 | assert.isTrue(errorCaught); 202 | }); 203 | }); 204 | 205 | /** 206 | * @testname Decode file to file 207 | * Convert a .mp3 file to a .wav file 208 | */ 209 | assertions("Decode file to file", () => { 210 | const targetBitrate = 128; 211 | 212 | const instance = new Lame({ 213 | output: OUTPUT_FILE, 214 | bitrate: targetBitrate 215 | }); 216 | 217 | instance.setFile(TEST_FILE); 218 | 219 | return instance.decode().then(() => { 220 | // Test expected file size 221 | return fsp.stat(OUTPUT_FILE).then(stats => { 222 | fs.unlinkSync(OUTPUT_FILE); 223 | 224 | const actualSize = stats.size; 225 | const isSizeWithinTolerance = 226 | EXPECTED_WAV_SIZE - actualSize < WAV_SIZE_TOLERANCE && 227 | EXPECTED_WAV_SIZE - actualSize > 228 | -1 * WAV_SIZE_TOLERANCE; 229 | assert.isTrue(isSizeWithinTolerance); 230 | }); 231 | }); 232 | }); 233 | 234 | /** 235 | * @testname Decode file to buffer 236 | * Convert a .mp3 file to a buffer 237 | */ 238 | assertions("Decode file to buffer", () => { 239 | const targetBitrate = 128; 240 | const output = "buffer"; 241 | 242 | const instance = new Lame({ 243 | output: output, 244 | bitrate: targetBitrate 245 | }); 246 | 247 | instance.setFile(TEST_FILE); 248 | 249 | return instance.decode().then(() => { 250 | // Test expected file size 251 | const buffer = instance.getBuffer(); 252 | 253 | const actualSize = buffer.byteLength; 254 | const isSizeWithinTolerance = 255 | EXPECTED_WAV_SIZE - actualSize < WAV_SIZE_TOLERANCE && 256 | EXPECTED_WAV_SIZE - actualSize > -1 * WAV_SIZE_TOLERANCE; 257 | assert.isTrue(isSizeWithinTolerance); 258 | }); 259 | }); 260 | 261 | /** 262 | * @testname Decode buffer to file 263 | * Read a .mp3 file into a buffer. Then convert the buffer to a .wav file. 264 | */ 265 | assertions("Decode buffer to file", () => { 266 | const targetBitrate = 128; 267 | 268 | return fsp.readFile(TEST_FILE).then(inputBuffer => { 269 | const instance = new Lame({ 270 | output: OUTPUT_FILE, 271 | bitrate: targetBitrate 272 | }); 273 | 274 | instance.setBuffer(inputBuffer); 275 | 276 | return instance.decode().then(() => { 277 | // Test expected file size 278 | return fsp.stat(OUTPUT_FILE).then(stats => { 279 | fs.unlinkSync(OUTPUT_FILE); 280 | 281 | const actualSize = stats.size; 282 | const isSizeWithinTolerance = 283 | EXPECTED_WAV_SIZE - actualSize < 284 | WAV_SIZE_TOLERANCE && 285 | EXPECTED_WAV_SIZE - actualSize > 286 | -1 * WAV_SIZE_TOLERANCE; 287 | assert.isTrue(isSizeWithinTolerance); 288 | }); 289 | }); 290 | }); 291 | }); 292 | 293 | /** 294 | * @testname Decode buffer to buffer 295 | * Read a .mp3 file into a buffer. Then convert the buffer to a buffer containing .wav data. 296 | */ 297 | assertions("Decode buffer to buffer", () => { 298 | const targetBitrate = 128; 299 | 300 | return fsp.readFile(TEST_FILE).then(inputBuffer => { 301 | const instance = new Lame({ 302 | output: "buffer", 303 | bitrate: targetBitrate 304 | }); 305 | instance.setBuffer(inputBuffer); 306 | 307 | return instance.decode().then(() => { 308 | // Test expected file size 309 | const buffer = instance.getBuffer(); 310 | 311 | const actualSize = buffer.byteLength; 312 | const isSizeWithinTolerance = 313 | EXPECTED_WAV_SIZE - actualSize < WAV_SIZE_TOLERANCE && 314 | EXPECTED_WAV_SIZE - actualSize > 315 | -1 * WAV_SIZE_TOLERANCE; 316 | assert.isTrue(isSizeWithinTolerance); 317 | }); 318 | }); 319 | }); 320 | }); 321 | 322 | testCase("Other", () => { 323 | const TEST_FILE = "./test/example.wav"; 324 | const OUTPUT_FILE = "./test/encoded.mp3"; 325 | 326 | 327 | /** 328 | * @testname Encode empty buffer to not existing path 329 | */ 330 | assertions("Encode empty buffer to not existing path", () => { 331 | let errorCaught = false; 332 | const invalidBuffer = Buffer.alloc(100, 0x00); 333 | 334 | const instance = new Lame({ 335 | raw: true, 336 | output: "DOES_NOT_EXIST/output.mp3" 337 | }); 338 | 339 | instance.setBuffer(invalidBuffer); 340 | 341 | return instance.encode().catch(error => { 342 | errorCaught = true; 343 | }) 344 | .finally(() => { 345 | assert.isTrue(errorCaught); 346 | }); 347 | }); 348 | 349 | /** 350 | * @testname Option output required 351 | * Call Lame constructor with empty options object 352 | */ 353 | assertions("Option output required", () => { 354 | let errorCaught = false; 355 | 356 | try { 357 | const instance = new Lame({}); 358 | } catch (error) { 359 | errorCaught = true; 360 | const expected = "lame: Invalid option: 'output' is required"; 361 | const actual = error.message; 362 | 363 | assert.equal(actual, expected); 364 | } 365 | 366 | assert.isTrue(errorCaught); 367 | }); 368 | 369 | /** 370 | * @testname Option bitrate is required 371 | * Call Lame constructor with no bitrate specified in options object 372 | */ 373 | assertions("Option bitrate is required", () => { 374 | let errorCaught = false; 375 | 376 | const instance = new Lame({ 377 | output: OUTPUT_FILE 378 | }); 379 | 380 | instance.setFile("./test/notAWavFile.wav"); 381 | 382 | return instance.encode().catch(error => { 383 | errorCaught = true; 384 | 385 | const expected = 386 | "lame: Warning: unsupported audio format\nCan't init infile './test/notAWavFile.wav'"; 387 | const actual = error.message; 388 | 389 | assert.equal(actual, expected); 390 | assert.isTrue(errorCaught); 391 | }); 392 | }); 393 | 394 | /** 395 | * @testname Set not existing file 396 | * Try to convert not existing file 397 | */ 398 | assertions("Set not existing file", () => { 399 | let errorCaught = false; 400 | 401 | try { 402 | const instance = new Lame({ 403 | output: OUTPUT_FILE 404 | }); 405 | 406 | instance.setFile("./test/not-existing.wav"); 407 | } catch (error) { 408 | errorCaught = true; 409 | 410 | const expected = "Audio file (path) does not exist"; 411 | const actual = error.message; 412 | 413 | assert.equal(actual, expected); 414 | } 415 | 416 | assert.isTrue(errorCaught); 417 | }); 418 | 419 | /** 420 | * @testname Get status object before start 421 | * Setup the converter properly, then read the status object without calling the encode function. 422 | */ 423 | assertions("Get status object before start", () => { 424 | const targetBitrate = 128; 425 | 426 | const instance = new Lame({ 427 | output: OUTPUT_FILE, 428 | bitrate: targetBitrate 429 | }); 430 | 431 | instance.setFile(TEST_FILE); 432 | 433 | const actual = instance.getStatus(); 434 | 435 | const expected = { 436 | started: false, 437 | finished: false, 438 | progress: undefined, 439 | eta: undefined 440 | }; 441 | 442 | assert.deepEqual(actual, expected); 443 | }); 444 | 445 | /** 446 | * @testname Get status object during converting 447 | * Setup the converter properly, call the encode function and immediately read the status object. 448 | */ 449 | assertions("Get status object during converting", () => { 450 | const targetBitrate = 128; 451 | 452 | const instance = new Lame({ 453 | output: OUTPUT_FILE, 454 | bitrate: targetBitrate 455 | }); 456 | 457 | instance.setFile(TEST_FILE); 458 | const emitter = instance.getEmitter(); 459 | 460 | instance.encode().then(() => { 461 | fs.unlinkSync(OUTPUT_FILE); 462 | }); 463 | 464 | const actual = instance.getStatus(); 465 | const expected = { 466 | started: true, 467 | finished: false, 468 | progress: 0, 469 | eta: undefined 470 | }; 471 | 472 | assert.deepEqual(actual, expected); 473 | 474 | // Ensure next test will executed after finishing encoding 475 | return new Promise(resolve => { 476 | emitter.on("finish", resolve); 477 | }); 478 | }); 479 | 480 | /** 481 | * @testname Get status object after converting 482 | * Setup the converter properly, call the encode function and read the status object afterwards. 483 | */ 484 | assertions("Get status object after converting", () => { 485 | const targetBitrate = 128; 486 | 487 | const instance = new Lame({ 488 | output: OUTPUT_FILE, 489 | bitrate: targetBitrate 490 | }); 491 | 492 | instance.setFile(TEST_FILE); 493 | 494 | return instance.encode().then(() => { 495 | const actual = instance.getStatus(); 496 | 497 | const expected = { 498 | started: true, 499 | finished: true, 500 | progress: 100, 501 | eta: "00:00" 502 | }; 503 | 504 | fs.unlinkSync(OUTPUT_FILE); 505 | assert.deepEqual(actual, expected); 506 | }); 507 | }); 508 | 509 | /** 510 | * @testname Get status eventEmitter successful converting 511 | * Setup the converter properly, call the encode function and check if progress and finish were emitted. 512 | */ 513 | assertions("Get status eventEmitter successful converting", () => { 514 | const targetBitrate = 128; 515 | 516 | const instance = new Lame({ 517 | output: OUTPUT_FILE, 518 | bitrate: targetBitrate 519 | }); 520 | 521 | instance.setFile(TEST_FILE); 522 | 523 | const emitter = instance.getEmitter(); 524 | 525 | let progressTriggered = false; 526 | let finishTriggered = false; 527 | 528 | emitter.on("progress", () => { 529 | progressTriggered = true; 530 | }); 531 | 532 | emitter.on("finish", () => { 533 | finishTriggered = true; 534 | 535 | fs.unlinkSync(OUTPUT_FILE); 536 | }); 537 | 538 | emitter.on("error", error => { 539 | assert.isTrue(false); 540 | }); 541 | 542 | return instance.encode().then(() => { 543 | // error expected is irrelevant for this test 544 | assert.isTrue(progressTriggered); 545 | assert.isTrue(finishTriggered); 546 | }); 547 | }); 548 | 549 | /** 550 | * @testname Get status eventEmitter unsuccessful converting 551 | * Setup the converter with invalid source file, call the encode function and check if an error is emitted. 552 | */ 553 | assertions("Get status eventEmitter unsuccessful converting", () => { 554 | const targetBitrate = 128; 555 | 556 | const instance = new Lame({ 557 | output: OUTPUT_FILE, 558 | bitrate: targetBitrate 559 | }); 560 | 561 | instance.setFile("./test/notAWavFile.wav"); 562 | 563 | const emitter = instance.getEmitter(); 564 | 565 | let errorTriggered = false; 566 | 567 | emitter.on("error", error => { 568 | errorTriggered = true; 569 | }); 570 | 571 | return instance.encode().catch(() => { 572 | return new Promise(resolve => { 573 | setTimeout(() => { 574 | assert.isTrue(errorTriggered); 575 | 576 | resolve(); 577 | }, 500); 578 | }); 579 | }); 580 | }); 581 | 582 | /** 583 | * @testname Options 584 | * Specify optional Options and check if they are set in the options object. 585 | */ 586 | assertions("Options", () => { 587 | const instance = new Lame({ 588 | output: OUTPUT_FILE, 589 | bitrate: 128, 590 | raw: true, 591 | "swap-bytes": true, 592 | sfreq: 22.05, 593 | bitwidth: 32, 594 | signed: true, 595 | unsigned: true, 596 | "little-endian": true, 597 | "big-endian": true, 598 | mp2Input: true, 599 | mp3Input: true, 600 | mode: "r", 601 | "to-mono": true, 602 | "channel-different-block-sizes": true, 603 | freeformat: "FreeAmp", 604 | "disable-info-tag": true, 605 | comp: 5, 606 | scale: 2, 607 | "scale-l": 1, 608 | "scale-r": 3, 609 | "replaygain-fast": true, 610 | "replaygain-accurate": true, 611 | "no-replaygain": true, 612 | "clip-detect": true, 613 | preset: "medium", 614 | noasm: "sse", 615 | quality: 3, 616 | "force-bitrate": true, 617 | cbr: true, 618 | abr: 45, 619 | vbr: true, 620 | "vbr-quality": 6, 621 | "ignore-noise-in-sfb21": true, 622 | emp: "5", 623 | "mark-as-copyrighted": true, 624 | "mark-as-copy": true, 625 | "crc-error-protection": true, 626 | nores: true, 627 | "strictly-enforce-ISO": true, 628 | lowpass: 55, 629 | "lowpass-width": 9, 630 | highpass: 400, 631 | "highpass-width": 4, 632 | resample: 44.1, 633 | meta: { 634 | title: "test title", 635 | artist: "test artist", 636 | album: "test album", 637 | year: "2017", 638 | comment: "test comment", 639 | track: "3", 640 | genre: "test genre", 641 | artwork: "testpic.jpg", 642 | "add-id3v2": true, 643 | "id3v1-only": true, 644 | "id3v2-only": true, 645 | "id3v2-latin1": true, 646 | "id3v2-utf16": true, 647 | "space-id3v1": true, 648 | "pad-id3v2": true, 649 | "pad-id3v2-size": 2, 650 | "ignore-tag-errors": true, 651 | "genre-list": "test, genres" 652 | } 653 | }); 654 | instance.setFile(TEST_FILE); 655 | 656 | expected = [ 657 | "-b", 658 | 128, 659 | "-r", 660 | "-x", 661 | "-s", 662 | 22.05, 663 | "--bitwidth", 664 | 32, 665 | "--signed", 666 | "--unsigned", 667 | "--little-endian", 668 | "--big-endian", 669 | "--mp2input", 670 | "--mp3input", 671 | "-m", 672 | "r", 673 | "-a", 674 | "-d", 675 | "--freeformat", 676 | "FreeAmp", 677 | "-t", 678 | "--comp", 679 | 5, 680 | "--scale", 681 | 2, 682 | "--scale-l", 683 | 1, 684 | "--scale-r", 685 | 3, 686 | "--replaygain-fast", 687 | "--replaygain-accurate", 688 | "--noreplaygain", 689 | "--clipdetect", 690 | "--preset", 691 | "medium", 692 | "--noasm", 693 | "sse", 694 | "-q", 695 | 3, 696 | "-F", 697 | "--cbr", 698 | "--abr", 699 | 45, 700 | "-v", 701 | "-V", 702 | 6, 703 | "-Y", 704 | "-e", 705 | "5", 706 | "-c", 707 | "-o", 708 | "-p", 709 | "--nores", 710 | "--strictly-enforce-ISO", 711 | "--lowpass", 712 | 55, 713 | "--lowpass-width", 714 | 9, 715 | "--highpass", 716 | 400, 717 | "--highpass-width", 718 | 4, 719 | "--resample", 720 | 44.1, 721 | "--tt", 722 | "test title", 723 | "--ta", 724 | "test artist", 725 | "--tl", 726 | "test album", 727 | "--ty", 728 | "2017", 729 | "--tc", 730 | "test comment", 731 | "--tn", 732 | "3", 733 | "--tg", 734 | "test genre", 735 | "--ti", 736 | "testpic.jpg", 737 | "--add-id3v2", 738 | "--id3v1-only", 739 | "--id3v2-only", 740 | "--id3v2-latin1", 741 | "--id3v2-utf16", 742 | "--space-id3v1", 743 | "--pad-id3v2", 744 | "--pad-id3v2-size", 745 | "2", 746 | "--ignore-tag-errors", 747 | "--genre-list", 748 | "test, genres" 749 | ]; 750 | 751 | const actual = instance.args; 752 | assert.deepEqual(expected, actual); 753 | }); 754 | }); 755 | }); 756 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "module": "commonjs", 5 | "jsx": "preserve", 6 | "outDir": "lib/build/", 7 | "sourceMap": true, 8 | "removeComments": false, 9 | "alwaysStrict": true, 10 | "noImplicitAny": false, 11 | "noImplicitReturns": false 12 | }, 13 | "include": ["lib/src/*.ts"], 14 | "formatCodeOptions": { 15 | "indentSize": 5, 16 | "tabSize": 5, 17 | "newLineCharacter": "\r\n", 18 | "convertTabsToSpaces": false, 19 | "insertSpaceAfterCommaDelimiter": true, 20 | "insertSpaceAfterSemicolonInForStatements": true, 21 | "insertSpaceBeforeAndAfterBinaryOperators": true, 22 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 23 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 24 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 25 | "placeOpenBraceOnNewLineForFunctions": false, 26 | "placeOpenBraceOnNewLineForControlBlocks": false 27 | }, 28 | "compileOnSave": true, 29 | "buildOnSave": false 30 | } 31 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:recommended", 5 | "tslint-config-airbnb", 6 | "tslint-config-prettier" 7 | ], 8 | "jsRules": { 9 | "indent": [true, "spaces", 4] 10 | }, 11 | "rules": { 12 | "indent": [true, "spaces", 4] 13 | }, 14 | "rulesDirectory": [] 15 | } 16 | --------------------------------------------------------------------------------