├── README.md ├── css └── style.css ├── index.php ├── js └── color_palette.js ├── res └── favicon.png └── scripts ├── GetVideoInfo.php ├── download_img.php └── download_video.php /README.md: -------------------------------------------------------------------------------- 1 | # youtube_video_downloader 2 | 3 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;800;900&display=swap"); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: border-box; 7 | font-family: "Poppins", sans-serif; 8 | } 9 | 10 | :root { 11 | --primary-color: #4193f0; 12 | --text-color-dark: #333; 13 | --text-color-light: #fff; 14 | --light-grey: #f5f5f5; 15 | } 16 | 17 | .downloader { 18 | height: 100vh; 19 | width: 100%; 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | flex-direction: column; 24 | background-color: var(--primary-color); 25 | } 26 | 27 | .main { 28 | width: 426px; 29 | display: flex; 30 | flex-direction: column; 31 | padding: 15px; 32 | border-radius: 5px; 33 | /* background: var(--text-color-light); 34 | box-shadow: 0.1px 4px 8px 2px rgba(0, 0, 0, 0.05); */ 35 | background: rgba(255, 255, 255, 0.25); 36 | box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); 37 | backdrop-filter: blur(4px); 38 | -webkit-backdrop-filter: blur(4px); 39 | border-radius: 10px; 40 | border: 1px solid rgba(255, 255, 255, 0.18); 41 | } 42 | 43 | .main form { 44 | width: 100%; 45 | height: 45px; 46 | display: flex; 47 | justify-content: space-between; 48 | } 49 | 50 | .main form input:first-child { 51 | width: 80%; 52 | height: 100%; 53 | padding: 10px; 54 | border: none; 55 | outline: none; 56 | margin-right: 4px; 57 | border-radius: 5px; 58 | font-size: 1em; 59 | box-shadow: 0.1px 2px 8px 4px rgba(0, 0, 0, 0.05); 60 | } 61 | 62 | .main form input:last-child { 63 | width: 20%; 64 | height: 100%; 65 | padding: 10px; 66 | margin-left: 4px; 67 | border: none; 68 | outline: none; 69 | border-radius: 5px; 70 | background: var(--primary-color); 71 | color: var(--text-color-light); 72 | font-size: 1em; 73 | cursor: pointer; 74 | box-shadow: 0.1px 2px 8px 4px rgba(0, 0, 0, 0.05); 75 | } 76 | 77 | .video_detail_box { 78 | width: 100%; 79 | margin-top: 1em; 80 | } 81 | 82 | .video_detail_box .thumbnail_box { 83 | position: relative; 84 | } 85 | 86 | .thumbnail_box #img_download_btn { 87 | position: absolute; 88 | right: 10px; 89 | bottom: 10px; 90 | color: var(--text-color-light); 91 | height: 35px; 92 | width: 35px; 93 | border-radius: 50%; 94 | text-decoration: none; 95 | display: inline-flex; 96 | align-items: center; 97 | justify-content: center; 98 | background: var(--primary-color); 99 | } 100 | 101 | .thumbnail_box #original_video_link_btn { 102 | position: absolute; 103 | right: 55px; 104 | bottom: 10px; 105 | color: var(--text-color-light); 106 | height: 35px; 107 | width: 35px; 108 | border-radius: 50%; 109 | text-decoration: none; 110 | display: inline-flex; 111 | align-items: center; 112 | justify-content: center; 113 | background: #ec407a; 114 | } 115 | 116 | .thumbnail_box img { 117 | height: auto; 118 | width: 100%; 119 | border-radius: 5px; 120 | object-fit: cover; 121 | } 122 | 123 | .text_info { 124 | width: 100%; 125 | display: flex; 126 | flex-direction: column; 127 | margin-top: 10px; 128 | } 129 | 130 | .text_info table { 131 | border: 1px dashed #ccc; 132 | margin-top: 10px; 133 | } 134 | 135 | .text_info table th { 136 | padding: 10px; 137 | } 138 | .text_info table td { 139 | text-align: center; 140 | padding: 10px; 141 | } 142 | 143 | .additional_info { 144 | display: flex; 145 | align-items: center; 146 | margin-top: 10px; 147 | } 148 | 149 | .additional_info a { 150 | padding: 5px 10px 5px 10px; 151 | color: var(--text-color-light); 152 | font-size: 13px; 153 | border-radius: 5px; 154 | text-decoration: none; 155 | background: var(--primary-color); 156 | } 157 | 158 | .additional_info p { 159 | padding: 5px 10px 5px 10px; 160 | color: #000; 161 | font-size: 13px; 162 | border-radius: 5px; 163 | margin-left: 5px; 164 | box-shadow: 0.1px 2px 8px 4px rgba(0, 0, 0, 0.05); 165 | } 166 | 167 | #download_btn { 168 | color: var(--text-color-light); 169 | text-decoration: none; 170 | background: var(--primary-color); 171 | padding-left: 10px; 172 | padding-right: 10px; 173 | padding-top: 5px; 174 | padding-bottom: 5px; 175 | border-radius: 5px; 176 | font-size: 15px; 177 | display: inline-block; 178 | } 179 | 180 | .instruction_box { 181 | width: 100%; 182 | display: flex; 183 | align-items: center; 184 | justify-content: center; 185 | flex-direction: column; 186 | margin-top: 2em; 187 | } 188 | 189 | .instruction_box h3 { 190 | margin-top: 10px; 191 | } 192 | .instruction_box p { 193 | font-size: 14px; 194 | margin-top: 5px; 195 | } 196 | 197 | .instruction_box label { 198 | height: 50px; 199 | width: 50px; 200 | border-radius: 50%; 201 | background: var(--primary-color); 202 | display: flex; 203 | align-items: center; 204 | justify-content: center; 205 | } 206 | 207 | .instruction_box label i { 208 | color: var(--text-color-light); 209 | font-size: 1.2em; 210 | } 211 | 212 | /* COLOR PALETTE */ 213 | 214 | .color-palette { 215 | position: absolute; 216 | display: flex; 217 | flex-direction: column; 218 | justify-content: center; 219 | margin: 12px; 220 | right: 0; 221 | background: rgba(255, 255, 255, 0.2); 222 | box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); 223 | backdrop-filter: blur(1.5px); 224 | -webkit-backdrop-filter: blur(1.5px); 225 | border-radius: 10px; 226 | border: 1px solid rgba(255, 255, 255, 0.18); 227 | border-radius: 30px; 228 | padding: 8px; 229 | text-align: center; 230 | top: 50%; 231 | -ms-transform: translateY(-50%); 232 | transform: translateY(-50%); 233 | } 234 | 235 | .color-palette .theme-color { 236 | background-color: red; 237 | border-radius: 50%; 238 | width: 30px; 239 | height: 30px; 240 | cursor: pointer; 241 | } 242 | 243 | .color-palette .theme-color:not(:last-child) { 244 | margin-bottom: 10px; 245 | } 246 | 247 | /* drak mode palette */ 248 | 249 | .dark-mode { 250 | position: absolute; 251 | top: 12px; 252 | right: 12px; 253 | background: rgba(255, 255, 255, 0.25); 254 | box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); 255 | backdrop-filter: blur(4px); 256 | -webkit-backdrop-filter: blur(4px); 257 | border-radius: 50%; 258 | padding: 8px 13px; 259 | border: 1px solid rgba(255, 255, 255, 0.18); 260 | } 261 | 262 | .dark-mode span { 263 | font-size: 20px; 264 | cursor: pointer; 265 | } 266 | 267 | @media (max-width: 800px) { 268 | .main { 269 | width: 70%; 270 | } 271 | } 272 | 273 | @media (max-width: 500px) { 274 | .main { 275 | width: 80%; 276 | } 277 | } 278 | 279 | @media (max-width: 400px) { 280 | .text_info table tbody tr th { 281 | font-size: 14px; 282 | } 283 | 284 | #download_btn { 285 | font-size: 8px; 286 | } 287 | } 288 | 289 | /* Media Queries */ 290 | @media only screen and (max-width: 436px) { 291 | .color-palette { 292 | max-width: 90%; 293 | min-width: 90%; 294 | } 295 | 296 | .color-palette .theme-color { 297 | width: 22px; 298 | height: 22px; 299 | } 300 | } 301 | 302 | @media only screen and (max-width: 636px) { 303 | .color-palette { 304 | flex-direction: row; 305 | justify-content: center; 306 | left: 50%; 307 | bottom: 0; 308 | padding: 0; 309 | margin: 0 auto; 310 | width: 400px; 311 | margin-bottom: 16px; 312 | text-align: center; 313 | /*to remove*/ 314 | top: auto; 315 | transform: translateX(-50%); 316 | } 317 | 318 | .color-palette .theme-color { 319 | margin-top: 10px; 320 | } 321 | 322 | .color-palette .theme-color:not(:last-child) { 323 | margin-right: 10px; 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | playabilityStatus->status; 17 | 18 | $formats = $video->streamingData->formats; 19 | $thumbnails = $video->videoDetails->thumbnail->thumbnails; 20 | $title = $video->videoDetails->title; 21 | $short_description = $video->videoDetails->shortDescription; 22 | $channel_id = $video->videoDetails->channelId; 23 | $channel_name = $video->videoDetails->author; 24 | $views = $video->videoDetails->viewCount; 25 | $video_duration_in_seconds = $video->videoDetails->lengthSeconds; 26 | $thumbnail = end($thumbnails)->url; 27 | 28 | // seconds to minutes&hours 29 | $hours = floor($video_duration_in_seconds / 3600); 30 | $minutes = floor(($video_duration_in_seconds / 60) % 60); 31 | $seconds = $video_duration_in_seconds % 60; 32 | } 33 | } 34 | } 35 | 36 | ?> 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Youtube Video Downloader 51 | 52 | 53 | 54 | 55 | 56 |
57 | 58 | 59 | 60 |
61 | 62 | 63 | 64 |
65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
75 | 76 |
77 | 78 |
79 |
80 | 81 | 82 |
83 | 84 | 86 |
87 | 88 |

