Video downloading

Downloading a video

A video can be downloaded via its Video.download() method.

import phub
from phub.locals import Quality

video = ...

video.download(path = 'my-video.mp4',
               quality = Quality.BEST)

Download options

Output path

The video output path can be either a path to a file, in which case the given file will be erased, or a directory. If that is the case, the final path of the file can be found by capturing the output of the Video.download() method.

video.download('video.mp4')  # video.mp4
video.download('dir/')       # dir/<video-key>.mp4

Video quality

There are multiple ways you can create a quality object.

from phub import Quality

quality = Quality.BEST             # Using a constant
quality = Quality('best')          # Using a string
quality = Quality(1080)            # Using an int
quality = Quality(Quality('best')) # Using an object

# Alternatively, you can also enter a raw quality inside most PHUB methods:
video.download(quality = Quality.BEST)
# is the same as
video.download(quality = 'best')

Simple progress display

The progress of the download can be displayed using built-in functions, from the .display submodule. There are several presets available:

>>> import phub
>>> import phub.display as display
>>> video = phub.Client().get('xxx')

# Simple colored progress (default)
>>> video.download(..., display = display.progress(color = True))
Downloading 50% [150/300]

# Bar progress
>>> video.download(..., display = bar())
Downloading |========        | [150/300]

# STD file progress
>>> video.download(..., display = std(file = sys.stdout))
50

You can also define your own progress callback. Your callback shall take 2 arguments: the currently processing segment, and the total segment to process.

def show_progress(current_segment: int, total_segment: int):
    # E.g. Display percentage progress

    percentage = round( (current_segment / total_segment) * 100 )

    print(f'Downloading: {percentage}%')

video.download(..., display = show_progress)

FFmpeg converting

Videos are downloaded using HLS streaming. Basically we use smaller segments and put them into one file. This file can usually be played by any video player except for a few exceptions. However, you won’t be able to add metadata to it. Although it has a .mp4 extension it actually is a .ts file. If you want to convert a video to a valid mp4 file and assign the needed headers to it, you can use FFmpeg for that.

When downloading a video, use convert = True as an argument in there. For example:

You can define the location for ffmpeg using:

By default, phub will search for it in your system’s path

Downloaders

You can specify custom downloaders to download your video. There are a few presets available in the .download submodule.

import phub
import phub.download as download

client = phub.Client()
video = client.get('xxx')

# Dummy download - Slow, but stable
video.download(..., downloader = download.default)

# FFMPEG download - Everything is handled by FFMPEG
# Note - you need to have FFMPEG installed to your system.
video.download(..., downloader = download.FFMPEG)

# Threaded download - Uses python futures to download
# the video as fast as possible. Multiple settings are available
# for you to set an appropriate download speed depending on your
# computer and internet connection.
video.download(..., downloader = download.threaded(max_workers = 50,
                                                   timeout = 10))

You can also specify custom downloaders. You can use Video.get_segments(), which outputs a generator containing a list of segment URLs.

import phub

def my_downloader(video, quality, callback, path):
    # Over simplified downloader

    # Get segment list
    segments = list(video.get_segments(quality))
    length = len(segments)

    # Open file
    with open(path, 'wb') as file:
        for i, url in enumerate(segments):

            # Download one segment and write it
            raw = video.client.call(url)
            file.write(raw)

            # Update the callback
            callback(i, length)

video.download(..., downloader = my_downloader)

Alternatively, Video.get_M3U_url() outputs the URL of the master M3U file for a desired quality.

For instance, the following downloader will download the M3U8 file of a video:

import os
import phub

client = phub.Client()
video = client.get('...')

def m3u_downloader(video, quality, callback, path):

    url = video.get_M3U_url(quality = quality)

    with open(path, 'wb') as file:

        raw = video.client.call(url)
        file.write(raw.content)

video.download('master.m3u8', quality = 'best', downloader = m3u_downloader)