Pornhub 视频一键下载

Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率

当前为 2025-03-26 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name              Pornhub video download with one click
// @name:ar           Pornhub Video Download بنقرة واحدة
// @name:bg           Pornhub видео Изтеглете с едно щракване
// @name:cs           PornHub Video Stáhnout s jedním kliknutím
// @name:da           Pornhub video download med et enkelt klik
// @name:de           Pornhub Video Download mit einem Klick
// @name:el           Λήψη βίντεο pornhub με ένα κλικ
// @name:en           Pornhub video download with one click
// @name:eo           Pornhub Video Elŝuti per unu klako
// @name:es           Descarga de video pornhub con un solo clic
// @name:fi           Pornhub -videon lataa yhdellä napsautuksella
// @name:fr           Téléchargement vidéo pornhub en un clic
// @name:fr-CA        Téléchargement vidéo pornhub en un clic
// @name:he           הורדת וידאו של Pornhub בלחיצה אחת
// @name:hr           PornHub video preuzmi s jednim klikom
// @name:hu           Pornhub videó letöltése egy kattintással
// @name:id           Unduh video pornhub dengan satu klik
// @name:it           Download video di Pornhub con un clic
// @name:ja           ポルノハブビデオダウンロードワンクリックでダウンロードします
// @name:ka           Pornhub Video ჩამოტვირთვა ერთი დაჭერით
// @name:ko           한 번의 클릭으로 Pornhub 비디오 다운로드
// @name:nb           Pornhub video nedlasting med ett klikk
// @name:nl           Pornhub video downloaden met één klik
// @name:pl           Pobierz wideo Pornhub za pomocą jednego kliknięcia
// @name:pt-BR        Download de vídeo pornHub com um clique
// @name:ro           Descărcare video PornHub cu un singur clic
// @name:ru           Скачать видео Pornhub с одним щелчком
// @name:sk           Stiahnutie videa pornhub s jedným kliknutím
// @name:sr           ПорнХуб Видео Довнлоад са једним кликом
// @name:sv           Pornhub video nedladdning med ett klick
// @name:th           ดาวน์โหลดวิดีโอ Pornhub ด้วยคลิกเดียว
// @name:tr           Pornhub Video İndir Bir Tıkla İndir
// @name:ug           Pornhub سىن چۈشۈرۈش بىر چېكىش ئارقىلىق
// @name:uk           Завантажити відео Pornhub одним клацанням
// @name:vi           Tải xuống video pornhub chỉ bằng một cú nhấp chuột
// @name:zh           Pornhub 视频一键下载
// @name:zh-CN        Pornhub 视频一键下载
// @name:zh-HK        Pornhub 視頻一鍵下載
// @name:zh-SG        Pornhub 视频一键下载
// @name:zh-TW        Pornhub 視頻一鍵下載
// @description       Pornhub video download with one click | pornhub.com | Download directly without login | Download free to watch paid videos | Download videos that are prohibited | Download all viewable resolutions
// @description:ar    Pornhub تنزيل مع نقرة واحدة
// @description:bg    Pornhub Video с едно щракване |
// @description:cs    Stahování videa PornHub |
// @description:da    Pornhub -video Download med et klik |
// @description:de    Pornhub -Video Download mit einem Klick | Pornhub.com |
// @description:el    Pornhub Video Download με ένα κλικ | Pornhub.com |
// @description:en    Pornhub video download with one click | pornhub.com | Download directly without login | Download free to watch paid videos | Download videos that are prohibited | Download all viewable resolutions
// @description:eo    Pornhub Video Elŝuti kun unu klako | Pornhub.com |
// @description:es    Pornhub Video Descarga con un clic |
// @description:fi    PornHub -video
// @description:fr    Téléchargement de la vidéo PornHub en un clic | Pornhub.com |
// @description:fr-CA Téléchargement de la vidéo PornHub en un clic | Pornhub.com |
// @description:he    הורדת וידאו של Pornhub עם לחיצה אחת |
// @description:hr    Porno preuzimanje s jednim klikom |
// @description:hu    Pornhub videó egy kattintással |
// @description:id    Unduh video pornhub dengan satu klik |
// @description:it    Download video di Pornhub con un clic |
// @description:ja    Pornhubのダウンロード|
// @description:ka    Pornhub ვიდეო ჩამოტვირთვა ერთი დაჭერით |
// @description:ko    Pornhub는 한 번의 클릭으로 다운로드하십시오
// @description:nb    Pornhub Video nedlasting med ett klikk |
// @description:nl    Pornhub -video downloaden met één klik | Pornhub.com | Download direct zonder inloggen |
// @description:pl    Pornhub Pobierz z jednym kliknięciem |
// @description:pt-BR Download de vídeo porn, com um clique |
// @description:ro    Pornhub Descărcare cu un singur clic |
// @description:ru    Pornhub Video Скачать с одним кликом |
// @description:sk    Stiahnutie videa s jedným kliknutím
// @description:sr    ПорнХуб Видео Довнлоад са једним кликом | ПорнХуб.цом | Преузмите директно без пријаве | Преузмите бесплатни за гледање плаћених видео записа | Преузмите видео забрањене видео снимке | Преузмите све видљиве резолуције
// @description:sv    Pornhub Video Ladda ner med ett klick |
// @description:th    ดาวน์โหลดวิดีโอ Pornhub ด้วยการคลิกหนึ่งครั้ง |
// @description:tr    Pornhub bir tıklama ile indirin |
// @description:ug    PornHub سىن يوللاش بىر چېكىش ئارقىلىق چۈشۈرۈش | PornHub.com | بىۋاسىتە كىرىش | ھەقسىز سىنلارنى كۆرۈش ئۈچۈن ھەقسىز چۈشۈرۈڭ | چەكلەنگەن بارلىق كۆرگەزمە قىلىش
// @description:uk    Відео PornHub одним натисніть
// @description:vi    Tải xuống Video của Pornhub với một lần nhấp chuột |
// @description:zh    Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率
// @description:zh-CN Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率
// @description:zh-HK Pornhub 視頻一鍵下載 | pornhub.com | 無需登錄直接下載 | 可直接下載免費觀看付費下載視頻 | 可下載已禁止下載的視頻 | 可下載所有可觀看分辨率
// @description:zh-SG Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率
// @description:zh-TW Pornhub 視頻一鍵下載 | pornhub.com | 無需登錄直接下載 | 可直接下載免費觀看付費下載視頻 | 可下載已禁止下載的視頻 | 可下載所有可觀看分辨率
// @grant             unsafeWindow
// @grant             GM_setClipboard
// @grant             GM_download
// @grant             GM_addStyle
// @match             *://*.pornhub.com/view_video.php?viewkey=*
// @match             *://*.pornhubpremium.com/view_video.php?viewkey=*
// @require           https://update.greasyfork.org/scripts/498897/1404834/Toastnew.js
// @require           https://code.jquery.com/jquery-3.7.1.min.js
// @author            liuwanlin,heckles,人民的勤务员 <[email protected]>
// @namespace         https://github.com/ChinaGodMan/UserScripts
// @supportURL        https://github.com/ChinaGodMan/UserScripts/issues
// @homepageURL       https://github.com/ChinaGodMan/UserScripts
// @license           MIT
// @icon              data:image/svg+xml;charset=utf-8;base64,Cjxzdmcgd2lkdGg9IjE5OCIgaGVpZ2h0PSI3MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjE5OCIgaGVpZ2h0PSI3MCIvPgo8cmVjdCB4PSIxMDgiIHk9IjEwIiB3aWR0aD0iODAiIGhlaWdodD0iNTAiIHJ4PSI0IiBmaWxsPSIjZjc5NzFkIi8+Cgo8ZyB0cmFuc2Zvcm09Im1hdHJpeCguMSAwIDAgLjEgODYuODUgMzAuMTUpIiBzdHJva2Utd2lkdGg9IjEwIj4KPHBhdGggZD0ibTg4Ny0zMGMtNS0yLTExLTMtMTctMy0yNC0yLTU0IDctNjggMTlsMy05N2gtNTd2MzAxaDUzdi0xN2MyNSAxNCA0MyAyMSA2NiAyMSA2Ni01IDkzLTY0IDkzLTExNi0xLTUyLTIzLTk3LTczLTEwOHptLTMyIDE3OWMtMzUgMC01MC00MS01MC03M3MxMS02NSA0OC02NSA0OCA0MSA0OCA3MGMwIDMyLTExIDY4LTQ2IDY4em0tMjAwLTg1YzAgMzEtMiA1MC01IDU4LTggMTgtMjQgMjgtNDIgMjktMTgtMS0yNi0xMC0zMy0yMy0yLTctMy0yNi0zLTU2di0xMDBoLTU4djEzOGMtMSA0OSAyNSA4NCA3MyA4NCAyNiAwIDU0LTkgNzItMjh2MjNoNTN2LTIxN2gtNTd6bS0yNDEtOTdjLTI4LTEtNTkgNi03NCAyMHYtOThoLTU3djMwMGg1N3YtMTA5YzAtMTggMi0zMiA1LTQxIDktMTggMjQtMjggNDMtMjggMTYgMCAyNSA4IDMyIDIwIDIgNiAzIDIxIDMgNDR2MTE1aDU4di0xMjhjMC0yMC0xLTM0LTMtNDMtMTItMzQtMzYtNTEtNjQtNTIiLz4KPHBhdGggZD0ibTY4LTQ1Yy0yNC0xLTYzIDgtNzUgMjd2LTIyaC01NnYyMjloNjB2LTEwM2MwLTI2IDItNDMgNS01MyA4LTIwIDI2LTMxIDQ1LTMxIDE4IDAgMjcgOSAzNCAyMyAyIDcgNCAyMyA0IDQ4djExNmg2MHYtMTQyYzAtMTgtMS0zMS0zLTQxLTEwLTM1LTQxLTUwLTc0LTUxem0tMjU3IDI3di0yMmgtNTZ2MjI5aDYwdi03MGMwLTM5IDItNjUgNS03NyA0LTEyIDgtMjEgMTQtMjYgNi00IDEzLTcgMjItNyA4IDAgMTggNCAyOCAxMGwxOS01MmMtMTMtOC0yNi0xMi00MC0xMi0yMCAxLTQwIDEyLTUyIDI3em0tMjA1LTI3Yy0yMiAwLTQyIDUtNjAgMTUtMTkgMTAtMzMgMjQtNDMgNDNzLTE1IDM4LTE1IDU5YzAgMjYgNSA0OCAxNSA2NiAxMCAxOSAyNSAzMyA0NCA0MiAxOSAxMCAzOSAxNCA2MCAxNCAzNCAwIDYyLTExIDg0LTM0IDIzLTIzIDM0LTUxIDM0LTg2IDAtMzQtMTEtNjMtMzMtODUtMjMtMjMtNTEtMzQtODYtMzRtNDAgMTcyYy0xMCAxMi0yNCAxOC0zOSAxOC0xNiAwLTI5LTYtNDAtMThzLTE2LTMwLTE2LTUyYzAtMjMgNS00MCAxNi01MnMyNC0xOCA0MC0xOGMxNSAwIDI5IDYgMzkgMTggMTEgMTIgMTYgMjkgMTYgNTEgMCAyMy01IDQxLTE2IDUzbS0zMTAtMjU0aC0xMDN2MzE2aDY0di0xMTloNDJjNTEgMiAxMDItNiAxMjYtNTEgNy0xMyAxMC0yOSAxMC00OSAwLTQzLTI0LTgxLTYzLTkyLTEyLTMtMzctNS03Ni01em00NyAxMzhjLTkgNC0yNiA1LTUxIDVoLTM1di04OWgzMWMyMyAwIDM4IDAgNDYgMiAyMiA1IDM2IDIyIDM2IDQyLTEgMTktMTEgMzQtMjcgNDAiIGZpbGw9IiNmZmYiLz4KPC9nPgo8L3N2Zz4K

// @compatible        chrome
// @compatible        firefox
// @compatible        edge
// @compatible        opera
// @compatible        safari
// @compatible        kiwi
// @version           2025.03.05.0145
// @created           2025-03-05 01:45:13
// @modified          2025-03-05 01:45:13
// ==/UserScript==
//!人民的勤务员修改自以下脚本 感谢heckles和liuwanlin
/*https://greasyfork.org/zh-CN/scripts/491333
https://greasyfork.org/zh-CN/scripts/491329
 */
GM_addStyle(`
    .download-urls ul { padding: 10px; font-weight: bold; line-height: 1.5; }
    .download-urls ul li { display: flex; align-items: center; height: 20px; max-width:400px; }
    .download-url-label { /* width: 100px; */ text-align: right; }
    .download-url-copy { flex: 1; }
    .download-url-mp4 { flex: 1; }
    .download-url-input { flex: 3; font-size: 12px; padding: 0 5px; border: 1px solid #ffff; margin: 0 5px; }
`);

(function () {
    'use strict'
    const userLang = (navigator.languages && navigator.languages[0]) || navigator.language || 'en'
    const translations = {
        'en': {
            downloading: 'Downloading...',
            finderror: 'Video download link not found',
            fetcherror: 'Error fetching video, please check the console for details',
            downloadsuccess: 'Download successful',
            downloaderror: 'Error downloading video, please check the console for details',
            downloadfailed: 'Download failed',
            downloadfailed_nosize: 'Unable to retrieve file size',
            copydownloadbtn: 'Copy address',
            copysuccess: 'Copy successful',
            downloadbtn: 'Download video',
            linkTip: 'Video download URL:'
        },
        'zh-CN,zh,zh-SG': {
            downloading: '下载中...',
            finderror: '未找到视频下载链接',
            fetcherror: '获取视频时出错,请到控制台查看详细信息',
            downloadsuccess: '下载成功',
            downloaderror: '下载视频时出错,请到控制台查看详细信息',
            downloadfailed: '下载失败',
            downloadfailed_nosize: '无法获取文件大小',
            copydownloadbtn: '复制地址',
            copysuccess: '复制成功',
            downloadbtn: '下载视频',
            linkTip: '视频下载地址:'
        },
        'zh-TW,zh-HK,zh-MO': {
            downloading: '下載中...',
            finderror: '未找到視頻下載連結',
            fetcherror: '獲取視頻時出錯,請到控制台查看詳細信息',
            downloadsuccess: '下載成功',
            downloaderror: '下載視頻時出錯,請到控制台查看詳細信息',
            downloadfailed: '下載失敗',
            downloadfailed_nosize: '無法獲取文件大小',
            copydownloadbtn: '複製地址',
            copysuccess: '複製成功',
            downloadbtn: '下載視頻',
            linkTip: '視頻下載地址:'
        },
        'ja': {
            downloading: 'ダウンロード中...',
            finderror: 'ビデオのダウンロードリンクが見つかりません',
            fetcherror: 'ビデオの取得中にエラーが発生しました。詳細はコンソールを確認してください',
            downloadsuccess: 'ダウンロード成功',
            downloaderror: 'ビデオのダウンロード中にエラーが発生しました。詳細はコンソールを確認してください',
            downloadfailed: 'ダウンロード失敗',
            downloadfailed_nosize: 'ファイルサイズを取得できません',
            copydownloadbtn: 'アドレスをコピー',
            copysuccess: 'コピー成功',
            downloadbtn: 'ビデオをダウンロード',
            linkTip: 'ビデオダウンロードURL:'
        },
        'vi': {
            downloading: 'Đang tải xuống...',
            finderror: 'Không tìm thấy liên kết tải video',
            fetcherror: 'Lỗi khi tải video, vui lòng kiểm tra bảng điều khiển để biết chi tiết',
            downloadsuccess: 'Tải xuống thành công',
            downloaderror: 'Lỗi khi tải video, vui lòng kiểm tra bảng điều khiển để biết chi tiết',
            downloadfailed: 'Tải xuống thất bại',
            downloadfailed_nosize: 'Không thể lấy kích thước tệp',
            copydownloadbtn: 'Sao chép địa chỉ',
            copysuccess: 'Sao chép thành công',
            downloadbtn: 'Tải xuống video',
            linkTip: 'URL tải video:'
        },
        'fr': {
            downloading: 'Téléchargement...',
            finderror: 'Lien de téléchargement vidéo introuvable',
            fetcherror: 'Erreur lors de la récupération de la vidéo, veuillez vérifier la console pour plus de détails',
            downloadsuccess: 'Téléchargement réussi',
            downloaderror: 'Erreur lors du téléchargement de la vidéo, veuillez vérifier la console pour plus de détails',
            downloadfailed: 'Échec du téléchargement',
            downloadfailed_nosize: 'Impossible de récupérer la taille du fichier',
            copydownloadbtn: 'Copier l’adresse',
            copysuccess: 'Copie réussie',
            downloadbtn: 'Télécharger la vidéo',
            linkTip: 'URL de téléchargement vidéo :'
        },
        'es': {
            downloading: 'Descargando...',
            finderror: 'No se encontró el enlace de descarga del video',
            fetcherror: 'Error al obtener el video, consulte la consola para más detalles',
            downloadsuccess: 'Descarga exitosa',
            downloaderror: 'Error al descargar el video, consulte la consola para más detalles',
            downloadfailed: 'Error en la descarga',
            downloadfailed_nosize: 'No se puede obtener el tamaño del archivo',
            copydownloadbtn: 'Copiar dirección',
            copysuccess: 'Copia exitosa',
            downloadbtn: 'Descargar video',
            linkTip: 'URL de descarga del video:'
        }
    }

    const getTranslations = (lang) => {
        for (const key in translations) {
            if (key === lang || key.split(',').includes(lang)) {
                return translations[key]
            }
        }
        return translations['en']
    }
    const translate = new Proxy(
        function (key) {
            const lang = userLang
            const strings = getTranslations(lang)
            return strings[key] || translations['en'][key]
        },
        {
            get(target, prop) {
                const lang = userLang
                const strings = getTranslations(lang)
                return strings[prop] || translations['en'][prop]
            }
        }
    )
    unsafeWindow.translate = translate
    const MutationObserver = unsafeWindow.MutationObserver || unsafeWindow.WebKitMutationObserver || unsafeWindow.MozMutationObserver
    const mutationObserver = new MutationObserver(mutations => {
        mutationObserver.disconnect()
        setTimeout(() => {
            unsafeWindow.VideoParsing.init()
        }, 200)
    })
    //PC和非PC,注意判断条件里不能用$简写,不知为问什么
    let playerdiv//let可以先不赋值,用在这里
    if (document.querySelector('#player')) {
        playerdiv = document.querySelector('#player')
    }
    else {
        console.log('安卓')
        playerdiv = document.querySelector('.playerWrapper')
    }
    const playerDom = playerdiv
    //

    if (playerDom) {
        mutationObserver.observe(playerDom, {
            childList: true,
            subtree: true
        })
    } else {
        Toast(translate('finderror'), 3000, 'rgb(219, 18, 35)', '#ffffff', 'top')
    }
})();

