-
use livestream_saver to download from the first segment. Can also record membership-only streams by supplying it your cookies (uses yt-dlp to download)
-
use ytarchive which basically does the same thing, except a bit better.
-
use youtube_stream_capture. You can use cookies file to get member-only streams too. Be aware that this script currently fails to download chunks as soon as the stream has ended (this might be a bug).
-
or use live-dl which does monitoring of streams too. This is a wrapper around streamlink and yt-dlp.
If you know a program that downloads chat messages while the stream is live, please leave a comment.
Currently, the only reliable way of downloading chat messages is to use yt-dlp with the following arguments to generate a JSON file. The JSON file can be compressed afterward. For example: bzip2 *.json
.
yt-dlp --skip-download --write-subs --sub-langs "live_chat" -o "%(upload_date)s [%(uploader)s] %(title)s [%(id)s].%(ext)s" <video_id>
Known downside: this only works after the video has become a VOD, it won't work during live stream.
This is an example script that does this automatically: glubsy/ytdl_batch/subs.py
- streamlink, to download from the segment being broadcast currently
- yt-dlp which downloads from the first segment BUT stops downloading once it reaches the currently broadcast segment (or maybe there is a way to avoid this, in which case, leave a comment).
A reliable way to get the best quality and not miss any data currently is this:
-
(RECOMMENDED) run streamlink in a loop with save_livestream.py script to download [x% ----> 100%]. Setting the retry delay to about 1 minute reduces the chance of missing a big chunk of the beginning of a stream, so this solution should be enough for now.
-
run yt-dlp to download from the beginning but lose the rest [0% ----> x%]. A script to handle this better would be nice.
-
Note: better download the best video quality possible for two reasons. 1) Audio quality depends on video quality ("progressive" streams) 2) Lower resolutions on Twitch are very poorly compressed, so it is better to compress ourselves.
-
Streams downloaded by streamlink-based solutions are in TS format which may cause issues with some players or when uploading to VOD services. You might want to convert them to mp4 (or whatever container you prefer) with ffmpeg like so:
ffmpeg -i twitch_live.ts -c copy twitch_live.mp4
-
If you get warnings from streamlink saying
Encountered a stream discontinuity. This is unsupported and will result in incoherent output data
, the resulting .ts file will be corrupted. This is because of ads served by Twitch. The only way to avoid this is to pay the streamer for a subscription, then pass the following argument to streamlink:--twitch-api-header 'Authorization=OAuth YOUR_TOKEN'
. You can get the header from your web browser's devtool while logged into Twitch. You can pass this argument to the save_livestream.py script by calling it like this:
python3 livestream_scripts/save_livestream.py --author-name 'nanobites' https://www.twitch.tv/nanobites_ "--twitch-api-header 'Authorization=OAuth YOUR_TOKEN'"
If you know a program that downloads chat messages while the stream is live, please leave a comment.
Once a stream has become a VOD, you may use TwitchDownloader. You can embed the emoticons inside the resulting chat log for archival purposes with the -E
or --embed-images
parameter.
For example:
TwitchDownloader chatdownload --id $video_Id -E -o $video_Id.json
This is an example script that does this automatically: glubsy/ytdl_batch/subs.py
In order to concatenate the videos (and audio) you will most likely need to fix the container files.
Example case: we have two recordings of the same live stream, one partial from the start, and one full but with muted audio segments. Exactly same audio and video codecs (1080p x264/aac). First, split the full video file at the (shared) junction timestamp.
# ffmpeg -i full.mp4 -ss 1:06:36.0 -c copy full_split.mp4
To avoid the "Non-monotonous DTS in output stream", we have to fix the containers by recreating them (do it for all of them just in case), use "-fflags +igndts" to regenerate DTS based on PTS:
# ffmpeg -i full_split.mp4 -fflags +igndts -c copy -movflags +faststart full_split_dts_fix.mp4
# ffmpeg -i start.mp4 -fflags +igndts -c copy -movflags +faststart start_dts_fix.mp4
Then concatenate with the concat demuxer as normal (create list.txt with files to concatenate)
# ffmpeg -f concat -safe 0 -i list.txt -c copy -movflags +faststart final_full.mp4
Then compress the video, but keep audio (and reduce fps from 60 to 30 while we are at it):
# ffmpeg -i final_full -c:v libx264 -crf 30 -vf scale=iw/3:ih/3 -c:a copy -r 30 final_compressed.mp4
To extract from Firefox you may use this: https://github.com/rotemdan/ExportCookies (add-on page)
To extract from Chromium-based browsers: https://github.com/dandv/convert-chrome-cookies-to-netscape-format
If you use streamlink, you may want to avoid passing cookies as arguments, in which case you can create the following file ~/.config/streamlink/config.twitch
:
twitch-api-header=Authorization=OAuth <auth_token value>
This is especially useful if you use the save_livestream.py
script mentioned above.
As of 2023/07/20, the
/live
tab in Youtube is redirecting to/streams
, which unfortunately breaks the following yt-dlp based solution: