warren-bank / workplace

https://resume.github.io/?warren-bank
0 stars 1 forks source link

Paid gig #1

Open Elite opened 4 days ago

Elite commented 4 days ago

Hi Warren,

Hope you remember me (https://github.com/warren-bank/browser-ytdl-core/issues/1#issue-2580249130), I am a rookie with browser scripts and would love if you can get me the following done for a paid task.

I need to create a simple web extension (Manifest V3) that utilizes your browser-ytdl-core library. The goal is to patch it with ffmpeg.js to enable MP3 audio conversion directly in the browser. The web extension should display a dropdown menu on the YouTube page, providing users with an option to download audio as an MP3 file. I would be happy to pay for your time, hope it suites my limited budget for this :)

Thank you for considering this!

Thanks

warren-bank commented 4 days ago

Hi again.

What you're asking to do seems simple enough. Most (all?) videos already have audio-only streams in "audio/mp4" format (using an mp4a.40.2 codec), which ffmpeg can resample to mp3. The only trouble that I see is.. the browser-ytdl-core library doesn't seem ready for a production release. I've since updated my Youtube userscript and have made a troubling observation.. although true for any video, I'll use this video as an example.. only "itag: 18" currently works.. all other streams still return a 403 status.. and this includes the "audio/mp4" stream.

Something is still very hinky in the upstream library.. probably relating to the same regex pattern(s) that the pending PR is touching.

And I should probably warn you.. that this library is a moving target.. even if they do get everything working again for right now.. the next time Youtube makes the slightest change to their website.. then everything will stop working again, until the library can be updates to make the necessary adjustments. So, if you build something on a shaky foundation like this.. just be aware that it will inevitably require constant upkeep.. and will periodically break.

Elite commented 4 days ago

Have you seen this https://github.com/LuanRT/YouTube.js

warren-bank commented 4 days ago

I have, but.. that's entirely unrelated to ytdl-core.. in the sense that neither project is dependent upon the other.

If you're suggesting/asking whether this other library could be used in a userscript instead of ytdl-core, then my answer would be.. maybe? I haven't tried, though they do claim that it works in a browser environment.

update: a quick glance at their documentation says otherwise:

To use YouTube.js in the browser, you must proxy requests through your own server.
warren-bank commented 4 days ago
notes pertaining to ffmpeg wasm:

https://ffmpegwasm.netlify.app/docs/getting-started/usage#transcode-webm-to-mp4-video

https://ffmpegwasm.netlify.app/docs/getting-started/examples/ https://github.com/ffmpegwasm/ffmpeg.wasm/tree/main/apps/vanilla-app https://github.com/ffmpegwasm/ffmpeg.wasm/blob/main/apps/vanilla-app/public/transcode.html

https://www.jsdelivr.com/package/npm/@ffmpeg/core https://cdn.jsdelivr.net/npm/@ffmpeg/core/ https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.6/dist/umd/ffmpeg-core.js https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.6/dist/umd/ffmpeg-core.wasm

https://www.jsdelivr.com/package/npm/@ffmpeg/ffmpeg https://cdn.jsdelivr.net/npm/@ffmpeg/ffmpeg/ https://cdn.jsdelivr.net/npm/@ffmpeg/ffmpeg@0.12.10/dist/umd/ffmpeg.js

https://www.jsdelivr.com/package/npm/@ffmpeg/util https://cdn.jsdelivr.net/npm/@ffmpeg/util/ https://cdn.jsdelivr.net/npm/@ffmpeg/util@0.12.1/dist/umd/index.js

https://ffmpegwasm.netlify.app/docs/api/ffmpeg/classes/FFmpeg

Elite commented 3 days ago

I haven't tried it yet, but this should work https://github.com/ybd-project-ver1/ytdl-core/issues/31. Additionally, what we need to do is send API requests to the Innertube API with client data, such as "web." The reason other downloaders are experiencing issues is that they operate server-side, whereas we are browser-side and can extract the poToken value directly from the browser. This should make implementation fairly simple.

I had took help of Claude AI and was able to extract potoken using something like this (lost track of the original script):


// Function to wait for a specified time
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

// Function to wait for a network request
const waitForRequest = (urlPattern, timeout = 30000) => {
    return new Promise((resolve, reject) => {
        const originalFetch = window.fetch;
        const timeoutId = setTimeout(() => {
            window.fetch = originalFetch;
            reject(new Error(`Timeout waiting for request: ${urlPattern}`));
        }, timeout);

        window.fetch = function(...args) {
            const result = originalFetch.apply(this, args);
            if (args[0].includes(urlPattern)) {
                clearTimeout(timeoutId);
                window.fetch = originalFetch;
                resolve(result);
            }
            return result;
        };
    });
};

// Main function
async function main() {
    console.log("[INFO] Starting automation.");

    // Check if we're already on the correct page
    if (!window.location.href.includes('youtube.com/embed/jNQXAC9IVRw')) {
        console.log("[INFO] Navigating to the correct page.");
        localStorage.setItem('runYouTubeScript', 'true');
        window.location.href = 'https://www.youtube.com/embed/jNQXAC9IVRw';
        return; // Exit the function, it will be called again after navigation
    }

    console.log("[INFO] On the correct page. Proceeding with automation.");
    localStorage.removeItem('runYouTubeScript');

    // Wait for the page to load
    await sleep(5000);
    console.log("[INFO] Waited 5 seconds for page load.");

    // Click the play button
    const buttonPlay = document.querySelector("#movie_player");
    if (buttonPlay) {
        buttonPlay.click();
        console.log("[INFO] Play button clicked.");
    } else {
        console.error("[ERROR] Play button not found.");
        return;
    }

    // Wait for the player request
    console.log("[INFO] Waiting for player request.");
    try {
        const response = await waitForRequest('/youtubei/v1/player');
        const data = await response.json();

        // Extract and log the required information
        console.log("visitor_data: " + data.context.client.visitorData);
        console.log("po_token: " + data.serviceIntegrityDimensions.poToken);
    } catch (error) {
        console.error("[ERROR] Failed to intercept player request:", error);
    }

    console.log("[INFO] Automation completed.");
}

// Check if we should run the script
if (localStorage.getItem('runYouTubeScript') === 'true' || window.location.href.includes('youtube.com/embed/jNQXAC9IVRw')) {
    console.log("[INFO] Conditions met, running main function.");
    main().catch(error => console.error("[ERROR] An error occurred in the main function:", error));
} else {
    console.log("[INFO] Conditions not met, script not running automatically.");
    console.log("[INFO] To run the script manually, call main() in the console.");
}```
warren-bank commented 3 days ago

quick status update..

warren-bank commented 2 days ago

quick update regarding Tampermonkey in Chrome..

Elite commented 2 days ago
  • merely including the .wasm as a resource prevents the script from running in Chrome

Maybe search for SharedArray buffer issue