(function () {
    class VideoParsing {
        // 根据 key 开头字母获取对象中的值,返回数组
        static getObjectValueByStartsWithChar(obj, char) {
            const vars = []
            Object.keys(obj).forEach(key => {
                if (key.startsWith(char)) {
                    vars.push({
                        key: key,
                        value: obj[key]
                    })
                }
            })
            return vars
        }

        // 获取下载地址信息,返回数组
        static getUrlInfo() {
            const flashvars = this.getObjectValueByStartsWithChar(unsafeWindow, 'flashvars_')
            if (!flashvars.length) {
                Toast(translate('fetcherror'), 3000, 'rgb(219, 18, 35)', '#ffffff', 'top')
                return
            }
            let videosInfo = []
            try {
                videosInfo = flashvars[0]['value']['mediaDefinitions']
            } catch (e) {
                Toast(translate('fetcherror'), 3000, 'rgb(219, 18, 35)', '#ffffff', 'top')
                console.error(translate('fetcherror'), e, flashvars)
                return
            }
            let remoteAddress = undefined
            let urlInfo = []
            for (let i = 0; i < videosInfo.length; i++) {
                if (videosInfo[i]['remote']) {
                    remoteAddress = videosInfo[i]['videoUrl']
                    break
                }
            }

            // MP4 信息
            if (remoteAddress) {
                $.ajax({
                    url: remoteAddress,
                    async: false,
                    success: (data) => {
                        if (data && data.length) {
                            urlInfo = urlInfo.concat(data.map(item => ({
                                quality: item.quality + '.' + item.format,
                                url: item.videoUrl
                            })))
                        }
                    }
                })
            }
            console.log(videosInfo)
            return urlInfo
        }

        // 注入到下载面板
        static injectUrls2Dom(urlInfo) {
            const li = []
            urlInfo.forEach(item => {
                li.push(`
            <li>
                <span class="download-url-label">[ ${item.quality} ]</span>
                <input class="download-url-input" value="${item.url}" style="width: 50px;" />
                <a target="_blank" class="download-url-copy" data-href="${item.url}" href="javascript: void(0);">${translate('copydownloadbtn')}</a>
                <a target="_blank" class="download-url-mp4" data-href="${item.url}" href="javascript: void(0);">${translate('downloadbtn')}</a>
            </li>
            `)
            })
            //pc和非PC两种情况都加上
            $('.playerWrapper').after(`<div class="download-urls"><h3>${translate('linkTip')}</h3><ul>${li.join('')}</ul></div>`)
            $('#player').after(`<div class="download-urls"><h3>${translate('linkTip')}</h3><ul>${li.join('')}</ul></div>`)
        }

        // 初始化事件
        static initEvens() {
            // 点击下载复制到粘贴板中
            $(document).on('click', '.download-url-copy', function (e) {
                e.preventDefault()
                GM_setClipboard($(this).data('href'))
                Toast(translate('copysuccess'), 3000, 'rgb(18, 219, 18)', '#ffffff', 'top')
            })
        }
        static initDownEvens() {
            $(document).on('click', '.download-url-mp4', function (e) {
                e.preventDefault()
                downloadMp4($(this).data('href'), $(this))
            })
        }
        static init() {
            this.injectUrls2Dom(this.getUrlInfo())
            this.initEvens()
            this.initDownEvens()
        }
    }
    unsafeWindow.VideoParsing = VideoParsing

    //转换字节
    function getHumanReadableSize(sizeb) {
        const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
        const size = sizeb
        let i = parseInt(Math.floor(Math.log(size) / Math.log(1024)))
        const humanReadableSize = (size / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i]
        return humanReadableSize
    }
    function sanitizeTitle() {
        var title = document.title
        title = title.replace(/- Pornhub\.com/, '')
        return title.replace(/[/:*?"<>|]/g, '_')
    }


    //下载函数
    async function downloadMp4(videoUrl, targetElement) {
        try {
            const response = await fetch(videoUrl)
            if (!response.ok) {
                $(targetElement).text(translate('downloadfailed'))
            }

            const contentLength = response.headers.get('Content-Length')
            if (!contentLength) {
                $(targetElement).text(translate('downloadfailed_nosize'))

                return
            }
            const reader = response.body.getReader()
            const totalSize = contentLength ? parseInt(contentLength, 10) : 0 // 文件总大小
            let downloadedSize = 0 // 已下载大小
            const chunks = [] // 存储数据块
            while (true) {
                const { done, value } = await reader.read()
                if (done) break
                // 更新下载大小
                downloadedSize += value.length
                chunks.push(value)
                if (totalSize) {
                    const progress = ((downloadedSize / totalSize) * 100).toFixed(2)
                    $(targetElement).text(`${translate('downloading')} ${progress}% (${getHumanReadableSize(downloadedSize)} / ${getHumanReadableSize(totalSize)})`)
                } else {
                    $(targetElement).text(`${translate('downloading')} ${getHumanReadableSize(downloadedSize)}`)
                }
            }
            const blob = new Blob(chunks)
            const url = window.URL.createObjectURL(blob)
            const a = document.createElement('a')
            a.style.display = 'none'
            a.href = url
            a.download = sanitizeTitle() + '.mp4'
            document.body.appendChild(a)
            a.click()
            window.URL.revokeObjectURL(url)
            document.body.removeChild(a)
            Toast(translate('downloadsuccess'), 3000, 'rgb(18, 219, 18)', '#ffffff', 'top')
        } catch (error) {
            Toast(translate('downloaderror'), 3000, 'rgb(173, 7, 7)', '#ffffff', 'top')
            console.error(translate('downloaderror'), error)
        }
    }
})()