Last active
March 4, 2021 11:33
-
-
Save su-thomas/b3422e7e049e306d3858d85c1503fc28 to your computer and use it in GitHub Desktop.
Panopto Video Downloader w/ progress bar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import requests | |
import ffpb | |
import subprocess | |
from pathlib import Path | |
""" | |
Change the following values to your own. | |
To get your token, you'll need to log into panopto on a browser and view the .ASPXAUTH cookie value | |
""" | |
PANOPTO_BASE = "https://westernsydney.ap.panopto.com/" | |
TOKEN = "" | |
DEST_FOLDER = "/Users/calcifer/OneDrive/Uni/recordings" | |
DOWNLOAD_FOLDER = "panopto" | |
PANOPTO_SUBJECTS = ("200025_2021_aut: 200025 (Autumn 2021) Discrete Mathematics", | |
"300103_2021_aut: 300103 (Autumn 2021) Data Structures and Algorithms", | |
"300167_2021_aut: 300167 (Autumn 2021) Systems Programming 1") | |
def json_api(endpoint, params=None, is_post=False, param_type="params"): | |
if params is None: | |
params = dict() | |
if is_post: | |
r = s.post(PANOPTO_BASE + endpoint, **{param_type: params}) | |
else: | |
r = s.get(PANOPTO_BASE + endpoint, **{param_type: params}) | |
if not r.ok: | |
print(r.text) | |
return r.json() | |
def name_normalize(name): | |
for c in ['/', ':']: | |
name = name.replace(c, '') | |
return name | |
def dl_session(session, parent_path): | |
# Generate destination directory path | |
dest_dir = os.path.join(parent_path, name_normalize(session["SessionName"])) | |
# Prepare directories | |
if not os.path.exists(dest_dir): | |
os.makedirs(dest_dir) | |
# Get destination file name | |
delivery_info = json_api("/Panopto/Pages/Viewer/DeliveryInfo.aspx", { | |
"deliveryId": session["DeliveryID"], | |
"responseType": "json" | |
}, True, "data") | |
filename = "{}.mp4".format(delivery_info["Delivery"]["SessionName"]) | |
dest_filename = os.path.join(dest_dir, filename) | |
# Skip if file exists | |
if os.path.exists(dest_filename): | |
print("File '{}' already exists, skipping.".format(dest_filename)) | |
return | |
# Download file | |
print("Downloading:", dest_filename) | |
video_url = session['IosVideoUrl'] | |
Path(dest_filename).parent.mkdir(parents=True, exist_ok=True) | |
temp_filename = dest_filename + '.part' | |
cmd = ['-i', video_url, '-c', 'copy', '-f', 'mp4', temp_filename, '-y'] | |
if ffpb.main(cmd) == 0: | |
os.rename(temp_filename, dest_filename) | |
def dl_folder(folder, parent_path): | |
parent_path = os.path.join(("" if not parent_path else parent_path), name_normalize(folder["Name"])) | |
params = {"queryParameters": {"folderID": folder["Id"]}} | |
sessions = json_api("/Panopto/Services/Data.svc/GetSessions", params, True, "json")["d"]["Results"] | |
for session in sessions: | |
dl_session(session, parent_path) | |
# Download nested folders | |
folders = json_api("/Panopto/Api/Folders", {"parentId": folder["Id"], "folderSet": 1}) | |
for folder in folders: | |
dl_folder(folder, parent_path) | |
if __name__ == '__main__': | |
s = requests.session() | |
s.cookies = requests.utils.cookiejar_from_dict({".ASPXAUTH": TOKEN}) | |
dest_path = os.path.join(DEST_FOLDER, DOWNLOAD_FOLDER) | |
root_folders = json_api("/Panopto/Api/Folders", {"parentId": "null", "folderSet": 1}) | |
matches = 0 | |
for root_folder in root_folders: | |
if root_folder["Name"].startswith(PANOPTO_SUBJECTS): | |
matches += 1 | |
dl_folder(root_folder, dest_path) | |
if matches == 0: | |
print("No matches found. Check PANOPTO_SUBJECTS or TOKEN.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment