---
title: audio-downloader
desc: Одна функція в шелі, яка тягне аудіо з SoundCloud, YouTube і ще тисячі сайтів у ~/Music/unsorted_downloads. Встановлення під Windows/macOS/Linux, вибір формату, cookies і чому Spotify тут не буде.
locked: false
order: 1
section: music
featured: false
---

# Завантажувач музики на yt-dlp

Окремий «SoundCloud downloader» шукати не треба: [yt-dlp](https://github.com/yt-dlp/yt-dlp) вміє і SoundCloud, і YouTube, і ще близько тисячі сайтів. Нижче — обгортка на одну команду, яка складає все в `~/Music/unsorted_downloads`, і чесна межа: де воно працює, а де DRM.

---

## Рамка рішення

| Що на вході | Дія |
|---|---|
| Лінк на трек, сет, плейлист, профіль | `gt <url>` — обгортка сама розгортає список |
| Потрібен оригінальний файл із SoundCloud | `-Original` / `-o` — бере формат `download`, якщо аплоадер його відкрив |
| Стрім із платного тарифу, приватний або віковий лінк | `-Cookies` / `-c` — сесія береться з браузера |
| Архів, а не плеєр у машині | `-Format best` / `-f best` — без перекодування |
| Spotify, Apple Music, Tidal, Deezer | ніяк — DRM; лишається експорт списку і пошук треків деінде |
| Сумнів | `gt <url>` без прапорців: mp3 320, теги й обкладинка на місці |

---

## Встановлення і функція

Потрібні два бінарники: **yt-dlp** і **ffmpeg**. ffmpeg тут не опційний — через нього йде і витяг аудіо, і теги, і вшивання обкладинки. Повний перелік способів — у [офіційному гайді зі встановлення](https://github.com/yt-dlp/yt-dlp/wiki/Installation).

<div class="tabs" markdown="1">
<input type="radio" name="os" id="os-win" data-tab="1" checked>
<input type="radio" name="os" id="os-mac" data-tab="2">
<input type="radio" name="os" id="os-nix" data-tab="3">
<div class="tabbar" markdown="1">
<label for="os-win">Windows</label>
<label for="os-mac">macOS</label>
<label for="os-nix">Linux</label>
</div>

<div class="tab" data-label="Windows" markdown="1">

### 1. Бінарники

```powershell
winget install --id yt-dlp.yt-dlp
```

winget тягне `Gyan.FFmpeg` як залежність і сам прописує PATH — окремо ставити ffmpeg не треба. Термінал після цього перезапустити. Альтернатива, якщо в системі вже є [Scoop](https://scoop.sh/):

```powershell
scoop install yt-dlp ffmpeg
```

Перевірка: `yt-dlp --version` і `ffmpeg -version`.

### 2. Функція

```powershell
function Get-Track {
    [CmdletBinding()]
    [Alias('gt')]
    param(
        [Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromRemainingArguments)]
        [string[]]$Url,

        [string]$Dest = (Join-Path $HOME 'Music\unsorted_downloads'),

        [ValidateSet('mp3', 'opus', 'flac', 'best')]
        [string]$Format = 'mp3',

        [switch]$Original,
        [switch]$Cookies
    )

    begin {
        foreach ($bin in 'yt-dlp', 'ffmpeg') {
            if (-not (Get-Command $bin -ErrorAction SilentlyContinue)) {
                throw "$bin not found in PATH"
            }
        }
        if (-not (Test-Path -LiteralPath $Dest)) {
            New-Item -ItemType Directory -Path $Dest -Force | Out-Null
        }

        $ytArgs = @(
            '-f', $(if ($Original) { 'download/bestaudio/best' } else { 'bestaudio/best' })
            '--extract-audio'
            '--audio-quality', '0'
            '--embed-thumbnail'
            '--embed-metadata'
            '--no-overwrites'
            '--ignore-errors'
            '--download-archive', (Join-Path $Dest '.archive.txt')
            '-P', $Dest
            '-o', '%(uploader)s - %(title)s.%(ext)s'
        )
        if ($Format -ne 'best') { $ytArgs += @('--audio-format', $Format) }
        if ($Cookies)           { $ytArgs += @('--cookies-from-browser', 'edge') }

        $before = @(Get-ChildItem -LiteralPath $Dest -File -ErrorAction SilentlyContinue).Name
    }

    process {
        foreach ($u in $Url) {
            Write-Host "-> $u" -ForegroundColor Cyan
            & yt-dlp @ytArgs -- $u
        }
    }

    end {
        Get-ChildItem -LiteralPath $Dest -File |
            Where-Object { $_.Name -notin $before -and $_.Extension -ne '.txt' } |
            Select-Object Name, @{n = 'MB'; e = { [math]::Round($_.Length / 1MB, 1) } }
    }
}
```

### 3. Прописати в профіль

```powershell
if (-not (Test-Path $PROFILE)) { New-Item -ItemType File -Path $PROFILE -Force }
notepad $PROFILE     # вставити функцію, зберегти
. $PROFILE           # перечитати без перезапуску
```

### 4. Виклик

```powershell
gt https://soundcloud.com/artist/track      # один трек
gt https://soundcloud.com/artist/likes      # цілий розділ або плейлист
gt url1, url2, url3                         # пачкою
gt url -Original                            # оригінал, якщо аплоадер дозволив
gt url -Format best                         # без перекодування
gt url -Cookies                             # платні стріми, приватні лінки
gt url -Dest 'D:\library\Music\inbox'       # інша тека разово
Get-Content urls.txt | gt                   # зі списку у файлі
```

</div>

<div class="tab" data-label="macOS" markdown="1">

### 1. Бінарники

Через [Homebrew](https://brew.sh/):

```bash
brew install yt-dlp ffmpeg
```

Перевірка: `yt-dlp --version` і `ffmpeg -version`.

### 2. Функція

```bash
gt() {
  local dest="${MUSIC_DEST:-$HOME/Music/unsorted_downloads}"
  local format="mp3" fmt_sel="bestaudio/best"
  local urls=() cookies=()

  for bin in yt-dlp ffmpeg; do
    command -v "$bin" >/dev/null 2>&1 || { echo "$bin not found in PATH" >&2; return 1; }
  done

  while (( $# )); do
    case "$1" in
      -f|--format)   format="$2"; shift 2 ;;
      -o|--original) fmt_sel="download/bestaudio/best"; shift ;;
      -c|--cookies)  cookies=(--cookies-from-browser safari); shift ;;
      -d|--dest)     dest="$2"; shift 2 ;;
      -h|--help)     echo "gt [-f mp3|opus|flac|best] [-o] [-c] [-d DIR] URL..."; return 0 ;;
      -*)            echo "unknown flag: $1" >&2; return 1 ;;
      *)             urls+=("$1"); shift ;;
    esac
  done

  (( ${#urls[@]} )) || { echo "no URLs given" >&2; return 1; }
  mkdir -p "$dest"

  local args=(
    -f "$fmt_sel"
    --extract-audio
    --audio-quality 0
    --embed-thumbnail
    --embed-metadata
    --no-overwrites
    --ignore-errors
    --download-archive "$dest/.archive.txt"
    -P "$dest"
    -o "%(uploader)s - %(title)s.%(ext)s"
  )
  [[ "$format" != "best" ]] && args+=(--audio-format "$format")

  local u
  for u in "${urls[@]}"; do
    printf '\033[36m-> %s\033[0m\n' "$u"
    yt-dlp "${args[@]}" "${cookies[@]}" -- "$u"
  done
}
```

### 3. Прописати в профіль

Функція кладеться в окремий файл, профіль його підтягує:

```bash
echo 'source ~/.gt.sh' >> ~/.zshrc   # zsh — дефолт у macOS
source ~/.zshrc
```

### 4. Виклик

```bash
gt https://soundcloud.com/artist/track      # один трек
gt https://soundcloud.com/artist/likes      # цілий розділ або плейлист
gt url1 url2 url3                           # пачкою
gt -o url                                   # оригінал, якщо аплоадер дозволив
gt -f best url                              # без перекодування
gt -c url                                   # платні стріми, приватні лінки
gt -d ~/Desktop/inbox url                   # інша тека разово
xargs gt < urls.txt                         # зі списку у файлі
```

</div>

<div class="tab" data-label="Linux" markdown="1">

### 1. Бінарники

Пакет із репозиторію дистрибутива зазвичай відстає на кілька версій, а yt-dlp ламається щоразу, коли сайти міняють віддачу. Тому pipx:

```bash
sudo apt install pipx ffmpeg      # або dnf / pacman
pipx install yt-dlp
```

Оновлення — `pipx upgrade yt-dlp`. Альтернативи: `python3 -m pip install -U yt-dlp` або окремий бінарник зі [сторінки релізів](https://github.com/yt-dlp/yt-dlp/releases).

### 2. Функція

Та сама, що в macOS-вкладці, з однією заміною — браузер для cookies:

```bash
      -c|--cookies)  cookies=(--cookies-from-browser firefox); shift ;;
```

`--cookies-from-browser` приймає: `brave`, `chrome`, `chromium`, `edge`, `firefox`, `opera`, `safari`, `vivaldi`, `whale`. Chromium-браузери поза списком (Arc, Floorp) підключаються через шлях до профілю: `--cookies-from-browser "chromium:/шлях/до/профілю"`.

### 3. Прописати в профіль

```bash
echo 'source ~/.gt.sh' >> ~/.bashrc
source ~/.bashrc
```

### 4. Виклик

Ідентичний macOS-варіанту.

</div>
</div>

---

## Що реально віддає джерело

| Джерело | Що приходить | Що ставити |
|---|---|---|
| SoundCloud, аплоадер увімкнув download | оригінал (wav / flac / mp3 320) | `-Original` |
| SoundCloud звичайний | транскод mp3 128 або opus, HLS | `-Format best` |
| SoundCloud із сесією Go+ | AAC-пресет 256 kbps | `-Cookies` |
| YouTube / YouTube Music | opus ~160 kbps або m4a 128 | `-Format best` |

`-Format mp3` на будь-якому з транскодів — це перекодування вже стисненого в ще раз стиснене. Виправдано, коли файл поїде в машину, на флешку чи в старий плеєр; для архіву — `best`.

**Дефолт при сумніві:** `best` для колекції, `mp3` для того, що має грати будь-де.

---

## YouTube: два прапорці зверху

Обгортка працює з YouTube безмін, але для музики варто дописати у власну копію:

```
--sponsorblock-remove music_offtopic
--parse-metadata "%(title)s:%(artist)s - %(title)s"
```

Перший зрізає нем'юзичні вступи й кінцівки за розміткою SponsorBlock. Другий розбирає звичне `Виконавець - Назва` із заголовка в окремі теги, замість того щоб лишати все одним рядком.

---

## Spotify і решта DRM

Spotify не завантажується — і це не пробіл у yt-dlp. Потік зашифрований Widevine, тобто файлу, який можна витягти, там просто нема, а обхід DRM проєкт не реалізує принципово. Apple Music, Tidal і Deezer — та сама історія.

Робочий обхідний шлях полягає не в тому, щоб «зламати» Spotify, а в тому, щоб використати його як каталог: вивантажити список треків плейлиста (Web API або сторонній експортер дає виконавця, назву й альбом у CSV), а далі шукати ті самі треки там, де файл віддають — Bandcamp, Qobuz, офіційні завантаження артиста, YouTube-канал лейбла. Результат той самий, файли кращі, DRM ніде не заважає.

---

## Антипатерни

- Ставити `--audio-format mp3` для архіву — подвійна втрата якості замість збереження джерела.
- Забути `.archive.txt` і дивуватись, чому повторний прогін по профілю нічого не тягне: він тягне тільки нове, це і є задум.
- Качати профіль на 500 треків без `--ignore-errors` — один приватний трек валить увесь прогін.
- Тримати cookies-файл під git — це діючий доступ до акаунта, не конфіг.
- Забирати `--embed-metadata`, а потім розгрібати теку з файлами без тегів.
- Ставити yt-dlp з репозиторію дистрибутива і місяцями не оновлювати: половина помилок «сайт не працює» лікується `pipx upgrade`.

---

## Чекліст

- [ ] `yt-dlp --version` і `ffmpeg -version` віддають версії
- [ ] Функція в профілі шела, `gt` доступний у новій сесії
- [ ] `~/Music/unsorted_downloads` створюється сам, тека не захардкоджена під один диск
- [ ] Обрано формат під ціль: `best` для архіву, `mp3` для плеєрів
- [ ] Для приватних чи платних лінків браузер закритий перед `-Cookies`
- [ ] Перед повторним прогоном по профілю перевірено `.archive.txt`

<div class="ps">
<div class="ps-label">P.S. — про папку unsorted</div>

Тека називається `unsorted_downloads` із наміром колись розсортувати. Статистика по всіх подібних теках на планеті свідчить, що момент сортування настає рівно тоді, коли закінчується місце на диску.

Сортування, до речі, теж можна віддати yt-dlp: шаблон `-o` приймає `%(uploader)s/%(title)s.%(ext)s` і розкладе по теках виконавців одразу. Це переносить проблему на рівень вище, де вона зветься «сорок тек по одному треку».

</div>
