Here's another idea. Record the live stream direction, code stolen shamelessly from here
I wanted to download a youtube stream from https://www.youtube.com/watch?v=0R0T0mQmx7I adding the amount of time that I like. Therefore using youtube-dl, I get all its formats: $ youtube-dl --list-
superuser.com
https://archive.vn/wip/pE2JN
Consider the following function (I took out the -t 00:02:00 because I want to grab the whole thing, not just 2 minutes)
Bash:
function yt_record
{
ffmpeg -i $(youtube-dl -f 91 -g ${1}) \
-i $(youtube-dl -f 95 -g ${1} ) \
-c:v copy -c:a aac -strict experimental output.mp4
}
I tested it with this which was live at the time of writing
https://www.youtube.com/watch?v=d4ZV2zCq848
Code:
$ youtube-dl -F https://www.youtube.com/watch?v=d4ZV2zCq848
[youtube] d4ZV2zCq848: Downloading webpage
[youtube] d4ZV2zCq848: Downloading m3u8 information
[youtube] d4ZV2zCq848: Downloading MPD manifest
[info] Available formats for d4ZV2zCq848:
format code extension resolution note
91 mp4 256x144 HLS 269k , avc1.4d400c, 30.0fps, mp4a.40.5@ 48k
92 mp4 426x240 HLS 507k , avc1.4d4015, 30.0fps, mp4a.40.5@ 48k
93 mp4 640x360 HLS 962k , avc1.4d401e, 30.0fps, mp4a.40.2@128k
94 mp4 854x480 HLS 1282k , avc1.4d401f, 30.0fps, mp4a.40.2@128k
95 mp4 1280x720 HLS 2447k , avc1.4d401f, 30.0fps, mp4a.40.2@256k (best)
You use it like this
yt_record
https://www.youtube.com/watch?v=d4ZV2zCq848
It's a bit limited because it assumes that format codes 91 and 95 exist, that 91 is the audio and 95 is the video. It should probably do something like ytdl does and try to figure out the best ones at runtime. Also, it looks like it is reencoding the AAC audio and not copying it, and it is not clear if this is necessary. Lastly, for this stream it looks like both 91 and 95 are audio and video muxed together. It's not clear if this will always be the case and the superuser post seems to assume 91 is audio and 95 is video, reencodes the audio, and then muxes it to the video. It complains about http keepalives not working. I think this is because of the host changing in the .m3u8 file, or maybe it's because the audio and video streams are on different hosts and ffmpeg gets confused.
Bash:
[https @ 0x7ff33887ce00] Cannot reuse HTTP connection for different host: r5---sn-5hne6ns6.googlevideo.com:-1 != r5---sn-aigl6ned.googlevideo.com:-1
[hls @ 0x7ff33a000000] keepalive request failed for '[redacted]' when opening url, retrying with new connection: Invalid argument
Despite all that it works. output.mp4 was created. I killed the process with ctrl+C, which is obviously not ideal. Presumably, the last part of the video will be corrupted by that. Then again H.264 and AAC are designed to be streamable and, hopefully, your decoder won't crash when it hits the end of the rails. VLC just stops playing.
I've got no idea if the process will just stop when the stream ends.
It needs a bit more work, but it seems promising.
Another interesting thing I noticed with PPP's stream is that even after the channel was down Youtube would still play the stream if you kept the player window open. I think this implies the .m3u8 playlists and the TS files stay up. This means if you got the URLs to them with -g you'd still be able to capture the stream for some time after a channel takedown.
@Guntleman hopefully some of this information may prove useful the Autistic Crusade.
Here's an improved version
Bash:
function yt_record
{
echo ffmpeg -i $(youtube-dl -g ${1} ) -c copy out.mp4
ffmpeg -i $(youtube-dl -g ${1} ) -c copy out.mp4
}
Did a test here
https://www.youtube.com/watch?v=YBdBBU-kSgQ
See out.mp4
Here's version 3
Right now this stream is live
https://www.youtube.com/watch?v=B8a6Dp5bitY
Let's look at what formats are available
Bash:
$ youtube-dl -F https://www.youtube.com/watch?v=B8a6Dp5bitY
[youtube] B8a6Dp5bitY: Downloading webpage
[youtube] B8a6Dp5bitY: Downloading m3u8 information
[youtube] B8a6Dp5bitY: Downloading MPD manifest
[info] Available formats for B8a6Dp5bitY:
format code extension resolution note
91 mp4 256x144 HLS 197k , avc1.42c00b, 30.0fps, mp4a.40.5@ 48k
92 mp4 426x240 HLS 338k , avc1.4d4015, 30.0fps, mp4a.40.5@ 48k
93 mp4 640x360 HLS 829k , avc1.4d401e, 30.0fps, mp4a.40.2@128k
94 mp4 854x480 HLS 1380k , avc1.4d401f, 30.0fps, mp4a.40.2@128k
95 mp4 1280x720 HLS 2593k , avc1.4d401f, 30.0fps, mp4a.40.2@256k
96 mp4 1920x1080 HLS 4715k , avc1.640028, 30.0fps, mp4a.40.2@256k (best)
Now consider the following function
Bash:
function yt_record
{
ffmpeg -i $(youtube-dl -f "bestvideo[height<=${1}][ext=mp4]+bestaudio[ext=m4a]/best[height<=${1}][ext=mp4]" -g ${2} ) -c copy out.mp4
}
This works like ytdl - you pass the max resolution as the first parameter and the URL as the second.
E.g. if you do
yt_record 720
https://www.youtube.com/watch?v=B8a6Dp5bitY
You will get you a 720p capture. I will not upload this foulness here, but it works. You should probably see what formats are available first and then pick one. Because the comparison is <= if you pick a format which isn't available you'll get the next lowest one. E.g.
yt_record 700p
https://www.youtube.com/watch?v=B8a6Dp5bitY
Would get you the 480p in this example. To give you some idea of file sizes consider this stream
Code:
$ ytdl -F https://www.youtube.com/watch?v=YBdBBU-kSgQ
140 m4a audio only tiny 135k , m4a_dash container, mp4a.40.2@128k (44100Hz), 84.04MiB
160 mp4 256x144 144p 160k , avc1.4d400c, 30fps, video only, 44.08MiB
133 mp4 426x240 240p 298k , avc1.4d4015, 30fps, video only, 102.63MiB
134 mp4 640x360 360p 690k , avc1.4d401e, 30fps, video only, 199.30MiB
135 mp4 854x480 480p 1203k , avc1.4d401f, 30fps, video only, 353.82MiB
136 mp4 1280x720 720p 2373k , avc1.4d401f, 30fps, video only, 712.49MiB
137 mp4 1920x1080 1080p 4849k , avc1.640028, 30fps, video only, 1.35GiB
18 mp4 640x360 360p 427k , avc1.42001E, 30fps, mp4a.40.2@ 96k (44100Hz), 277.58MiB
22 mp4 1280x720 720p 1225k , avc1.64001F, 30fps, mp4a.40.2@192k (44100Hz) (best)
I.e. a one and a half hour stream is 199MB at 360p, 712MB at 720p and 1.35GB at 1080p. If you want to shrink a video to reduce the size, do something like this
ffmpeg -i in.mp4 -vf "scale=320:240" -c:v libx264 -preset medium -crf 23 -c:a copy output.mp4
This will reencode to 320x240 but you can easily change that. It seems like this produces 240p versions of 360p videos which are about half the size, which is the same ratio Youtube gives. Then again it's likely that Youtube is using ffmpeg or a fork of it in production.