Skip to content
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Download and tag SoundCloud tracks unlocked via Hypeddit, Droploud, GateRush, Do

- [**Bun**](https://bun.sh) - JavaScript runtime and package manager
- [**ffmpeg**](https://ffmpeg.org) - Must be installed and available in your `PATH`
- [**yt-dlp**](https://github.com/yt-dlp/yt-dlp) - Required for Bandcamp purchase/download links and for downloading a SoundCloud track directly when no gate is found
- [**yt-dlp**](https://github.com/yt-dlp/yt-dlp) - Required for Bandcamp purchase/download links and for downloading a SoundCloud track directly when no gate is found. Bandcamp support requires the optional `curl_cffi` backend (`python-curl-cffi` on Arch Linux or `yt-dlp[default,curl-cffi]` with pip) for Chrome impersonation.
- **SoundCloud account** - It is recommended to create a throwaway account for this. Even though there were no reports of accounts getting banned I can't guarantee it. Also most gate downloads require reposts/likes/follows which you might not want to do with your main account
- **Spotify account** (optional) - Required when a Hypeddit post has an unskippable Spotify gate. I also recommend creating a throwaway account as most Hypeddit downloads require saving playlists/songs to your library or following artists which you might not want on your main account.

Expand Down
13 changes: 12 additions & 1 deletion src/ytdlp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { lookpath } from 'find-bin';
import type { BandcampAlbumTrackChoice, JobProgress } from './types';
import {
isBandcampAlbumUrl,
isBandcampUrl,
isSoundcloudUrl,
writeSoundcloudNetscapeCookies,
} from './utils';
Expand All @@ -30,6 +31,8 @@ const YTDLP_DOWNLOAD_TIMEOUT_MS = 10 * 60_000;
const YTDLP_METADATA_TIMEOUT_MS = 60_000;
const ALBUM_MATCH_THRESHOLD = 0.5;
const PROGRESS_PREFIX = 'SC_GATE_DL_PROGRESS:';
// Work around Bandcamp's client challenge: https://github.com/yt-dlp/yt-dlp/issues/17356
const BANDCAMP_IMPERSONATION_ARGS = ['--impersonate', 'chrome'];
Comment thread
D3SOX marked this conversation as resolved.

type FlatEntry = {
id?: string;
Expand Down Expand Up @@ -284,11 +287,13 @@ export class YtDlpDownloader {
await mkdir(DOWNLOADS_DIR, { recursive: true });

const outputTemplate = join(DOWNLOADS_DIR, '%(title)s [%(id)s].%(ext)s');
const bandcamp = isBandcampUrl(downloadUrl);
const soundcloud = isSoundcloudUrl(downloadUrl);
// Prefer SoundCloud's original upload (`download`) when the track allows it.
// That format is only listed for registered users — pass cookies when available.
const format = soundcloud ? 'download/bestaudio/best' : 'bestaudio/best';
const args = [
...(bandcamp ? BANDCAMP_IMPERSONATION_ARGS : []),
'--no-mtime',
'--no-playlist',
'--newline',
Expand Down Expand Up @@ -415,7 +420,13 @@ export class YtDlpDownloader {

const stdout = await this.runYtDlp(
ytDlpBin,
['--flat-playlist', '-J', '--no-warnings', albumUrl],
[
...BANDCAMP_IMPERSONATION_ARGS,
'--flat-playlist',
'-J',
'--no-warnings',
albumUrl,
],
YTDLP_METADATA_TIMEOUT_MS,
);

Expand Down