Skip to content

Instantly share code, notes, and snippets.

@su-thomas
Last active March 4, 2021 02:26
Show Gist options
  • Save su-thomas/e56b85f7e398065a829a187d983282af to your computer and use it in GitHub Desktop.
Save su-thomas/e56b85f7e398065a829a187d983282af to your computer and use it in GitHub Desktop.
Panopto Video Download Tool
import os
import requests
import youtube_dl
"""
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")
s = requests.session()
s.cookies = requests.utils.cookiejar_from_dict({".ASPXAUTH": TOKEN})
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):
print(session["SessionName"])
# 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 exist
if os.path.exists(dest_filename):
print("File '{}' already exist, skipping.".format(dest_filename))
return
# Download file
print("Downloading:", dest_filename)
video_url = session['IosVideoUrl']
with youtube_dl.YoutubeDL({"outtmpl": dest_filename, "quiet": True}) as ydl:
ydl.download([video_url])
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__':
dest_path = os.path.join(DEST_FOLDER, DOWNLOAD_FOLDER)
root_folders = json_api("/Panopto/Api/Folders", {"parentId": "null", "folderSet": 1})
for root_folder in root_folders:
if root_folder["Name"].startswith(PANOPTO_SUBJECTS):
dl_folder(root_folder, dest_path)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment