Last active
December 7, 2025 02:23
-
-
Save su8/91f6a0753fa9f68f2d5e1220fd99bc5b to your computer and use it in GitHub Desktop.
yt-dl.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //g++ youtube_downloader.cpp -o youtube_downloader -lcurl | |
| #include <iostream> | |
| #include <string> | |
| #include <cstdio> | |
| #include <cstdlib> | |
| #include <array> | |
| #include <memory> | |
| #include <stdexcept> | |
| #include <sys/stat.h> | |
| #include <curl/curl.h> | |
| // Function to execute a shell command and capture its output | |
| std::string execCommand(const std::string &cmd) { | |
| std::array<char, 256> buffer{}; | |
| std::string result; | |
| FILE *pipe = popen(cmd.c_str(), "r"); | |
| if (!pipe) throw std::runtime_error("Failed to run command"); | |
| while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) { | |
| result += buffer.data(); | |
| } | |
| pclose(pipe); | |
| return result; | |
| } | |
| // Callback for libcurl to write data to file | |
| size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) { | |
| return fwrite(ptr, size, nmemb, stream); | |
| } | |
| // Progress callback for libcurl | |
| int progress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t, curl_off_t) { | |
| if (dltotal > 0) { | |
| double progress = (double)dlnow / (double)dltotal * 100.0; | |
| std::cout << "\rDownloading: " << (int)progress << "% (" << dlnow / 1024 << " KB / " << dltotal / 1024 << " KB)" << std::flush; | |
| } | |
| return 0; // return non-zero to abort | |
| } | |
| // Get file size if exists (for resume) | |
| long getFileSize(const std::string &filename) { | |
| struct stat st; | |
| if (stat(filename.c_str(), &st) == 0) { | |
| return st.st_size; | |
| } | |
| return 0; | |
| } | |
| int main(int argc, char *argv[]) { | |
| if (argc < 2) { std::cout << argv[0] << " requires argument with the yt video link." << std::endl; return EXIT_FAILURE; } | |
| std::string youtubeURL = argv[1]; | |
| if (youtubeURL.empty()) { | |
| std::cerr << "Error: No URL provided.\n"; | |
| return EXIT_FAILURE; | |
| } | |
| try { | |
| // Step 1: Get direct video URL using yt-dlp | |
| std::string cmd = "yt-dlp -g \"" + youtubeURL + "\" 2>/dev/null"; | |
| std::string directURL = execCommand(cmd); | |
| // Remove trailing newline | |
| if (!directURL.empty() && directURL.back() == '\n') { | |
| directURL.pop_back(); | |
| } | |
| if (directURL.empty()) { | |
| std::cerr << "Error: Could not retrieve direct video URL.\n"; | |
| return EXIT_FAILURE; | |
| } | |
| std::cout << "Direct video URL retrieved:\n" << directURL << "\n"; | |
| // Step 2: Download the file using libcurl | |
| CURL *curl = curl_easy_init(); | |
| if (!curl) { | |
| std::cerr << "Error: Could not initialize libcurl.\n"; | |
| return EXIT_FAILURE; | |
| } | |
| const char *outputFile = "video.mp4"; | |
| // Step 3: Resume support | |
| long existingSize = getFileSize(outputFile); | |
| FILE *fp = fopen(outputFile, existingSize > 0 ? "ab" : "wb"); | |
| if (!fp) { | |
| std::cerr << "Error: Could not open file for writing.\n"; | |
| return EXIT_FAILURE; | |
| } | |
| curl_easy_setopt(curl, CURLOPT_URL, directURL.c_str()); | |
| curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); | |
| curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); | |
| curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); | |
| curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0"); | |
| // Resume from existing size | |
| if (existingSize > 0) { | |
| std::cout << "Resuming from " << existingSize / 1024 << " KB...\n"; | |
| curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, (curl_off_t)existingSize); | |
| } | |
| // Progress bar | |
| curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); | |
| curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback); | |
| CURLcode res = curl_easy_perform(curl); | |
| if (res != CURLE_OK) { | |
| std::cerr << "Download failed: " << curl_easy_strerror(res) << "\n"; | |
| } else { | |
| std::cout << "Download completed successfully: " << outputFile << "\n"; | |
| } | |
| fclose(fp); | |
| curl_easy_cleanup(curl); | |
| } catch (const std::exception &e) { | |
| std::cerr << "Exception: " << e.what() << "\n"; | |
| return EXIT_FAILURE; | |
| } | |
| return EXIT_SUCCESS; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment