Skip to content

Instantly share code, notes, and snippets.

@curioustorvald
Last active February 27, 2024 15:00
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save curioustorvald/777dd08ff8b2cf18253dffc0ab14f47c to your computer and use it in GitHub Desktop.
Save curioustorvald/777dd08ff8b2cf18253dffc0ab14f47c to your computer and use it in GitHub Desktop.
How to record twitch live streaming PROPERLY

송출이 불안정한 스트리머의 방송을 최소한의 딜레이로 녹화하도록 만들어진 녹화 스크립트입니다. 호스팅 채널을 녹화하지 않고, TS파일을 직접 저장합니다.

이 스크립트는 24/7 상시감시 및 녹화를 위해 준비된 스크립트이고 설정 과정에서 약간의 프로그래밍적 지식이 필요합니다. 단타성 녹화를 원한다면 더 단순한 거 찾아다 쓰십쇼.

치지직용 스크립트를 테스트하고 있습니다. 여러분의 많은 기여가 필요합니다 🙏🙏

세팅하기 전에

윈도에서도 작동은 하겠지만, 진짜 봇을 구축하려면 이 글의 작성자는 리눅스를 사용하는 걸 추천합니다. 리눅스를 쓰는 이유는, 적어도 얘는 업데이트 있다고 지멋대로 재부팅하지는 않으니까요 (대충 트위치 카파 콘)

의존성 해결

python3와 streamlink가 설치되어야 합니다.

  1. 리눅스: 터미널 창에서 sudo apt install python3 (혹은 자신의 리눅스 배포판에 맞는 명령어) 를 실행해 파이썬3을 설치하세요. 윈도: 이 주소로 이동해 파이썬3를 설치하세요.
  2. PIP을 사용해 pip install --user streamlink를 실행하여 streamlink를 설치해주세요. (이대로 하지 않으면 엄청 구버전이 설치됩니다)
  3. 터미널 창에서 streamlink --version을 입력해 설치된 버전을 확인해주세요. 4.2.0 이상 버전이어야 합니다!

트위치 API를 사용하기 위한 Client ID 취득

트위치 API의 정책 변경으로 인해 OAuth 토큰이 필요하고, 이를 위해 Client ID를 발급받아야 합니다.

  1. 녹화 스크립트 소스코드를 다운받아 적당한 곳에 저장합니다.
  2. 트위치 개발자 콘솔에 접속해 앱을 먼저 등록합니다. (녹화 스크립트도 트위치의 시점에서는 제삼자 앱이기 때문에 토큰 발급을 위해 등록이 필요합니다) Name란에는 twitch라는 단어를 포함하지 않는 적당한 이름 (예: my_streaming_tool_test), OAuth Redirect URLs란에는 http://localhost, Category는 적당한 것을 선택하고 MrDestructoid이(가) 아님을 인증한 다음 Create를 눌러주세요
  3. Developer Applications 하에 방금 등록한 앱 이름이 있을 것입니다. 우측의 Manage를 누릅니다.
  4. Client ID를 복사해 녹화 스크립트의 TWITCH_API_CLIENT_ID에 붙여넣기해 주세요.
  5. New Secret 버튼을 눌러 Client Secret을 발급받아 녹화 스크립트의 TWITCH_API_CLIENT_SECRET에 붙여넣기해 주세요.
  6. 수정된 녹화 스크립트를 저장해 주세요.

여기서 발급된 Client ID와 Client Secret은 개인에게 발급된 비밀번호와 같은 것으로 타인과 공유하여서는 안 됩니다.

녹화 스크립트 사용자화

  • RECORDING_SAVE_ROOT_DIR: 녹화본이 저장되는 루트 디렉토리를 지정합니다. NAS에서 구동시키는 경우 /srv/nfs/twitchrecords 정도가 적당하겠지요. 녹화 스크립트가 저장돼있는 디렉토리를 사용하려면 ./를 입력해주세요.
  • FILE_NAME_FORMATTIME_FORMAT: 녹화되는 파일의 이름 형식을 지정합니다. 기본값은 이전 버전 녹화 스크립트와 동일하게 설정돼있습니다.

녹화 세팅

python 녹화스크립트.py -u 스트리머_아이디

녹화스크립트.py에는 저장된 녹화스크립트의 파일명을 입력하고 (.py는 떼면 안 됩니다!) 스트리머_아이디에는 녹화하고자 하는 스트리머의 이름이 아닌 스트리머의 트위치 아이디를 입력합니다. (예: 똘똘똘이_jungtaejune)

위의 명령어를 시스템이 부팅되면 자동으로 실행되도록 합니다. 윈도 사용자는 윈도용 bat 파일을 만들어 시작프로그램에 등록하면 되고, 리눅스 사용자는 사용하는 배포판에 맞게 설정해주세요. (.bashrc에 등록하기보다는 자신이 사용하는 데스크탑 환경 — KDE라던지 GNOME이라던지 — 에서 제공하는 방법을 사용하십시오)

위와 같이 세팅한 후 재부팅하면 자동으로 녹화가 이루어질 겁니다.

후처리

Streamlink를 업그레이드하려면 터미널 창에서 pip install --user --upgrade streamlink를 실행하여 주세요.

그냥 다시보기만 할 때는 후처리가 필요 없습니다. 그냥 TS파일 그대로 재생해서 보면 됩니다.

-트-가 -트-해서 (혹은 야방이어서) 녹화가 2개 이상으로 조각날 때가 있습니다. 그럴 때는 TS파일을 그냥 합쳐버리면 됩니다: cat 영상조각1.ts 영상조각2.ts 영상조각3.ts ... > 온전한영상.ts

이 글은 다음의 위치에서도 볼 수 있습니다:

자주 묻는 질문

  • ImportError: no module named requests
    • 터미널 창에서 pip install --user requests를 사용해 모듈을 설치해 주세요.
  • unrecognized arguments: twitch.tv/
    • 아래의 알려진 버그 — Windows에서 Streamlink 2.x를 3.x로 업그레이드 시 주의할 점을 봐 주세요.

트위치 한국발 접속의 720p 제한 우회하기

녹화 스크립트를 이 코드로 바꾸어 시도해 보세요. (외부 API를 사용해 일본 서버에서 m3u8 링크를 받아와서 작동합니다. Yoon0618님 제공)

알려진 버그

Windows에서 Streamlink 2.x를 3.x로 업그레이드 시 주의할 점

Streamlink가 2.x버전에서 3.0으로 업그레이드 되면서 기본설정이 바뀌었는데, 업그레이드 후 rtmp-rtmpdump 오류 혹은 unrecognized arguments: twitch.tv/ 오류가 발생할 수 있습니다. 이런 경우에는 Streamlink를 업그레이드한 다음, Streamlink의 설정파일을 만져줘야 합니다.

윈도키+R → %APPDATA% 입력후 엔터 → streamlink 폴더 → config 파일 메모장으로 열기 → rtmp-rtmpdump가 있는 줄 삭제 (한 개가 아닙니다!)

자세한 정보는 아래에서 확인할 수 있습니다:

스트리머가 설정한 최고 화질로 녹화가 이루어지지 않는 경우

Twitch 쪽에서 화질 옵션을 이상한 형식으로 반환하는 문제가 있기 때문에 간헐적으로 1080p로 송출중인 방송이 720p로 녹화되는 경우가 간혹 있습니다. 이러한 경우에는 Streamlink를 4.2.0 이상 버전으로 업데이트해 주세요.

자세한 정보는 아래에서 확인할 수 있습니다:

@letitbe5863
Copy link

녹화가 잘되다가 간헐적으로 'filtering out segments and pausing stream output' 라는 문구가뜨면서
이어받기가 되는데 그부분이 몇초간 뛰어넘고 받아지는 현상이 나타나네요
스트림링크도 최신버전으로 업데이트 했는데
스트림링크와 광고가 관련된 문제일까요?

@curioustorvald
Copy link
Author

광고 문제는 현재로서는 Streamlink쪽에서 해결해줘야 하는 문제입니다. 저도 녹화본에 간헐적으로 광고 안내가 삽입되고 있습니닷 🥲🥲

@leeshey
Copy link

leeshey commented Dec 6, 2022

TIME_FORMAT 의 %y 가 해당 연도의 끝 2자리만 표시되는데, 전체 자리(4자리)로 표시되게 하여 저장하는 방법은 없을까요?
%m 과 %d 는 2자리로 표시되어서 편합니다
yyyy mm dd 형식으로의 저장하는 방법을 알고 싶습니다

@curioustorvald
Copy link
Author

@Shey3750 %Y(대문자)를 사용해보십셔

@leeshey
Copy link

leeshey commented Dec 7, 2022

@curioustorvald 감사합니다! 해결했스빈다

@leeshey
Copy link

leeshey commented Dec 8, 2022

csrss_M4vjydxdox
녹화 중단을 위해 .bat 창을 닫았을 때, 위와 같은 사진의 오류가 나타납니다.
twitch-recorder-direct-japan.py 를 사용하는데, py파일 또는 bat파일의 문제일까요? 아니면 streamlink자체의 문제일까요..
'확인' 버튼을 눌러 오류 창을 닫으면 몇 초 내로 다시 창이 다시 나타납니다.
py 파일을 약간 수정해서 새로고침 타이밍을 줄였는데, 그것이 문제되나 잘 모르겠습니다

@sonseh
Copy link

sonseh commented Dec 8, 2022

@leeshey 저도 노트북 2대 중 한대에서 겪은 현상인데 .bat파일을 꺼도 재부팅 안하면 몇초마다 반복해서 같은 오류창이 떴습니다. 결국 원인은 못찾았는데 윈도우 10 노트북이 괜찮고 윈도우 11 노트북이 오류가 발생해서 의심만 해봅니다.

@SAKARETE
Copy link

올려주신 방법 다시보기 없어질 때를 대비하면서 정말 유용하게 잘 쓰고 있습니다.

다운로드 된 ts파일이 어떨때는 60fps로 녹화되고 어떨 때는 1000fps으로 녹화되어 편집이 불가능한데 이는 streamlink쪽 오류로 봐야할가요?

@kirk514
Copy link

kirk514 commented Dec 12, 2022

파이썬은 잘 모르는 초보자입니다. 그냥 제 추측으로는 일본 경유로 m3u8주소를 받아올경우 이 주소가 트위치 주소와는 전혀 상관없는 주소처럼 나오기 때문에 스트림링크의 트위치 광고 스킵이 먹히지 않는것 아닌가 이런 추측을 해봅니다. 만약 이게 맞다면 스트림링크에서 광고 스킵 필터를 공용으로 하나 설정을 해줘야 할텐데... 이게 가능성이 있을지 모르겠네요

@ty-kwon
Copy link

ty-kwon commented Dec 12, 2022

용량 이슈로 720p로 받고자 하는데 main부의 parser.add_argument("-q", "--quality", default="best")에서 best를 어떻게 수정해야할까요?

@eat-kiwi
Copy link

안녕하세요. 해당 기능을 사용하기 앞서 여쭈어보고 싶은 부분이 있습니다.
혹시 여러 스트리머들의 방송을 녹화하고 싶은 경우 이에 대한 코드 처리를 어떻게 하면 되는지 여쭈어뵙니다.

예를 들어 ABC 라는 스트리머와 DEF 라는 스트리머가 있고 이들의 방송을 녹화하고 싶다면
python 녹화스크립트.py -u ABC, DEF 로 하면 되는 것인지 아니면 개별적으로 코드를 하여 python 녹화스크립트.py -u ABC, python 녹화스크립트.py -u DEF 로 하면 되는지 여쭈어뵙니다.

@Hypertension-12
Copy link

시놀로지 NAS에서 돌리려고 하는데 혹시 NAS에서 돌리는 방법도 알려주실 수 있나요?

@wkd8176
Copy link

wkd8176 commented Dec 13, 2022

.... 형... 졸라 사랑해...
코드 짜려고 했는데 형 덕분에 오늘 저녁을 벌었네

@curioustorvald
Copy link
Author

@ty-kwon 녹화봇의 호출을 python 녹화스크립트.py -u 스트리머_아이디 -q 720p로 하면 될 겁니다

@curioustorvald
Copy link
Author

@Hypertension-12 시놀로지NAS를 써본 적이 없어서 저는 답변이 힘들 것 같네요 😅😅

@wkd8176
Copy link

wkd8176 commented Dec 13, 2022

시놀로지 NAS에서 돌리려고 하는데 혹시 NAS에서 돌리는 방법도 알려주실 수 있나요?

Docker 쓰실 줄 아시면 Docker에 우분투 이미지 설치하고 리눅스 방법 따라하시면 깔끔하게 가능합니다

@ty-kwon
Copy link

ty-kwon commented Dec 25, 2022

오늘까지도 720p 셋팅해서 잘 쓰고 있습니다. 감사합니다.

혹시 아직도 일본 우회 1080p의 시작부와 중간의 간혈적 광고 삽입은 해결이 안된걸까요?

@K-noob
Copy link

K-noob commented Dec 26, 2022

일본 우회버전으로 잘 사용하고 있습니다.\


그런데 최근들어 다운로드된 영상이 깨지는 경우가 좀 심각하게 많아지기 시작했습니다. 영상 중간중간 오디오는 정상 재생되지만 영상이 약 1분여간 날아가는 경우도 생기고, 심한경우 영상의 플레이타임이 늘어지는 버그도 생기기도 합니다. 타 프로그램으로 영상복구를 돌려도 영상 싱크가 밀립니다. 이에 대한 해결방법이 있을까요?

그리고 트위치에서 구독하고 있는 스트리머의 영상을 다운받는 경우에도 종종 광고 대체영상이 삽입되곤 합니다. 코드에 넣는 토큰이랑 개인 인식코드는 다른것인가요? 아니면 단순 버그로 봐야할까요?

해당문제는 구독 이후 토큰 재발행으로 해결되었습니다. 같은 문제를 겪고 계실 분이 있을까 해서 남겨봅니다.

위 문제 해결 이후 새로운 문제가 생겼습니다. 모든 영상이 초반 10분이 완전히 망가져 복구가 불가능합니다. 이후 영상은 전부 멀쩡히 재생이 됩니다.

스트림링크 버전은 5.0.1로 확인됩니다. 업그레이드 명령어를 입력해도 다운로드 이후 계속 5.0.1로 표기되는 상황입니다.

현재 인텔 8세대, 16기가 램, rax20 공유기 사용중입니다. 따로 오버클럭이나 공유기 프록시 등은 설정하지 않았습니다. 혹시 오류에 하드웨어 사양이 포함되면 좋을까 해서 남겨봅니다.

초보라 질문을 제대로 한 것인지 조차 잘 모르겠습니다. 죄송합니다.

@red-crate
Copy link

한국에서 일본, 홍콩 등 외국서버 접속을 차단하는 업데이트가 이루어졌다고 합니다.
따라서 일본 우회 소스로 이용하시는 분은 오류가 날 것입니다.
원본으로 돌리시면 되는데, subprocess.call에서 m3u8_link로 호출하는부분을 원래대로만 바꾸시면 다시 녹화가 됩니다.
물론 720p제한입니다.

@MilkClouds
Copy link

MilkClouds commented Jan 31, 2023

아나콘다 환경에서 돌리시는 분들 있으면 윈도우즈 배치파일은 아래와 같이 실행하시면 될 것 같습니다.

set root=C:\tools\Anaconda3
call %root%\Scripts\activate.bat %root%
python downloader_threadpool.py
pause

activate.bat 이후 %root% 부분을 원하는 아나콘다 환경 경로로 바꿔주면 됩니다.

그리고 병렬 다운로드 원하면 아래와 같이 구성하면 되는데 트위치 api rate limit에 안 걸리게 사용하셔야 합니다.

from multiprocessing.pool import ThreadPool
# ~~중략~~
    def record(username, quality):
        recorder = TwitchRecorder(username, quality)
        recorder.run()
    pool = ThreadPool()
    streamers = ("a", "b", "c")
    pool.starmap(record, ((streamer, "best") for streamer in streamers))

@PCBiS
Copy link

PCBiS commented Feb 10, 2023

해당 스크립트 잘 쓰고 있습니다. 혹시 현 시점에서 1080p 레코딩 진행할 방법이 Full VPN 태우는 방법 이외엔 없는걸까요?

@Helix-hy
Copy link

3

어찌저찌 따라해서 다운로드 하는것까지 성공하긴 했는데 다운로드 하면 시작부분 15초정도 저런영상 다들어가고 중간에도 저런화면이 한번씩 나오는데 이건 제거 못하나요 ? 트위치에서 광고나오는 시간에 저런화면이 뜨는거같은데 구독도 했는데 저렇게 돼서 해결하고싶어서요 ㅠ

위에 글들 보니까 213번째 줄인가 거기에 토큰 넣으니까 광고 안나온다고해서

ret = subprocess.call(["streamlink", "--twitch-disable-hosting", "twitch-api-header=Authorization=OAuth ", "--twitch-disable-ads", "twitch.tv/" + self.username, self.quality, "-o", file_path])

저렇게 해놓고 OAuth 뒤에 30자 토큰 써넣어도 저렇게 나와서 어떻게 해야하나싶어요..

녹화할때는 python recorder.py -u 스트리머닉네임 이렇게 쓰고있고

녹화는 시놀로지에 도커를 이용해서 녹화하고있어요 도와주십쇼 ㅠㅠ

@sonseh
Copy link

sonseh commented Mar 18, 2023

@Helix-hy 코드 중간에 이렇게 수정해보세요.
"--twitch-api-header", "Authorization=OAuth 30자토큰입력부분", "twitch.tv/"

@Helix-hy
Copy link

Helix-hy commented Mar 18, 2023

@sonseh 213번째줄을 # ret = subprocess.call(["streamlink", "--twitch-disable-hosting", "--twitch-api-header", "Authorization=OAuth 30자 토큰", "twitch.tv/" + self.username, self.quality, "-o", file_path]) 이렇게 수정을 했는데 계속 나와요
"--twitch-api-header", "Authorization=OAuth 30자토큰입력부분", "twitch.tv/" 이렇게 수정을 하라고 해서 30자토큰이랑 "twitch.tv/" 사이에있는 "--twitch-disable-ads" 이걸 지우고 해봤는데 또 앞에 저렇게 나오길래

ret = subprocess.call(["streamlink", "--twitch-disable-hosting", "--twitch-disable-ads", "--twitch-api-header", "Authorization=OAuth 30자토큰", "twitch.tv/" + self.username, self.quality, "-o", file_path]) 이렇게 api-header 앞에 쓰긴 했었는데 이렇게 하고 해봐도 저렇게 생기더라구요

@meamde
Copy link

meamde commented Mar 19, 2023

@Helix-hy

뭔가 이상한데서 꼬이는거 같아서 다음과 같이 바꾸니 제대로 광고스킵되고 정상동작합니다.
전 시놀로지에서 VPN 다중게이트웨이 걸어두고 1080p 녹화중입니다. (스크립트가 아니라 VPN우회)

213번째 줄

