A local learning portal for Udemy courses — stream, study, and master any course offline.
This player is built to help you learn faster and retain more information:
- Intelligent Course Scanner: Point the player at your downloaded course folder. It automatically organizes lessons, chapters, and companion files into a clean sidebar menu. Supports
.mp4,.m4v, and.mkvvideo files. (Auto-generated.chapters.jsonand.summary.*.txtfiles are automatically filtered out to keep your companion resources list clean and uncluttered.) - Coordinated Tab View: Study side-by-side. If a lesson contains both a video and companion resources (like PDFs or cheat sheets), the player shows them together in coordinated tabs.
- Custom HTML5 Video Stage:
- Supports adjustable playback speeds (
1x,1.25x,1.5x,1.75x,2x). - Theater Mode (
t): collapses headers and sidebars with smooth animated transitions for a distraction-free viewing experience. A floating tab bar overlays the video area, letting you switch between video and companion resources or exit theater mode without leaving full focus. - Auto-Hide Floating Controls: overlay panels (subtitles, speed, autoplay, panel toggles) fade out after 2.5s of mouse inactivity while the video plays, keeping the focus on the content.
- Subtitle Size Control: fine-tune subtitle display from 50% to 160%.
- Browser hotkeys:
Space(play/pause),Arrow Left/Right(skip 5 seconds),Arrow Up/Down(volume),F(fullscreen),B(sidebar),N(notes),C(toggle chapters panel), andT(theater mode).
- Supports adjustable playback speeds (
- Interactive Notes Timeline: Type notes as you watch. The player pauses the video automatically while you type, and links each note to a click-to-seek timestamp.
- Auto-Completion & Auto-Save: Lessons are marked complete at
90%watch progress. Your playback position saves every 5 seconds so you can resume exactly where you left off. - Multi-Provider AI Subtitle Translation: Automatically translate English subtitle tracks to your native language using your active AI provider—supporting Google Gemini, Anthropic Claude, or OpenAI / OpenAI-compatible endpoints (such as OpenRouter, DeepSeek, Ollama, LM Studio, vLLM, Groq).
- Dual Subtitle Display: Watch with two subtitle tracks simultaneously (e.g., English + your native language). The player merges both WebVTT tracks in real time, showing the secondary language in a distinct style below the primary subtitles.
- Offline AI Lesson & Chapter Summarization: Generate structured, bulleted summaries for individual video lessons or entire course chapters in any supported language using your configured AI provider (Google Gemini, Anthropic Claude, or OpenAI / Compatible). Select your target output language via the dropdown selector prior to generating to control output and conserve AI quota. Summaries cache locally on disk (
.summary.<lang>.txtandsection.summary.<lang>.txt), letting you review them instantly without internet access. - Transcript-Grounded AI Chat: Ask questions about the lesson in the chat sidebar. The AI answers using the active subtitle transcript as context, powered by your selected AI provider.
- Auto-Generated Timeline Chapters: The player automatically analyzes lesson subtitle transcripts via AI (Gemini, Anthropic, or OpenAI / Compatible) to generate structured video chapters on the playback timeline, allowing you to easily browse and jump to different sections of the video.
- Video Duration Display: The sidebar shows individual lesson durations, section totals, and overall course duration, helping you plan your study sessions.
- Dynamic Window Title: The window/document title updates to show the currently playing lesson and its playback status (▶ playing / ⏸ paused).
udemy-player/
├── backend/
│ ├── server.js # Express server with range-streaming, VTT conversion, MKV remux/cache, & persistence APIs
│ ├── scanner.js # File grouping and section sorting scanner (.mp4, .m4v, .mkv)
│ ├── lib/
│ │ ├── ffmpeg-path.js # 3-tier binary resolution (bundled → local dev → system PATH)
│ │ ├── path-env.js # PATH augmentation for macOS GUI / Electron contexts
│ │ └── subtitle.js # Subtitle cue parser
│ ├── progress_db.json # Local user notes and completion database (JSON)
│ └── package.json # Backend server dependencies
├── bin/ # Static ffmpeg/ffprobe binaries (downloaded, git-ignored)
├── bin-paths.js # Shared bin/ directory structure constants
├── scripts/
│ └── download-binaries.js # Downloads platform-specific ffmpeg/ffprobe static builds
├── docs/ # Technical specifications, implementation plans, and task lists
├── frontend/ # Vite React client
│ ├── src/
│ │ ├── components/ # CourseSelector, Sidebar, VideoPlayer, DocViewer, NotesPanel, ChapterSummaryModal
│ │ ├── App.jsx # App logic controller
│ │ ├── main.jsx # Client entry
│ │ └── index.css # Dark-mode styling tokens and layout rules
│ ├── vite.config.js # Dev server proxy configuration
│ └── package.json # Client dependencies
├── package.json # Root runner scripts (starts concurrently)
└── README.md # Project documentation
- Node.js (v16+)
ffmpeg(v5+) andffprobe— required for.mkvvideo playback. Thepostinstallscript automatically downloads static builds intobin/, so a system-wide install is optional. If you prefer a system install:To manually re-download the static binaries at any time:brew install ffmpeg # macOSnpm run download-binaries
Install all root, client, and server dependencies in one command.
The postinstall hook will also download static ffmpeg / ffprobe binaries for
your platform into bin/.
npm run install:allStart both the API backend (Express on port 3003) and client frontend (Vite on port 3002) concurrently:
npm run devVisit http://localhost:3002 to browse and play your courses.
To package and run the application as a standalone desktop app on macOS:
- Ensure the static binaries are downloaded (they are bundled into the app):
npm run download-binaries
- Build the frontend and compile the package:
npm run package
- Drag Udemy Offline Player.app from
dist-desktop/to your/Applicationsfolder. - If macOS Gatekeeper blocks the app from running, remove the quarantine attribute and self-sign it:
# Remove the quarantine attribute xattr -cr /Applications/Udemy\ Offline\ Player.app # Self-sign the application codesign --force --deep --sign - /Applications/Udemy\ Offline\ Player.app
- Launch the application normally from Applications or Launchpad.
GET /api/course-content?path=<absolute-path>: Scans the folder and returns grouped chapters and lesson resources.GET /api/stream?path=<video-file-path>: Streams local video assets supporting Byte-Range header requests..mkvfiles are auto-remuxed to MP4 and cached in the OS temp directory for subsequent instant playback.GET /api/subtitle?path=<subtitle-file-path>: Feeds SubRip (.srt) contents converted to WebVTT format on-the-fly.GET /api/resource?path=<document-file-path>: Serves PDFs and HTML checkpoints securely.GET /api/userdata: Returns completion logs, note timelines, and active paths.POST /api/userdata/course: Scans and adds new course path to recent history.POST /api/userdata/progress: Updates completion states and watch logs.POST /api/userdata/notes: Inserts or updates annotation notes.DELETE /api/userdata/notes: Removes note entries from a lesson timeline.POST /api/userdata/settings: Saves application settings (such as Active AI Provider selection, API Keys, Model Names, and Custom Base URLs for Gemini, Anthropic, and OpenAI / Compatible endpoints).POST /api/translate-subtitle: Translates subtitles using the active AI provider.POST /api/summarize-lesson: Checks cache or generates lesson summaries using AI.POST /api/clear-summary: Removes cached lesson summary file for a given language.POST /api/summarize-section: Checks cache or aggregates subtitles across a chapter to generate chapter summaries using AI.POST /api/clear-section-summary: Removes cached chapter summary file for a given language.POST /api/chat-lesson: Chat assistant grounded in the subtitles transcript.POST /api/browse-folder: Launches native OS folder dialog window.GET /api/chapters?videoPath=<path>&subtitlePath=<path>: Loads cached timeline chapters or generates them from subtitles via AI.POST /api/chapters/regenerate: Forces regeneration of timeline chapters using subtitles and overwrites the local cache.
