Created
May 15, 2022 20:53
-
-
Save hack0x90/57a11e8b33598ec24119480a433a17de to your computer and use it in GitHub Desktop.
SoundCloud mp3 Download Index.js File
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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