Greasy Fork

Greasy Fork is available in English.

YouTube 视频下载助手|多种清晰度HD🔥|Video&Audio 📥

YouTube视频下载神器,支持1080P/2K高清视频下载,支持字幕下载,支持视频/音频分离下载,跳转下载页

当前为 2024-12-22 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         YouTube 视频下载助手|多种清晰度HD🔥|Video&Audio 📥
// @name:en      YouTube Video Downloader | HD Quality Options | Video&Audio 📥
// @name:ja      YouTube動画ダウンローダー|HD高画質|ビデオ&オーディオ 📥
// @name:es      Descargador de YouTube | Alta Calidad HD | Video y Audio 📥
// @name:pt      Baixador de YouTube | Qualidade HD | Vídeo e Áudio 📥
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  YouTube视频下载神器,支持1080P/2K高清视频下载,支持字幕下载,支持视频/音频分离下载,跳转下载页
// @description:en  Download YouTube videos in HD(1080P/2K), subtitles support, video/audio separate download, shorts download, completely free & no ads
// @description:ja  YouTubeビデオをHD(1080P/2K)でダウンロード、字幕対応、ビデオ/オーディオ分離ダウンロード、ショート動画対応、完全無料&広告なし
// @description:es  Descarga videos de YouTube en HD(1080P/2K), soporte de subtítulos, descarga separada de video/audio, descarga de shorts, completamente gratis y sin anuncios
// @description:pt  Baixe vídeos do YouTube em HD(1080P/2K), suporte a legendas, download separado de vídeo/áudio, download de shorts, totalmente gratuito e sem anúncios
// @author       YouhouLab
// @license      MIT
// @match        https://www.youtube.com/watch*
// @match        https://www.youtube.com/shorts/*
// @match        https://m.youtube.com/watch*
// @match        https://m.youtube.com/shorts/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @connect      www.y2mate.com
// @run-at       document-end
// @homepage     https://github.com/youhou-project
// @supportURL   https://github.com/youhou-project/issues
// @require      https://cdn.jsdelivr.net/npm/sweetalert2@11
// @compatible   chrome
// @compatible   firefox
// @compatible   opera
// @compatible   edge
// @compatible   safari
// @keywords     youtube, download, video, audio, subtitle, shorts, hd, 1080p, 2k, free, no ads, y2mate
// ==/UserScript==