ret = subprocess.call(f"streamlink --twitch-disable-hosting --twitch-disable-ads --twitch-api-header \"Authorization={self.oauth_token}\" twitch.tv/{self.username} {self.quality} -o \"{file_path}\"", shell=True)

이렇게 리스트 안쓰고 전체 url, shell=True 옵션주고, 밑부분에 215~220번 줄(#get m3u8 link... ~ ret = subprocess...)은 주석처리후 사용중입니다.
Auth 토큰 부분에 OAuth 안쓰고 코드 윗부분에서 발급받은 Bearer 토큰 그대로 저렇게 박아넣으니 정상동작하네요.

@Helix-hy
Copy link

@meamde 제가 진짜 컴퓨터 게임만 하고 이런걸 안해서 전혀 몰라서 개고생 하고 있었는데 써주신글 읽다가 주석처리 라는 글을보고 해결 했습니다 ! 구글링 하다보니 213번째줄에 이것저것 추가하면 된다 해서 했었는데 안되더라구요 그래서 질문하고 혼자 몇일을 찾아보고 이것저것 개고생 했었는데 드디어 해결 했습니다. c언어같은걸 전혀 모르다보니 # 이거 있으면 주석처리돼서 인식이 안된다 이걸 몰라서 고생했던거였네요 .. 본문에 있는 녹화 스크립트 소스코드 저거 받아서 무작정 따라 했던거였는데 저기 213번째줄에 # 으로 주석처리 되어있고 215줄이 주석처리가 안되어있어서 본문 대로라면 215번째 줄에다가 문구를 추가 했어야했는데 주석처리 되어있는 213번째 줄에 계속 수정만 해댔으니 항상 광고가 나왔었던거같아요ㅎㅎ 덕분에 하나 배워갑니다 그리고 저도 1080p로 녹화하려고 openvpn써서 하고있는데 다중게이트웨이랑 다른방법인지는 모르겠지만 또 해볼게 생긴거 같네요 ㅋㅋ 도와주셔서 감사합니다

@caca0408
Copy link

안녕하세요, 윗분과 마찬가지로 213번째줄을 수정해 광고 제거를 하려고 스크립트 수정을 하여 녹화 중 입니다. 그런데 이전에는 없던 문제가 발생하여 질문 드립니다. 이전에는 60프레임으로 녹화 되었는데, 저 보라색 화면이 뜬 뒤로는 (=213번줄 수정 후) 1000프레임으로 녹화되어 해결 방법을 모르겠어서 댓글 남깁니다. 도와주시면 감사하겠습니다 :)

@Helix-hy
Copy link

@caca0408 저도 따라하기만 한거라 잘은 모르지만 전 213번째줄을 #으로 주석처리해서 안쓰고 위에 meamde님이 써주신 ret = 저 코드를 215번째줄에 그대로 붙여넣기를 해서 사용하고 있습니다.

@Helix-hy
Copy link

@meamde 따라해서 저번에 있던 광고 이미지는 없어졌는데 이번에 녹화한거 확인해보니까 중간에 광고들어가는부분이 되면 광고는 안나오는데 화면이 멈추면서 소리가 광고가 끝난후 인거같은부분부터 소리가 나고 조금있으면 영상 빨리감기 한것처럼 되면서 싱크가 맞춰지는데 혹시 토큰쓰면 이런현상도 없앨수있나요 ? 구독 되어있는데도 이런현상이 있더라구요 만약 토큰을 써야한다면 어디부분에 토큰을 써야할까요 ?

@Scorps0530
Copy link

Scorps0530 commented Jun 1, 2023

2023-06-01 22:50:05,470 INFO root The video will be saved on 파일위치
[cli][info] Found matching plugin twitch for URL twitch.tv/스트리머이름
error: No playable streams found on this URL: twitch.tv/스트리머이름
2023-06-01 22:50:06,470 WARNING root Unexpected error. Will try again in 5 seconds.
이것처럼 오류가 뜨는데 왜 이럴까요?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment