본문으로 건너뛰기
50% 할인 모든 플랜, 기간 한정. 시작 가격 $2.48/mo
11 min left
게이밍 및 미디어

개인 아카이빙을 위해 VPS에서 yt-dlp를 헤드리스로 실행하기

S 작성자 Sajjad 11 분 분량
yt-dlp running headless on a VPS, feeding scheduled downloads into an organized video library that a media server can scan

VPS에서 yt-dlp를 돌리면, 노트북을 닫은 뒤에도 계속 온라인에 남아 긴 다운로드를 이어 갈 머신이 생깁니다. 예약된 채널 수집에서 Jellyfin이 스캔할 수 있는 미디어 라이브러리까지 깔끔한 경로도 만들어집니다.

서버는 워크플로의 세 부분을 바꿉니다. 설치에는 최신 YouTube 의존성이, 계정이 필요한 영상에는 안전한 쿠키 전달이, 자동화에는 의도적인 요청 속도 조절이 필요합니다. 아래 설정은 모든 다운로드에 쿠키나 웹 인터페이스, PO Token 공급자가 필요하다고 전제하지 않으면서 이 세 가지를 모두 처리합니다.

요약

  • Python 가상 환경에 yt-dlp를 ffmpeg, ffprobe, yt-dlp-ejs 및 지원되는 JavaScript 런타임과 함께 설치하세요. 현재 프로젝트가 권장하는 런타임은 Deno입니다.
  • 계정 쿠키 없이 시작하세요. 비공개 재생목록, 연령 제한 영상, 멤버 전용 콘텐츠처럼 계정이 필요한 경우에만 추가합니다.
  • 측정에 근거한 이유가 생기기 전까지는 yt-dlp의 기본 단일 프래그먼트 동작을 유지하세요. 요청 부담을 줄이려면 sleep 옵션과 시간을 어긋나게 잡은 일정을 사용합니다.
  • 순수 CLI에 systemd를 더한 조합이 가장 단순하면서 믿을 만한 구성입니다. 손대지 않고 굴러가는 채널 규칙에는 Pinchflat, 브라우저 기반 대기열에는 MeTube, 검색 가능한 시청 인터페이스에는 Tube Archivist를 고르세요.
  • 저장 공간을 사이징의 핵심 변수로 다루세요. 전체 아카이브용 디스크 용량을 구매하기 전에 대표 표본으로 먼저 시험해 보세요.

yt-dlp를 책임감 있게 사용하세요

권한이 있고, 사용 방식이 플랫폼 약관과 관련 법률을 지키는 경우에만 미디어를 보관하세요.

  • 좋은 대상으로는 본인이 올린 영상, 퍼블릭 도메인 자료, 그리고 권리자가 다운로드를 허용한 자료가 있습니다.
  • YouTube Premium 구독만으로 YouTube가 제공하는 기능 밖에서 영상을 복제할 권한이 생기지는 않습니다.
  • YouTube의 이용 권한과 제한 사항 은 서비스나 해당 권리자가 허용하지 않는 한 다운로드와 자동화된 접근을 제한합니다.
  • 이 튜토리얼은 DRM 우회, 상업적 재배포, 플랫폼 제재를 회피하는 방법을 다루지 않습니다.

시작하기 전에 필요한 것

기본 설치는 가볍지만 미디어 파일은 그렇지 않습니다. 채널 전체를 내려받기 전에 서버와 저장 경로를 준비하세요.

  • SSH로 접속할 수 있는 Ubuntu 22.04 이상 또는 최신 Debian 릴리스의 VPS
  • Python 3.10 이상
  • 대표 표본을 담을 만한 저장 공간에, 부분 파일과 후처리를 위한 여유까지
  • 계정 쿠키가 필요할 때만 쓰는 별도의 로컬 브라우저
  • 선택 사항: 아카이브 디렉터리를 읽을 수 있는 Jellyfin, Emby 또는 다른 미디어 서버

