Sunday, 11 May 2025

Need Node Js video downloader

 Here's an HTML implementation of your YouTube video downloader code with syntax highlighting and a user interface to make it more usable:


```html

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>YouTube Video Downloader</title>

    <style>

        body {

            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

            max-width: 900px;

            margin: 0 auto;

            padding: 20px;

            background-color: #f5f5f5;

            color: #333;

        }

        h1 {

            color: #ff0000;

            text-align: center;

        }

        .container {

            background-color: white;

            border-radius: 8px;

            padding: 20px;

            box-shadow: 0 2px 10px rgba(0,0,0,0.1);

        }

        .input-group {

            margin-bottom: 20px;

        }

        label {

            display: block;

            margin-bottom: 5px;

            font-weight: bold;

        }

        input, select {

            width: 100%;

            padding: 10px;

            border: 1px solid #ddd;

            border-radius: 4px;

            font-size: 16px;

        }

        button {

            background-color: #ff0000;

            color: white;

            border: none;

            padding: 12px 20px;

            border-radius: 4px;

            cursor: pointer;

            font-size: 16px;

            width: 100%;

            transition: background-color 0.3s;

        }

        button:hover {

            background-color: #cc0000;

        }

        .progress-container {

            margin-top: 20px;

            display: none;

        }

        .progress-bar {

            height: 20px;

            background-color: #e0e0e0;

            border-radius: 10px;

            margin-bottom: 10px;

            overflow: hidden;

        }

        .progress {

            height: 100%;

            background-color: #4CAF50;

            width: 0%;

            transition: width 0.3s;

        }

        .progress-info {

            display: flex;

            justify-content: space-between;

        }

        pre {

            background-color: #282c34;

            color: #abb2bf;

            padding: 15px;

            border-radius: 5px;

            overflow-x: auto;

            margin-top: 20px;

        }

        .comment { color: #5c6370; font-style: italic; }

        .keyword { color: #c678dd; }

        .string { color: #98c379; }

        .function { color: #61afef; }

        .variable { color: #e06c75; }

        .number { color: #d19a66; }

        .operator { color: #56b6c2; }

    </style>

</head>

<body>

    <div class="container">

        <h1>YouTube Video Downloader</h1>

        

        <div class="input-group">

            <label for="videoUrl">YouTube Video URL:</label>

            <input type="text" id="videoUrl" placeholder="https://www.youtube.com/watch?v=..." value="https://www.youtube.com/watch?v=aR-KAldshAE">

        </div>

        

        <div class="input-group">

            <label for="quality">Video Quality:</label>

            <select id="quality">

                <option value="highest">Highest Quality</option>

                <option value="lowest">Lowest Quality</option>

                <option value="720p">720p</option>

                <option value="480p">480p</option>

                <option value="360p">360p</option>

            </select>

        </div>

        

        <div class="input-group">

            <label for="outputFormat">Output Format:</label>

            <select id="outputFormat">

                <option value="mp4">MP4</option>

                <option value="mkv">MKV</option>

                <option value="webm">WebM</option>

                <option value="mp3">MP3 (Audio Only)</option>

            </select>

        </div>

        

        <button id="downloadBtn">Download Video</button>

        

        <div class="progress-container" id="progressContainer">

            <h3>Download Progress</h3>

            <div class="progress-info">

                <span>Audio:</span>

                <span id="audioProgress">0% (0MB of 0MB)</span>

            </div>

            <div class="progress-bar">

                <div class="progress" id="audioBar"></div>

            </div>

            

            <div class="progress-info">

                <span>Video:</span>

                <span id="videoProgress">0% (0MB of 0MB)</span>

            </div>

            <div class="progress-bar">

                <div class="progress" id="videoBar"></div>

            </div>

            

            <div class="progress-info">

                <span>Time Elapsed:</span>

                <span id="timeElapsed">0 Minutes</span>

            </div>

        </div>

    </div>


    <div class="container">

        <h2>Underlying Code</h2>

        <pre><code><span class="comment">/**

 * Reencode audio & video without creating files first

 *

 * Requirements: ffmpeg, ether via a manual installation or via ffmpeg-static

 */</span>


<span class="comment">// Buildin with nodejs</span>

<span class="keyword">const</span> fs = <span class="function">require</span>(<span class="string">'fs'</span>);

<span class="keyword">const</span> cp = <span class="function">require</span>(<span class="string">'child_process'</span>);

<span class="keyword">const</span> readline = <span class="function">require</span>(<span class="string">'readline'</span>);

<span class="comment">// External modules</span>

<span class="keyword">const</span> ytdl = <span class="function">require</span>(<span class="string">'../'</span>);

<span class="keyword">const</span> ffmpeg = <span class="function">require</span>(<span class="string">'ffmpeg-static'</span>);

<span class="comment">// Global constants</span>

<span class="keyword">const</span> ref = <span class="string">'https://www.youtube.com/watch?v=aR-KAldshAE'</span>;

<span class="keyword">const</span> tracker = {

  start: <span class="function">Date</span>.<span class="function">now</span>(),

  audio: { downloaded: <span class="number">0</span>, total: <span class="keyword">Infinity</span> },

  video: { downloaded: <span class="number">0</span>, total: <span class="keyword">Infinity</span> },

};


<span class="comment">// Get audio and video stream going</span>

<span class="keyword">const</span> audio = <span class="function">ytdl</span>(ref, { filter: <span class="string">'audioonly'</span>, quality: <span class="string">'highestaudio'</span> })

  .<span class="function">on</span>(<span class="string">'progress'</span>, (_, downloaded, total) => {

    tracker.audio = { downloaded, total };

  });

<span class="keyword">const</span> video = <span class="function">ytdl</span>(ref, { filter: <span class="string">'videoonly'</span>, quality: <span class="string">'highestvideo'</span> })

  .<span class="function">on</span>(<span class="string">'progress'</span>, (_, downloaded, total) => {

    tracker.video = { downloaded, total };

  });


<span class="comment">// Get the progress bar going</span>

<span class="keyword">const</span> progressbar = <span class="function">setInterval</span>(() => {

  readline.<span class="function">cursorTo</span>(process.stdout, <span class="number">0</span>);

  <span class="keyword">const</span> toMB = i => (i / <span class="number">1024</span> / <span class="number">1024</span>).<span class="function">toFixed</span>(<span class="number">2</span>);


  process.stdout.<span class="function">write</span>(<span class="string">`Audio | ${(tracker.audio.downloaded / tracker.audio.total * 100).toFixed(2)}% processed `</span>);

  process.stdout.<span class="function">write</span>(<span class="string">`(${toMB(tracker.audio.downloaded)}MB of ${toMB(tracker.audio.total)}MB).${' '.repeat(10)}\n`</span>);


  process.stdout.<span class="function">write</span>(<span class="string">`Video | ${(tracker.video.downloaded / tracker.video.total * 100).toFixed(2)}% processed `</span>);

  process.stdout.<span class="function">write</span>(<span class="string">`(${toMB(tracker.video.downloaded)}MB of ${toMB(tracker.video.total)}MB).${' '.repeat(10)}\n`</span>);


  process.stdout.<span class="function">write</span>(<span class="string">`running for: ${((Date.now() - tracker.start) / 1000 / 60).toFixed(2)} Minutes.`</span>);

  readline.<span class="function">moveCursor</span>(process.stdout, <span class="number">0</span>, -<span class="number">2</span>);

}, <span class="number">1000</span>);


<span class="comment">// Start the ffmpeg child process</span>

<span class="keyword">const</span> ffmpegProcess = cp.<span class="function">spawn</span>(ffmpeg, [

  <span class="comment">// Remove ffmpeg's console spamming</span>

  <span class="string">'-loglevel'</span>, <span class="string">'0'</span>, <span class="string">'-hide_banner'</span>,

  <span class="comment">// 3 second audio offset</span>

  <span class="string">'-itsoffset'</span>, <span class="string">'3.0'</span>, <span class="string">'-i'</span>, <span class="string">'pipe:3'</span>,

  <span class="string">'-i'</span>, <span class="string">'pipe:4'</span>,

  <span class="comment">// Rescale the video</span>

  <span class="string">'-vf'</span>, <span class="string">'scale=320:240'</span>,

  <span class="comment">// Choose some fancy codes</span>

  <span class="string">'-c:v'</span>, <span class="string">'libx265'</span>, <span class="string">'-x265-params'</span>, <span class="string">'log-level=0'</span>,

  <span class="string">'-c:a'</span>, <span class="string">'flac'</span>,

  <span class="comment">// Define output container</span>

  <span class="string">'-f'</span>, <span class="string">'matroska'</span>, <span class="string">'pipe:5'</span>,

], {

  windowsHide: <span class="keyword">true</span>,

  stdio: [

    <span class="comment">/* Standard: stdin, stdout, stderr */</span>

    <span class="string">'inherit'</span>, <span class="string">'inherit'</span>, <span class="string">'inherit'</span>,

    <span class="comment">/* Custom: pipe:3, pipe:4, pipe:5 */</span>

    <span class="string">'pipe'</span>, <span class="string">'pipe'</span>, <span class="string">'pipe'</span>,

  ],

});

ffmpegProcess.<span class="function">on</span>(<span class="string">'close'</span>, () => {

  process.stdout.<span class="function">write</span>(<span class="string">'\n\n\n'</span>);

  <span class="function">clearInterval</span>(progressbar);

  console.<span class="function">log</span>(<span class="string">'done'</span>);

});


<span class="comment">// Link streams</span>

<span class="comment">// FFmpeg creates the transformer streams and we just have to insert / read data</span>

audio.<span class="function">pipe</span>(ffmpegProcess.stdio[<span class="number">3</span>]);

video.<span class="function">pipe</span>(ffmpegProcess.stdio[<span class="number">4</span>]);

ffmpegProcess.stdio[<span class="number">5</span>].<span class="function">pipe</span>(fs.<span class="function">createWriteStream</span>(<span class="string">'./out.mkv'</span>));</code></pre>

    </div>


    <script>

        document.getElementById('downloadBtn').addEventListener('click', function() {

            const videoUrl = document.getElementById('videoUrl').value;

            const quality = document.getElementById('quality').value;

            const outputFormat = document.getElementById('outputFormat').value;

            

            if (!videoUrl) {

                alert('Please enter a YouTube URL');

                return;

            }

            

            // Show progress container

            document.getElementById('progressContainer').style.display = 'block';

            

            // Simulate download progress (in a real app, this would connect to your Node.js backend)

            let audioProgress = 0;

            let videoProgress = 0;

            const startTime = Date.now();

            

            const simulateDownload = setInterval(() => {

                // Random progress increment

                if (audioProgress < 100) audioProgress += Math.random() * 5;

                if (videoProgress < 100) videoProgress += Math.random() * 3;

                

                // Cap at 100%

                if (audioProgress > 100) audioProgress = 100;

                if (videoProgress > 100) videoProgress = 100;

                

                // Update UI

                document.getElementById('audioProgress').textContent = 

                    `${audioProgress.toFixed(2)}% (${(audioProgress * 5).toFixed(2)}MB of 5MB)`;

                document.getElementById('videoProgress').textContent = 

                    `${videoProgress.toFixed(2)}% (${(videoProgress * 20).toFixed(2)}MB of 20MB)`;

                document.getElementById('audioBar').style.width = `${audioProgress}%`;

                document.getElementById('videoBar').style.width = `${videoProgress}%`;

                

                // Update time

                const minutes = ((Date.now() - startTime) / 1000 / 60).toFixed(2);

                document.getElementById('timeElapsed').textContent = `${minutes} Minutes`;

                

                // Check if download is complete

                if (audioProgress === 100 && videoProgress === 100) {

                    clearInterval(simulateDownload);

                    setTimeout(() => {

                        alert('Download complete!');

                    }, 500);

                }

            }, 500);

        });

    </script>

</body>

</html>

```


This HTML page includes:


1. **User Interface**:

   - URL input field with a default YouTube URL

   - Quality selection dropdown

   - Output format selection

   - Download button

   - Progress bars for audio and video download


2. **Code Display**:

   - Your original Node.js code with syntax highlighting

   - Properly formatted and easy to read


3. **Interactive Simulation**:

   - When you click "Download", it simulates the download progress

   - Shows progress bars, MB downloaded, and time elapsed

   - In a real implementation, this would connect to your Node.js backend


Note that this is a frontend simulation. To actually make this work, you would need to:

1. Set up a Node.js server with your code

2. Create an API endpoint that handles the download

3. Connect the frontend to the backend using fetch or WebSockets for real progress updates


Would you like me to provide the Node.js server implementation as well?

No comments:

Post a Comment