나무모에 미러 (일반/밝은 화면)
최근 수정 시각 : 2025-12-16 16:38:16

Streamlink


#!if code = "display: inline; padding: .125rem .25rem; background: #dddddd; border-radius: .25rem; font-size: .875rem; font-family: Cascadia Mono, Menlo, Monaco, Consolas, monospace"
#!if codeds = "display: inline; padding: .125rem .25rem; background: #383b40; border-radius: .25rem; font-size: .875rem; font-family: Cascadia Mono, Menlo, Monaco, Consolas, monospace"
<colbgcolor=#0073bd,#121657><colcolor=#ffffff,#ffffff> Streamlink
스트림링크
파일:Streamlink 로고.svg
개발 Streamlink Community
최초 공개 2016년 9월 23일[1]
전신 Livestreamer
최신 버전 8.1.0 (2025년 12월 14일) 파일:GitHub 아이콘.svg파일:GitHub 아이콘 화이트.svg
운영체제 Windows, macOS, Linux, BSD
종류 오픈 소스, CLI 프로그램, 스트리밍 유틸리티, Python 라이브러리
언어 Python (>=3.10)
라이선스 BSD 2-Clause Simplified License
관련 링크 파일:홈페이지 아이콘.svg | 파일:GitHub 아이콘.svg파일:GitHub 아이콘 화이트.svg | PyPI
1. 개요2. 역사3. 주요 기능 및 특징4. 지원 플랫폼5. 설치 방법6. 기본 명령어 및 형식
6.1. 스트림 품질 선택6.2. 자주 사용되는 옵션6.3. 전체 CLI 명령어 목록6.4. JSON 출력 및 메타데이터 추출6.5. 특정 플랫폼 전용 옵션
7. 심화 명령어
7.1. 설정 파일 사용7.2. 외부 플러그인 추가
7.2.1. 플러그인 디렉토리 위치7.2.2. 사용 방법
7.3. 인증 정보 활용7.4. 고급 스트림 처리7.5. FFmpeg 관련 옵션7.6. Python 라이브러리로 사용
7.6.1. 세션 및 옵션 관리7.6.2. 데이터 유효성 검사 및 메타데이터 추출7.6.3. 예외 처리
7.7. TermuxVLC와 연계
8. 활용 사례
8.1. 유로 트럭 시뮬레이터 2에서 사용8.2. 개인 스트리밍 중계 서버 구축8.3. 자동 녹화 환경 구축
9. 여담10. 관련 문서11. 외부 링크

1. 개요

||<table width=100%><width=10%><table bgcolor=transparent><table bordercolor=transparent><keepall>A Python library and command-line interface which pipes streams from various services into a video player.
Avoid resource-heavy and unoptimized websites, and still enjoy streamed content.

Streamlink was forked in 2016 from the abandoned Livestreamer project.
Streamlink 소개 ||


Streamlink는 다양한 온라인 스트리밍 서비스의 영상 및 음성 콘텐츠를 미디어 플레이어로 바로 재생하거나 파일로 저장할 수 있도록 지원하는 Python 기반 소프트웨어이자 명령줄 인터페이스(CLI) 형태의 개발자 도구다.

웹 브라우저를 거치지 않고 스트림에 직접 연결하기 때문에, 광고나 번거로운 웹 인터페이스 없이 쾌적하게 콘텐츠를 감상할 수 있다.

시스템 자원 소모가 적어 손쉽게 스트리밍 환경을 구축할 수 있으며, Python 라이브러리 형태로도 제공되어 다른 프로그램과 연동하는 것도 가능하다.

2. 역사

Streamlink의 초기 개발은 Livestreamer 프로젝트에서 시작되었다. Livestreamer는 한동안 널리 사용되었으나, 2016년경부터 유지보수가 멈추면서 최신 플랫폼 지원이 어려워지고 기존 기능도 유지가 어려워졌다.

이러한 한계를 극복하기 위해 기존 Livestreamer의 사용자와 개발자들은 프로젝트를 포크(fork)하여 Streamlink라는 새로운 이름으로 발전시켰다.

이후 Python 3 지원, 다양한 스트리밍 서비스 확대, 플러그인 구조 개선 등을 중심으로 지속적으로 개발되고 있다.

2025년 11월 공개된 8.0.0 버전에서는 내부 구조가 개선되어 플러그인 지연 로딩(Lazy Loading)이 도입되었다. 이를 통해 실행 시 모든 플러그인을 한 번에 불러오지 않고 필요한 플러그인만 로드하게 되어 초기 구동 속도가 빨라지고 메모리 점유율이 감소했다. 또한 Python 3.9 버전에 대한 지원이 공식적으로 중단되었다.

Streamlink는 HLS와 MPEG-DASH 같은 최신 스트리밍 프로토콜을 지원하며, 다양한 인증 방식 도입, 커뮤니티 피드백 반영, 플러그인 주기적 갱신 등 실질적인 변화가 이어지고 있다.

3. 주요 기능 및 특징

4. 지원 플랫폼

Streamlink는 전 세계의 다양한 스트리밍 플랫폼에 대응하는 플러그인을 제공한다.

주요 지원 플랫폼은 다음과 같다.
전체 지원 플랫폼 목록은 공식 플러그인 목록에서 확인할 수 있다.

5. 설치 방법

Streamlink는 Windows, macOS, Linux 등 다양한 운영체제를 지원하며, 환경과 목적에 따라 다양한 설치 방법을 제공한다.

각 방법의 장단점이 다르므로, 목적에 맞는 방식을 선택해 설치하면 된다. 자세한 설치 방법과 환경별 안내는 공식 문서에서 확인할 수 있다.
<rowcolor=#ffffff,#ffffff> 구분 설치 방법 설명
파일:파이썬 로고.svg
pip

(권장)
pip install streamlink

업그레이드:
pip install --upgrade streamlink
Streamlink는 Python 기반으로, OS에 관계없이
pip
로 설치할 수 있다.
Python이 설치되어 있어야 하며,
pip
명령이 인식되지 않는 경우 환경 변수 설정이 필요할 수 있다. 일부 OS에서는
pip3
명령을 사용해야 할 수 있다.
파일:Windows 아이콘.svg
Windows
Windows 설치 파일 다운로드
WinGet:
winget install streamlink

Chocolatey:
choco install streamlink
Python이 설치되어 있지 않은 Windows 사용자를 위해 .exe 설치 프로그램 또는 포터블 버전이 제공된다.
설치가 완료되면 명령 프롬프트PowerShell에서
streamlink
명령을 사용할 수 있다.
Windows 10 이상의 64비트 환경이 필요하다.
macOS homebrew:
brew install streamlink
파일:Linux 로고.svg파일:Linux 로고 화이트.svg
Linux
Streamlink AppImage
다운로드 설치 방법
Streamlink AppImage는 사용 중인 Linux 배포판이나 패키지 매니저에 관계없이 사용할 수 있는 포터블 실행 파일로, Streamlink에 Python 가상 환경이 포함된 형태이며 FFmpeg가 포함된 버전도 있다. AArch64x86_64 환경을 지원한다.
Linux 배포판 패키지 매니저
Fedora:
sudo dnf install streamlink

Arch:
sudo pacman -S streamlink
Ubuntu에서는 권장되지 않는 방법. 각 리눅스 배포판의 패키지 매니저를 통해 설치할 수 있으나, pip보다 버전이 낮을 수 있다.
소스 코드 컴파일 설치 방법GitHub 저장소에서 소스 코드를 받아 직접 설치할 수도 있다.
참고: Windows 환경에서 {{{#!wiki style="@code@" dark-style="@codeds@"
pip install streamlink}}}가 작동하지 않는 경우 Python 설치 시 add to PATH를 체크하지 않았을 수 있다.
이 경우 시작 메뉴 검색창에 '계정의 환경 변수 편집'을 입력하여 설정을 열고, Path 환경 변수에 아래 예시와 같이 Python과 pip가 설치된 경로를 직접 입력해야 한다. Python 설치 방법과 버전에 따라 경로가 다를 수 있다.
* Python: {{{#!wiki style="@code@" dark-style="@codeds@"
%LocalAppdata%\\Programs\\Python314}}}%LocalAppdata%\\Programs\\Python314\\Scripts}}}

6. 기본 명령어 및 형식

#!syntax sh
streamlink [옵션] <URL> [품질]
예:
streamlink twitch.tv/twitch best


별도의 플레이어를 지정하지 않으면, 시스템 기본 플레이어나 Streamlink가 자동으로 인식한 플레이어(주로 VLC)를 통해 스트림을 실행한다.

6.1. 스트림 품질 선택

스트림 품질을 지정하지 않고 URL만 입력하면, 아래와 같이 지원되는 전체 품질 목록이 먼저 확인된다.
#!syntax sh
streamlink twitch.tv/twitch
#!syntax sh
[cli][info] Found matching plugin twitch for URL twitch.tv/twitch
Available streams: audio_only, 160p (worst), 360p, 480p, 720p, 720p60, 1080p, 1080p60 (best)
이를 참고해 원하는 품질을 직접 입력하거나 worst, best와 같은 키워드로 최저·최고 품질을 선택할 수 있다.
#!syntax sh
streamlink twitch.tv/twitch 480p
품질이 높을수록 네트워크 대역폭 사용량이 증가하므로, 자신의 인터넷 환경을 고려해 적절한 품질을 선택해야 한다. 또한, 각 플랫폼 또는 지역마다 지원 품질과 키워드에 차이가 있다.
<rowcolor=#ffffff,#ffffff> 품질 키워드 설명 비고
best 시청 가능한 최고 화질 스트림 오디오도 포함된 경우가 일반적이다.
worst 시청 가능한 최저 화질 스트림 데이터 사용량을 최소화하고 싶을 때 유용하다.
best-unfiltered 필터링되지 않은 품질 목록 중 최고 화질 스트림 후술할
--stream-sorting-excludes
옵션을 사용하여 사용 가능한 품질 목록을 필터링했을 때 사용할 수 있는 키워드
worst-unfiltered 필터링되지 않은 품질 목록 중 최저 화질 스트림
오디오 전용 스트림 일부 플랫폼에서 제공하는 오디오 스트림
audio-only
,
audio-opus
,
audio_mp4

6.2. 자주 사용되는 옵션

<rowcolor=#ffffff,#ffffff> 범주 옵션 설명 비고
일반 -h
--help
사용 가능한 모든 옵션과 도움말을 출력하고 종료한다.
--version 설치된 Streamlink의 버전을 출력하고 종료한다.
스트림 --url 주소 스트림의 주소를 지정한다. 예:
\--url twitch.tv/twitch

m3u8 주소도 입력할 수 있다.
--default-stream 품질 URL만 입력 시 기본으로 선택할 스트림 품질을 지정한다.
쉼표로 우선순위 지정 가능.
예:
\--default-stream "1080p,best"
[3]
재생 -p 경로
--player 경로
사용할 미디어 플레이어의 경로를 지정한다.
가능하다면 VLC를 기본으로 사용한다.[4]
예:
\--player "C:\\Program Files\\VideoLAN\\VLC\\vlc.exe"
-a 인자
--player-args 인자
플레이어에 전달할 인자를 지정한다. 예:
\player-args "\fullscreen"

mpv 저지연:
\player-args "\profile=low-latency \--no-cache"
--player-passthrough 타입 Streamlink를 거치지 않고 플레이어가 직접 스트림을 처리하게 한다.
http
,
hls
등을 지정.
CPU 부하를 줄일 수 있다.
--player-no-close 스트림이 종료되거나 오류가 발생해도 플레이어 창을 닫지 않고 유지한다.오류 메시지를 확인하거나 마지막 장면을 유지하고 싶을 때 유용하다.
네트워크 --stream-timeout 시간(초) 스트림 데이터를 읽을 때 타임아웃(대기) 시간을 설정한다. 기본값: 20(초). 네트워크가 불안정하여 연결이 자주 끊기면 이 값을 늘리는 것이 좋다.
--http-proxy 주소 HTTP 및 HTTPS 요청 시 사용할 프록시 서버를 지정한다. 예:
\--http-proxy "http://127.0.0.1:8080"
--locale 지역코드 특정 국가/언어 설정을 에뮬레이션한다.지역 제한 콘텐츠에 접근하거나 언어를 변경할 때 사용한다.
예:
\--locale en_US
저장 -o 파일경로
--output 파일경로
스트림 데이터를 파일로 저장한다. 예:
\--output video.ts

\--output -
(표준 출력)
-r 파일경로
--record 파일경로
스트림을 재생하면서 동시에 파일로 저장한다. 예:
\--record video.ts

\--record -
(표준 출력)
-O
--stdout
스트림 데이터를 표준 출력으로 보낸다. FFmpeg 등 외부 도구와 파이프 연결 시 사용.
재시도 --retry-streams 시간(초) 스트림을 찾지 못한 경우, 지정된 시간(초) 이후 재시도한다. 예:
\--retry-streams 3
--retry-open 횟수 스트림이 중단된 경우, 지정된 횟수만큼 재시도한다. 기본값: 1
정보 -l 레벨
--loglevel 레벨
로그 출력 수준을 설정한다. (
info
,
debug
,
none
등)
문제 발생 시
debug
로 설정하여 상세 정보를 확인한다.
--stream-url 변환된 실제 스트림 주소(URL)만 출력하고 종료한다.
-j
--json
스트림 정보를 JSON 형식으로 출력한다. 스크립트 작성 시 유용하다.

위의 옵션 중,
--retry-streams
,
--retry-open
등의 재시도 옵션은 불안정한 네트워크 환경 등으로 인하여 스트림이 일시적으로 중단될 때 상당히 유용하게 사용될 수 있다.

사용 예시streamlink -p vlc twitch.tv/twitch best}}}streamlink -o "{author}_{time:%Y%m%d}_{id}_{title}.ts" chzzk.naver.com/live/xxxxx 720p}}}
→ 스트림 제목, 시간 등 메타데이터를 파일명에 사용하는 자세한 방법은 #JSON 출력 및 메타데이터 추출 문단 참고.
* SOOP 스트림을 팟플레이어의 새 창에서 최고 품질로 재생: {{{#!wiki style="@code@" dark-style="@codeds@"
streamlink -p "C:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe" --player-args "/new" play.sooplive.co.kr/xxxxx best}}}

6.3. 전체 CLI 명령어 목록

Streamlink의 실행 옵션은 일반 설정, 플레이어 제어, 파일 출력, 네트워크 설정, 스트림 제어, 웹 브라우저 통합 등으로 나뉜다.

[ 전체 명령어 목록 펼치기 · 접기 ]
||<table width=100%><table bordercolor=#0073bd,#064d90><table bgcolor=transparent><rowbgcolor=#0073bd,#121657><rowcolor=#ffffff,#ffffff><colkeepall> 범주 ||<colkeepall> 옵션 ||<colkeepall> 설명 ||<colkeepall> 비고 ||
일반/세션 -h
--help
사용 가능한 옵션과 도움말을 출력하고 종료한다.
-V
--version
설치된 Streamlink의 버전을 출력한다.
--version-check 버전 업데이트 확인을 수행하고 종료한다.
--auto-version-check 새 버전 자동 확인 기능을 켜거나 끈다. 기본값:
no
--locale 지역 특정 국가/언어 설정을 에뮬레이션한다. 예:
\--locale en_US
--config 경로 기본 경로 외의 다른 설정 파일을 로드한다. 여러 번 사용하여 병합 가능.
--no-config 설정 파일을 로드하지 않는다. 순정 상태로 테스트할 때 유용.
-l 레벨
--loglevel 레벨
로그 출력 수준을 설정한다.
(debug, info, warning, error, none)
기본값:
info

문제 해결 시
debug
권장.
--logfile 경로 로그 출력을 파일로 저장한다.
-
사용 시 표준 출력으로 지정.
-Q
--quiet
터미널에 로그를 출력하지 않고, 사용자 입력 요구도 비활성화한다.
플레이어 -p 경로
--player 경로
미디어 플레이어의 실행 경로를 지정한다. 가능하다면 VLC를 기본으로 사용한다.[5]
-a 인자
--player-args 인자
플레이어에 전달할 인자를 지정한다.
{playerinput} , {playertitleargs} 변수 사용 가능.
예:
\player-args "\fullscreen"
--player-env 변수 플레이어 프로세스에 환경 변수를 추가한다. 예:
KEY=VALUE
-v
--player-verbose
플레이어의 콘솔 출력을 Streamlink 출력에 표시한다.
-n
--player-fifo
(Linux/macOS) 명명된 파이프(Named Pipe)를 사용해 데이터를 전달한다.
--player-http 로컬 HTTP 서버를 열어 플레이어가 접속하게 한다.
--player-continuous-http HTTP 스트림 연결이 끊겨도 플레이어가 재접속하도록 유지한다.
--player-external-http 외부 장치 접속을 허용하는 HTTP 서버를 연다. 다른 기기(스마트폰 등)에서 시청 시 사용.
--player-external-http-port 포트 외부 HTTP 서버의 포트를 지정한다. 기본값: 0 (랜덤 포트)
--player-passthrough 방식 Streamlink를 거치지 않고 플레이어가 직접 스트림을 처리하게 한다.
http
,
hls
등 지정.
CPU 부하를 줄일 수 있다.
--player-no-close 스트림 종료 후에도 플레이어 창을 닫지 않는다. 오류 메시지 확인용.
-t 제목
--title 제목
플레이어 창의 제목(Title)을 설정한다.
지원 플레이어: mpv, PotPlayer, VLC
예:
\--title "{author} - {game}"
파일 출력 -o 경로
--output 경로
스트림 데이터를 파일로 저장한다. 동시에 재생되지 않음.
예:
\--output -
(표준 출력)
-r 경로
--record 경로
스트림을 재생하면서 동시에 파일로 저장한다. 예:
\--record -
(재생하며 표준 출력)
-O
--stdout
데이터를 표준 출력(Standard Output)으로 보낸다. FFmpeg 등 외부 도구와 파이프 연결 시 사용.
-f
--force
출력 파일 경로에 이미 파일이 존재할 경우 덮어쓴다.
--skip 출력 파일이 이미 존재하면 덮어쓰지 않고 건너뛴다.
--force
보다 우선순위 높음.
--fs-safe-rules 규칙 파일 시스템 안전 규칙을 강제한다. (POSIX 또는 Windows)
--progress 모드 다운로드 진행률 표시 방식을 변경한다.
yes
,
no
,
force
스트림 제어 --url 주소 스트림 주소를 지정한다. 명령어 맨 뒤에 주소만 적어도 된다.
--default-stream 품질 기본으로 선택할 화질을 지정한다.
쉼표로 우선순위 지정 가능.
예:
\--default-stream "1080p,best"
--stream-url 실제 스트림 주소(M3U8 등)만 출력하고 종료한다.
--retry-streams 시간 스트림을 찾을 때까지 지정된 시간(초)만큼 대기하며 재시도한다. 방송 시작 대기 시 유용.
--retry-max 횟수 스트림을 찾지 못했을 때 최대 재시도 횟수.
--retry-open 횟수 스트림을 여는 데 실패했을 때 재시도 횟수. 기본값: 1
--stream-types 허용할 스트림 타입을 지정한다. 기본값:
hls,http,*
--stream-sorting-excludes 특정 화질을 제외하고 정렬한다. 예:
--stream-sorting-excludes ">480p"
(480p보다 좋은 화질만 포함)
--check-streams 지원되는 스트림 목록만 확인하고 종료한다.
--can-handle-url 입력된 URL을 지원하는 플러그인이 있는지 확인한다. 스크립트용 (상태 코드 반환)
웹 브라우저 --webbrowser 브라우저 API 지원을 활성화/비활성화한다. 기본값:
true
--webbrowser-executable 경로 사용할 웹 브라우저의 실행 파일 경로를 지정한다.
--webbrowser-timeout 시간 브라우저 실행 대기 시간.
--webbrowser-cdp-host CDP 인터페이스 호스트. 기본값: 127.0.0.1
--webbrowser-cdp-port CDP 인터페이스 포트.
--webbrowser-cdp-timeout CDP 명령 응답 대기 시간.
--webbrowser-headless 브라우저를 헤드리스 모드(창 없이)로 실행한다. 봇 감지 회피 시
false
권장.
네트워크 --http-proxy 주소 HTTP/HTTPS 요청에 사용할 프록시를 지정한다. 예:
\--http-proxy "http://127.0.0.1:8080"
--stream-timeout 시간 스트림 데이터 읽기 타임아웃(초). 기본값: 60.0
--stream-segment-timeout 시간 세그먼트 다운로드 타임아웃(초). 기본값: 10.0
--stream-segment-threads 개수 세그먼트 다운로드 병렬 스레드 수. 기본값: 1, 최대: 10
--http-header 헤더 HTTP 요청에 사용자 정의 헤더를 추가한다. 예:
\--http-header "Foo=Bar"
--http-query-param 파라미터 HTTP 요청 URL에 쿼리 파라미터를 추가한다. 예:
\--http-query-param "foo=bar"
--http-cookie 쿠키 HTTP 요청에 쿠키를 추가한다. 인증이 필요한 스트림에 사용.
--http-no-ssl-verify SSL 인증서 검증을 비활성화한다. 보안상 권장되지 않음.
--http-disable-dh Diffie-Hellman 키 교환을 비활성화한다.
--http-ssl-cert 파일 SSL 인증서(.pem) 파일을 지정한다.
--http-timeout 시간 일반 HTTP 요청 타임아웃(초). 기본값: 20.0
--interface 주소 특정 네트워크 인터페이스(IP)로 통신을 강제한다.
-4
--ipv4
IPv4 주소만 사용한다.
-6
--ipv6
IPv6 주소만 사용한다.
플러그인 --plugins 설치된 모든 플러그인 목록을 출력한다.
--skip-plugins 해당 플러그인을 로드하지 않고 건너뛴다.

6.4. JSON 출력 및 메타데이터 추출

파일:관련 문서 아이콘.svg   관련 문서: JSON
#!if 문서명2 != null
, [[jq]]
#!if 문서명3 != null
, [[]]
#!if 문서명4 != null
, [[]]
#!if 문서명5 != null
, [[]]
#!if 문서명6 != null
, [[]]

Streamlink는
-j
또는
--json
옵션을 사용하여 스트림 정보를 JSON 형식으로 출력할 수 있다.

#!syntax sh
streamlink --json https://www.twitch.tv/twitch
#!syntax json
{
  "plugin": "twitch",
  "metadata": {
    "id": "123456789012",
    "author": "Twitch",
    "category": "Just Chatting",
    "title": "Twitch Stream Title"
  },
  "streams": {
    "audio_only": {
      "type": "hls",
      "url": "https://....",
      "headers": {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:144.0)",
        "Accept-Encoding": "gzip, deflate, br, zstd",
        "Accept": "*/*",
        "Connection": "keep-alive",
        "referer": "https://player.twitch.tv",
        "origin": "https://player.twitch.tv"
      },
      "master": "https://..."
    },
    "160p": { ... },
    "360p": { ... },
    "480p": { ... },
    "720p": { ... },
    "worst": { ... },
    "best": { ... }
  }
}

[[jq|
jq
]]를 활용한 데이터 추출

메타데이터만 추출:
#!syntax sh
streamlink -j twitch.tv/twitch | jq '.metadata'
#!syntax json
{
   "id": "123456789012",
   "author": "Twitch",
   "category": "Just Chatting",
   "title": "Twitch Stream Title"
}

스트리머 이름 추출:
#!syntax sh
streamlink -j twitch.tv/twitch | jq -r '.metadata.author'
#!syntax json
Twitch

방송 제목 추출:
#!syntax sh
streamlink --json https://www.twitch.tv/twitch | jq -r '.metadata.title'
#!syntax json
Twitch Stream Title

플레이어 또는 출력 파일명에 메타데이터 활용

--title
[6],
--output
또는
--record
옵션에서 다음 변수를 사용할 수 있다.

플러그인별로 제공하는 메타데이터가 다르거나 없을 수 있으므로, 메타데이터 변수를 사용하기 전에 플러그인이 해당 변수를 지원하는지 확인해야 한다. 해당 값이 존재하지 않으면
--title
에는 짧은 자리 표시자로 변수를 대체할 수 있고,
--output
--record
에는 빈 문자열이 변수에 할당될 수 있다.
<rowcolor=#ffffff,#ffffff> 변수 설명 예시 값
스트림 관련 메타데이터 변수
{author}​
스트리머/채널 이름 Twitch
{category}​
카테고리/게임 Just Chatting
{game}​
{category}​
의 별칭
Just Chatting
{title}​
스트림/방송 제목 Twitch Stream Title
{id}​
스트림 고유 ID 123456789012
범용 메타데이터 변수
{time}​
현재 시간 20XX-12-31_12-34-56
{url}​
스트림 URL https://...
{plugin}​
사용된 플러그인 이름 twitch

시간 형식 지정

{time}​
변수는 Python의 strftime 형식을 따른다.
<rowcolor=#ffffff,#ffffff> 형식 설명 예시
{time:%Y}​
연도 (4자리) 20XX
{time:%m}​
월 (2자리) 12
{time:%d}​
일 (2자리) 31
{time:%H}​
시 (24시간, 2자리) 12
{time:%M}​
분 (2자리) 34
{time:%S}​
초 (2자리) 56
{time:%Y%m%d}​
날짜 (YYYYMMDD) 20XX1231
{time:%Y-%m-%d_%H-%M-%S}​
날짜+시간 20XX-12-31_12-34-56

날짜와 스트리머 이름으로 파일 저장:
#!syntax sh
streamlink -o "{time:%Y%m%d}_{author}.ts" https://www.twitch.tv/twitch best
결과:
20XX1231_Twitch.ts

상세한 메타데이터를 포함한 파일명으로 저장:
#!syntax sh
streamlink -o "{author}_{time:%Y%m%d_%H%M}_{category}_{title}.ts" https://www.twitch.tv/twitch best
결과:
Twitch_20XX1231_1234_Just Chatting_Twitch Stream Title.ts

플레이어 창 제목 설정:
#!syntax sh
streamlink --player mpv --title "{author} - {title}" https://www.twitch.tv/twitch best

Streamlink는 메타데이터를 가져오는 범용 도구로 개발된 것이 아니므로 각 플랫폼의 API를 사용하여 메타데이터를 가져오는 것이 더 적절하다.

6.5. 특정 플랫폼 전용 옵션

각 플랫폼별로 특화된 기능을 제어하기 위한 옵션들이다.
대부분
--<플랫폼이름>-<옵션>
형태를 띠며, 로그인이 필요한 경우 아이디/비밀번호를 입력하거나 인증 토큰을 전달하는 데 사용된다.
<rowcolor=#ffffff,#ffffff> 플랫폼 옵션 설명
SOOP --soop-username 아이디 SOOP 로그인 아이디
--soop-password 비밀번호 SOOP 로그인 비밀번호
--soop-stream-password 비밀번호 비밀번호가 설정된 방송(비번방)을 시청하기 위한 비밀번호
--soop-purge-credentials 캐시된 자격 증명을 제거하고 새 세션을 시작하여 다시 인증한다.
트위치 --twitch-low-latency 저지연 스트리밍(Low Latency)을 활성화한다.
HLS 라이브 엣지를 줄여 버퍼링 위험이 있으나 지연 시간을 최소화한다.
--twitch-supported-codecs 코덱 선호하는 코덱을 지정한다. (예:
av1,h265
)
--twitch-api-header 헤더 API 요청에 포함될 HTTP 헤더를 지정한다.
광고 차단 등을 위해 인증 데이터를 추가할 때 유용하다.
--twitch-access-token-param 파라미터 액세스 토큰 획득 요청 시 추가 파라미터를 전달한다.
--twitch-force-client-integrity
--twitch-purge-client-integrity
클라이언트 무결성 토큰 사용을 강제하거나, 캐시된 토큰을 제거한다.
Kick --kick-low-latency 저지연 스트리밍을 활성화한다. (HLS 세그먼트 프리페치 등)
별도의 로그인 옵션 없이 브라우저 쿠키 등을 활용해야 할 수 있다.
BBC iPlayer --bbciplayer-username 아이디 bbc.co.uk 계정 아이디
--bbciplayer-password 비밀번호 bbc.co.uk 계정 비밀번호
--bbciplayer-hd 가능한 경우 SD 대신 HD 스트림을 선호한다.
니코니코 동화 --niconico-email 이메일 니코니코 계정 이메일 또는 전화번호
--niconico-password 비밀번호 니코니코 계정 비밀번호
--niconico-user-session 토큰 패스워드 대신 user-session 토큰 값을 직접 입력한다.
--niconico-purge-credentials 캐시된 인증 정보를 제거한다.
pixiv --pixiv-sessionid ID PHPSESSID 쿠키에 사용되는 세션 ID
--pixiv-devicetoken 토큰 device_token 쿠키에 사용되는 디바이스 토큰
--pixiv-performer 사용자 공동 호스트(Co-host) 방송 시 특정 사용자의 시점을 선택한다.
--pixiv-purge-credentials 캐시된 인증 정보를 제거한다.
Steam --steam-email 이메일 스팀 계정 이메일 (친구/비공개 방송 시청 시 필요)
--steam-password 비밀번호 스팀 계정 비밀번호
유스트림 --ustream-password 비밀번호 비밀번호가 걸린 채널을 시청하기 위한 비밀번호
USTVNow --ustvnow-username 아이디
--ustvnow-password 비밀번호
USTVNow 계정 정보
WWE 네트워크 --wwenetwork-email 이메일
--wwenetwork-password 비밀번호
WWE Network 계정 정보
Zattoo --zattoo-email 이메일 Zattoo 계정 이메일
--zattoo-password 비밀번호 Zattoo 계정 비밀번호
--zattoo-stream-types 타입 사용할 스트림 타입을 지정한다. (dash, hls7 등)
Clubbing TV --clubbingtv-username 아이디
--clubbingtv-password 비밀번호
Clubbing TV 계정 정보
OpenRec --openrectv-email 이메일
--openrectv-password 비밀번호
OpenRec 계정 정보
RaiPlay --raiplay-email 이메일
--raiplay-password 비밀번호
RaiPlay 계정 정보
TF1 --tf1-email 이메일
--tf1-password 비밀번호
TF1 계정 정보
트윗캐스팅 --twitcasting-password 비밀번호 비공개 방송 시청을 위한 비밀번호
YuppTV --yupptv-boxid ID
--yupptv-yuppflixtoken 토큰
YuppTV 쿠키 인증 정보 (BoxId, YuppflixToken)

7. 심화 명령어

7.1. 설정 파일 사용

반복적인 옵션이나 민감한 정보(예: API 키)는 설정 파일에 미리 정의해두면 편리하다.
<rowcolor=#ffffff,#ffffff> 운영체제 설정 파일 위치
Linux, BSD 경로:
${XDG_CONFIG_HOME:-${HOME}/.config}/streamlink/config

예시:
/home/USERNAME/.config/streamlink/config
macOS 경로:
${HOME}/Library/Application Support/streamlink/config

예시:
/Users/USERNAME/Library/Application Support/streamlink/config
Windows 경로:
%APPDATA%\\streamlink\\config

예시:
C:\\Users\\USERNAME\\AppData\\Roaming\\streamlink\\config

특정 플러그인에 종속되는 설정 파일은
config.플러그인명
과 같이 파일 이름을 지정한다.

예를 들어, Streamlink에 내장된 치지직 플러그인 'chzzk'에 종속되는 설정 파일의 이름은
config.chzzk
과 같다.
<rowcolor=#ffffff,#ffffff> 운영체제 플러그인 설정 파일 위치
Linux, BSD 경로:
${XDG_CONFIG_HOME:-${HOME}/.config}/streamlink/config.플러그인명

예시:
/home/USERNAME/.config.chzzk/streamlink/config.chzzk
macOS 경로:
${HOME}/Library/Application Support/streamlink/config.플러그인명

예시:
/Users/USERNAME/Library/Application Support/streamlink/config.chzzk
Windows 경로:
%APPDATA%\\streamlink\\config.플러그인명

예시:
C:\\Users\\USERNAME\\AppData\\Roaming\\streamlink\\config.chzzk
#!syntax sh
# 기본 플레이어 설정 (경로를 자신의 환경에 맞게 수정)
player="C:\Program Files\VideoLAN\VLC\vlc.exe"

# 플레이어 옵션: 전체화면으로 시청
player-args=--fullscreen

# 기본 화질: 1080p가 있으면 1080p, 없으면 최고화질
default-stream=1080p,best

# 스트림이 종료되어도 플레이어를 닫지 않는 옵션 (선택사항)
player-no-close

# 네트워크 설정: 불안정한 인터넷 환경을 위한 타임아웃 증가
stream-timeout=60
retry-open=3

# 로그 레벨: 문제 발생 시 debug로 변경
loglevel=info

# HTTP 요청 시 특정 헤더 추가 (전역 적용)
http-header User-Agent=Mozilla/5.0

# 트위치 전용 옵션 (트위치 시청 시에만 적용됨)
twitch-low-latency
twitch-api-header Authorization=OAuth YOUR_TWITCH_TOKEN
 
# 쿠키 값 전달 (예: 네이버 로그인 토큰)
http-cookie NID_AUT=YOUR_AUT_TOKEN
http-cookie NID_SES=YOUR_SES_TOKEN

각 옵션은 명령어 앞의
--
를 제외하고 한 줄에 하나씩 작성한다.
url_matcher
를 사용하여 특정 URL 패턴에만 적용될 옵션을 지정할 수도 있다. 트위치 OAuth 토큰은 트위치 개발자 콘솔에서 확장 프로그램을 생성한 뒤 발급받을 수 있다.

기본적으로 제공되는 설정 파일의 내용은 다음과 같다. 플레이어 경로나 FFmpeg 경로를 설정할 때 참고하면 유용하다.
[ 기본 설정 파일(Windows x86_64) 내용 펼치기 · 접기 ]
#!syntax sh
# Streamlink config file

# Please see the Streamlink CLI documentation for all available options:
# https://streamlink.github.io/cli.html#command-line-usage

# The format is option=value
# Lines starting with a # are considered comments and are ignored.

# All leading dashes need to be ignored,
# e.g. --default-stream=STREAM becomes default-stream=STREAM

# Option values must not be quoted, or quotes become part of the option's actual value.

# ----

# By default, Streamlink will attempt to locate VLC on your system
# and use that, but you can also specify the location of a player yourself.
# Here are a couple of common player paths:

# VLC
#player=C:\Program Files\VideoLAN\VLC\vlc.exe
#player=C:\Program Files (x86)\VideoLAN\VLC\vlc.exe

# MPC-HC
#player=C:\Program Files\MPC-HC\mpc-hc64.exe
#player=C:\Program Files (x86)\MPC-HC\mpc-hc.exe

# MPV
#player=C:\Program Files\mpv-x86_64\mpv.exe

# Custom player arguments can be set using the player-args option.
# Please see the documentation of the used player for its available arguments.

# VLC
#player-args=--no-one-instance --play-and-exit
#player-args=--qt-minimal-view
#player-args=--file-caching=5000

# MPC-HC
#player-args=/new /play /close

# MPV
#player-args=--keep-open=no --force-window=yes
#player-args=--no-border
#player-args=--cache=yes --demuxer-max-bytes=2M


# Custom player window titles can automatically be set when a supported player
# and plugin are used. The title option has several variables available, which
# can show the stream's author, category/game, title, URL, etc.
#title={author} - {category} - {title}


# Use this if you want to transport the stream to the player via a named pipe.
#player-fifo

# Use one of these if you want to transport the stream to the player via HTTP.
# The continuous option will allow the player to stop and resume the output.
#player-http
#player-continuous-http

# Use player-passthrough if you want Streamlink to only pass the resolved URL
# to your player and let it handle the transport of the stream itself.
# Please note that the player needs to support the streaming protocol
# and that custom stream implementations in plugins will become unavailable,
# same as buffering options and those which change the network behavior.
#player-passthrough=http,hls

# By default, Streamlink will close the player when the stream is over.
# Use this option to let the player stay or close itself instead.
#player-no-close

# Show the player's console output
#player-verbose

# FFMPEG is used to mux separate video and audio streams into a single
# stream, so that they can be played. The full or relative path to ffmpeg
# should be specified here.
#ffmpeg-ffmpeg=C:\Program Files\Streamlink\ffmpeg\ffmpeg.exe
ffmpeg-ffmpeg=C:\Program Files\Streamlink\ffmpeg\ffmpeg.exe

# Log level, default is info
#loglevel=debug

# Number of threads to use when streaming HLS streams
#stream-segment-threads=1

--config 경로
를 사용하여 별도의 설정 파일 경로를 지정할 수 있고,
--no-config
옵션을 사용하여 설정 파일 로딩을 비활성화할 수도 있다.