왜 yt-dlp를 VPS에 두는가?

작업이 평소 쓰는 컴퓨터와 무관하게 계속 돌아가야 할 때 VPS가 쓸모 있습니다. 다운로더에 지속적인 프로세스와 예측 가능한 파일 시스템, 그리고 노트북이 절전에 들어가거나 네트워크를 바꿔도 멈추지 않는 스케줄러를 제공합니다.

트레이드오프가 중요합니다. 아카이브를 다시 스트리밍해 내보낼 때는 서버의 월간 전송량이 제약이 될 수 있고, VPS의 IP는 집 회선보다 요청 제한에 먼저 걸릴 수 있습니다. 업데이트, 자격 증명 관리, 백업, 저장 공간 정리, 미디어 서버 보안도 모두 사용자의 몫입니다. 한 번뿐인 다운로드라면 노트북이 더 간단합니다. 반복적인 수집이나 공유 미디어 라이브러리라면 VPS가 운영하기 더 쉽습니다.

저장 공간과 재생을 기준으로 VPS 크기를 정하세요

yt-dlp VPS sizing guide: starting allocations of 2 vCPU and 2 GB RAM for raw yt-dlp with systemd, 2 vCPU and 4 GB RAM for MeTube or Pinchflat, and 4 vCPU and 8 GB RAM for Tube Archivist, beside a method for projecting storage from a sample download

yt-dlp는 미디어를 내려받고 리먹싱합니다. 보통 모든 파일을 트랜스코딩하지는 않습니다. 그래서 다운로더의 상시 CPU와 메모리 요구는 크지 않은 반면, 디스크 사용량은 영상 길이와 해상도, 코덱, 선택한 포맷에 따라 달라집니다.

아래 수치는 공식 최소 사양이 아니라 보수적인 출발점으로 삼으세요:

설치시작 사양저장 공간 접근법최적 맞춤
순수 yt-dlp + systemd2 vCPU, 2 GB RAM표본으로 용량 산정UI 없는 예약 다운로드
MeTube 또는 Pinchflat2 vCPU, 4 GB RAM표본으로 용량 산정브라우저 대기열 또는 채널 구독
Tube Archivist4 vCPU, 8 GB RAM증가 여유를 둔 로컬 디스크검색 가능한 아카이브와 내장 재생

소규모 테스트에는 약 2 GB, 중대형 설치에는 약 4 GB의 가용 메모리가 필요합니다. 출처는 Tube Archivist 배포 가이드. 이 하한선보다 여유 있게 시작하면 운영체제와 Docker, Elasticsearch의 활동, 그리고 Jellyfin 같은 다른 서비스가 쓸 공간이 남습니다.

전체 아카이브 용량을 잡기 전에, 원하는 해상도로 대표 그룹을 시뮬레이션하거나 내려받아 보세요. 결과 디렉터리를 du로 확인하고, 완료된 영상 수로 나눈 뒤, 유난히 긴 영상까지 감안하세요.

du -sh ~/archive
find ~/archive -type f \( -name '*.mp4' -o -name '*.mkv' \) | wc -l
df -h ~/archive

표본은 영상당 기가바이트라는 일반적인 추정치보다 유용합니다. 해당 채널의 실제 길이와 포맷 구성이 반영되기 때문입니다.

yt-dlp와 최신 의존성 설치하기

yt-dlp 프로젝트는 Python 3.10 이상을 지원합니다. yt-dlp 의존성 목록 은 완전한 YouTube 지원을 위해 ffmpeg, ffprobe, yt-dlp-ejs와 지원되는 JavaScript 런타임을 강력히 권장합니다.

시스템 패키지와 격리된 Python 환경부터 시작하세요:

sudo apt update
sudo apt install -y python3 python3-venv ffmpeg curl nano
python3 -m venv ~/yt-dlp-venv
source ~/yt-dlp-venv/bin/activate
python -m pip install -U --pre "yt-dlp[default]"

