diff --git a/lib/audioconv.js b/lib/audioconv.js index fbd72ed..f17467c 100644 --- a/lib/audioconv.js +++ b/lib/audioconv.js @@ -46,8 +46,8 @@ const { * Options for configuring the audio conversion. * * @typedef {Object} ConvertAudioOptions - * @property {string[]} [inputOptions] - The input options for the conversion. - * @property {string[]} [outputOptions] - The output options for the conversion. + * @property {string[]} [inputOptions=[]] - The input options for the conversion. + * @property {string[]} [outputOptions=[]] - The output options for the conversion. * @property {string} [format='mp3'] - The desired output format (e.g., `'mp3'`, `'aac'`). * @property {string | number} [bitrate=128] - The audio bitrate (e.g., `'128k'`), * it may be a number or a string with an optional `k` suffix. @@ -77,24 +77,39 @@ const { * @property {boolean} deleteOld - Whether to delete the original file after conversion. * @property {boolean} quiet - Whether to suppress the conversion progress and error message or not. * + * @package * @since 1.0.0 * @see {@link module:audioconv~defaultOptions defaultOptions} */ +/** + * An object representing the information data when FFmpeg emits the `'progress'` event. + * + * @typedef {Object} FFmpegInfo + * @property {number} frames - Total processed frame count. + * @property {number} currentFps - Framerate at which FFmpeg is currently processing. + * @property {number} currentKbps - Throughput at which FFmpeg is currently processing. + * @property {number} targetSize - Current size of the target file in kilobytes. + * @property {number} timemark - The timestamp of the current frame in seconds. + * @property {number} percent - An estimation of the progress percentage, may be (very) inaccurate. + * + * @package + * @since 1.1.0 + * @see ['progress' event]{@linkplain https://github.com/fluent-ffmpeg/node-fluent-ffmpeg#progress-transcoding-progress-information} + */ /** * Default options of audio converter options. * - * Any option that are not specified on `options` argument in `convertAudio` function - * will fallback to this options. This default options will convert the audio - * to the MP3 format with bitrate of 128 kbps, frequency of 44100 Hz (Hertz), - * stereo channel and use the default MP3 codec. + * This default options will convert the audio to the MP3 format with bitrate of 128 kbps, + * frequency of 44100 Hz (Hertz), stereo channel and use the default MP3 codec. * * If you want to delete the old audio file after conversion, set the * `deleteOld` option to `true`. * - * @constant - * @type {ResolvedConvertAudioOptions} + * @public + * @readonly + * @type {Readonly} * @since 0.2.0 */ const defaultOptions = Object.freeze({ @@ -111,6 +126,23 @@ const defaultOptions = Object.freeze({ // region Utilities +/** + * Splits and resolves FFmpeg options from a string or array format into an array of individual options. + * + * This function handles both single string input, where options are space-separated, and array input. + * It correctly pairs options with their respective values and avoids accidental concatenation with subsequent options. + * + * @example + * const optionsStr = '-f -vcodec libx264 -preset slow'; + * const result1 = splitOptions(optionsStr); + * // Output: ['-f', '-vcodec libx264', '-preset slow'] + * + * @param {string | string[]} options - The options to split, either as a string or an array. + * @returns {string[]} The resolved options as an array of individual options. + * + * @package + * @since 1.0.0 + */ function splitOptions(options) { if (typeof options === 'string') { const optionsList = options.trim().split(' '); @@ -156,9 +188,9 @@ function splitOptions(options) { /** * Resolves the given {@link ConvertAudioOptions} options. * - * @private + * @package * @param {ConvertAudioOptions} options - The unresolved audio converter options. - * @return {ResolvedConvertAudioOptions} The resolved options. + * @return {module:audioconv~ResolvedConvertAudioOptions} The resolved options. * @since 1.0.0 */ function resolveOptions(options, useDefault=true) { @@ -242,6 +274,32 @@ async function checkFfmpeg(verbose=false) { return false; } +/** + * Writes error details and associated video information to a log file. + * + * The error message is written to the log file in the following format: + * + * ```txt + * [ERROR] + * Input Audio: + * Output Audio: + * File Size: MiB + * --------------------------------------------- + * ``` + * + * Generated log file will be saved in {@link module:utils~LOGDIR `LOGDIR`} directory + * with file name typically prefixed with `'audioConvError'`. + * + * @param {string} logFile - The name of the log file where the error details should be written. + * @param {Object} data - An object containing information about the audio associated with the error. + * @param {Error} [error] - The error object, optional. If not provided, + * an error message will be `'Unknown error'`. + * @returns {Promise} + * + * @async + * @package + * @since 1.0.0 + */ async function writeErrorLog(logFile, data, error) { // Return immediately if given log file is not a string type if (isNullOrUndefined(logFile) || typeof logFile !== 'string') return; @@ -270,7 +328,16 @@ async function writeErrorLog(logFile, data, error) { // region Audio Conversion - +/** + * Creates a string representing the progress bar for audio conversion progress. + * + * @param {FFmpegInfo} info - The progress data from FFmpeg. + * @param {string[]} extnames - A list of extension names of both input and output files. + * @returns {string} A formatted string representing the progress bar with percentage. + * + * @package + * @since 1.0.0 + */ function createConversionProgress(info, extnames) { const percentage = Math.max(0, Math.round(info.percent || 0)); const currentKbps = Math.max(0, info.currentKbps || 0); diff --git a/lib/utils.js b/lib/utils.js index ed1d42f..ab55baa 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -69,11 +69,25 @@ const FrozenProperty = { enumerable: true }; -/** The root directory of the project. */ +/** + * The root directory of the project. + * @since 1.0.0 + */ const ROOTDIR = path.join(__dirname, '..'); -/** The output directory for the downloaded audio files. */ +/** + * The output directory for the downloaded audio files. + * @since 1.0.0 + */ const OUTDIR = path.join(ROOTDIR, 'download'); -/** The log directory for the download error logs. */ +/** + * The log directory for error logs. + * + * Basically, the log directory is set to: + * - **POSIX**: `$HOME/.ytmp3-js/logs` + * - **Windows**: `%USERPROFILE%\.ytmp3-js\logs` + * + * @since 1.0.0 + */ const LOGDIR = path.join(os.homedir(), '.ytmp3-js', 'logs');