자세한 내용은 공식 문서 참고.

7.2. 외부 플러그인 추가

Streamlink는 기본적으로 내장된 플러그인 외에도 사용자가 직접 추가한 외부 플러그인을 로드할 수 있는 사이드로딩(sideloading) 기능을 지원한다. # 이를 통해 공식 릴리즈에 포함되지 않은 새로운 플러그인을 테스트하거나, 특정 웹사이트의 변경사항에 맞춰 커뮤니티에서 임시로 수정한 플러그인을 사용하거나, 개인이 개발한 맞춤형 플러그인을 적용할 수 있다.

Streamlink가 베타 서비스 당시의 치지직을 정식으로 지원하지 않았을 때, 몇몇 사람들은 직접 개발하거나 다른 사람들이 올린 치지직 플러그인을 Streamlink에 연결하여 사용하기도 했다.

7.2.1. 플러그인 디렉토리 위치

사이드로딩할 플러그인 파일(
.py
)는 Streamlink 설정 파일이 위치한 디렉토리 내의
plugins
라는 하위 폴더에 위치시켜야 한다.
각 운영체제별 기본 경로는 다음과 같다.
<rowcolor=#ffffff,#ffffff> 운영체제 플러그인 디렉토리 경로
Linux, BSD 경로:
${XDG_DATA_HOME:-${HOME}/.local/share}/streamlink/plugins

예시:
/home/USERNAME/.local/share/streamlink/plugins
macOS 경로:
${HOME}/Library/Application Support/streamlink/plugins

예시:
/Users/USERNAME/Library/Application Support/streamlink/plugins
Windows 경로:
%APPDATA%\\streamlink\\plugins

예시:
C:\\Users\\USERNAME\\AppData\\Roaming\\streamlink\\plugins
#!syntax sh
 /data/data/com.termux/files/usr/lib/python3.12/site-packages/streamlink/plugins

7.2.2. 사용 방법

플러그인을 사이드로딩하는 방법은 간단하다.
  1. 신뢰할 수 있는 출처로부터 플러그인 파일(일반적으로 단일 {{{#!wiki style="@code@" dark-style="@codeds@"
.py}}} 파일)을 구한다.
  1. 해당 플러그인 파일을 위에서 설명한 운영체제별 {{{#!wiki style="@code@" dark-style="@codeds@"
plugins}}} 디렉토리 안에 복사한다.
예를 들어, {{{#!wiki style="@code@" dark-style="@codeds@"
custom.py}}}라는 플러그인 파일이 있다면 해당 파일을
plugins
폴더 내에 그대로 넣어두면 된다.플러그인명/plugin.py}}}와 같은 디렉토리 구조를 가질 수도 있다. 이 경우 해당 디렉토리 전체를
plugins
내에 복사한다.
  1. Streamlink를 실행하면 {{{#!wiki style="@code@" dark-style="@codeds@"
plugins}}} 디렉토리 내의 플러그인들을 자동으로 인식하고 로딩한다.

사이드로딩된 플러그인은 Streamlink에 내장된 기본 플러그인보다 우선적으로 로드된다. 다시 말해, 사이드로딩한 플러그인이 특정 URL을 처리하도록 작성되었고, 동일한 URL을 처리하는 기본 플러그인이 이미 존재하면 사이드로딩된 플러그인이 먼저 사용된다. 이는 기존 플러그인의 동작을 덮어쓰거나 수정하는 데 유용하게 사용될 수 있다.

만약
plugins
디렉토리에서의 플러그인 사이드로딩을 비활성화하려면
--no-plugin-sideloading
옵션을 사용하면 된다.

또한, 별도의 디렉토리를 지정하여 플러그인을 로드하고자 할 경우, Streamlink 실행 시 다음과 같이
--plugin-dir
옵션을 사용할 수 있다. 이 옵션은 여러 번 사용할 수 있으며, 지정된 각 디렉토리에서 플러그인을 로드한다.
#!syntax sh
streamlink --plugin-dir "/path/to/plugin" --plugin-dir "/path/to/second_plugin" <URL> [품질]

이 방식은 특정 디렉토리의 플러그인을 테스트하거나 분리하여 관리하고자 할 때 유용하며, 기본 플러그인 디렉토리의 플러그인보다 우선적으로 적용된다.

필요하다면,
--no-plugin-cache
옵션을 사용하여 키-값 저장소(key-value store)의 캐시 파일 입출력을 비활성화할 수도 있다.

7.3. 인증 정보 활용

로그인이 필요한 스트림을 시청하거나 특정 기능을 사용하기 위해 인증 정보가 필요할 수 있다.
민감한 정보는 명령어에 직접 입력하기보다 설정 파일이나 환경 변수를 통해 관리하는 것이 안전하다.
<rowcolor=#ffffff,#ffffff> 구분 옵션 설명 및 예시
HTTP 쿠키 --http-cookie KEY=VALUE 형태로 쿠키를 전달한다.
여러 개의 쿠키는 세미콜론(;)으로 구분하거나 옵션을 반복하여 전달한다.
예:
--http-cookie "NID_AUT=val; NID_SES=val"

예2:
\http-cookie NID_AUT=val http-cookie NID_SES=val
HTTP 헤더 --http-header KEY=VALUE 형태로 헤더를 전달한다.
예:
--http-header "Authorization=OAuth TOKEN"
치지직 (쿠키 사용) 치트키 타임머신 녹화 또는 연령 제한 방송 접근 시 네이버 로그인 쿠키가 필요하다.
브라우저 개발자 도구(F12)에서 NID_AUT, NID_SES 값을 찾아 입력한다.
트위치 (API 헤더) API 토큰이 필요한 경우 사용한다.
예:
--twitch-api-header "Authorization=OAuth TOKEN"

7.4. 고급 스트림 처리

Streamlink는 네트워크 성능 최적화와 재생 방식 변경 등의 활용을 위해 세밀하고 다양한 고급 옵션들을 제공한다.
<rowcolor=#ffffff,#ffffff> 범주 옵션 설명
다운로드/연결 --stream-segment-threads 숫자 세그먼트 병렬 다운로드 스레드 수를 지정한다. (기본: 1, 최대: 10)
--stream-segment-timeout 숫자 세그먼트 다운로드 시간 초과(Timeout)를 설정한다. (기본: 10.0초)
--player-continuous-http HTTP 스트림 연결이 끊겨도 플레이어가 계속 재접속을 시도하도록 유지한다.
--url-query 데이터 스트림 URL에 쿼리 문자열(Query String)을 추가하거나 덮어쓴다.
예:
--url-query "foo=bar"
URL?foo=bar 형태로 요청을 보낸다.
HLS/DASH 제어 --hls-live-edge 숫자 실시간 방송 끝부분과의 지연(세그먼트 수)을 설정한다.
낮을수록 지연이 줄지만 버퍼링 위험이 커진다. (기본: 3)
--hls-live-restart 가능한 경우 방송의 처음부터 재생을 시도한다. (치지직 타임머신 기능 등)
--stream-segmented-duration DASH 등에서 전체 재생 시간 정보가 없을 때, 시간을 강제로 설정하여 탐색바(Seek bar) 오류를 해결한다.
--stream-sorting-excludes 품질 자동 품질 선택 시 제외할 품질 조건을 지정한다.
예:
--stream-sorting-excludes ">480p"
→ 480p 초과 화질 제외
예2:
--stream-sorting-excludes "<720p,!=audio_only"
→ 720p 미만 화질 포함, 오디오 전용 스트림 제외
출력 제어 --ringbuffer-size 데이터를 플레이어로 보내기 전 임시 저장할 버퍼 크기.
(기본: 16M)
--player-external-http 로컬 HTTP 서버를 열어 외부 장치(모바일 등)에서 스트림을 볼 수 있게 중계한다.
[ 명령어 예시 ]
#!syntax sh
# 포트를 8080으로 지정하여 실행
streamlink --player-external-http --player-external-http-port 8080 twitch.tv/twitch best
기타 -n
--player-fifo
(Linux/macOS) 표준 출력 대신 명명된 파이프(Named Pipe)를 사용해 데이터를 전달한다.
[ 명령어 예시 ]
#!syntax sh
mkfifo /tmp/streamfifo
streamlink --player-fifo /tmp/streamfifo  best & mpv /tmp/streamfifo
rm /tmp/streamfifo

7.5. FFmpeg 관련 옵션

아래 나열된 옵션들은 스트림을 파일로 저장할 때, 인코딩을 변경할 때, 또는 자막/오디오를 다중화(Muxing)할 때만 필요하며, 단순히 미디어 플레이어로 시청할 때는 거의 사용되지 않는다.

시스템에 FFmpeg가 설치되었거나, FFmpeg가 포함된 Linux AppImage로 Streamlink를 구동하는 경우에 아래 옵션을 사용할 수 있다.
<rowcolor=#ffffff,#ffffff> 옵션 설명 비고
--ffmpeg-ffmpeg 파일명 FFmpeg 실행 파일의 경로를 지정한다.예:
--ffmpeg-ffmpeg="/usr/local/bin/ffmpeg"
--ffmpeg-no-validation FFmpeg의 유효성 검사 및 버전 로깅을 비활성화한다.
--ffmpeg-verbose FFmpeg의 표준 에러(stderr) 출력을 Streamlink의 표준 에러 출력으로 내보낸다.
--ffmpeg-verbose-path 경로 지정된 경로에 FFmpeg의 표준 에러 출력을 기록한다.예:
--ffmpeg-verbose-path /var/log/ffmpeg/error.log
--ffmpeg-loglevel 레벨 FFmpeg의 로그 레벨을 설정한다.이 옵션은
--ffmpeg-verbose
또는
--ffmpeg-verbose-path
를 사용할 때만 적용된다.
가능한 값:
quiet
[8],
panic
[9],
fatal
[10],
error
[11],
warning
[12],
info
[13],
verbose
[14],
debug
[15],
trace