Deno는 yt-dlp에서 기본으로 활성화되어 있으며, 프로젝트의 EJS 가이드 EJS 가이드가 현재 권장하는 런타임입니다. 설치한 뒤 셸 PATH에 추가하고, 각 구성 요소를 확인하세요:

curl -fsSL https://deno.land/install.sh | sh
export PATH="$HOME/.deno/bin:$PATH"
echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.profile
yt-dlp --version
ffmpeg -version | head -1
deno --version
yt-dlp --simulate --verbose "https://www.youtube.com/watch?v=VIDEO_ID"

verbose 출력은 yt-dlp가 인식하는 의존성을 나열합니다. ffmpeg가 없으면 yt-dlp가 경고를 내고, 최고 화질의 분리된 비디오와 오디오 스트림을 합치거나 여러 후처리 단계를 수행할 수 없습니다.

pip으로 설치했다면 가상 환경 안에서 pip을 다시 실행해 업데이트하세요. 내장된 yt-dlp -U 명령은 릴리스 바이너리용이지 pip 패키지용이 아닙니다.

source ~/yt-dlp-venv/bin/activate
python -m pip install -U --pre "yt-dlp[default]"

업데이트 채널은 다음 문서에서 다룹니다: yt-dlp 업데이트 노트. stable, nightly, master 채널을 모두 쓸 수 있으며, 일반 사용자에게 프로젝트가 권하는 것은 nightly입니다. 추출기 수정 사항이 다음 안정 릴리스보다 먼저 그쪽에 도착하기 때문입니다.

계정이 필요한 콘텐츠에만 쿠키를 추가하세요

대상 URL을 먼저 쿠키 없이 시도해 보세요. yt-dlp의 YouTube 가이드는 쿠키가 계정을 요구하는 콘텐츠, 즉 비공개 재생목록과 연령 제한 영상, 멤버 전용 콘텐츠에만 필요하다고 설명합니다. OAuth 로그인은 이제 yt-dlp에서 동작하지 않습니다.

쿠키가 정말 필요하다면, 로컬 컴퓨터에서 전용 YouTube 세션을 내보내세요. 프로젝트의 쿠키 내보내기 절차는 시크릿 창을 사용합니다. 그래야 열려 있는 일반 탭에서 YouTube가 내보낸 세션을 교체하지 않습니다:

  1. 시크릿 창 또는 개인정보 보호 창을 하나만 열고 YouTube에 로그인합니다.
  2. 같은 탭에서 YouTube의 robots.txt 파일을 엽니다.
  3. yt-dlp FAQ에 나열된 확장 프로그램 중 하나로, youtube.com 쿠키만 Netscape 형식으로 내보냅니다.
  4. 시크릿 창을 닫고, 그 세션을 다시 열지 마세요.
  5. 파일을 VPS로 복사하고 권한을 제한하세요.
scp cookies.txt your-user@your-vps-ip:~/cookies.txt
ssh your-user@your-vps-ip 'chmod 600 ~/cookies.txt'

계정이 필요한 URL로 파일을 시험해 보세요:

~/yt-dlp-venv/bin/yt-dlp \
  --cookies ~/cookies.txt \
  --simulate \
  "https://www.youtube.com/watch?v=VIDEO_ID"

쿠키 파일은 세션 자격 증명이며 브라우저 확장 프로그램은 신중히 골라야 합니다. 근거는 yt-dlp 쿠키 FAQ입니다. YouTube 추출기 가이드는 yt-dlp에 계정을 사용하면 일시적 또는 영구적 정지로 이어질 수 있다고도 경고합니다. 대상이 요구할 때만 쿠키를 쓰고, 파일은 비공개로 유지하며, 주력 Google 계정 대신 별도의 계정을 사용하세요.

대상 대부분이 공개 콘텐츠라면 --cookies를 전역 설정에 넣지 마세요. 두 번째 설정 파일을 쓰거나, 필요한 작업에만 이 플래그를 붙이세요.

PO 토큰은 조건부 문제 해결 수단으로 다루세요

yt-dlp access troubleshooting flow: simulate the URL first, then branch to no cookies needed for a working public video, a cookie export for account-gated content, or a dependency update and PO Token check when failures continue

Proof of Origin Token은 설치 시 반드시 필요한 것이 아닙니다. YouTube는 현재 일부 클라이언트와 요청 조합에 대해서만 이 토큰을 요구하며, 정확한 조합표는 계속 바뀝니다.

기본 클라이언트가 실패할 때는 mweb 클라이언트용 공급자 플러그인이 권장됩니다. 근거는 yt-dlp PO 토큰 가이드입니다. 여기에는 bgutil-ytdlp-pot-provider가 대표적인 선택지로 소개되어 있지만, 이 플러그인은 토큰 공급자와 yt-dlp 플러그인이 둘 다 있어야 합니다. Python 패키지만 설치해서는 설정이 완성되지 않습니다.

YouTube 다운로드가 실패하면 다음 순서로 접근하세요:

  1. yt-dlp, yt-dlp-ejs, JavaScript 런타임을 업데이트합니다.
  2. --verbose를 붙이고 별도의 클라이언트 지정 없이 실패를 재현합니다.
  3. 영상이 계정을 요구할 때만 쿠키를 추가합니다.
  4. 오류가 PO 토큰 강제 적용을 가리키면, 공식 가이드에서 링크된 최신 공급자 지침을 따르세요.

이렇게 하면 변동이 잦은 임시방편이, 그 외에는 안정적인 기본 설치에 섞여 들어가지 않습니다.

워크플로에 맞춰 프런트엔드 고르기

핵심 결정은 어느 인터페이스의 기능 목록이 더 긴가가 아닙니다. 브라우저 대기열이 필요한지, 규칙 기반 구독이 필요한지, 아니면 YouTube 같은 완전한 로컬 라이브러리가 필요한지를 정하세요.

옵션배포강점주요 단점
순수 CLI프런트엔드 없음스크립트, 설정 파일, systemd, 옵션의 정밀한 제어브라우저 UI 없음
MeTubeDocker 컨테이너 하나브라우저 기반 다운로드에 채널 및 재생목록 구독까지다운로드 이후의 라이브러리 관리가 제한적
PinchflatDocker 컨테이너 하나채널과 재생목록 규칙, RSS, 보관 정책, 미디어 센터용 출력앱 안에서 시청하기보다 다운로드 관리를 위해 만들어짐
Tube Archivist앱, Redis, Elasticsearch 컨테이너검색, 메타데이터, 대기열, 채널 페이지, 재생메모리와 운영 부담이 가장 큼

가벼운 브라우저 워크플로라면, MeTube는 새 항목을 주기적으로 확인해 자동으로 대기열에 넣는 채널 및 재생목록 구독을 지원합니다. 웹 폼과 다운로드 대기열만 있으면 되는 경우에는 여전히 가장 단순한 선택입니다.

Pinchflat은 Jellyfin, Plex, Kodi, 또는 RSS 클라이언트로 볼 채널을 꾸준히 아카이빙하는 데 가장 잘 맞습니다. 자체 완결적이고, 소스를 주기적으로 확인하며, 보관 규칙을 지원하고, 재생은 의도적으로 다른 애플리케이션에 맡깁니다.

아카이브 자체가 검색 가능한 영상 사이트처럼 동작하길 원한다면, Tube Archivist는 추가로 띄우는 서비스만큼의 값어치를 합니다. 재생 인터페이스를 이미 Jellyfin이 담당하고 있다면 순수 CLI나 Pinchflat으로 시작하고, 그 검색·메타데이터 모델이 실제 문제를 해결해 줄 때만 Tube Archivist를 추가하세요.

반복 가능한 아카이브 설정 만들기

