No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
egoreast afeb645ea1 Add youtube-playlist-to-peertube.sh and 2FA support for token auth
Wraps youtube-list-to-peertube.sh: given a YouTube playlist URL, looks up
its title and video list via yt-dlp and forwards them, naming the PeerTube
playlist after the YouTube one unless PT_PLAYLIST is set explicitly (a
stale .env value should not override the derived title).

Also adds PT_OTP support to youtube-list-to-peertube.sh's token request,
matching move-to-watch-later.sh, and surfaces the actual error body on
auth failure instead of a generic message.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P4bKubsWmVho2TsjBHkcQ7
2026-09-14 23:19:54 +03:00
.env.example Add .env support for persistent configuration 2026-09-03 15:05:57 +03:00
.gitignore Add youtube-playlist-to-peertube.sh and 2FA support for token auth 2026-09-14 23:19:54 +03:00
add-unlisted-videos-to-playlist.sh Add .env support for persistent configuration 2026-09-03 15:05:57 +03:00
dedupe-across-playlists.sh Add .env support for persistent configuration 2026-09-03 15:05:57 +03:00
dedupe-channel-videos.sh Add .env support for persistent configuration 2026-09-03 15:05:57 +03:00
dedupe-playlist.sh Add .env support for persistent configuration 2026-09-03 15:05:57 +03:00
freetube-backfill-descriptions.sh Add .env support for persistent configuration 2026-09-03 15:05:57 +03:00
freetube-playlist-to-peertube.sh Add move-to-watch-later.sh and @watch-later target for uploads 2026-09-14 16:52:34 +03:00
load-env.sh Add .env support for persistent configuration 2026-09-03 15:05:57 +03:00
move-to-watch-later.sh Add move-to-watch-later.sh and @watch-later target for uploads 2026-09-14 16:52:34 +03:00
peertube-hide-all-videos.sh Add .env support for persistent configuration 2026-09-03 15:05:57 +03:00
README.md Add youtube-playlist-to-peertube.sh and 2FA support for token auth 2026-09-14 23:19:54 +03:00
youtube-list-to-peertube.sh Add youtube-playlist-to-peertube.sh and 2FA support for token auth 2026-09-14 23:19:54 +03:00
youtube-playlist-to-peertube.sh Add youtube-playlist-to-peertube.sh and 2FA support for token auth 2026-09-14 23:19:54 +03:00

Утилиты миграции YouTube → PeerTube

Набор bash-скриптов для переноса видео и плейлистов с YouTube (в том числе из бэкапов FreeTube) на собственный инстанс PeerTube, а также для наведения порядка на канале PeerTube: удаление дублей, чистка плейлистов, массовое скрытие видео.

Все скрипты работают через официальный REST API PeerTube и yt-dlp для скачивания с YouTube. Конфигурация передаётся через переменные окружения.

Зависимости

Утилита Нужна для
curl всех скриптов
jq всех скриптов
yt-dlp скриптов, которые скачивают видео с YouTube
# Debian/Ubuntu
sudo apt install curl jq
python3 -m pip install -U yt-dlp

Файл .env

Постоянные настройки (адрес инстанса, логин, handle канала, путь к кукам) удобно один раз положить в файл .env рядом со скриптами — он подхватывается всеми скриптами автоматически.

cp .env.example .env
$EDITOR .env

Формат — KEY=value, по одной паре на строку; пустые строки и #-комментарии игнорируются. Значения, переданные при запуске (PT_DRY_RUN=0 ./dedupe-channel-videos.sh) или уже заданные в окружении, имеют приоритет над .env — так разовые параметры не приходится держать в файле.

.env в репозиторий не коммитится (см. .gitignore); пример — в .env.example.

Общие переменные окружения

Почти все скрипты понимают один и тот же набор переменных для доступа к PeerTube:

Переменная Обязательна Описание
PT_HOST да адрес инстанса, например https://tube.example.com
PT_USERNAME да логин PeerTube
PT_PASSWORD нет пароль; если не задан — скрипт спросит интерактивно
PT_CHANNEL зависит handle канала, например my_channel
PT_DRY_RUN нет 1 — только показать, что будет сделано, без изменений

У разрушительных операций (dedupe-channel-videos.sh, peertube-hide-all-videos.sh) PT_DRY_RUN=1 включён по умолчанию — чтобы реально применить изменения, нужно явно указать PT_DRY_RUN=0.

Куки YouTube