기본:
info
--ffmpeg-fout 출력 포맷 스트림의 다중화가 필요한 경우 사용할 출력 포맷을 지정할 수 있다.예:
--ffmpeg-fout "mpegts"

기본:
matroska
--ffmpeg-video-transcode 코덱 스트림의 다중화가 필요한 경우 지정한 '코덱'으로 비디오를 트랜스코딩한다.예:
--ffmpeg-video-transcode "h264"

기본:
copy
[16]
--ffmpeg-audio-transcode 코덱 스트림의 다중화가 필요한 경우 지정한 '코덱'으로 오디오를 트랜스코딩한다.예:
--ffmpeg-audio-transcode "aac"

기본:
copy
--ffmpeg-copyts FFmpeg에
-copyts
옵션을 전달한다.
스트림 세그먼트의 비디오/오디오 동기화 등 일관된 타이밍 처리가 필요할 때 사용한다.
--ffmpeg-start-at-zero FFmpeg에
-start_at_zero
옵션을 전달한다.
--ffmpeg-copyts
옵션을 사용할 때만 적용된다.
FFmpeg에서 입력받은 스트림의 타임스탬프를 0에서 시작하도록 이동(shift)한다.
--ffmpeg-validation-timeout 시간(초) FFmpeg 시작 및 유효성 검사를 기다리는 최대 시간을 설정한다.예:
--ffmpeg-validation-timeout 20.0

기본:
10.0

7.6. Python 라이브러리로 사용

Streamlink는 CLI 명령어뿐만 아니라 Python 코드 내에서 라이브러리로 사용될 수 있다.
[ Python 예제 코드 펼치기 · 접기 ]
#!syntax python
import shutil
import subprocess
from typing import Any, cast

from streamlink import NoPluginError, PluginError, Streamlink
from streamlink.options import Options


def play_stream(url: str, quality: str = 'best') -> None:
    """Streamlink를 사용하여 URL의 스트림을 추출하고 VLC 플레이어로 재생한다.

    Args:
        url: 스트리밍 플랫폼의 방송 주소 (예: twitch.tv/...).
        quality: 희망하는 화질. 기본값은 'best'입니다.
    """
    # 1. 세션 생성 및 전역 옵션 설정
    session = Streamlink()
    session.set_option('http-timeout', 20)
    session.set_option('stream-timeout', 30)

    try:
        # 2. URL 해석 및 플러그인 로드
        plugin_name, plugin_class, resolved_url = session.resolve_url(url)

        # 3. 플러그인별 전용 옵션 설정
        plugin_options = Options()
        if plugin_name == 'twitch':
            plugin_options.set('low-latency', True)

        # 4. 옵션을 주입하여 플러그인 인스턴스 생성
        plugin = plugin_class(session, resolved_url, options=plugin_options)

        # 5. 사용 가능한 스트림 목록 가져오기
        streams = plugin.streams()

        # 6. 메타데이터(제목, 작성자) 추출 - VLC 창 제목 표시용
        try:
            author = plugin.get_author()
            title = plugin.get_title()
            if author and title:
                media_title = f'{author} - {title}'
            else:
                media_title = f'Streamlink - {url}'
        except (PluginError, AttributeError):
            media_title = f'Streamlink - {url}'

    except NoPluginError:
        print(f"오류: '{url}'은(는) 지원되지 않는 주소입니다.")
        return
    except PluginError as e:
        print(f'오류: 플러그인 실행 중 문제가 발생했습니다.\n{e}')
        return

    # 스트림 존재 여부 확인
    if not streams:
        print('오류: 해당 URL에서 스트림을 찾을 수 없습니다. (방송 종료 등)')
        return

    # 7. 화질 선택 로직 (Fallback)
    if quality not in streams:
        available_streams = ', '.join(streams.keys())
        print(f"알림: '{quality}' 화질이 없습니다. 사용 가능: {available_streams}")
        if 'best' in streams:
            print("대신 'best' 화질을 선택합니다.")
            quality = 'best'
        else:
            # best조차 없는 경우(오디오 전용 등) 첫 번째 스트림 선택
            quality = next(iter(streams))
            print(f"대신 '{quality}' 스트림을 선택합니다.")

    print(f'스트림 연결 중... [{quality}]')
    stream = streams[quality]

    # 8. VLC 플레이어 경로 탐색
    vlc_cmd = shutil.which('vlc')
    if not vlc_cmd:
        # Windows 기본 설치 경로 (시스템에 맞게 수정 필요)
        vlc_cmd = r'C:\Program Files\VideoLAN\VLC\vlc.exe'

    # VLC 실행 명령어 구성
    # - : 표준 입력(stdin)으로부터 데이터를 읽음
    vlc_args = [
        vlc_cmd,
        '--meta-title', media_title,
        '-'
    ]

    try:
        # 플레이어 프로세스 시작 (stdin 파이프 개방)
        player_process = subprocess.Popen(
            vlc_args,
            stdin=subprocess.PIPE
        )
    except FileNotFoundError:
        print('오류: VLC 플레이어를 찾을 수 없습니다. 설치 경로를 확인하세요.')
        return

    if player_process.stdin is None:
        print('오류: 플레이어의 표준 입력(stdin) 파이프를 열 수 없습니다.')
        player_process.terminate()
        return

    # [IDE 경고 해결] Any로 캐스팅하여 정적 분석기에게 "모든 타입을 허용함"을 명시
    process_stdin = cast(Any, player_process.stdin)

    # 9. 데이터 파이핑 (Streamlink -> VLC)
    try:
        with stream.open() as fd:
            print(f'재생 시작: {url}')
            print(f'창 제목: {media_title}')

            try:
                # shutil.copyfileobj는 대용량 데이터를 효율적으로 버퍼링하여 복사한다.
                shutil.copyfileobj(fd, process_stdin)
            except BrokenPipeError:
                print('플레이어가 종료되었습니다.')
            except OSError as e:
                # Windows 파이프 종료 이슈(Errno 22) 처리
                if e.errno == 22:
                    print('플레이어가 종료되었습니다. (정상)')
                else:
                    print(f'네트워크 또는 재생 오류 발생: {e}')

    except Exception as e:
        print(f'스트림을 여는 중 오류 발생: {e}')
    finally:
        # 10. 리소스 정리 및 프로세스 종료
        try:
            if player_process.stdin:
                player_process.stdin.close()
        except OSError:
            pass

        if player_process.poll() is None:
            player_process.terminate()
            player_process.wait()
        print('종료되었습니다.')


if __name__ == '__main__':
    _TARGET_URL = 'https://www.twitch.tv/twitch'
    play_stream(_TARGET_URL, quality='1080p60')

이 방식은 디스코드 봇 등에서 방송 알림을 구현할 때 효율적으로 정보를 추출하는 방법으로 쓰일 수 있다.

Streamlink 라이브러리는 이와 같이 스트림을 재생하거나 정보를 추출하는 등 다양한 방식으로 활용될 수 있다. 예를 들면 다음과 같다.
더 자세한 API 사용법은 API 가이드 문서에 설명되어 있다.

7.6.1. 세션 및 옵션 관리

  1. Streamlink 세션 객체를 통해 전역 설정을 관리하고 플러그인을 로드한다.
  2. {{{#!wiki style="@code@" dark-style="@codeds@"
Options}}} 객체를 통해 플러그인별 옵션을 설정한다.
#!syntax python
from streamlink import Streamlink
from streamlink.options import Options

# 1. 세션 생성
session = Streamlink()

# 2. 전역 옵션 설정 (모든 연결에 적용)
# 예: HTTP 타임아웃 20초 설정
session.set_option("http-timeout", 20)

# 프록시 설정 (http-proxy 옵션 하나로 HTTP/HTTPS 모두 적용됨)
session.set_option("http-proxy", "http://127.0.0.1:8080")

# 3. 특정 플러그인 전용 옵션 설정 (Options 객체 활용)
# 예: 트위치 저지연 모드 활성화
twitch_options = Options()
twitch_options.set("low-latency", True)

# 4. 플러그인 로드 및 옵션 적용
# URL에 맞는 플러그인 클래스를 찾고, 위에서 만든 옵션을 주입한다.
plugin_name, plugin_class, resolved_url = session.resolve_url("https://www.twitch.tv/twitch")
plugin = plugin_class(session, resolved_url, options=twitch_options)

이처럼 전역 설정은 세션에서, 플러그인별 고유 설정은
Options
객체에서 별도로 관리함으로써 코드의 유연성을 높일 수 있다.

7.6.2. 데이터 유효성 검사 및 메타데이터 추출

Streamlink는 외부 API의 응답 데이터(JSON, XML 등)를 안전하게 처리하기 위한 유효성 검사 모듈
streamlink.plugin.api.validate
를 내장하고 있다. 이를 사용하면 플러그인에서 가져온 데이터의 형식을 검증하고, 값이 없거나(None) 예상치 못한 타입일 경우를 안전하게 처리할 수 있다.

다음은 입력받은 URL의 스트림 정보를 조회하여 작성자와 제목을 가져오는 예제 코드이다.
[ Python 예제 코드 펼치기 · 접기 ]
#!syntax python
from typing import Any, Dict

from streamlink import NoPluginError, PluginError, Streamlink
from streamlink.plugin.api import validate


def get_stream_metadata(url: str) -> str:
    """URL에서 스트림 메타데이터(작성자, 제목)를 안전하게 추출하여 반환한다.

    Streamlink의 validate 모듈을 사용하여 API 응답 구조를 검증한다.

    Args:
        url: 대상 스트림 URL.

    Returns:
        포맷팅된 메타데이터 문자열 또는 오류 발생 시 에러 메시지.
    """
    session = Streamlink()
    session.set_option('http-timeout', 10)

    try:
        # 플러그인 로드
        _, _, resolved_url = session.resolve_url(url)
        plugin = session.resolve_url(url)[1](session, resolved_url)

        # 1. 원본 메타데이터 추출 (API 호출)
        raw_metadata: Dict[str, Any] = {
            'id': plugin.get_id(),
            'author': plugin.get_author(),
            'title': plugin.get_title()
        }

        # 2. 데이터 유효성 검사 스키마 정의 (Schema)
        # validate.any(type, None)은 값이 해당 타입이거나 None인 경우를 모두 허용한다.
        schema = validate.Schema({
            'id': validate.any(int, str, None),
            'author': validate.any(str, None),
            'title': validate.any(str, None)
        })

        # 3. 검증 실행 (스키마와 맞지 않으면 PluginError 발생)
        data = schema.validate(raw_metadata)

        # 4. 결과 포맷팅 및 반환
        author = data.get('author')
        title = data.get('title')

        if author and title:
            return f'[{author}] {title}'
        if author:
            return f'[{author}] 방송 제목 없음'

        return f'메타데이터 없음 ({url})'

    except NoPluginError:
        return '오류: 지원되지 않는 URL입니다.'
    except PluginError as e:
        return f'오류: 플러그인 실행 중 문제 발생 ({e})'
    except Exception as e:
        return f'알 수 없는 오류: {e}'


if __name__ == '__main__':
    _TARGET_URL = 'https://www.twitch.tv/twitch'
    print(get_stream_metadata(_TARGET_URL))

위 코드는
validate.Schema
를 사용하여 가져온 메타데이터가 문자열(
str
)이거나 값이 없는(
None
) 상태인지 명확히 검증하므로, API 응답이 변경되거나 불안정할 때 발생할 수 있는 프로그램 오류를 방지하는 데 유용하다.

7.6.3. 예외 처리

라이브러리 사용 시 발생할 수 있는 주요 예외(Exception)는 다음과 같다.NoPluginError}}}: 입력한 URL을 처리할 수 있는 플러그인이 없을 때 발생한다.PluginError}}}: API 변경, 파싱 실패 등 플러그인 내부 로직에서 오류가 발생했을 때 발생한다.StreamError}}}: 스트림을 여는 과정이나 데이터 전송 중에 문제가 발생했을 때의 상위 예외 클래스이다.

#!syntax python
from streamlink import Streamlink, NoPluginError, PluginError

session = Streamlink()
try:
    streams = session.streams("https://unsupported-site.com")
except NoPluginError:
    print("지원하지 않는 URL입니다.")
except PluginError as e:
    print(f"플러그인 처리 중 오류 발생: {e}")

7.7. TermuxVLC와 연계

AndroidTermuxVLC 어플리케이션이 설치된 상태에서 Streamlink를 사용하여 스트림을 재생하는 방법이다.
  1. 먼저, Termux를 실행하고 콘솔에 다음과 같이 입력하여 리포지토리를 업데이트한다.
    {{{#!syntax sh
pkg update}}}
  1. 필요한 패키지를 설치한다.
    {{{#!syntax sh
pkg install clang libxslt libxml2 python ffmpeg libsodium}}}
  1. (선택 사항) CFLAGS 환경 변수를 설정한다. (빌드 오류 발생 시)
    {{{#!syntax sh
export CFLAGS="-Wno-incompatible-function-pointer-types -Wno-implicit-function-declaration"}}}
  1. (선택 사항) lxml 라이브러리를 재설치한다. (빌드 오류 발생 시)
    {{{#!syntax sh
pip install lxml --no-cache-dir}}}
  1. streamlink 라이브러리를 설치한다.
    {{{#!syntax sh
pip install streamlink}}}
  1. 다음과 같이 스크립트를 생성한다. (예: {{{#!wiki style="@code@" dark-style="@codeds@"
nano slink}}})
{{{#!folding [ 셸 스크립트 펼치기 · 접기 ]
{{{#!syntax sh
#!/bin/bash
set -e

# 인터페이스 주소 및 포트 설정
INTERFACE=${INTERFACE:-127.0.0.1}
PORT=${PORT:-4567}
# VLC를 플레이어로 지정
PLAYER=${PLAYER:-org.videolan.vlc/org.videolan.vlc.gui.video.VideoPlayerActivity}

# 백그라운드에서 streamlink 실행
streamlink "$@" \
--player-external-http \
--player-external-http-interface "${INTERFACE}" \
--player-external-http-port "${PORT}" \
&

# 방금 실행된 streamlink의 프로세스 pid를 slpid에 저장
slpid=$!
# 스크립트 종료 시 streamlink 프로세스도 종료
trap "kill ${slpid} 2>/dev/null" EXIT

# HTTP 서버가 준비될 때까지 대기
while ! curl output /dev/null silent head fail "http://${INTERFACE}:${PORT}"; do
sleep 0.1
done

# VLC 실행 (Termux Activity Manager; TermuxAm 사용)
am start \
-n "${PLAYER}" \
-a android.intent.action.VIEW \
-d "http://${INTERFACE}:${PORT}"

# 사용자가 아무 키나 누를 때까지 대기
read -n1 -s -r -p "VLC가 실행되었습니다. 아무 키나 누르면 스크립트를 종료합니다..."
# Streamlink 프로세스가 종료될 때까지 대기.
# 사용자가 VLC를 닫거나 스트림이 끝나면 Streamlink도 종료됨
# 이 부분을 주석 해제하면 스크립트가 바로 끝나지 않고 Streamlink 종료를 기다림
# wait $slpid
}}}
}}}
  1. slink 스크립트 파일에 심볼릭 링크를 생성하고 실행 권한을 부여한다. (이때, 기본 홈 디렉토리에 slink 파일이 있다고 가정)
    {{{#!syntax sh
ln -s $HOME/slink $PREFIX/bin/slink
chmod +x slink}}}
  1. slink 파일을 다음과 같이 실행한다. (원격 SSH 셸에서 실행할 경우, Termux가 반드시 포그라운드에 실행되고 있어야 한다.)
    {{{#!syntax sh
slink twitch.tv/twitch best}}}
자세한 사용법은 이 링크 참조.

8. 활용 사례

8.1. 유로 트럭 시뮬레이터 2에서 사용

파일:상세 내용 아이콘.svg   자세한 내용은 유로 트럭 시뮬레이터 2 문서
#!if (문단 == null) == (앵커 == null)
를
#!if 문단 != null & 앵커 == null
의 [[유로 트럭 시뮬레이터 2#s-|]]번 문단을
#!if 문단 == null & 앵커 != null
의 [[유로 트럭 시뮬레이터 2#인터넷 방송을 이용하는 방법|인터넷 방송을 이용하는 방법]] 부분을
참고하십시오.

8.2. 개인 스트리밍 중계 서버 구축

Streamlink가 추출한 스트림을 FFmpeg로 넘겨 실시간으로 HLS(m3u8) 파일로 변환하고, 이를 웹 서버(Nginx, Apache 등)를 통해 송출하면 나만의 개인 중계 서버를 구축할 수 있다.

집 밖에서 데이터 소모를 줄이기 위해 트랜스코딩을 거쳐 저화질로 다시 송출하거나, 지원되지 않는 구형 기기에서 방송을 볼 때 유용하다.
#!syntax sh
streamlink --stdout twitch.tv/twitch best | \
ffmpeg -i - \
  -c:v copy -c:a copy \
  -f hls -hls_time 4 -hls_list_size 5 \
  -hls_flags delete_segments \
  /var/www/html/stream/playlist.m3u8

위와 같이 실행 후, 외부에서 http://서버IP/stream/playlist.m3u8 주소로 접속하여 시청할 수 있다.

8.3. 자동 녹화 환경 구축

Streamlink 명령어와 운영체제의 스케줄링 도구[17]를 결합하여 특정 시간 또는 주기적으로 방송을 자동 녹화하는 환경을 구축할 수 있다.

예를 들어, 매일 특정 시간에 라이브 스트림을 녹화하는 크론탭은 다음과 같이 설정할 수 있다.
#!syntax sh
0 21 * * * streamlink -o "/home/namu/녹화폴더/$(date +\%Y\%m\%d)_방송제목.ts" twitch.tv/채널명 best >> /var/log/stream_record.log 2>&1

또한, 간단한 셸 스크립트나 Powershell 스크립트, Python 코드 등을 작성하여 방송 시작 여부를 주기적으로 활용하고 방송이 시작되면 자동으로 녹화를 시작하도록 구성할 수도 있다.

아래 예제는 치지직 스트림의 온라인 상태를 지속적으로 확인하고 스트리머_연-월-일_시-분-초_화질.mp4 파일로 실시간 녹화하는 간단한 Python 예제 코드이다. FFmpeg가 설치되어 있어야 정상적으로 작동한다.

FFmpeg 설치 방법winget install ffmpeg}}} 또는 EXE 파일 다운로드 후 환경 변수(Path) 설정sudo apt install ffmpeg}}} 등 배포판별 패키지 관리자