오래 유지할 옵션은 한 파일에 모아 두고, 채널 URL은 명령줄이나 스케줄러에서 넘기세요. 이 예시는 출력을 1080p로 제한하고, 완료된 영상 ID를 기록하고, 요청 간격을 살짝 두고, yt-dlp 밖에서도 쓸모 있는 메타데이터를 남깁니다.

디렉터리와 설정 파일을 만듭니다:

mkdir -p ~/.config/yt-dlp ~/archive
nano ~/.config/yt-dlp/archive.conf

다음 옵션을 추가합니다:

-P "~/archive"
-o "%(channel)s/%(upload_date>%Y-%m-%d)s - %(title)s [%(id)s].%(ext)s"
-f "bv*[height<=1080]+ba/b[height<=1080]"
--merge-output-format mp4
--download-archive ~/archive/downloaded.txt
--sleep-requests 1
--sleep-interval 5
--max-sleep-interval 10
--write-info-json
--write-thumbnail
--write-subs
--write-auto-subs
--sub-langs en.*
--embed-subs
--embed-thumbnail
--embed-metadata
--sponsorblock-mark all

yt-dlp에 채널 전체를 넘기기 전에, 영상 하나로 테스트해 보세요:

~/yt-dlp-venv/bin/yt-dlp \
  --config-location ~/.config/yt-dlp/archive.conf \
  "https://www.youtube.com/watch?v=VIDEO_ID"

그다음 같은 설정으로 채널이나 재생목록 URL을 실행하세요:

~/yt-dlp-venv/bin/yt-dlp \
  --config-location ~/.config/yt-dlp/archive.conf \
  "https://www.youtube.com/@CHANNEL/videos"

--download-archive 파일은 성공적으로 내려받은 ID를 기록하므로, 이후 실행에서는 그것들을 건너뜁니다. 처음에는 기본값인 --concurrent-fragments 1을 유지하세요. yt-dlp의 YouTube 가이드는 세션이 요청 한도에 다다르면 영상 사이에 지연을 두라고 권하지만, VPS IP에 두루 안전한 프래그먼트 동시성 상한을 제시하지는 않습니다.

systemd로 다운로드 예약하기

사용자 수준의 systemd 타이머는 cron에 긴 명령을 넣지 않고도 작업에 지속적인 예약과 로그를 제공합니다. 무작위 지연은 예약된 모든 소스가 같은 초에 시작하는 것도 막아 줍니다. 사용자 관리자의 PATH에 기대지 않으려고, 이 서비스는 yt-dlp가 Deno의 기본 설치 위치를 직접 가리키게 합니다.

서비스를 만듭니다:

mkdir -p ~/.config/systemd/user
nano ~/.config/systemd/user/yt-dlp-archive.service
[Unit]
Description=Archive a YouTube channel with yt-dlp

[Service]
Type=oneshot
ExecStart=%h/yt-dlp-venv/bin/yt-dlp --js-runtimes deno:%h/.deno/bin/deno --config-location %h/.config/yt-dlp/archive.conf https://www.youtube.com/@CHANNEL/videos

타이머를 만듭니다:

nano ~/.config/systemd/user/yt-dlp-archive.timer
[Unit]
Description=Run the yt-dlp archive daily

[Timer]
OnCalendar=*-*-* 04:00:00
RandomizedDelaySec=30m
Persistent=true

[Install]
WantedBy=timers.target

타이머를 활성화하고, 로그인하지 않은 상태에서도 사용자 서비스가 실행되도록 허용하세요:

systemctl --user daemon-reload
systemctl --user enable --now yt-dlp-archive.timer
sudo loginctl enable-linger "$USER"
systemctl --user list-timers
journalctl --user -u yt-dlp-archive.service -n 100 --no-pager

채널이 여러 개라면 채널마다 서비스 인스턴스를 하나씩 만들거나 타이머를 따로 두세요. 큰 작업 여러 개를 한꺼번에 띄우지 말고 시간을 어긋나게 배치하세요.

