Skip to content

Instantly share code, notes, and snippets.

@hack0x90
Created May 15, 2022 20:53
Show Gist options
  • Save hack0x90/57a11e8b33598ec24119480a433a17de to your computer and use it in GitHub Desktop.
Save hack0x90/57a11e8b33598ec24119480a433a17de to your computer and use it in GitHub Desktop.
SoundCloud mp3 Download Index.js File
import { spawn } from 'child_process';
import { parse } from 'node-html-parser';
const client_id = process.env.SOUNDCLOUD_CLIENT_ID;
const link = process.argv[2] || 'https://soundcloud.com/rashidaliofficial/kabhi-kabhi-aditi';
/*
* Download SoundCloud track page HTML code
*/
const getSoundCloundHtml = () => {
return new Promise((resolve, reject) => {
const scUrl = link;
const curl = spawn("curl", [
"-A",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15",
scUrl
]);
let chunks = [];
curl.stdout.on("data", data => { chunks.push(data); });
curl.stderr.on("data", data => { console.log(`stderr: ${data}`); });
curl.on('error', (error) => {
console.log(`error: ${error.message}`);
reject(error);
});
curl.on("close", () => {
let body = Buffer.concat(chunks);
resolve(body.toString());
});
});
};
/*
* Get m3u8 playlist link from SoundCloud
*/
const getPlaylistLink = (url) => {
return new Promise((resolve, reject) => {
const curl = spawn("curl", ["--location", "--request", "GET", url]);
let chunks = [];
curl.stdout.on("data", data => { chunks.push(data); });
curl.stderr.on("data", data => { console.log(`stderr: ${data}`); });
curl.on('error', (error) => {
console.log(`error: ${error.message}`);
reject(error);
});
curl.on("close", () => {
let body = Buffer.concat(chunks);
resolve(body.toString());
});
});
};
/*
* Save mp3 file on disk
*/
const saveTrack = (playlistUrl) => {
return new Promise((resolve, reject) => {
const tmp = link.split('/')
const fileName = `${tmp[tmp.length - 1]}.mp3`;
const ffmpeg = spawn("ffmpeg", ["-i", playlistUrl, fileName]);
ffmpeg.on('error', (error) => {
console.log(`error: ${error.message}`);
reject(error);
});
ffmpeg.on("close", () => {
console.log('done');
resolve('done');
});
});
};
async function main () {
let dataText = '';
// Step 1 : Download HTML
const html = await getSoundCloundHtml();
const root = parse(html);
// Step 2: Parse html and get the script tag
root.querySelectorAll('script').forEach((el, idx) => {
if (el.innerText.startsWith('window.__sc_hydration')) {
dataText = el.innerText;
}
});
// Step 3: Execute the javascript, and get the link for m3u8 playlist
let x;
let startIndex = dataText.indexOf('[');
let endIndex = dataText.lastIndexOf(']');
let str = dataText.substring(startIndex, endIndex + 1);
eval('x = ' + str);
const url = `${x[7].data.media.transcodings[0].url}?client_id=${client_id}&track_authorization=${x[7].data.track_authorization}`;
// Step 4: Download m3u8 playlist file
const playlistUrl = await getPlaylistLink(url);
// Step 5: Save the mp3 file using ffmpeg
const result = await saveTrack(JSON.parse(playlistUrl).url);
console.log(result);
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment