Skip to content

AhmadRamadan74/Youtube-Downloader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Youtube-Downloader

A full-stack video downloader with a built-in trim feature. Supports YouTube, X (Twitter), Instagram, and Facebook. Download any quality, or trim the video to an exact clip before downloading — all for free with a real-time progress bar.


Features

  • Download videos from YouTube, X, Instagram, and Facebook
  • Choose download quality (144p up to 1080p+)
  • Trim videos to an exact start and end time before downloading
  • Real-time progress bar during download and trim phases
  • Automatic server-side caching — re-downloading the same video is instant
  • Files auto-deleted from server after 2 hours

Tech Stack

Frontend

  • React + Vite
  • Tailwind CSS v4
  • React Router DOM
  • Axios

Backend

  • Node.js + Express
  • yt-dlp (video fetching and downloading)
  • ffmpeg (video trimming and re-encoding)
  • Server-Sent Events (SSE) for real-time progress streaming

Prerequisites

Make sure these are installed globally on your machine before running the project.

Node.jshttps://nodejs.org (LTS version)

yt-dlp

winget install yt-dlp

ffmpeg

winget install ffmpeg

Verify both are on your PATH:

yt-dlp --version
ffmpeg -version

Project Structure

youtube-downloader/
├── backend/
│   ├── src/
│   │   ├── controllers/
│   │   │   ├── video.controller.js       # Fetch video metadata
│   │   │   └── download.controller.js    # SSE stream, serve files
│   │   ├── middleware/
│   │   │   ├── cors.js
│   │   │   └── errorHandler.js
│   │   ├── routes/
│   │   │   ├── video.routes.js
│   │   │   └── download.routes.js
│   │   ├── services/
│   │   │   ├── ytdlp.service.js          # yt-dlp wrapper
│   │   │   ├── ffmpeg.service.js         # ffmpeg trim wrapper
│   │   │   └── cache.service.js          # disk cache + cleanup
│   │   ├── app.js
│   │   └── server.js
│   ├── temp/                             # Raw yt-dlp downloads (auto-created)
│   ├── output/                           # Trimmed files (auto-created)
│   ├── .env
│   └── package.json
│
└── frontend/
    ├── src/
    │   ├── components/
    │   │   ├── PlatformSelector.jsx
    │   │   ├── VideoCard.jsx
    │   │   ├── QualitySelector.jsx
    │   │   ├── TrimControls.jsx
    │   │   └── ProgressBar.jsx
    │   ├── pages/
    │   │   ├── HomePage.jsx
    │   │   ├── VideoPage.jsx
    │   │   └── ResultPage.jsx
    │   ├── services/
    │   │   └── api.js
    │   ├── App.jsx
    │   ├── main.jsx
    │   └── index.css
    └── package.json

Setup

Backend

cd backend
npm install

Create a .env file in the backend/ folder:

PORT=5000
TEMP_DIR=./temp
OUTPUT_DIR=./output
MAX_FILE_AGE_HOURS=2

Start the dev server:

npm run dev

Backend runs on http://localhost:5000


Frontend

cd frontend
npm install
npm run dev

Frontend runs on http://localhost:5173


API Endpoints

Method Endpoint Description
GET /api/video/info?url= Fetch video metadata and available qualities
POST /api/download/start Start download or trim+download via SSE stream
GET /api/download/file/:filename Serve the final file for download

POST /api/download/start body

{
  "url": "https://www.youtube.com/watch?v=...",
  "formatId": "137",
  "height": 1080,
  "trim": { "start": 30, "end": 90 }
}

trim is optional — omit it for a normal download without trimming.

SSE Events

The /api/download/start endpoint streams Server-Sent Events:

event: progress
data: { "phase": "download", "percent": 45.3 }

event: progress
data: { "phase": "trim", "percent": 72.1 }

event: done
data: { "filename": "abc123.mp4" }

event: error
data: { "message": "Download failed" }

How It Works

  1. User pastes a video URL on the home page and clicks Fetch
  2. Backend calls yt-dlp --dump-json to get metadata without downloading
  3. Frontend shows video info, available qualities, and Download / Trim & Download tabs
  4. User picks quality and optionally sets trim start/end points
  5. Frontend opens a fetch() stream to the backend (POST with JSON body)
  6. Backend spawns yt-dlp to download the video to temp/, streaming progress via SSE
  7. If trimming, backend then spawns ffmpeg to re-encode the clip to output/, also streaming progress
  8. When complete, backend sends a done event with the filename
  9. Frontend navigates to the result page where the user can save the file
  10. Files are automatically deleted from the server after 2 hours

Caching

The first time a URL + quality combination is downloaded, the file is saved to temp/ with an MD5 hash of the URL+formatId as the filename. If the same video and quality are requested again within 2 hours, the cached file is used immediately — no re-download.


Notes

  • For personal use only. Respect content creators and platform terms of service.
  • Trim re-encodes the video using libx264 at CRF 18 (near-lossless) to avoid keyframe boundary artifacts that occur with stream copying.
  • The progress bar uses SSE instead of WebSockets because progress only flows in one direction — server to client — making SSE simpler and sufficient.

About

A full-stack video downloader with a built-in trim feature. Supports YouTube, X (Twitter), Instagram, and Facebook.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors