| .. _streams: | |
| Working with Streams and StreamQuery | |
| ==================================== | |
| The next section will explore the various options available for working with | |
| media streams, but before we can dive in, we need to review a new-ish streaming | |
| technique adopted by YouTube. It assumes that you have already created a | |
| YouTube object in your code called "yt". | |
| DASH vs Progressive Streams | |
| --------------------------- | |
| Begin by running the following to list all streams:: | |
| >>> yt.streams | |
| [<Stream: itag="18" mime_type="video/mp4" res="360p" fps="30fps" vcodec="avc1.42001E" acodec="mp4a.40.2" progressive="True" type="video">, | |
| <Stream: itag="22" mime_type="video/mp4" res="720p" fps="30fps" vcodec="avc1.64001F" acodec="mp4a.40.2" progressive="True" type="video">, | |
| <Stream: itag="137" mime_type="video/mp4" res="1080p" fps="30fps" vcodec="avc1.640028" progressive="False" type="video">, | |
| ... | |
| <Stream: itag="250" mime_type="audio/webm" abr="70kbps" acodec="opus" progressive="False" type="audio">, | |
| <Stream: itag="251" mime_type="audio/webm" abr="160kbps" acodec="opus" progressive="False" type="audio">] | |
| You may notice that some streams listed have both a video codec and audio | |
| codec, while others have just video or just audio, this is a result of YouTube | |
| supporting a streaming technique called Dynamic Adaptive Streaming over HTTP | |
| (DASH). | |
| In the context of pytube, the implications are for the highest quality streams; | |
| you now need to download both the audio and video tracks and then post-process | |
| them with software like FFmpeg to merge them. | |
| The legacy streams that contain the audio and video in a single file (referred | |
| to as "progressive download") are still available, but only for resolutions | |
| 720p and below. | |
| Filtering Streams | |
| ================= | |
| Pytube has built-in functionality to filter the streams available in a YouTube | |
| object with the .filter() method. You can pass it a number of different keyword | |
| arguments, so let's review some of the different options you're most likely to | |
| use. For a complete list of available properties to filter on, you can view the | |
| API documentation here: :meth:`pytube.StreamQuery.filter`. | |
| Filtering by streaming method | |
| ----------------------------- | |
| As mentioned before, progressive streams have the video and audio in a single | |
| file, but typically do not provide the highest quality media; meanwhile, | |
| adaptive streams split the video and audio tracks but can provide much higher | |
| quality. Pytube makes it easy to filter based on the type of stream that you're | |
| interested. | |
| For example, you can filter to only progressive streams with the following:: | |
| >>> yt.streams.filter(progressive=True) | |
| [<Stream: itag="18" mime_type="video/mp4" res="360p" fps="30fps" vcodec="avc1.42001E" acodec="mp4a.40.2" progressive="True" type="video">, | |
| <Stream: itag="22" mime_type="video/mp4" res="720p" fps="30fps" vcodec="avc1.64001F" acodec="mp4a.40.2" progressive="True" type="video">] | |
| Conversely, if you only want to see the DASH streams (also referred to as | |
| "adaptive") you can do:: | |
| >>> yt.streams.filter(adaptive=True) | |
| [<Stream: itag="137" mime_type="video/mp4" res="1080p" fps="30fps" vcodec="avc1.640028" progressive="False" type="video">, | |
| <Stream: itag="248" mime_type="video/webm" res="1080p" fps="30fps" vcodec="vp9" progressive="False" type="video">, | |
| <Stream: itag="399" mime_type="video/mp4" res="None" fps="30fps" vcodec="av01.0.08M.08" progressive="False" type="video">, | |
| ... | |
| <Stream: itag="250" mime_type="audio/webm" abr="70kbps" acodec="opus" progressive="False" type="audio">, | |
| <Stream: itag="251" mime_type="audio/webm" abr="160kbps" acodec="opus" progressive="False" type="audio">] | |
| Filtering for audio-only streams | |
| -------------------------------- | |
| To query the streams that contain only the audio track:: | |
| >>> yt.streams.filter(only_audio=True) | |
| [<Stream: itag="140" mime_type="audio/mp4" abr="128kbps" acodec="mp4a.40.2" progressive="False" type="audio">, | |
| <Stream: itag="249" mime_type="audio/webm" abr="50kbps" acodec="opus" progressive="False" type="audio">, | |
| <Stream: itag="250" mime_type="audio/webm" abr="70kbps" acodec="opus" progressive="False" type="audio">, | |
| <Stream: itag="251" mime_type="audio/webm" abr="160kbps" acodec="opus" progressive="False" type="audio">] | |
| Filtering for MP4 streams | |
| ------------------------- | |
| To query only streams in the MP4 format:: | |
| >>> yt.streams.filter(file_extension='mp4') | |
| [<Stream: itag="18" mime_type="video/mp4" res="360p" fps="30fps" vcodec="avc1.42001E" acodec="mp4a.40.2" progressive="True" type="video">, | |
| <Stream: itag="22" mime_type="video/mp4" res="720p" fps="30fps" vcodec="avc1.64001F" acodec="mp4a.40.2" progressive="True" type="video">, | |
| <Stream: itag="137" mime_type="video/mp4" res="1080p" fps="30fps" vcodec="avc1.640028" progressive="False" type="video">, | |
| ... | |
| <Stream: itag="394" mime_type="video/mp4" res="None" fps="30fps" vcodec="av01.0.00M.08" progressive="False" type="video">, | |
| <Stream: itag="140" mime_type="audio/mp4" abr="128kbps" acodec="mp4a.40.2" progressive="False" type="audio">] | |
| Downloading Streams | |
| =================== | |
| After you've selected the :class:`Stream <pytube.Stream>` you're interested, | |
| you're ready to interact with it. At this point, you can query information | |
| about the stream, such as its filesize, whether the stream is adaptive, and | |
| more. You can also use the download method to save the file:: | |
| >>> stream = yt.streams.get_by_itag(22) | |
| >>> stream.download() | |
| The download method has a number of different useful arguments, which are | |
| documented in the API reference here: :meth:`pytube.Stream.download`. | |