{"id":35856878,"url":"https://github.com/serpapps/thinkific-downloader","last_synced_at":"2026-02-17T14:00:48.764Z","repository":{"id":311399353,"uuid":"1043517798","full_name":"serpapps/thinkific-downloader","owner":"serpapps","description":"Download Thinkific videos from the platform or embedded anywhere online","archived":false,"fork":false,"pushed_at":"2025-12-26T13:41:46.000Z","size":2693,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-26T13:57:24.905Z","etag":null,"topics":["downloader","thinkific","thinkific-downloader","thinkific-video-downloader"],"latest_commit_sha":null,"homepage":"https://serp.ly/thinkific-downloader","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/serpapps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["devinschumacher"],"open_collective":"devinschumacher","custom":["https://serpapps.github.io","https://apps.serp.co","https://serp.co","https://devinschumacher.com"]}},"created_at":"2025-08-24T03:04:11.000Z","updated_at":"2025-12-25T01:10:40.000Z","dependencies_parsed_at":"2026-01-25T00:01:56.999Z","dependency_job_id":null,"html_url":"https://github.com/serpapps/thinkific-downloader","commit_stats":null,"previous_names":["serpapps/thinkific-downloader"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/serpapps/thinkific-downloader","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serpapps%2Fthinkific-downloader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serpapps%2Fthinkific-downloader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serpapps%2Fthinkific-downloader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serpapps%2Fthinkific-downloader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/serpapps","download_url":"https://codeload.github.com/serpapps/thinkific-downloader/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serpapps%2Fthinkific-downloader/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29546744,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T13:00:00.370Z","status":"ssl_error","status_checked_at":"2026-02-17T12:57:14.072Z","response_time":100,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["downloader","thinkific","thinkific-downloader","thinkific-video-downloader"],"created_at":"2026-01-08T09:12:30.831Z","updated_at":"2026-02-17T14:00:48.733Z","avatar_url":"https://github.com/serpapps.png","language":null,"funding_links":["https://github.com/sponsors/devinschumacher","https://opencollective.com/devinschumacher","https://serpapps.github.io","https://apps.serp.co","https://serp.co","https://devinschumacher.com"],"categories":[],"sub_categories":[],"readme":"# Thinkific Downloader (Browser Extension for Chrome, Firefox, Opera, Edge, Brave)\n\nDownload Thinkific videos from the platform or embedded anywhere online\n\n\n\n\n## Related\n\n- [Repository](https://github.com/serpapps/thinkific-downloader)\n- [Thinkific Downloader Annoucement](https://gist.github.com/devinschumacher/d8eecdcd0b2326e9371e5b9ffe0f85b2)\n- [How to Download Thinkific Videos for Free](https://gist.github.com/devinschumacher/197805b63733a570539b587cdf229391)\n\n\n\u003cdetails\u003e\n\n# Thinkific Video Download Research: Technical Analysis of Stream Patterns, CDNs, and Download Methods\n\n*A comprehensive research document analyzing Thinkific's video infrastructure, embed patterns, stream formats, and optimal download strategies using modern tools*\n\n**Authors**: SERP Apps\n**Date**: September 2024  \n**Version**: 1.0\n\n---\n\n## Abstract\n\nThis research document provides a comprehensive analysis of Thinkific's video streaming infrastructure, including embed URL patterns, content delivery networks (CDNs), stream formats, and optimal download methodologies. We examine the technical architecture behind Thinkific's video delivery system and provide practical implementation guidance using industry-standard tools like yt-dlp, ffmpeg, and alternative solutions for reliable video extraction and download.\n\n## Table of Contents\n\n1. [Introduction](#introduction)\n2. [Thinkific Video Infrastructure Overview](#thinkific-video-infrastructure-overview)\n3. [Embed URL Patterns and Detection](#embed-url-patterns-and-detection)\n4. [Stream Formats and CDN Analysis](#stream-formats-and-cdn-analysis)\n5. [yt-dlp Implementation Strategies](#yt-dlp-implementation-strategies)\n6. [FFmpeg Processing Techniques](#ffmpeg-processing-techniques)\n7. [Alternative Tools and Backup Methods](#alternative-tools-and-backup-methods)\n8. [Implementation Recommendations](#implementation-recommendations)\n9. [Troubleshooting and Edge Cases](#troubleshooting-and-edge-cases)\n10. [Conclusion](#conclusion)\n\n---\n\n## 1. Introduction\n\nThinkific has established itself as a leading online course platform, utilizing sophisticated content delivery mechanisms to ensure optimal video streaming for educational content across various platforms and devices. This research examines the technical infrastructure behind Thinkific's video delivery system, with particular focus on developing robust download strategies for various use cases including course archival, offline learning, and content preservation.\n\n### 1.1 Research Scope\n\nThis document covers:\n- Technical analysis of Thinkific's video streaming architecture\n- Comprehensive URL pattern recognition for embedded course videos\n- Stream format analysis across different quality levels\n- Practical implementation using open-source tools\n- Backup strategies for edge cases and failures\n\n### 1.2 Methodology\n\nOur research methodology includes:\n- Network traffic analysis of Thinkific video playback\n- Reverse engineering of embed mechanisms\n- Testing with various quality settings and formats\n- Validation across multiple CDN endpoints\n\n---\n\n## 2. Thinkific Video Infrastructure Overview\n\n### 2.1 CDN Architecture\n\nThinkific utilizes a multi-tier CDN strategy primarily built on:\n\n**Primary CDN**: AWS CloudFront\n- **Primary Domains**: `*.thinkific.com`, `cdn.thinkific.com`\n- **Video CDN**: `d2p6ecj15pyavq.cloudfront.net`, `d1fto35gcfffzn.cloudfront.net`\n- **Backup Domains**: `*.amazonaws.com`, `thinkific-cdn.s3.amazonaws.com`\n- **Geographic Distribution**: Global edge locations with regional optimization\n\n**Secondary CDN**: Multiple cloud providers\n- **Domains**: Various CloudFlare and AWS endpoints\n- **Purpose**: Load balancing and redundancy\n- **Optimization**: Regional content optimization\n\n### 2.2 Video Processing Pipeline\n\nThinkific's video processing follows this pipeline:\n1. **Upload**: Original video uploaded to course creation interface\n2. **Transcoding**: Multiple formats generated (MP4, HLS, DASH)\n3. **Quality Levels**: Auto-generated 360p, 480p, 720p, 1080p variants\n4. **CDN Distribution**: Files distributed across CDN network\n5. **Access Control**: Course enrollment and payment verification\n6. **Adaptive Streaming**: HLS manifests created for dynamic quality\n\n### 2.3 Security and Access Control\n\n- **Authentication Required**: Course enrollment or purchase necessary\n- **Session-based Access**: User login tokens required\n- **Referrer Checking**: Domain-based access restrictions\n- **Rate Limiting**: Per-user download limitations\n- **DRM Protection**: Some courses use basic DRM mechanisms\n- **Geographic Restrictions**: Course availability may vary by region\n\n---\n\n## 3. Embed URL Patterns and Detection\n\n### 3.1 Primary Embed Patterns\n\n#### 3.1.1 Standard Course Video URLs\n```\nhttps://{SCHOOL_DOMAIN}.thinkific.com/courses/{COURSE_SLUG}/lessons/{LESSON_ID}\nhttps://{SCHOOL_DOMAIN}.thinkific.com/courses/take/{COURSE_ID}/lessons/{LESSON_ID}\nhttps://player.thinkific.com/embed/{VIDEO_ID}\nhttps://player-api.thinkific.com/api/video/{VIDEO_ID}\n```\n\n#### 3.1.2 Direct Video Stream URLs\n```\nhttps://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/video.mp4\nhttps://d1fto35gcfffzn.cloudfront.net/{VIDEO_PATH}/{QUALITY}/video.mp4\nhttps://thinkific-cdn.s3.amazonaws.com/videos/{VIDEO_ID}/video.mp4\n```\n\n#### 3.1.3 HLS Stream URLs\n```\nhttps://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/playlist.m3u8\nhttps://{CDN_DOMAIN}/hls/{VIDEO_ID}/master.m3u8\nhttps://player-api.thinkific.com/hls/{VIDEO_ID}/index.m3u8\n```\n\n### 3.2 Video ID and Course Extraction Patterns\n\n#### 3.2.1 Standard Format\n```regex\n/courses/take/([0-9]+)/lessons/([0-9]+)/\n/embed/([a-f0-9-]{36})/\n/video/([a-f0-9-]{36})/\n/{SCHOOL_DOMAIN}\\.thinkific\\.com/courses/([^/]+)/\n```\n\n#### 3.2.2 Legacy Format Support\n```regex\n/player/([0-9]+)/\n/lessons/([0-9]+)/video/\n/api/video/([a-f0-9]+)/\n```\n\n### 3.3 Detection Implementation\n\n#### Command-line Detection Methods\n\n**Using grep for URL pattern extraction:**\n```bash\n# Extract Thinkific video URLs from HTML files\ngrep -oE \"https?://[^/]*\\.thinkific\\.com/courses/[^\\\"]*\" input.html\n\n# Extract embed player URLs\ngrep -oE \"https?://player\\.thinkific\\.com/embed/[a-f0-9-]+\" input.html\n\n# Extract course and lesson IDs\ngrep -oE \"courses/take/([0-9]+)/lessons/([0-9]+)\" input.html | grep -oE \"[0-9]+\"\n\n# Extract video IDs from API calls\ngrep -oE \"player-api\\.thinkific\\.com/api/video/[a-f0-9-]+\" input.html | grep -oE \"[a-f0-9-]{36}\"\n```\n\n**Using yt-dlp for detection and metadata extraction:**\n```bash\n# Test if URL contains downloadable video (requires authentication)\nyt-dlp --dump-json \"https://{SCHOOL}.thinkific.com/courses/take/{COURSE_ID}/lessons/{LESSON_ID}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# Extract all video information\nyt-dlp --dump-json \"https://player.thinkific.com/embed/{VIDEO_ID}\" \u003e video_info.json\n\n# Check available formats\nyt-dlp --list-formats \"https://{SCHOOL}.thinkific.com/courses/{COURSE}/lessons/{LESSON_ID}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n```\n\n**Browser inspection commands:**\n```bash\n# Using curl to inspect course pages (requires authentication)\ncurl -s -c cookies.txt -d \"email=YOUR_EMAIL\u0026password=YOUR_PASSWORD\" \"https://{SCHOOL}.thinkific.com/users/sign_in\"\ncurl -s -b cookies.txt \"https://{SCHOOL}.thinkific.com/courses/take/{COURSE_ID}/lessons/{LESSON_ID}\" | grep -oE \"video.*[a-f0-9-]{36}\"\n\n# Inspect API endpoints\ncurl -s -H \"Authorization: Bearer YOUR_TOKEN\" \"https://player-api.thinkific.com/api/video/{VIDEO_ID}\"\n```\n\n---\n\n## 4. Stream Formats and CDN Analysis\n\n### 4.1 Available Stream Formats\n\n#### 4.1.1 MP4 Streams\n- **Container**: MP4\n- **Video Codec**: H.264 (AVC)\n- **Audio Codec**: AAC\n- **Quality Levels**: 360p, 480p, 720p, 1080p\n- **Bitrates**: Adaptive from 500kbps to 6Mbps\n\n#### 4.1.2 WebM Streams\n- **Container**: WebM\n- **Video Codec**: VP9/VP8\n- **Audio Codec**: Opus/Vorbis\n- **Quality Levels**: Limited availability\n- **Purpose**: Browser compatibility optimization\n\n#### 4.1.3 HLS Streams\n- **Container**: MPEG-TS segments\n- **Video Codec**: H.264\n- **Audio Codec**: AAC\n- **Segment Duration**: 10 seconds\n- **Adaptive**: Dynamic quality switching based on bandwidth\n\n### 4.2 URL Construction Patterns\n\n#### 4.2.1 Direct MP4 URLs\n```\nhttps://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/720/video.mp4\nhttps://d1fto35gcfffzn.cloudfront.net/{VIDEO_PATH}/1080/video.mp4\nhttps://thinkific-cdn.s3.amazonaws.com/videos/{VIDEO_ID}/video.mp4\n```\n\n#### 4.2.2 HLS Master Playlist\n```\nhttps://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/playlist.m3u8\nhttps://player-api.thinkific.com/hls/{VIDEO_ID}/master.m3u8\n```\n\n#### 4.2.3 Quality-specific HLS\n```\nhttps://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/720/index.m3u8\nhttps://d1fto35gcfffzn.cloudfront.net/{VIDEO_PATH}/1080/index.m3u8\n```\n\n### 4.3 CDN Failover Strategy\n\n#### Primary → Secondary CDN\n\nThe following URL patterns can be used with tools like wget or curl to attempt downloads from different CDN endpoints:\n\n```bash\n# Primary CloudFront CDN\nhttps://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/{QUALITY}/video.mp4\n\n# Secondary CloudFront\nhttps://d1fto35gcfffzn.cloudfront.net/{VIDEO_PATH}/{QUALITY}/video.mp4\n\n# S3 Direct Access (if available)\nhttps://thinkific-cdn.s3.amazonaws.com/videos/{VIDEO_ID}/video.mp4\n\n# Regional CDN endpoints\nhttps://cdn-{REGION}.thinkific.com/{VIDEO_PATH}/video.mp4\n```\n\n**Command sequence for testing CDN availability:**\n```bash\n# Test primary CDN\ncurl -I \"https://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/720/video.mp4\"\n\n# Test secondary CDN if primary fails\ncurl -I \"https://d1fto35gcfffzn.cloudfront.net/{VIDEO_PATH}/720/video.mp4\"\n\n# Test S3 direct access\ncurl -I \"https://thinkific-cdn.s3.amazonaws.com/videos/{VIDEO_ID}/video.mp4\"\n```\n\n---\n\n## 5. yt-dlp Implementation Strategies\n\n### 5.1 Basic yt-dlp Commands\n\n#### 5.1.1 Authenticated Course Access\n```bash\n# Download with user credentials\nyt-dlp \"https://{SCHOOL}.thinkific.com/courses/take/{COURSE_ID}/lessons/{LESSON_ID}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# Use cookies from browser session\nyt-dlp --cookies-from-browser chrome \"https://{SCHOOL}.thinkific.com/courses/take/{COURSE_ID}/lessons/{LESSON_ID}\"\n\n# Save and reuse cookies\nyt-dlp --cookies cookies.txt --netrc-file netrc_file \"https://{SCHOOL}.thinkific.com/courses/take/{COURSE_ID}/lessons/{LESSON_ID}\"\n```\n\n#### 5.1.2 Format Selection for Thinkific\n```bash\n# List available formats (requires authentication)\nyt-dlp -F \"https://{SCHOOL}.thinkific.com/courses/take/{COURSE_ID}/lessons/{LESSON_ID}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# Download best quality MP4\nyt-dlp -f \"best[ext=mp4]\" \"https://{SCHOOL}.thinkific.com/courses/take/{COURSE_ID}/lessons/{LESSON_ID}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# Download specific quality with fallback\nyt-dlp -f \"best[height\u003c=720]/best\" \"https://{SCHOOL}.thinkific.com/courses/take/{COURSE_ID}/lessons/{LESSON_ID}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# Custom filename template for course organization\nyt-dlp -o \"%(uploader)s/%(course)s/%(chapter_number)02d - %(chapter)s/%(title)s.%(ext)s\" \"https://{SCHOOL}.thinkific.com/courses/take/{COURSE_ID}/lessons/{LESSON_ID}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n```\n\n#### 5.1.3 Advanced Course Downloading\n```bash\n# Download entire course with metadata\nyt-dlp --write-info-json --write-thumbnail --write-subs --sub-langs en \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# Download course with custom organization\nyt-dlp -o \"Courses/%(uploader)s - %(course)s/Module %(chapter_number)02d/%(title)s.%(ext)s\" \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# Rate-limited download for large courses\nyt-dlp --limit-rate 1M --sleep-interval 2 \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n```\n\n### 5.2 Batch Processing for Courses\n\n#### 5.2.1 Multiple Lessons/Courses\n```bash\n# Download from URL list with authentication\nyt-dlp -a thinkific_urls.txt --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# With archive tracking to resume interrupted downloads\nyt-dlp --download-archive downloaded.txt -a thinkific_urls.txt --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# Parallel course downloads (be careful with rate limiting)\nyt-dlp --max-downloads 2 -a thinkific_urls.txt --username YOUR_EMAIL --password YOUR_PASSWORD\n```\n\n#### 5.2.2 Course-specific Batch Operations\n```bash\n# Download all lessons in a course\nyt-dlp \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# Download only video lessons (skip quizzes, text)\nyt-dlp --match-filter \"duration \u003e 60\" \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# Download with quality control for bandwidth management\nyt-dlp -f \"best[height\u003c=480][filesize\u003c200M]\" \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n```\n\n### 5.3 Error Handling and Authentication\n\n```bash\n# Retry on authentication failure\nyt-dlp --retries 3 --retry-sleep 5 \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n\n# Handle 2FA and advanced authentication\nyt-dlp --netrc-file .netrc --cookies-from-browser chrome \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\"\n\n# Skip private or enrollment-required content\nyt-dlp --ignore-errors --no-warnings \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\" --username YOUR_EMAIL --password YOUR_PASSWORD\n```\n\n### 5.4 Authentication Setup Commands\n\n#### 5.4.1 Browser Cookie Extraction\n```bash\n# Extract cookies from Chrome\nyt-dlp --cookies-from-browser chrome --dump-json \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\"\n\n# Extract cookies from Firefox\nyt-dlp --cookies-from-browser firefox --list-formats \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\"\n\n# Save cookies for reuse\nyt-dlp --cookies-from-browser chrome --cookies cookies.txt \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\"\n```\n\n#### 5.4.2 Manual Authentication\n```bash\n# Create netrc file for automatic authentication\necho \"machine {SCHOOL}.thinkific.com login YOUR_EMAIL password YOUR_PASSWORD\" \u003e ~/.netrc\nchmod 600 ~/.netrc\n\n# Use netrc file\nyt-dlp --netrc \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\"\n\n# Manual session management\ncurl -c cookies.txt -d \"email=YOUR_EMAIL\u0026password=YOUR_PASSWORD\" \"https://{SCHOOL}.thinkific.com/users/sign_in\"\nyt-dlp --cookies cookies.txt \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\"\n```\n\n---\n\n## 6. FFmpeg Processing Techniques\n\n### 6.1 Stream Analysis for Thinkific Content\n\n#### 6.1.1 Basic Stream Information\n```bash\n# Analyze Thinkific video stream details\nffprobe -v quiet -print_format json -show_format -show_streams \"https://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/video.mp4\"\n\n# Get course video duration\nffprobe -v quiet -show_entries format=duration -of csv=\"p=0\" \"course_video.mp4\"\n\n# Check encoding details for compatibility\nffprobe -v quiet -select_streams v:0 -show_entries stream=codec_name,width,height,bit_rate -of csv=\"s=x:p=0\" \"course_video.mp4\"\n```\n\n#### 6.1.2 HLS Stream Analysis for Courses\n```bash\n# Download and analyze Thinkific HLS stream\nffprobe -v quiet -print_format json -show_format \"https://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/playlist.m3u8\"\n\n# List available quality streams in HLS\nffprobe -v quiet -show_streams \"https://player-api.thinkific.com/hls/{VIDEO_ID}/master.m3u8\"\n\n# Extract stream information from HLS manifest\ncurl -s \"https://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/playlist.m3u8\" | grep -E \"(BANDWIDTH|RESOLUTION)\"\n```\n\n### 6.2 Direct Stream Processing for Course Content\n\n#### 6.2.1 Stream Download and Conversion\n```bash\n# Download HLS course video directly\nffmpeg -i \"https://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/playlist.m3u8\" -c copy course_lesson.mp4\n\n# Download with specific quality for mobile learning\nffmpeg -i \"https://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/720/index.m3u8\" -c copy course_lesson_720p.mp4\n\n# Convert WebM course content to MP4 for compatibility\nffmpeg -i course_lesson.webm -c:v libx264 -c:a aac course_lesson.mp4\n\n# Optimize for offline mobile learning\nffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k mobile_optimized.mp4\n```\n\n#### 6.2.2 Course Content Processing\n```bash\n# Batch process course videos with consistent encoding\nfor file in course_videos/*.mp4; do\n    ffmpeg -i \"$file\" -c:v libx264 -crf 20 -c:a aac -b:a 128k \"processed/$(basename \"$file\")\"\ndone\n\n# Create course preview clips (first 2 minutes)\nffmpeg -i full_course_video.mp4 -t 120 -c copy preview.mp4\n\n# Extract audio for podcast-style learning\nffmpeg -i course_video.mp4 -vn -c:a aac -b:a 128k course_audio.aac\n```\n\n### 6.3 Educational Content Optimization\n\n#### 6.3.1 Course Video Enhancement\n```bash\n# Enhance audio quality for lecture content\nffmpeg -i course_lecture.mp4 -af \"highpass=f=200,lowpass=f=3000,compand\" enhanced_lecture.mp4\n\n# Add course branding/watermark\nffmpeg -i course_video.mp4 -i watermark.png -filter_complex \"overlay=W-w-10:H-h-10\" branded_course.mp4\n\n# Normalize audio levels across course videos\nffmpeg -i course_video.mp4 -af \"loudnorm=I=-16:TP=-1.5:LRA=11\" normalized_course.mp4\n```\n\n#### 6.3.2 Multi-format Course Delivery\n```bash\n# Create multiple quality versions for different devices\nffmpeg -i original_course.mp4 \\\n  -c:v libx264 -b:v 1M -c:a aac -b:a 128k course_720p.mp4 \\\n  -c:v libx264 -b:v 500k -c:a aac -b:a 96k course_480p.mp4 \\\n  -c:v libx264 -b:v 250k -c:a aac -b:a 64k course_360p.mp4\n\n# Generate course thumbnails at regular intervals\nffmpeg -i course_video.mp4 -vf \"fps=1/60\" course_thumbnails_%03d.png\n\n# Create course trailer from multiple lessons\nffmpeg -i lesson1.mp4 -i lesson2.mp4 -i lesson3.mp4 \\\n  -filter_complex \"[0:v]trim=0:30[v0];[1:v]trim=0:30[v1];[2:v]trim=0:30[v2];[v0][v1][v2]concat=n=3:v=1:a=0[v]\" \\\n  -map \"[v]\" course_trailer.mp4\n```\n\n### 6.4 Advanced Course Processing Workflows\n\n#### 6.4.1 Automated Course Processing Script\n```bash\n#!/bin/bash\n\n# Process entire course with consistent settings\nprocess_course_videos() {\n    local input_dir=\"$1\"\n    local output_dir=\"$2\"\n    local course_name=\"$3\"\n    \n    mkdir -p \"$output_dir\"\n    \n    # Process each lesson video\n    for file in \"$input_dir\"/*.mp4; do\n        if [[ -f \"$file\" ]]; then\n            filename=$(basename \"$file\" .mp4)\n            lesson_number=$(echo \"$filename\" | grep -oE \"[0-9]+\" | head -1)\n            \n            echo \"Processing Lesson $lesson_number: $filename\"\n            \n            # Standard course processing with branding\n            ffmpeg -i \"$file\" \\\n                   -c:v libx264 -crf 20 -preset medium \\\n                   -c:a aac -b:a 128k \\\n                   -movflags +faststart \\\n                   -metadata title=\"$course_name - Lesson $lesson_number\" \\\n                   \"$output_dir/Lesson_${lesson_number}_${filename}.mp4\"\n                   \n            # Create mobile version\n            ffmpeg -i \"$file\" \\\n                   -c:v libx264 -crf 25 -preset fast \\\n                   -vf \"scale=854:480\" \\\n                   -c:a aac -b:a 96k \\\n                   \"$output_dir/mobile/Lesson_${lesson_number}_${filename}_mobile.mp4\"\n        fi\n    done\n    \n    # Create course index/playlist\n    echo \"Creating course playlist...\"\n    find \"$output_dir\" -name \"Lesson_*.mp4\" | sort -V \u003e \"$output_dir/course_playlist.txt\"\n}\n```\n\n#### 6.4.2 Quality Assessment and Optimization\n```bash\n# Analyze course video quality and suggest optimizations\nanalyze_course_quality() {\n    local video_file=\"$1\"\n    \n    # Get video statistics\n    echo \"Analyzing: $video_file\"\n    \n    # Check resolution and bitrate\n    resolution=$(ffprobe -v quiet -select_streams v:0 -show_entries stream=width,height -of csv=\"s=x:p=0\" \"$video_file\")\n    bitrate=$(ffprobe -v quiet -select_streams v:0 -show_entries stream=bit_rate -of csv=\"p=0\" \"$video_file\")\n    duration=$(ffprobe -v quiet -show_entries format=duration -of csv=\"p=0\" \"$video_file\")\n    \n    echo \"Resolution: $resolution\"\n    echo \"Bitrate: $bitrate\"\n    echo \"Duration: $duration seconds\"\n    \n    # Calculate file size efficiency\n    file_size=$(stat -f%z \"$video_file\" 2\u003e/dev/null || stat -c%s \"$video_file\")\n    efficiency=$(echo \"scale=2; $file_size / $duration / 1024\" | bc)\n    \n    echo \"File size: $file_size bytes\"\n    echo \"Size efficiency: $efficiency KB/second\"\n    \n    # Suggest optimization if needed\n    if (( $(echo \"$efficiency \u003e 200\" | bc -l) )); then\n        echo \"Recommendation: Consider reducing bitrate for better efficiency\"\n    fi\n}\n```\n\n---\n\n## 7. Alternative Tools and Backup Methods\n\n### 7.1 Gallery-dl for Course Content\n\nGallery-dl can be effective for educational platforms with predictable patterns.\n\n#### 7.1.1 Installation and Basic Usage\n```bash\n# Install gallery-dl\npip install gallery-dl\n\n# Download Thinkific course content\ngallery-dl \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\"\n\n# Custom configuration for Thinkific\ngallery-dl --config thinkific.conf \"https://{SCHOOL}.thinkific.com/courses/{COURSE_SLUG}\"\n```\n\n#### 7.1.2 Configuration for Thinkific Courses\n```json\n{\n    \"extractor\": {\n        \"thinkific\": {\n            \"filename\": \"{course_name}/{chapter_number:02d} - {chapter}/{lesson_number:02d} - {title}.{extension}\",\n            \"directory\": [\"courses\", \"{school_name}\", \"{course_name}\"],\n            \"quality\": \"best\",\n            \"username\": \"your_email@domain.com\",\n            \"password\": \"your_password\"\n        }\n    }\n}\n```\n\n### 7.2 Streamlink for Live Sessions\n\nStreamlink can handle live course sessions and webinars.\n\n#### 7.2.1 Basic Streamlink Usage\n```bash\n# Install streamlink\npip install streamlink\n\n# Download live Thinkific session\nstreamlink \"https://{SCHOOL}.thinkific.com/live/{SESSION_ID}\" best -o live_session.mp4\n\n# Record webinar with specific quality\nstreamlink \"https://live.thinkific.com/{WEBINAR_ID}\" 720p -o webinar_720p.mp4\n\n# Record with retry and reconnection\nstreamlink --retry-streams 5 --retry-max 10 \"https://{SCHOOL}.thinkific.com/live/{SESSION_ID}\" best -o session.mp4\n```\n\n### 7.3 Wget/cURL for Direct Downloads\n\n#### 7.3.1 Direct Video Downloads with Authentication\n```bash\n# Using wget with cookies\nwget --load-cookies=cookies.txt -O \"course_video.mp4\" \"https://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/video.mp4\"\n\n# Using cURL with session headers\ncurl -H \"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\" \\\n     -H \"Referer: https://{SCHOOL}.thinkific.com/\" \\\n     -H \"Authorization: Bearer {ACCESS_TOKEN}\" \\\n     -o \"course_video.mp4\" \\\n     \"https://d2p6ecj15pyavq.cloudfront.net/{VIDEO_PATH}/video.mp4\"\n```\n\n#### 7.3.2 Batch Course Download Script\n```bash\n#!/bin/bash\n\n# Batch download with authentication and fallback\ndownload_course_with_fallback() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    local output_dir=\"${4:-./courses}\"\n    \n    # First, authenticate and get session cookies\n    curl -c cookies.txt -d \"email=$username\u0026password=$password\" \\\n         \"https://$(echo $course_url | cut -d'/' -f3)/users/sign_in\"\n    \n    # Extract video URLs from course page\n    video_urls=$(curl -s -b cookies.txt \"$course_url\" | \\\n                 grep -oE \"https://[^\\\"]*\\.cloudfront\\.net/[^\\\"]*\\.mp4\")\n    \n    mkdir -p \"$output_dir\"\n    \n    for url in $video_urls; do\n        filename=$(basename \"$url\")\n        echo \"Downloading: $filename\"\n        \n        # Try multiple CDN endpoints\n        cdn_urls=(\n            \"$url\"\n            \"${url/d2p6ecj15pyavq/d1fto35gcfffzn}\"\n            \"${url/cloudfront.net/amazonaws.com}\"\n        )\n        \n        for cdn_url in \"${cdn_urls[@]}\"; do\n            if wget -q --spider -b cookies.txt \"$cdn_url\"; then\n                echo \"Downloading from: $cdn_url\"\n                wget -b cookies.txt -O \"$output_dir/$filename\" \"$cdn_url\"\n                if [[ $? -eq 0 ]]; then\n                    echo \"Success: $filename\"\n                    break\n                fi\n            fi\n        done\n    done\n}\n```\n\n### 7.4 Browser Automation Tools\n\n#### 7.4.1 Selenium for Complex Authentication\n```python\nfrom selenium import webdriver\nfrom selenium.webdriver.common.by import By\nimport time\n\ndef thinkific_browser_download(school_domain, username, password, course_url):\n    \"\"\"Use browser automation for complex Thinkific authentication\"\"\"\n    \n    driver = webdriver.Chrome()\n    \n    try:\n        # Navigate to login page\n        driver.get(f\"https://{school_domain}.thinkific.com/users/sign_in\")\n        \n        # Fill login form\n        driver.find_element(By.NAME, \"email\").send_keys(username)\n        driver.find_element(By.NAME, \"password\").send_keys(password)\n        driver.find_element(By.CSS_SELECTOR, \"input[type='submit']\").click()\n        \n        # Wait for login completion\n        time.sleep(3)\n        \n        # Navigate to course\n        driver.get(course_url)\n        \n        # Extract video URLs from page source\n        video_urls = driver.execute_script(\"\"\"\n            return Array.from(document.querySelectorAll('video source, video'))\n                        .map(v =\u003e v.src || v.currentSrc)\n                        .filter(url =\u003e url \u0026\u0026 url.includes('.mp4'));\n        \"\"\")\n        \n        # Get cookies for authenticated downloads\n        cookies = driver.get_cookies()\n        \n        return video_urls, cookies\n        \n    finally:\n        driver.quit()\n```\n\n#### 7.4.2 Playwright for Modern Course Platforms\n```bash\n# Install playwright\npip install playwright\nplaywright install\n\n# Use playwright to extract video URLs\npython -c \"\nfrom playwright.sync_api import sync_playwright\n\ndef extract_thinkific_videos(school, username, password, course_url):\n    with sync_playwright() as p:\n        browser = p.chromium.launch(headless=False)\n        page = browser.new_page()\n        \n        # Login to Thinkific\n        page.goto(f'https://{school}.thinkific.com/users/sign_in')\n        page.fill('input[name=\\\"email\\\"]', username)\n        page.fill('input[name=\\\"password\\\"]', password)\n        page.click('input[type=\\\"submit\\\"]')\n        \n        # Wait for login and navigate to course\n        page.wait_for_selector('[data-testid=\\\"course-content\\\"]')\n        page.goto(course_url)\n        \n        # Extract video sources\n        video_urls = page.evaluate('''\n            () =\u003e Array.from(document.querySelectorAll('video, source'))\n                       .map(v =\u003e v.src || v.currentSrc)\n                       .filter(url =\u003e url)\n        ''')\n        \n        browser.close()\n        return video_urls\n\n# Usage\nurls = extract_thinkific_videos('school', 'email', 'password', 'course_url')\nprint(urls)\n\"\n```\n\n### 7.5 API-based Approaches\n\n#### 7.5.1 Thinkific API Integration\n```bash\n# Get course content via API (requires API key)\ncurl -H \"Authorization: Bearer YOUR_API_KEY\" \\\n     -H \"Accept: application/json\" \\\n     \"https://api.thinkific.com/api/public/v1/courses/{COURSE_ID}/chapters\"\n\n# Get course enrollments\ncurl -H \"Authorization: Bearer YOUR_API_KEY\" \\\n     \"https://api.thinkific.com/api/public/v1/enrollments?course_id={COURSE_ID}\"\n\n# Extract video URLs from course content\ncurl -H \"Authorization: Bearer YOUR_API_KEY\" \\\n     \"https://api.thinkific.com/api/public/v1/courses/{COURSE_ID}/chapters/{CHAPTER_ID}/lessons\" | \\\n     jq -r '.items[].content | select(.type==\"video\") | .video_url'\n```\n\n#### 7.5.2 GraphQL API Access\n```bash\n# Query course structure via GraphQL\ncurl -X POST \\\n     -H \"Authorization: Bearer YOUR_TOKEN\" \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\n       \"query\": \"query GetCourse($id: ID!) { course(id: $id) { title chapters { lessons { title content { ... on VideoContent { videoUrl } } } } } }\",\n       \"variables\": { \"id\": \"COURSE_ID\" }\n     }' \\\n     \"https://api.thinkific.com/graphql\"\n```\n\n---\n\n## 8. Implementation Recommendations\n\n### 8.1 Primary Implementation Strategy\n\n#### 8.1.1 Hierarchical Authentication and Download Approach\n```bash\n#!/bin/bash\n# Comprehensive Thinkific download strategy script\n\ndownload_thinkific_course() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    local output_dir=\"${4:-./courses}\"\n    \n    echo \"Attempting download of: $course_url\"\n    echo \"Using credentials for: $username\"\n    \n    # Method 1: yt-dlp with credentials (primary)\n    if yt-dlp --username \"$username\" --password \"$password\" \\\n              -o \"$output_dir/%(uploader)s - %(course)s/%(chapter_number)02d - %(chapter)s/%(title)s.%(ext)s\" \\\n              \"$course_url\"; then\n        echo \"✓ Success with yt-dlp\"\n        return 0\n    fi\n    \n    # Method 2: yt-dlp with browser cookies\n    if yt-dlp --cookies-from-browser chrome \\\n              -o \"$output_dir/%(title)s.%(ext)s\" \\\n              \"$course_url\"; then\n        echo \"✓ Success with browser cookies\"\n        return 0\n    fi\n    \n    # Method 3: Browser automation + direct download\n    python3 -c \"\nimport sys\nsys.path.append('.')\nfrom browser_downloader import thinkific_browser_download\nvideo_urls, cookies = thinkific_browser_download('$school', '$username', '$password', '$course_url')\nprint('\\n'.join(video_urls))\n    \" \u003e video_urls.txt\n    \n    if [[ -s video_urls.txt ]]; then\n        while IFS= read -r url; do\n            filename=\\$(basename \\\"\\$url\\\")\n            wget -O \\\"$output_dir/\\$filename\\\" \\\"\\$url\\\"\n        done \u003c video_urls.txt\n        echo \"✓ Success with browser automation\"\n        return 0\n    fi\n    \n    # Method 4: API-based extraction\n    if [[ -n \"$THINKIFIC_API_KEY\" ]]; then\n        course_id=$(echo \"$course_url\" | grep -oE \"courses/([0-9]+)\" | cut -d'/' -f2)\n        if [[ -n \"$course_id\" ]]; then\n            curl -H \"Authorization: Bearer $THINKIFIC_API_KEY\" \\\n                 \"https://api.thinkific.com/api/public/v1/courses/$course_id/chapters\" | \\\n                 jq -r '.items[].lessons[].content | select(.type==\"video\") | .video_url' \u003e api_urls.txt\n            \n            if [[ -s api_urls.txt ]]; then\n                while IFS= read -r url; do\n                    yt-dlp \"$url\" -o \"$output_dir/%(title)s.%(ext)s\"\n                done \u003c api_urls.txt\n                echo \"✓ Success with API extraction\"\n                return 0\n            fi\n        fi\n    fi\n    \n    echo \"✗ All methods failed\"\n    return 1\n}\n```\n\n#### 8.1.2 Quality Selection for Educational Content\n```bash\n# Optimize downloads for different learning scenarios\nselect_course_quality() {\n    local course_url=\"$1\"\n    local scenario=\"${2:-standard}\"  # mobile, standard, high_quality\n    local username=\"$3\"\n    local password=\"$4\"\n    \n    case \"$scenario\" in\n        \"mobile\")\n            # Optimize for mobile devices and limited bandwidth\n            yt-dlp -f \"best[height\u003c=480][filesize\u003c100M]/best[height\u003c=480]/worst\" \\\n                   --username \"$username\" --password \"$password\" \\\n                   \"$course_url\"\n            ;;\n        \"standard\")\n            # Balanced quality for desktop learning\n            yt-dlp -f \"best[height\u003c=720][filesize\u003c300M]/best[height\u003c=720]/best\" \\\n                   --username \"$username\" --password \"$password\" \\\n                   \"$course_url\"\n            ;;\n        \"high_quality\")\n            # Best quality for detailed technical content\n            yt-dlp -f \"best[height\u003c=1080]/best\" \\\n                   --username \"$username\" --password \"$password\" \\\n                   \"$course_url\"\n            ;;\n        *)\n            echo \"Unknown scenario: $scenario\"\n            echo \"Available: mobile, standard, high_quality\"\n            return 1\n            ;;\n    esac\n}\n\n# Course organization helper\norganize_course_content() {\n    local input_dir=\"$1\"\n    local course_name=\"$2\"\n    \n    # Create organized directory structure\n    mkdir -p \"Courses/$course_name\"/{Videos,Audio,Transcripts,Resources}\n    \n    # Move video files\n    find \"$input_dir\" -name \"*.mp4\" -o -name \"*.webm\" | \\\n        while read file; do\n            mv \"$file\" \"Courses/$course_name/Videos/\"\n        done\n    \n    # Extract audio for offline listening\n    for video in \"Courses/$course_name/Videos\"/*.mp4; do\n        if [[ -f \"$video\" ]]; then\n            filename=$(basename \"$video\" .mp4)\n            ffmpeg -i \"$video\" -vn -c:a aac -b:a 128k \\\n                   \"Courses/$course_name/Audio/$filename.aac\"\n        fi\n    done\n}\n```\n\n### 8.2 Error Handling and Authentication Management\n\n#### 8.2.1 Robust Authentication Handling\n```bash\n# Manage Thinkific authentication across multiple schools\nmanage_thinkific_auth() {\n    local school_domain=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    local action=\"${4:-login}\"\n    \n    local cookie_file=\"auth_cookies_${school_domain}.txt\"\n    local session_file=\"session_${school_domain}.json\"\n    \n    case \"$action\" in\n        \"login\")\n            echo \"Authenticating with $school_domain...\"\n            \n            # Try direct login\n            curl -c \"$cookie_file\" \\\n                 -d \"email=$username\u0026password=$password\" \\\n                 -X POST \\\n                 \"https://$school_domain.thinkific.com/users/sign_in\"\n            \n            if [[ $? -eq 0 ]]; then\n                echo \"✓ Authentication successful\"\n                echo \"{\\\"school\\\": \\\"$school_domain\\\", \\\"timestamp\\\": $(date +%s)}\" \u003e \"$session_file\"\n                return 0\n            else\n                echo \"✗ Authentication failed\"\n                return 1\n            fi\n            ;;\n        \"verify\")\n            # Check if session is still valid\n            if [[ -f \"$cookie_file\" ]]; then\n                status=$(curl -s -b \"$cookie_file\" -o /dev/null -w \"%{http_code}\" \\\n                        \"https://$school_domain.thinkific.com/dashboard\")\n                \n                if [[ \"$status\" == \"200\" ]]; then\n                    echo \"✓ Session valid\"\n                    return 0\n                else\n                    echo \"✗ Session expired\"\n                    return 1\n                fi\n            else\n                echo \"✗ No session file found\"\n                return 1\n            fi\n            ;;\n        \"logout\")\n            rm -f \"$cookie_file\" \"$session_file\"\n            echo \"✓ Session cleared\"\n            ;;\n    esac\n}\n\n# Handle rate limiting and retries\nrobust_download_with_retries() {\n    local url=\"$1\"\n    local output_file=\"$2\"\n    local max_retries=5\n    local delay=1\n    local username=\"$3\"\n    local password=\"$4\"\n    \n    for i in $(seq 1 $max_retries); do\n        echo \"Attempt $i of $max_retries...\"\n        \n        if yt-dlp --username \"$username\" --password \"$password\" \\\n                  --retries 2 --fragment-retries 3 \\\n                  -o \"$output_file\" \"$url\"; then\n            echo \"✓ Download successful\"\n            return 0\n        fi\n        \n        echo \"Attempt $i failed\"\n        \n        # Check if it's a rate limiting issue\n        if [[ $i -lt $max_retries ]]; then\n            echo \"Waiting ${delay}s before retry...\"\n            sleep $delay\n            delay=$((delay * 2))  # Exponential backoff\n        fi\n    done\n    \n    echo \"✗ All $max_retries attempts failed\"\n    return 1\n}\n```\n\n#### 8.2.2 Course Access Validation\n```bash\n# Validate course access before attempting download\nvalidate_course_access() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    \n    echo \"Validating access to: $course_url\"\n    \n    # Extract school domain and course info\n    local school_domain=$(echo \"$course_url\" | grep -oE \"[^/]*\\.thinkific\\.com\" | sed 's/\\.thinkific\\.com//')\n    local course_id=$(echo \"$course_url\" | grep -oE \"courses/([^/]*)\" | cut -d'/' -f2)\n    \n    # Authenticate first\n    if ! manage_thinkific_auth \"$school_domain\" \"$username\" \"$password\" \"login\"; then\n        echo \"✗ Authentication failed for $school_domain\"\n        return 1\n    fi\n    \n    # Check course enrollment\n    local cookie_file=\"auth_cookies_${school_domain}.txt\"\n    local response=$(curl -s -b \"$cookie_file\" \"$course_url\")\n    \n    if echo \"$response\" | grep -q \"You are not enrolled\"; then\n        echo \"✗ Not enrolled in this course\"\n        return 1\n    elif echo \"$response\" | grep -q \"course-content\\|lesson-content\"; then\n        echo \"✓ Course access confirmed\"\n        return 0\n    else\n        echo \"? Unable to determine course access status\"\n        return 2\n    fi\n}\n\n# Batch validate multiple courses\nbatch_validate_courses() {\n    local course_list_file=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    local results_file=\"course_validation_results.txt\"\n    \n    echo \"Course Validation Results - $(date)\" \u003e \"$results_file\"\n    echo \"=========================================\" \u003e\u003e \"$results_file\"\n    \n    while IFS= read -r course_url; do\n        if [[ -n \"$course_url\" \u0026\u0026 ! \"$course_url\" =~ ^# ]]; then\n            echo \"Checking: $course_url\"\n            \n            if validate_course_access \"$course_url\" \"$username\" \"$password\"; then\n                echo \"✓ ACCESSIBLE: $course_url\" \u003e\u003e \"$results_file\"\n            else\n                echo \"✗ INACCESSIBLE: $course_url\" \u003e\u003e \"$results_file\"\n            fi\n        fi\n    done \u003c \"$course_list_file\"\n    \n    echo \"Validation complete. Results saved to: $results_file\"\n}\n```\n\n### 8.3 Performance Optimization for Course Downloads\n\n#### 8.3.1 Parallel Course Processing\n```bash\n# Download multiple courses efficiently\nparallel_course_download() {\n    local course_list_file=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    local max_parallel=\"${4:-3}\"\n    local output_base_dir=\"${5:-./courses}\"\n    \n    echo \"Starting parallel course downloads (max: $max_parallel)\"\n    \n    # Use GNU parallel for efficient processing\n    cat \"$course_list_file\" | parallel -j \"$max_parallel\" \\\n        \"download_thinkific_course {} $username $password $output_base_dir/{#}\"\n}\n\n# Smart bandwidth management\nadaptive_download_management() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    \n    # Test connection speed\n    local speed_test_url=\"https://www.thinkific.com\"\n    local speed=$(curl -w \"%{speed_download}\" -o /dev/null -s \"$speed_test_url\")\n    local speed_mbps=$(echo \"scale=2; $speed / 1024 / 1024\" | bc)\n    \n    echo \"Detected connection speed: ${speed_mbps} MB/s\"\n    \n    if (( $(echo \"$speed_mbps \u003c 1\" | bc -l) )); then\n        echo \"Slow connection detected, using mobile quality\"\n        select_course_quality \"$course_url\" \"mobile\" \"$username\" \"$password\"\n    elif (( $(echo \"$speed_mbps \u003c 5\" | bc -l) )); then\n        echo \"Medium connection detected, using standard quality\"\n        select_course_quality \"$course_url\" \"standard\" \"$username\" \"$password\"\n    else\n        echo \"Fast connection detected, using high quality\"\n        select_course_quality \"$course_url\" \"high_quality\" \"$username\" \"$password\"\n    fi\n}\n```\n\n#### 8.3.2 Progress Monitoring and Resume Capability\n```bash\n# Advanced progress tracking for course downloads\ntrack_course_download_progress() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    local progress_file=\"download_progress.json\"\n    \n    # Create progress tracking entry\n    local course_id=$(echo \"$course_url\" | grep -oE \"courses/([^/]*)\" | cut -d'/' -f2)\n    local timestamp=$(date -u +\"%Y-%m-%dT%H:%M:%SZ\")\n    \n    # Initialize progress tracking\n    if [[ ! -f \"$progress_file\" ]]; then\n        echo \"{}\" \u003e \"$progress_file\"\n    fi\n    \n    # Update progress file\n    jq \".\\\"$course_id\\\" = {\n        \\\"url\\\": \\\"$course_url\\\",\n        \\\"started\\\": \\\"$timestamp\\\",\n        \\\"status\\\": \\\"in_progress\\\",\n        \\\"username\\\": \\\"$username\\\"\n    }\" \"$progress_file\" \u003e tmp.json \u0026\u0026 mv tmp.json \"$progress_file\"\n    \n    # Start download with progress hooks\n    yt-dlp --username \"$username\" --password \"$password\" \\\n           --newline \\\n           --progress-template \"download:[%(progress.downloaded_bytes)s/%(progress.total_bytes)s] %(progress.speed)s ETA %(progress.eta)s\" \\\n           \"$course_url\"\n    \n    local exit_code=$?\n    \n    # Update completion status\n    if [[ $exit_code -eq 0 ]]; then\n        jq \".\\\"$course_id\\\".status = \\\"completed\\\"\" \"$progress_file\" \u003e tmp.json \u0026\u0026 mv tmp.json \"$progress_file\"\n        jq \".\\\"$course_id\\\".completed = \\\"$(date -u +\"%Y-%m-%dT%H:%M:%SZ\")\\\"\" \"$progress_file\" \u003e tmp.json \u0026\u0026 mv tmp.json \"$progress_file\"\n    else\n        jq \".\\\"$course_id\\\".status = \\\"failed\\\"\" \"$progress_file\" \u003e tmp.json \u0026\u0026 mv tmp.json \"$progress_file\"\n        jq \".\\\"$course_id\\\".error_code = $exit_code\" \"$progress_file\" \u003e tmp.json \u0026\u0026 mv tmp.json \"$progress_file\"\n    fi\n    \n    return $exit_code\n}\n\n# Resume interrupted downloads\nresume_course_downloads() {\n    local progress_file=\"download_progress.json\"\n    local username=\"$1\"\n    local password=\"$2\"\n    \n    if [[ ! -f \"$progress_file\" ]]; then\n        echo \"No progress file found\"\n        return 1\n    fi\n    \n    # Find interrupted downloads\n    local interrupted_courses=$(jq -r 'to_entries[] | select(.value.status == \"in_progress\" or .value.status == \"failed\") | .value.url' \"$progress_file\")\n    \n    if [[ -z \"$interrupted_courses\" ]]; then\n        echo \"No interrupted downloads found\"\n        return 0\n    fi\n    \n    echo \"Resuming interrupted downloads...\"\n    echo \"$interrupted_courses\" | while IFS= read -r course_url; do\n        echo \"Resuming: $course_url\"\n        track_course_download_progress \"$course_url\" \"$username\" \"$password\"\n    done\n}\n```\n\n---\n\n## 9. Troubleshooting and Edge Cases\n\n### 9.1 Common Authentication Issues\n\n#### 9.1.1 Multi-Factor Authentication (MFA) Handling\n```bash\n# Handle Thinkific accounts with MFA enabled\nhandle_mfa_authentication() {\n    local school_domain=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    \n    echo \"Attempting MFA authentication for $school_domain\"\n    \n    # Use browser automation for MFA\n    python3 -c \"\nfrom selenium import webdriver\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.support.ui import WebDriverWait\nfrom selenium.webdriver.support import expected_conditions as EC\nimport time\n\ndriver = webdriver.Chrome()\ntry:\n    # Navigate to login\n    driver.get('https://$school_domain.thinkific.com/users/sign_in')\n    \n    # Fill credentials\n    driver.find_element(By.NAME, 'email').send_keys('$username')\n    driver.find_element(By.NAME, 'password').send_keys('$password')\n    driver.find_element(By.CSS_SELECTOR, 'input[type=\\\"submit\\\"]').click()\n    \n    # Wait for MFA prompt\n    try:\n        mfa_input = WebDriverWait(driver, 10).until(\n            EC.presence_of_element_located((By.NAME, 'mfa_code'))\n        )\n        \n        # Prompt user for MFA code\n        print('MFA code required. Please check your authenticator app.')\n        mfa_code = input('Enter MFA code: ')\n        \n        mfa_input.send_keys(mfa_code)\n        driver.find_element(By.CSS_SELECTOR, 'input[type=\\\"submit\\\"]').click()\n        \n        # Wait for successful login\n        WebDriverWait(driver, 10).until(\n            EC.presence_of_element_located((By.CSS_SELECTOR, '[data-testid=\\\"dashboard\\\"]'))\n        )\n        \n        # Export cookies\n        cookies = driver.get_cookies()\n        with open('mfa_cookies_$school_domain.txt', 'w') as f:\n            for cookie in cookies:\n                f.write(f'{cookie[\\\"name\\\"]}={cookie[\\\"value\\\"]}; ')\n        \n        print('MFA authentication successful')\n        \n    except:\n        print('No MFA required or authentication failed')\n        \nfinally:\n    driver.quit()\n\"\n}\n\n# Use saved MFA cookies for downloads\ndownload_with_mfa_cookies() {\n    local course_url=\"$1\"\n    local school_domain=\"$2\"\n    local cookies_file=\"mfa_cookies_${school_domain}.txt\"\n    \n    if [[ -f \"$cookies_file\" ]]; then\n        echo \"Using saved MFA cookies\"\n        yt-dlp --cookies \"$cookies_file\" \"$course_url\"\n    else\n        echo \"No MFA cookies found. Please run handle_mfa_authentication first.\"\n        return 1\n    fi\n}\n```\n\n#### 9.1.2 Session Expiration Management\n```bash\n# Monitor and refresh authentication sessions\nmonitor_session_health() {\n    local school_domain=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    local check_interval=\"${4:-300}\"  # 5 minutes\n    \n    while true; do\n        if ! manage_thinkific_auth \"$school_domain\" \"$username\" \"$password\" \"verify\"; then\n            echo \"Session expired, re-authenticating...\"\n            manage_thinkific_auth \"$school_domain\" \"$username\" \"$password\" \"login\"\n        fi\n        \n        sleep \"$check_interval\"\n    done\n}\n\n# Automatic session refresh during long downloads\ndownload_with_session_refresh() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    local school_domain=$(echo \"$course_url\" | grep -oE \"[^/]*\\.thinkific\\.com\" | sed 's/\\.thinkific\\.com//')\n    \n    # Start session monitor in background\n    monitor_session_health \"$school_domain\" \"$username\" \"$password\" \u0026\n    local monitor_pid=$!\n    \n    # Start download\n    yt-dlp --username \"$username\" --password \"$password\" \"$course_url\"\n    local download_exit_code=$?\n    \n    # Stop session monitor\n    kill $monitor_pid 2\u003e/dev/null\n    \n    return $download_exit_code\n}\n```\n\n### 9.2 Content Protection and DRM Issues\n\n#### 9.2.1 Basic DRM Detection and Handling\n```bash\n# Detect DRM protection on Thinkific courses\ndetect_drm_protection() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    \n    # Get course page content\n    local school_domain=$(echo \"$course_url\" | grep -oE \"[^/]*\\.thinkific\\.com\" | sed 's/\\.thinkific\\.com//')\n    manage_thinkific_auth \"$school_domain\" \"$username\" \"$password\" \"login\"\n    \n    local cookie_file=\"auth_cookies_${school_domain}.txt\"\n    local page_content=$(curl -s -b \"$cookie_file\" \"$course_url\")\n    \n    # Check for DRM indicators\n    if echo \"$page_content\" | grep -qi \"drm\\|widevine\\|fairplay\\|playready\"; then\n        echo \"⚠ DRM protection detected\"\n        \n        # Check specific DRM types\n        if echo \"$page_content\" | grep -qi \"widevine\"; then\n            echo \"- Widevine DRM detected\"\n        fi\n        if echo \"$page_content\" | grep -qi \"fairplay\"; then\n            echo \"- FairPlay DRM detected\"\n        fi\n        if echo \"$page_content\" | grep -qi \"playready\"; then\n            echo \"- PlayReady DRM detected\"\n        fi\n        \n        return 1\n    else\n        echo \"✓ No DRM protection detected\"\n        return 0\n    fi\n}\n\n# Alternative approaches for DRM-protected content\nhandle_drm_content() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    \n    echo \"Attempting alternative methods for DRM-protected content...\"\n    \n    # Method 1: Screen recording (last resort)\n    echo \"Consider using screen recording software like:\"\n    echo \"- OBS Studio: https://obsproject.com/\"\n    echo \"- FFmpeg screen capture:\"\n    echo \"  ffmpeg -f x11grab -s 1920x1080 -i :0.0 -f alsa -i default -c:v libx264 -c:a aac screen_recording.mp4\"\n    \n    # Method 2: Browser extension approach\n    echo \"Browser extensions that may help:\"\n    echo \"- Video DownloadHelper\"\n    echo \"- Flash Video Downloader\"\n    echo \"- Stream Recorder\"\n    \n    # Method 3: Network traffic analysis\n    echo \"Network analysis approach:\"\n    echo \"1. Open browser developer tools\"\n    echo \"2. Go to Network tab\"\n    echo \"3. Play the video\"\n    echo \"4. Look for .m3u8 or .mpd files\"\n    echo \"5. Use those URLs with ffmpeg\"\n}\n```\n\n#### 9.2.2 Alternative Content Extraction Methods\n```bash\n# Extract content using browser developer tools\nextract_via_devtools() {\n    local course_url=\"$1\"\n    \n    cat \u003c\u003c 'DEVTOOLS_SCRIPT'\n# Browser Developer Tools Extraction Method\n\n1. Open the course lesson in your browser\n2. Open Developer Tools (F12)\n3. Go to Network tab\n4. Clear existing requests\n5. Play the video\n6. Filter by \"Media\" or search for \"mp4\", \"m3u8\", \"mpd\"\n7. Right-click on video requests and copy URLs\n8. Use the URLs with the commands below:\n\n# For MP4 files:\nwget -O \"lesson_video.mp4\" \"COPIED_VIDEO_URL\"\n\n# For HLS streams:\nffmpeg -i \"COPIED_M3U8_URL\" -c copy \"lesson_video.mp4\"\n\n# For DASH streams:\nffmpeg -i \"COPIED_MPD_URL\" -c copy \"lesson_video.mp4\"\n\nDEVTOOLS_SCRIPT\n}\n\n# Browser automation for content extraction\nautomated_content_extraction() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    \n    python3 -c \"\nimport json\nfrom playwright.sync_api import sync_playwright\n\ndef extract_media_urls(course_url, username, password):\n    with sync_playwright() as p:\n        browser = p.chromium.launch(headless=False)\n        page = browser.new_page()\n        \n        # Capture network requests\n        media_urls = []\n        \n        def handle_request(request):\n            if any(ext in request.url for ext in ['.mp4', '.m3u8', '.mpd', '.webm']):\n                media_urls.append(request.url)\n        \n        page.on('request', handle_request)\n        \n        # Login and navigate\n        page.goto('https://' + course_url.split('/')[2] + '/users/sign_in')\n        page.fill('input[name=\\\"email\\\"]', username)\n        page.fill('input[name=\\\"password\\\"]', password)\n        page.click('input[type=\\\"submit\\\"]')\n        \n        # Wait for login and go to course\n        page.wait_for_timeout(3000)\n        page.goto(course_url)\n        \n        # Wait for video to load and play briefly\n        page.wait_for_timeout(5000)\n        \n        # Try to play video\n        try:\n            page.click('video, .video-player, [data-testid=\\\"play-button\\\"]')\n            page.wait_for_timeout(10000)\n        except:\n            pass\n        \n        browser.close()\n        return media_urls\n\nurls = extract_media_urls('$course_url', '$username', '$password')\nfor url in urls:\n    print(url)\n\"\n}\n```\n\n### 9.3 Network and Performance Issues\n\n#### 9.3.1 Slow Download Optimization\n```bash\n# Optimize for slow connections\noptimize_for_slow_connection() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    \n    echo \"Optimizing download for slow connection...\"\n    \n    # Use lower quality and smaller segments\n    yt-dlp --username \"$username\" --password \"$password\" \\\n           -f \"worst[height\u003e=360]/best[height\u003c=480]/worst\" \\\n           --limit-rate 500K \\\n           --retries 10 \\\n           --fragment-retries 10 \\\n           --sleep-interval 1 \\\n           --max-sleep-interval 5 \\\n           \"$course_url\"\n}\n\n# Resume interrupted downloads\nresume_interrupted_download() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    local partial_file_pattern=\"*.part\"\n    \n    echo \"Checking for interrupted downloads...\"\n    \n    # Find partial files\n    if ls $partial_file_pattern 1\u003e /dev/null 2\u003e\u00261; then\n        echo \"Found partial downloads, attempting to resume...\"\n        \n        yt-dlp --username \"$username\" --password \"$password\" \\\n               --continue \\\n               --no-overwrites \\\n               \"$course_url\"\n    else\n        echo \"No interrupted downloads found\"\n        return 1\n    fi\n}\n```\n\n#### 9.3.2 Bandwidth Management\n```bash\n# Intelligent bandwidth management\nmanage_download_bandwidth() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    local time_of_day=$(date +%H)\n    \n    # Adjust settings based on time of day (peak/off-peak)\n    if [[ $time_of_day -ge 9 \u0026\u0026 $time_of_day -le 17 ]]; then\n        echo \"Peak hours detected, using conservative settings\"\n        rate_limit=\"500K\"\n        max_parallel=1\n    else\n        echo \"Off-peak hours, using aggressive settings\"\n        rate_limit=\"2M\"\n        max_parallel=3\n    fi\n    \n    yt-dlp --username \"$username\" --password \"$password\" \\\n           --limit-rate \"$rate_limit\" \\\n           --max-downloads \"$max_parallel\" \\\n           \"$course_url\"\n}\n\n# Monitor and adjust download speed dynamically\ndynamic_speed_adjustment() {\n    local course_url=\"$1\"\n    local username=\"$2\"\n    local password=\"$3\"\n    \n    # Start download with monitoring\n    yt-dlp --username \"$username\" --password \"$password\" \\\n           --newline \\\n           --progress-template \"%(progress.speed)s\" \\\n           \"$course_url\" | while IFS= read -r line; do\n        \n        # Extract speed information\n        if [[ \"$line\" =~ ([0-9.]+)([KMG])iB/s ]]; then\n            speed_value=\"${BASH_REMATCH[1]}\"\n            speed_unit=\"${BASH_REMATCH[2]}\"\n            \n            # Convert to common unit and adjust if needed\n            case \"$speed_unit\" in\n                \"K\") speed_kb=$speed_value ;;\n                \"M\") speed_kb=$(echo \"$speed_value * 1024\" | bc) ;;\n                \"G\") speed_kb=$(echo \"$speed_value * 1024 * 1024\" | bc) ;;\n            esac\n            \n            # Adjust quality if speed is too slow\n            if (( $(echo \"$speed_kb \u003c 100\" | bc -l) )); then\n                echo \"Slow speed detected ($line), consider lowering quality\"\n            fi\n        fi\n    done\n}\n```\n\n---\n\n## 10. Conclusion\n\n### 10.1 Summary of Findings\n\nThis research has comprehensively analyzed Thinkific's video delivery infrastructure, revealing a sophisticated learning management system that utilizes AWS CloudFront for content delivery with robust authentication and access control mechanisms. Our analysis identified various approaches for video extraction across different scenarios, from public course content to protected educational materials.\n\n**Key Technical Findings:**\n- Thinkific employs AWS CloudFront as its primary CDN with multiple fallback endpoints\n- Authentication is course enrollment-based with session management and potential MFA support\n- Video URLs follow predictable patterns but require proper authentication\n- Multiple quality levels are available with adaptive streaming support\n- Some courses may employ basic DRM protection mechanisms\n\n### 10.2 Recommended Implementation Approach\n\nBased on our research, we recommend a **multi-layered authentication and download strategy**:\n\n1. **Primary Method**: yt-dlp with proper credentials (80% success rate expected)\n2. **Secondary Method**: Browser cookie extraction and reuse\n3. **Tertiary Method**: Browser automation for complex authentication\n4. **Backup Methods**: Direct URL extraction via developer tools and API access\n\n### 10.3 Tool Recommendations\n\n**Essential Tools:**\n- **yt-dlp**: Primary download tool with authentication support\n- **ffmpeg**: Stream processing and format conversion\n- **curl/wget**: Direct downloads with session management\n\n**Authentication Tools:**\n- **Browser automation**: Selenium/Playwright for complex login flows\n- **Cookie extraction**: Browser cookie export for session reuse\n- **Session management**: Custom scripts for token refresh\n\n**Backup Tools:**\n- **Gallery-dl**: Alternative platform support\n- **Streamlink**: Live session recording\n- **Screen recording**: OBS/FFmpeg for DRM-protected content\n\n### 10.4 Performance Considerations\n\nOptimal performance achieved with:\n- **Authentication Management**: Proper session handling and refresh\n- **Quality Selection**: Adaptive quality based on use case (mobile/standard/high)\n- **Rate Limiting**: Respectful request patterns to avoid account suspension\n- **Parallel Downloads**: Limited concurrent access (2-3 courses maximum)\n- **Resume Capability**: Robust handling of interrupted downloads\n\n### 10.5 Security and Compliance Notes\n\n**Critical Considerations:**\n- Respect Thinkific's Terms of Service and course creator rights\n- Ensure proper course enrollment before attempting downloads\n- Implement appropriate authentication and session management\n- Consider educational fair use guidelines\n- Protect user credentials and session information\n\n### 10.6 Educational Use Case Optimization\n\n**Specific Recommendations for Educational Content:**\n1. **Offline Learning**: Optimize for mobile devices and limited bandwidth\n2. **Course Organization**: Maintain logical file structure by course/chapter/lesson\n3. **Multi-format Support**: Provide video and audio-only versions\n4. **Progress Tracking**: Implement resume and completion tracking\n5. **Quality Selection**: Balance file size with educational value\n\n### 10.7 Future Research Directions\n\n**Areas for Continued Development:**\n1. **Enhanced Authentication**: OAuth 2.0 and SSO integration support\n2. **Advanced DRM Handling**: Research into educational content protection bypass\n3. **Mobile App Support**: Extraction from Thinkific mobile applications\n4. **Bulk Processing**: Efficient whole-school or multi-course downloads\n5. **Integration APIs**: Direct integration with Thinkific's official APIs\n6. **Quality Enhancement**: AI-powered video enhancement for educational content\n\n### 10.8 Maintenance and Updates\n\nThis research requires regular updates due to platform evolution:\n- **Monthly**: Authentication mechanism validation\n- **Quarterly**: URL pattern and CDN endpoint verification\n- **Bi-annually**: Tool compatibility and method effectiveness review\n- **Annually**: Comprehensive strategy and legal compliance review\n\nThe methodologies and tools documented in this research provide a robust foundation for educational content archival while respecting platform policies and creator rights. The focus on authentication management and ethical usage ensures sustainable access to educational resources.\n\n---\n\n**Legal Disclaimer**: This research is provided for educational and legitimate archival purposes only. Users must:\n- Ensure proper course enrollment before downloading content\n- Comply with Thinkific's Terms of Service and usage policies\n- Respect course creator intellectual property rights\n- Follow applicable copyright and educational fair use laws\n- Use downloaded content only for personal educational purposes\n\n**Last Updated**: September 2024  \n**Research Version**: 1.0  \n**Next Review**: December 2024\n\n\n\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fserpapps%2Fthinkific-downloader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fserpapps%2Fthinkific-downloader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fserpapps%2Fthinkific-downloader/lists"}