您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Download any video on Facebook (post/chat/comment)
// ==UserScript== // @name Facebook video downloader // @icon https://www.facebook.com/favicon.ico // @namespace Violentmonkey Scripts // @match https://www.facebook.com/* // @match https://web.facebook.com/* // @grant GM_registerMenuCommand // @version 1.3 // @author https://github.com/HoangTran0410 // @description Download any video on Facebook (post/chat/comment) // @license MIT // ==/UserScript== (() => { function getOverlapScore(el) { var rect = el.getBoundingClientRect(); return ( Math.min( rect.bottom, window.innerHeight || document.documentElement.clientHeight ) - Math.max(0, rect.top) ); } function getVideoIdFromVideoElement(video) { try { for (let k in video.parentElement) { if (k.startsWith("__reactProps")) { return video.parentElement[k].children.props.videoFBID; } } } catch (e) { return null; } } async function getWatchingVideoId() { let allVideos = Array.from(document.querySelectorAll("video")); let result = []; for (let video of allVideos) { let videoId = getVideoIdFromVideoElement(video); if (videoId) { result.push({ videoId, overlapScore: getOverlapScore(video), playing: !!( video.currentTime > 0 && !video.paused && !video.ended && video.readyState > 2 ), }); } } // if there is playing video => return that let playingVideo = result.find((_) => _.playing); if (playingVideo) return [playingVideo.videoId]; // else return all videos in-viewport return result .filter((_) => _.videoId && (_.overlapScore > 0 || _.playing)) .sort((a, b) => b.overlapScore - a.overlapScore) .map((_) => _.videoId); } async function getVideoUrlFromVideoId(videoId) { let dtsg = await getDtsg(); try { return await getLinkFbVideo2(videoId, dtsg); } catch (e) { return await getLinkFbVideo1(videoId, dtsg); } } async function getLinkFbVideo2(videoId, dtsg) { let res = await fetch( "https://www.facebook.com/video/video_data_async/?video_id=" + videoId, { method: "POST", headers: { "content-type": "application/x-www-form-urlencoded" }, body: stringifyVariables({ __a: "1", fb_dtsg: dtsg, }), } ); let text = await res.text(); text = text.replace("for (;;);", ""); let json = JSON.parse(text); const { hd_src, hd_src_no_ratelimit, sd_src, sd_src_no_ratelimit } = json?.payload || {}; return hd_src_no_ratelimit || hd_src || sd_src_no_ratelimit || sd_src; } async function getLinkFbVideo1(videoId, dtsg) { let res = await fetchGraphQl("5279476072161634", { UFI2CommentsProvider_commentsKey: "CometTahoeSidePaneQuery", caller: "CHANNEL_VIEW_FROM_PAGE_TIMELINE", displayCommentsContextEnableComment: null, displayCommentsContextIsAdPreview: null, displayCommentsContextIsAggregatedShare: null, displayCommentsContextIsStorySet: null, displayCommentsFeedbackContext: null, feedbackSource: 41, feedLocation: "TAHOE", focusCommentID: null, privacySelectorRenderLocation: "COMET_STREAM", renderLocation: "video_channel", scale: 1, streamChainingSection: !1, useDefaultActor: !1, videoChainingContext: null, videoID: videoId, }, dtsg); let text = await res.text(); let a = JSON.parse(text.split("\n")[0]), link = a.data.video.playable_url_quality_hd || a.data.video.playable_url; return link; } function fetchGraphQl(doc_id, variables, dtsg) { return fetch("https://www.facebook.com/api/graphql/", { method: "POST", headers: { "content-type": "application/x-www-form-urlencoded", }, body: stringifyVariables({ doc_id: doc_id, variables: JSON.stringify(variables), fb_dtsg: dtsg, server_timestamps: !0, }), }); } function stringifyVariables(d, e) { let f = [], a; for (a in d) if (d.hasOwnProperty(a)) { let g = e ? e + "[" + a + "]" : a, b = d[a]; f.push( null !== b && "object" == typeof b ? stringifyVariables(b, g) : encodeURIComponent(g) + "=" + encodeURIComponent(b) ); } return f.join("&"); } async function getDtsg() { return require("DTSGInitialData").token; } function downloadURL(url, name) { var link = document.createElement("a"); link.target = "_blank"; link.download = name; link.href = url; document.body.appendChild(link); link.click(); document.body.removeChild(link); } async function downloadWatchingVideo() { try { let listVideoId = await getWatchingVideoId(); if (!listVideoId?.length > 0) throw Error("No video found in the page"); console.log(listVideoId) for (let videoId of listVideoId) { let videoUrl = await getVideoUrlFromVideoId(videoId); if (videoUrl) downloadURL(videoUrl, "fb_video.mp4"); } } catch (e) { alert("ERROR: " + e); } } function resisterMenuCommand() { GM_registerMenuCommand("Download watching video", downloadWatchingVideo); } resisterMenuCommand(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址