Скриптам с yt-dlp для многих видео нужны куки авторизованного аккаунта YouTube:

  • YTDLP_COOKIES_FILE=~/youtube-cookies.txt — файл в формате Netscape, экспортированный расширением браузера (надёжнее всего);
  • YTDLP_COOKIES_BROWSER=chromium — брать куки напрямую из браузера, если файл не задан (закройте браузер перед запуском).

Файлы куки и бэкапы в репозиторий не коммитятся (см. .gitignore).


Скрипты

Перенос с YouTube на PeerTube

youtube-list-to-peertube.sh

Скачивает видео по списку ссылок YouTube (txt-файл, по одной ссылке на строку; пустые строки и строки с # игнорируются), проверяет по названию (и опционально длительности), нет ли уже такого видео на канале PeerTube, загружает новые через API и добавляет каждое в указанный плейлист.

PT_HOST="https://tube.example.com" PT_USERNAME="me" \
PT_CHANNEL="my_channel" PT_PLAYLIST="Мой плейлист" \
  ./youtube-list-to-peertube.sh links.txt

Ключевые опции: PT_OTP (код 2FA, если включена), PT_PLAYLIST, PT_PLAYLIST_CREATE=1, PT_PRIVACY (1=Public, 2=Unlisted, 3=Private — по умолчанию, 4=Internal), PT_MATCH_DURATION=1, PT_DURATION_TOLERANCE, YTDLP_SLEEP, YTDLP_PLAYER_CLIENT. Прогресс пишется в <список>.done, ошибки yt-dlp — в <список>.errors.log.

youtube-playlist-to-peertube.sh

Принимает ссылку на плейлист YouTube целиком (например https://youtube.com/playlist?list=PL9DC9A8822E21DD87), сам узнаёт у YouTube через yt-dlp его название и список видео, формирует txt-список ссылок и передаёт его в youtube-list-to-peertube.sh — в плейлист PeerTube с тем же названием, что и у плейлиста YouTube (создаётся автоматически, если его ещё нет).

PT_HOST="https://tube.example.com" PT_USERNAME="me" PT_CHANNEL="my_channel" \
  ./youtube-playlist-to-peertube.sh "https://youtube.com/playlist?list=PL9DC9A8822E21DD87"

Список ссылок сохраняется в youtube-playlist-<ID>.txt рядом со скриптами — через него же youtube-list-to-peertube.sh ведёт файлы .done/.errors.log, поэтому повторный запуск на том же плейлисте продолжит закачку и подхватит новые видео, добавленные в плейлист с прошлого раза. Своё название плейлиста на PeerTube можно задать через PT_PLAYLIST; остальные опции — те же, что у youtube-list-to-peertube.sh.

freetube-playlist-to-peertube.sh

То же самое, но источник — бэкап плейлиста FreeTube (.db, один JSON-объект с полем videos[]). В бэкапе уже есть title и author, поэтому проверка дублей на PeerTube идёт без единого запроса к YouTube — yt-dlp вызывается только для тех видео, которых на канале ещё нет.

PT_HOST="https://tube.example.com" PT_USERNAME="me" PT_CHANNEL="my_channel" \
PT_PLAYLIST="Мой плейлист" \
  ./freetube-playlist-to-peertube.sh freetube-playlist.db

Опции те же, что у youtube-list-to-peertube.sh (PT_PRIVACY по умолчанию 3). Чтобы грузить сразу в системный плейлист «Watch later» аккаунта, не гадая, как он называется на вашем языке интерфейса, укажите PT_PLAYLIST="@watch-later" — плейлист найдётся по типу, а не по имени.

freetube-backfill-descriptions.sh

Дозаполняет описания у уже загруженных видео. Читает бэкап плейлиста FreeTube, сопоставляет каждое видео с каналом PeerTube по названию. Если у видео на PeerTube описание уже есть — пропускает; если нет — только тогда идёт к YouTube через yt-dlp за описанием и обновляет на PeerTube только поле description (название не трогается).

PT_HOST="https://tube.example.com" PT_USERNAME="me" PT_CHANNEL="my_channel" \
  ./freetube-backfill-descriptions.sh freetube-playlist.db

Опции: PT_FORCE_UPDATE=1 (обновлять даже при наличии описания), YTDLP_*.

Наведение порядка на канале PeerTube

dedupe-playlist.sh

Удаляет повторные элементы одного плейлиста: если одно и то же видео добавлено в плейлист несколько раз, оставляет один элемент.

PT_HOST="https://tube.example.com" PT_USERNAME="me" \
PT_PLAYLIST="Смотреть позже" PT_DRY_RUN=1 \
  ./dedupe-playlist.sh

dedupe-across-playlists.sh

Если видео состоит сразу в нескольких плейлистах из списка PT_PLAYLISTS (разделитель — |, потому что в названиях бывают запятые), оставляет его только в первом по приоритету, из остальных перечисленных — убирает. Плейлисты не из списка не затрагиваются.

PT_HOST="https://tube.example.com" PT_USERNAME="me" \
PT_PLAYLISTS="Посмотреть в первую очередь|Смотреть позже" PT_DRY_RUN=1 \
  ./dedupe-across-playlists.sh

dedupe-channel-videos.sh ⚠️ разрушительный

Находит на канале видео-дубли (по нормализованному названию и, по умолчанию, по длительности) и удаляет все, кроме самого раннего по дате загрузки. DELETE /api/v1/videos/{id} удаляет видео безвозвратно вместе с комментариями, статистикой и членством во всех плейлистах.

PT_DRY_RUN=1 по умолчанию — сначала посмотрите список.

PT_HOST="https://tube.example.com" PT_USERNAME="me" PT_CHANNEL="my_channel" \
  ./dedupe-channel-videos.sh                 # пробный прогон
PT_DRY_RUN=0 ... ./dedupe-channel-videos.sh  # реально удалить

Опции: PT_MATCH_DURATION (по умолчанию 1), PT_DURATION_TOLERANCE (2 сек). После удаления с PT_DRY_RUN=0 рекомендуется прогнать add-unlisted-videos-to-playlist.sh, чтобы восстановить членство оставшихся экземпляров в плейлистах.

add-unlisted-videos-to-playlist.sh

Находит все видео канала, которые не состоят ни в одном плейлисте аккаунта, и добавляет их в указанный плейлист (например «Смотреть позже»).

PT_HOST="https://tube.example.com" PT_USERNAME="me" PT_CHANNEL="my_channel" \
PT_PLAYLIST="Смотреть позже" PT_PLAYLIST_CREATE=1 \
  ./add-unlisted-videos-to-playlist.sh

Опции: PT_PLAYLIST_CREATE=1, PT_DRY_RUN=1.

move-to-watch-later.sh

Переносит все видео из указанного плейлиста в системный плейлист «Watch later» аккаунта. Системный плейлист ищется не по имени (его отображаемое имя локализовано и зависит от языка интерфейса аккаунта — «Watch later» / «Смотреть позже» / «Посмотреть позже» и т.п.), а по типу (type.id == 2), поэтому угадывать нужное название не нужно.

PT_HOST="https://tube.example.com" PT_USERNAME="me" \
PT_SOURCE_PLAYLIST="Смотреть позже" PT_DRY_RUN=1 \
  ./move-to-watch-later.sh

Опции: PT_OTP (код 2FA), PT_KEEP_SOURCE=1 (копировать, не удаляя из источника), PT_DRY_RUN=1.

peertube-hide-all-videos.sh

Переводит все видео канала в «скрытый» режим (по умолчанию PT_PRIVACY=2, Unlisted — видно только по прямой ссылке). Операция обратима: вернуть в Public можно тем же скриптом с PT_PRIVACY=1.

PT_DRY_RUN=1 по умолчанию.

PT_HOST="https://tube.example.com" PT_USERNAME="me" PT_CHANNEL="my_channel" \
  ./peertube-hide-all-videos.sh                 # пробный прогон
PT_DRY_RUN=0 ... ./peertube-hide-all-videos.sh  # реально скрыть

Опции: PT_PRIVACY, PT_OTP (код 2FA), PT_SLEEP (пауза между запросами).


Типовой сценарий миграции

  1. freetube-playlist-to-peertube.sh (или youtube-list-to-peertube.sh) — залить видео на PeerTube.
  2. freetube-backfill-descriptions.sh — дозаполнить описания.
  3. dedupe-channel-videos.sh — убрать дубли (сначала dry-run).
  4. add-unlisted-videos-to-playlist.sh — вернуть бесхозные видео в плейлист.
  5. dedupe-playlist.sh / dedupe-across-playlists.sh — почистить плейлисты.

Каждый скрипт подробно документирован в комментарии-шапке — смотрите его перед запуском.