[ 자동 녹화 Python 스크립트 펼치기 · 접기 ]
#!syntax python
from datetime import datetime
from http.client import HTTPException
import shutil
import subprocess
import time
from typing import Any, Optional, cast

import requests
from streamlink import Streamlink, StreamError

# 브라우저처럼 보이게 하는 HTTP 헤더 상수 (모듈 레벨 상수)
_HEADERS = {
    'User-Agent': (
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0) '
        'Gecko/20100101 Firefox/145.0'
    ),
    'Accept': 'application/json, text/plain, */*'
}


def validate_channel(request_id: str) -> Optional[str]:
    """채널 ID가 유효한지 확인하고 채널명을 반환한다.

    Args:
        request_id: 치지직 채널 고유 ID.

    Returns:
        유효한 경우 채널명을 반환하고, 그렇지 않으면 None을 반환한다.
    """
    api_url = f'https://api.chzzk.naver.com/service/v1/channels/{request_id}'

    try:
        response = requests.get(api_url, headers=_HEADERS, timeout=10)
        response.raise_for_status()
        content = response.json().get('content', {})

        if not content.get('channelId'):
            return None
        return content.get('channelName')
    except (requests.RequestException, HTTPException) as e:
        print(f'채널 확인 중 에러 발생: {e}')
        return None


def wait_online_state(request_id: str) -> str:
    """방송이 시작될 때까지 10초 간격으로 상태를 확인(Polling)한다.

    Args:
        request_id: 치지직 채널 고유 ID.

    Returns:
        방송이 시작되면 방송 제목을 반환한다.
    """
    channel_url = f'https://api.chzzk.naver.com/service/v1/channels/{request_id}'
    live_url = (
        f'https://api.chzzk.naver.com/polling/v2/channels/{request_id}/live-status'
    )

    while True:
        try:
            # 1. 채널 상태 확인 (Live 여부 flag)
            response = requests.get(channel_url, headers=_HEADERS, timeout=10)
            response.raise_for_status()
            channel_content = response.json().get('content', {})

            if channel_content.get('openLive'):
                # 2. 방송 상세 정보 확인 (제목 등)
                response = requests.get(live_url, headers=_HEADERS, timeout=10)
                response.raise_for_status()
                live_content = response.json().get('content', {})

                title = live_content.get('liveTitle', '제목 없음')
                print(f'방송 시작 감지! (제목: {title})')
                return title

            print('방송 오프라인... 10초 후 재확인')
            time.sleep(10)
        except Exception as e:
            print(f'상태 확인 중 오류 발생: {e}')
            time.sleep(10)


def streamlink_record(
    request_id: str,
    quality: str = 'best',
    stream_author: str = '',
    stream_title: str = ''
) -> None:
    """Streamlink로 스트림을 추출하고 FFmpeg를 통해 실시간 MP4 파일로 저장한다.

    Args:
        request_id: 채널 ID.
        quality: 희망 화질. 기본값은 'best'입니다.
        stream_author: 메타데이터용 스트리머 이름.
        stream_title: 메타데이터용 방송 제목.
    """
    # FFmpeg 설치 여부 확인
    if not shutil.which('ffmpeg'):
        print('오류: FFmpeg가 설치되어 있지 않거나 PATH 환경변수에 없습니다.')
        return

    url = f'https://chzzk.naver.com/live/{request_id}'

    # 세션 생성 및 HTTP 헤더 설정
    session = Streamlink()
    session.set_option('http-headers', _HEADERS)
    session.set_option('http-timeout', 30)

    try:
        print('스트림 정보를 가져오는 중...')
        streams = session.streams(url)
    except StreamError as e:
        print(f'스트림 열기 실패: {e}')
        return

    if not streams:
        print('활성화된 스트림을 찾을 수 없습니다.')
        return

    # 화질 선택 로직 (Fallback 지원)
    if quality not in streams:
        available = ', '.join(streams.keys())
        print(f"알림: '{quality}' 화질이 없습니다. 사용 가능: {available}")
        if 'best' in streams:
            print("대신 'best' 화질로 녹화를 시도합니다.")
            quality = 'best'
        else:
            quality = next(iter(streams))
            print(f"대신 '{quality}' 화질을 선택합니다.")

    stream = streams[quality]
    timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
    filename = f'{stream_author}_{timestamp}_{quality}.mp4'

    print(f'녹화 시작 (FFmpeg 연동): {filename}')

    # FFmpeg 명령어 구성
    # -c copy: 재인코딩 없이 복사 (CPU 부하 최소화)
    # -metadata: 파일 속성에 제목 및 아티스트 정보 삽입
    ffmpeg_cmd = [
        'ffmpeg',
        '-y',                 # 파일 덮어쓰기
        '-loglevel', 'error', # 로그 최소화
        '-i', '-',            # stdin 입력
        '-c', 'copy',         # 스트림 복사
        '-metadata', f'title={stream_title}',
        '-metadata', f'artist={stream_author}',
        '-f', 'mp4',          # MP4 포맷 강제
        filename
    ]

    ffmpeg_process = None

    try:
        # FFmpeg 프로세스 시작 (stdin 파이프 개방)
        ffmpeg_process = subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE)

        if ffmpeg_process.stdin is None:
            print('FFmpeg 파이프를 열 수 없습니다.')
            return

        # IDE 타입 경고 방지
        process_stdin = cast(Any, ffmpeg_process.stdin)

        # Streamlink 데이터를 FFmpeg로 파이핑 (실시간 저장)
        with stream.open() as fd:
            shutil.copyfileobj(fd, process_stdin)

    except KeyboardInterrupt:
        print('\n사용자에 의해 녹화가 중단되었습니다. 저장 중인 파일을 마무리합니다...')
    except OSError as e:
        # 파이프가 깨진 경우(Broken pipe)는 정상 종료로 간주할 수 있음
        if e.errno == 22 or e.errno == 32:
            pass
        else:
            print(f'파일 쓰기 또는 네트워크 오류 발생: {e}')
    finally:
        # 프로세스 및 파일 안전 종료 처리 (Moov atom 기록 보장)
        if ffmpeg_process:
            if ffmpeg_process.stdin:
                try:
                    ffmpeg_process.stdin.close()
                except OSError:
                    pass
            ffmpeg_process.wait()

        print('녹화가 종료되었습니다.')


if __name__ == '__main__':
    # 치지직 채널 고유 ID 입력 (URL의 마지막 부분)
    _CHANNEL_ID = '치지직_채널_ID'

    # 1. 채널 유효성 검사
    _author = validate_channel(_CHANNEL_ID)
    if not _author:
        print('유효하지 않은 채널입니다.')
        exit(1)

    # 2. 방송 시작 대기 (Polling)
    _title = wait_online_state(_CHANNEL_ID)

    # 3. 녹화 시작
    streamlink_record(
        _CHANNEL_ID,
        quality='1080p',
        stream_author=_author,
        stream_title=_title
    )

9. 여담

--loglevel debug}}} 옵션으로 상세 로그와 관련 플러그인 GitHub 이슈 등을 확인하면 된다.

10. 관련 문서

11. 외부 링크


[1] Streamlink 프로젝트가 Livestreamer로부터 포크(fork)되어 GitHub에 0.0.1 버전을 커밋한 시점을 기준으로 한다.[2] 실시간 방송의 경우, 채널 정책이나 기술적 변경으로 인해 간헐적으로 지원이 불안정할 수 있다. 일반 동영상은 yt-dlp 등 다른 도구가 더 적합할 수 있다.[3] 1080p60을 먼저 찾고, 없으면 1080p, 그것도 없으면 시청 가능한 최고 화질(best)을 자동으로 선택한다. 녹화 스크립트를 짤 때 매우 유용한 기능이다.[4] Linux 환경의 경우, Flatpak으로 설치된 VLC나 mpv도 자동으로 감지한다.[5] Linux 환경의 경우, Flatpak으로 설치된 VLC나 mpv도 자동으로 감지한다.[6] 플레이어에 전달할 스트림의 제목[7] 설치된 Python 버전에 따라 경로가 다를 수 있다.[8] 아무것도 출력하지 않는다.[9] 프로세스를 중지시킬 수 있는 치명적인 오류만을 출력한다.[10] 프로세스의 중지 원인이 된 치명적인 오류만을 출력한다.[11] 복구할 수 있는 오류를 포함한 모든 오류를 출력한다.[12] 잘못될 가능성이 있거나 예상치 못한 이벤트와 관련된 경고와 오류를 출력한다.[13] 경고와 오류를 포함한 정보성 내용을 출력한다.[14] 'info'보다 조금 더 자세히 출력한다.[15] 디버깅 정보를 포함한 모든 내용을 출력한다.[16] 원본 코덱을 유지한다.[17] Unix/Linux의 cron, Windows의 작업 스케줄러 등