Skip to content

Added spotify support, yt-dlp auto takes cookies from browser and updated README #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules/
songs/
cookies.*
*.exe
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# μshare
originally meant to be mushare (music share) but I realized μshare looks cooler

## running
install yt-dlp in root of project, and ffmpeg globally.
run node index.js, and go to http://localhost:3000
## Prerequisites
* [yt-dlp x86 in root folder](https://github.com/yt-dlp/yt-dlp/releases)
* [spotDL win32 in root folder](https://github.com/spotDL/spotify-downloader/releases)
* [ffmpeg globally](https://ffmpeg.org/download.html)

## Running
Set your browser inside of ```index.js```
Run ```node .``` and go to http://localhost:3000

## Warning
This does allow arbitrary file downloads on the server, so use with caution. I am not responsible for any accidents resulting of this.
This does allow arbitrary file downloads on the server, so use with caution. I am not responsible for any accidents resulting of this.
36 changes: 29 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const WebSocket = require('ws');
const fs = require('fs');
const path = require('path');
const { Worker } = require('worker_threads');
const ytdl = require('ytdl-core');
const browser = 'firefox'; // ADD .ENV FILE FOR USER BROWSER, OR AUTODETECT

// Create a Timer worker for precise timing
const timerWorker = new Worker(`
Expand Down Expand Up @@ -79,7 +79,7 @@ app.use(express.static('public'));
app.use(express.json());

// API endpoints for song management
app.get('/api/songs', (req, res) => {
app.get('/api/songs', (res) => {
const songs = Array.from(songLibrary.values());
res.json(songs);
});
Expand All @@ -105,11 +105,32 @@ app.get('/api/songs/:id/stream', (req, res) => {

app.post('/api/download', async (req, res) => {
const { url } = req.body;
const ytDlp = path.join(__dirname, 'yt-dlp_x86.exe');
const title = await ytdl.getBasicInfo(url).then(info => info.videoDetails.title);
const audioPath = path.join(SONGS_DIR, `${title}.mp3`);
const audioPath = path.join(SONGS_DIR);

// Check if url is a spotify link
if (url.includes('spotify.com')) {
console.log('Using spotDL for Spotify download');
const spotDL = path.join(__dirname, 'spotdl-4.2.11-win32.exe');
const spotDLProcess = require('child_process').spawn(spotDL, [url, '--bitrate', '192k', '--output', audioPath]);

spotDLProcess.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});

spotDLProcess.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});

spotDLProcess.on('close', (code) => {
console.log(`spotDL process exited with code ${code}`);
});

const ytDlpProcess = require('child_process').spawn(ytDlp, ['--extract-audio', '--audio-format', 'mp3', '--audio-quality', '0', '--output', audioPath, url]);
res.json({ message: 'Spotify Download started' });
} else {
// Use yt-dlp for other links
console.log('Using yt-dlp for download');
const ytDlp = path.join(__dirname, 'yt-dlp_x86.exe');
const ytDlpProcess = require('child_process').spawn(ytDlp, ['--extract-audio', '--audio-format', 'mp3', '--audio-quality', '0', '--cookies-from-browser', browser, '--output', path.join(audioPath, '%(title)s.%(ext)s'), url]);

ytDlpProcess.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
Expand All @@ -123,7 +144,8 @@ app.post('/api/download', async (req, res) => {
console.log(`yt-dlp process exited with code ${code}`);
});

res.json({ message: 'Download started' });
res.json({ message: 'yt-dlp Download started' });
}
});

// Handle precise timing updates from worker
Expand Down
6 changes: 3 additions & 3 deletions public/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ function updateSongList(songs) {

function updateNowPlaying() {
if (currentSong) {
document.title = `${currentSong.title} | mushare`;
document.title = `${currentSong.title} | μshare`;
} else {
document.title = "mushare";
document.title = "μshare";
}
}

Expand Down Expand Up @@ -183,7 +183,7 @@ async function downloadSong(youtubeUrl) {
};

function ask_link() {
let youtubeUrl = window.prompt('Enter the YouTube URL of the song to download:');
let youtubeUrl = window.prompt('Enter the YouTube/Spotify URL of the song to download:');

if (youtubeUrl) {
downloadSong(youtubeUrl);
Expand Down
4 changes: 2 additions & 2 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>mushare</title>
<title>μshare</title>
<link rel="stylesheet" href="styles.css" />
<link rel="shortcut icon" href="favicon.png" type="image/png" />
</head>
<body>
<div class="player-container">
<h2>mushare</h2>
<h2>μshare</h2>

<audio id="audioPlayer" preload="auto"></audio>

Expand Down