Entered url is invalid.

89 |

make sure url is valid.

90 |
91 | 92 |
93 | 94 |

Copy video url & paste here.

95 |

make sure url is valid.

96 |
97 | 98 | 99 | 100 |
101 |
102 | thumbnail 103 | 104 | 105 |
106 | 107 | url == "") { ?> 110 |
111 | 112 |

Unsupported.

113 |

This video is currently unsupported.

114 |
115 | 116 | 117 | 118 |
119 |

120 | 121 |
122 | 123 |

 

124 |

 

125 |
126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | url == "") { 138 | $signature = "https://youtube.com?" . $format->signatureCipher; 139 | parse_str(parse_url($signature, PHP_URL_QUERY), $parse_signature); 140 | $url = $parse_signature['url'] . "&sig=" . $parse_signature['s']; 141 | } else { 142 | $url = $format->url; 143 | } 144 | ?> 145 | 146 | 147 | 150 | 153 | 155 | 156 | 157 | 158 | 159 |
QualityFormatDownload
qualityLabel) echo $format->qualityLabel; 148 | else echo "Unknown"; ?> 149 | mimeType) echo explode(";", explode("/", $format->mimeType)[1])[0]; 151 | else echo "Unknown"; ?> 152 | mimeType)[1])[0]; 154 | else echo "mp4"; ?>" id="download_btn"> Download
160 | 161 |
162 |
163 | 164 | 167 |
168 | 169 |

Unable to fetch video info.

170 |

make sure url is valid.

171 |
172 | 173 |
174 |
175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /js/color_palette.js: -------------------------------------------------------------------------------- 1 | //get the theme from local storage 2 | getTheme(); 3 | 4 | //color palette 5 | const colors = [ 6 | "hsl(345, 80%, 50%)", 7 | "hsl(100, 80%, 50%)", 8 | "hsl(200, 80%, 50%)", 9 | "hsl(227, 66%, 55%)", 10 | "hsl(26, 80%, 50%)", 11 | "hsl(44, 90%, 51%)", 12 | "hsl(280, 100%, 65%)", 13 | "hsl(480, 100%, 25%)", 14 | "hsl(180, 100%, 25%)", 15 | ]; 16 | 17 | const colorBtns = document.querySelectorAll(".theme-color"); 18 | const darkModeBtn = document.querySelector(".dark-mode-btn"); 19 | 20 | //change theme to dark 21 | var isDark = false; 22 | darkModeBtn.addEventListener("click", () => { 23 | if(!isDark) { 24 | changeTheme("#000"); 25 | isDark = true; 26 | }else{ 27 | changeTheme(colors[3]); 28 | isDark = false; 29 | } 30 | }); 31 | 32 | //loop through colors array and set each color to a button 33 | for (let i = 0; i < colorBtns.length; i++) { 34 | colorBtns[i].style.backgroundColor = colors[i]; 35 | } 36 | 37 | colorBtns.forEach((btn) => { 38 | btn.addEventListener("click", () => { 39 | changeTheme(btn.style.backgroundColor); 40 | }); 41 | }); 42 | 43 | function changeTheme(color) { 44 | document.documentElement.style.setProperty("--primary-color", color); 45 | saveTheme(color); 46 | } 47 | 48 | //get the theme from local storage 49 | function getTheme() { 50 | const theme = localStorage.getItem("theme"); 51 | if (theme) { 52 | changeTheme(theme); 53 | } 54 | } 55 | 56 | //save the theme to local storage 57 | function saveTheme(color) { 58 | localStorage.setItem("theme", color); 59 | } 60 | -------------------------------------------------------------------------------- /res/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdellatif-laghjaj/youtube_video_downloader/aec23010efcbd10a6375d9d9c6b5f0a99f26e843/res/favicon.png -------------------------------------------------------------------------------- /scripts/GetVideoInfo.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/download_img.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/download_video.php: -------------------------------------------------------------------------------- 1 |