(function() {
    'use strict';

    const i18n = {
        'zh': {
            downloadText: '免费下载',
            error: {
                addNormalButton: '添加普通下载按钮时出错:',
                addShortsButton: '添加Shorts下载按钮时出错:'
            }
        },
        'en': {
            downloadText: 'Free Download',
            error: {
                addNormalButton: 'Error adding normal download button:',
                addShortsButton: 'Error adding Shorts download button:'
            }
        },
        'ja': {
            downloadText: '無料ダウンロード',
            error: {
                addNormalButton: '通常ダウンロードボタンの追加エラー:',
                addShortsButton: 'Shortsダウンロードボタンの追加エラー:'
            }
        },
        'es': {
            downloadText: 'Descarga Gratis',
            error: {
                addNormalButton: 'Error al agregar botón de descarga normal:',
                addShortsButton: 'Error al agregar botón de descarga Shorts:'
            }
        },
        'pt': {
            downloadText: 'Download Grátis',
            error: {
                addNormalButton: 'Erro ao adicionar botão de download normal:',
                addShortsButton: 'Erro ao adicionar botão de download Shorts:'
            }
        }
    };

    function getCurrentLanguage() {
        const lang = navigator.language.split('-')[0];
        return i18n[lang] ? lang : 'en';
    }

    const currentLang = getCurrentLanguage();
    const texts = i18n[currentLang];

    function getVideoId() {
        const url = window.location.href;
        if (url.includes('/shorts/')) {
            return url.split('/shorts/')[1].split('?')[0];
        }
        return new URLSearchParams(window.location.search).get('v');
    }

    function addNormalDownloadButton() {
        try {
            if (document.getElementById('download-btn')) return;

            const buttonContainer = document.querySelector('#top-level-buttons-computed');
            if (!buttonContainer) {
                return;
            }

            const downloadBtn = document.createElement('button');
            downloadBtn.id = 'download-btn';
            downloadBtn.className = 'yt-spec-button-shape-next yt-spec-button-shape-next--tonal yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m';
            downloadBtn.style.marginLeft = '8px';

            const btnContent = document.createElement('div');
            btnContent.className = 'cbox';
            btnContent.style.display = 'flex';
            btnContent.style.alignItems = 'center';
            
            const icon = document.createElement('span');
            icon.className = 'material-icons';
            icon.style.marginRight = '6px';
            
            const text = document.createElement('span');
            text.textContent = texts.downloadText;
            
            btnContent.appendChild(icon);
            btnContent.appendChild(text);
            downloadBtn.appendChild(btnContent);

            downloadBtn.addEventListener('click', function() {
                const videoId = getVideoId();
                if (videoId) {
                    window.open(`https://www.y2mate.com/youtube/${videoId}`, '_blank');
                }
            });

            buttonContainer.appendChild(downloadBtn);
        } catch (error) {
            console.error(texts.error.addNormalButton, error);
        }
    }

    function addShortsDownloadButton() {
        try {
            if (document.getElementById('shorts-download-btn')) return;

            const likeButton = document.querySelector('#like-button');
            if (!likeButton) {
                return;
            }

            const buttonContainer = likeButton.parentElement;
            if (!buttonContainer) {
                return;
            }

            const downloadBtn = document.createElement('button');
            downloadBtn.id = 'shorts-download-btn';
            downloadBtn.className = 'yt-spec-button-shape-next yt-spec-button-shape-next--tonal yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m';
            downloadBtn.style.cssText = `
                height: 36px;
                padding: 0 16px;
                margin: 8px 0;
                background: transparent;
                border: none;
                cursor: pointer;
                display: flex;
                align-items: center;
                justify-content: center;
                color: #fff;
            `;

            const btnContent = document.createElement('div');
            btnContent.style.display = 'flex';
            btnContent.style.alignItems = 'center';
            btnContent.style.gap = '6px';
            
            const icon = document.createElement('span');
            icon.className = 'material-icons';
            icon.style.fontSize = '20px';
            icon.textContent = 'download';
            
            const text = document.createElement('span');
            text.textContent = texts.downloadText;
            text.style.fontSize = '14px';
            
            btnContent.appendChild(icon);
            btnContent.appendChild(text);
            downloadBtn.appendChild(btnContent);

            downloadBtn.addEventListener('click', function() {
                const videoId = getVideoId();
                if (videoId) {
                    window.open(`https://www.y2mate.com/youtube/${videoId}`, '_blank');
                }
            });

            buttonContainer.appendChild(downloadBtn);
        } catch (error) {
            console.error(texts.error.addShortsButton, error);
        }
    }

    function addDownloadButton() {
        try {
            const isShorts = window.location.pathname.includes('/shorts/');
            if (isShorts) {
                addShortsDownloadButton();
            } else {
                addNormalDownloadButton();
            }
        } catch (error) {
            console.error('Error adding download button:', error);
        }
    }

    function debounce(func, wait) {
        let timeout;
        return function executedFunction(...args) {
            const later = () => {
                clearTimeout(timeout);
                func(...args);
            };
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
        };
    }

    const debouncedAddButton = debounce(addDownloadButton, 500);

    const observer = new MutationObserver((mutations) => {
        const shouldUpdate = mutations.some(mutation => {
            return mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0;
        });

        if (shouldUpdate) {
            debouncedAddButton();
        }
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', addDownloadButton);
    } else {
        addDownloadButton();
    }
})();