Skip to content

Commit

Permalink
Merge pull request #1 from mitsuki31/feature/add-internal-converter
Browse files Browse the repository at this point in the history
Add internal MP3 converter feature
  • Loading branch information
mitsuki31 authored Nov 12, 2023
2 parents a32a1cd + 38c726f commit 9cb5943
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 7 deletions.
22 changes: 15 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
* @since 0.1.0
*/

'use strict';

const fs = require('fs'), // File system module
os = require('os'), // OS module
path = require('path'), // Path module
ytdl = require('ytdl-core'); // Youtube Downloader module

const { convertToMp3 } = require('./lib/acodecs-cvt');

/**
* Normalizes a YouTube Music URL to its original YouTube format.
*
Expand Down Expand Up @@ -60,6 +64,9 @@ function normalizeYtMusicUrl(url) {
const urlsFile = path.resolve(inputFile);
console.log('File:', urlsFile);

// All illegal characters for file names
const illegalCharRegex = /[<>:"\/\\|?*\x00-\x1F]/g;

await fs.readFile(urlsFile, 'utf8', (err, contents) => {
if (err) throw err;
if (contents === '') throw new Error('File is empty, no URL found');
Expand All @@ -78,26 +85,27 @@ function normalizeYtMusicUrl(url) {
const info = await ytdl.getInfo(url);
const authorVideo = info.videoDetails.author.name
.replace(/\s-\s.+/, ''),
titleVideo = info.videoDetails.title;
titleVideo = info.videoDetails.title.replace(illegalCharRegex, '_');

// Filter the audio and create new audio format
const format = ytdl.chooseFormat(info.formats, {
quality: '140', // This itag refers to 'mp4a' codec
filter: 'audioonly' // Filter audio only
});

// The file name format
const filename = `${authorVideo} - ${titleVideo}.m4a`;
const outStream = fs.createWriteStream(
path.join('download', filename));
const filename = path.join('download', `${titleVideo}.m4a`);
const outStream = fs.createWriteStream(filename);

console.log(`Processing... '${titleVideo}' (${ytdl.getVideoID(url)})`);
// Start downloading the audio and save to file
ytdl.downloadFromInfo(info, { format: format })
await ytdl.downloadFromInfo(info, { format: format })
.pipe(outStream);
outStream.on('finish', () => {
console.log(`Finished: '${filename}' [${
console.log(`Finished: '${path.basename(filename)}' [${
(new Date()).toISOString()}]`);

// Convert to MP3
convertToMp3(filename);
});
});
});
Expand Down
67 changes: 67 additions & 0 deletions lib/acodecs-cvt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* `acodecs-cvt` is an abbreviation for Audio Codecs Converter.
* @author Ryuu Mitsuki
* @since 0.2.0
*/

'use strict';

const fs = require('fs'),
path = require('path'),
ffmpeg = require('fluent-ffmpeg');

const optionsMp3 = {
format: 'mp3',
bitrate: '128k',
frequency: 44100,
codec: 'libmp3lame',
channels: 2
};

function convertToMp3(inFile, options = optionsMp3) {
// Regular expressions for audio codecs
const audioCodecRegex = /(mp3|aac|wav|flac|ogg|wma|opus|amr|m4a)/i, // All known extension names of audio file
noExtRegex = new RegExp(`(.+)(?:\\.${audioCodecRegex.source})$`); // Get the file name without its extension

// Rename file extension to MP3 for the output file
const outFile = path.join(
path.dirname(inFile),
`${noExtRegex.exec(path.basename(inFile))[1]}.${options.format}`
);

// Store the file names only without their path directories
const ioBaseFile = [
path.basename(inFile),
path.basename(outFile)
];

console.log(`Processing '${noExtRegex.exec(ioBaseFile[0])[1]}' ...`);
ffmpeg(inFile) // Input
// Options
.toFormat(options.format)
.audioBitrate(options.bitrate)
.audioCodec(options.codec)
.audioChannels(options.channels)
.audioFrequency(options.frequency)

// Handlers
.on('error', (err) => {
console.error(err);
})
.on('progress', (info) => {
const percentage = Math.floor(info.percent);
// Write the progression percentage to the console
process.stdout.write(
`Progress: ${percentage < 0 ? 0 : percentage}%\r`);
})
.on('end', () => {
console.log('All done successfully.');
})
.save(outFile); // Output
}


module.exports = {
optionsMp3,
convertToMp3
};
34 changes: 34 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
"license": "MIT",
"dependencies": {
"fluent-ffmpeg": "^2.1.2",
"ytdl-core": "^4.11.5"
}
}

0 comments on commit 9cb5943

Please sign in to comment.