아카이브를 Jellyfin에 연결하기

같은 ~/archive 디렉터리를 Jellyfin에 마운트하거나 노출한 뒤 라이브러리로 추가하세요. 채널/날짜 형태의 원본 구조에는 Jellyfin의 Music Videos 라이브러리 라이브러리는 중첩 폴더와 임의의 파일 이름을 온라인 메타데이터 매칭 없이 받아들입니다. 음악이 아닌 아카이브에 이 이름표가 딱 맞지는 않지만, 시리즈와 시즌 폴더에 SxxEyy 형식의 에피소드 이름을 기대하는 "Shows" 유형보다 파일 구조 면에서 더 잘 맞습니다. 메타데이터 결과가 부정확할 수 있다는 Jellyfin의 경고를 감수할 게 아니라면 Mixed Content는 피하세요.

yt-dlp 설정의 메타데이터, 썸네일, 자막 옵션은 유용한 정보를 각 파일 옆이나 안에 남겨 둡니다. 그래도 Jellyfin에서는 메타데이터를 손으로 손봐야 할 수 있습니다. YouTube 채널이 TV 시리즈 데이터베이스에 깔끔하게 대응되지 않기 때문입니다.

손이 덜 가는 방식으로 Jellyfin에 맞는 파일 이름과 메타데이터를 원한다면, Pinchflat에 그 워크플로용 미디어 센터 프리셋이 있습니다. 미디어 서버들 사이의 더 큰 선택은 저희 Jellyfin과 Plex 비교 글에서 다룹니다 재생과 원격 접속, 트랜스코딩의 트레이드오프를

스택을 상시 가동 서버에 올리기

작은 테스트 세트에서 워크플로가 잘 돌아가면, 그것을 다음으로 옮기세요: Cloudzy의 Linux VPS . 그러면 예약된 다운로드와 미디어 라이브러리가 평소 쓰는 컴퓨터를 붙잡아 두지 않고도 계속 온라인에 있을 수 있습니다. 또한 다음도 배포할 수 있습니다: 원클릭 앱으로 제공되는 Jellyfin 그리고 그 라이브러리가 yt-dlp의 출력 디렉터리를 가리키게 하세요.

Linux 요금제 보기

루트 액세스, NVMe, AMD EPYC 성능을 갖춘 Linux VPS에서 개발하세요.

Linux 요금제 보기

자주 묻는 질문

VPS에서 yt-dlp에 GPU가 필요한가요?

아닙니다. yt-dlp는 GPU 없이도 미디어를 내려받고 리먹싱할 수 있습니다. GPU가 의미를 갖는 건 Jellyfin이나 다른 미디어 서버가 호환되지 않는 클라이언트나 대역폭이 낮은 연결을 위해 영상을 트랜스코딩해야 할 때입니다. 다이렉트 재생에는 그런 변환이 필요 없습니다.

yt-dlp가 중단된 다운로드를 이어받을 수 있나요?

네. yt-dlp는 부분 파일과 이어받기를 기본으로 켜 두므로, 나중에 실행하면 보통 이미 받은 조각부터 이어서 진행합니다. 이 동작을 원한다면 --no-continue, --no-part, --force-overwrites를 붙이지 마세요.

yt-dlp와 Jellyfin을 한 VPS에서 같이 돌려도 될까요?

저장 공간과 CPU, 아웃바운드 트래픽이 두 작업 모두에 충분하다면 한 VPS를 함께 써도 됩니다. 재생이나 트랜스코딩이 대용량 다운로드와 자원을 다툴 때, 유지보수 시간대를 따로 잡아야 할 때, 또는 아카이브를 스트리밍 서버보다 저렴한 저장소에 두는 편이 나을 때는 분리하세요.

공유

블로그 더 보기

계속 읽기.

배포할 준비가 되셨나요? 월 $2.48부터.

2008년부터 독립 클라우드. AMD EPYC, NVMe, 40 Gbps. 14일 환불 보장.