ow
This commit is contained in:
1 parent
90bb20e75f
commit
bcf82d0f45
8 files changed
+342
-37
No files matched your search
@@ -1,13 +1,70 @@
|
||||
// 点击"下载视频"时执行:读取当前 <video> 的播放源,并把嗅探到的候选地址一起返回给宿主。
|
||||
// 点击"下载视频"时执行:优先从页面内嵌数据 RENDER_DATA 精确提取当前视频地址,
|
||||
// 其次才用嗅探列表兜底。
|
||||
(function () {
|
||||
try {
|
||||
var pageUrl = location.href;
|
||||
|
||||
// 从 URL 提取视频 ID
|
||||
var videoId = "";
|
||||
var m = pageUrl.match(/[?&]modal_id=(\d+)/);
|
||||
if (m) videoId = m[1];
|
||||
if (!videoId) {
|
||||
var m0 = pageUrl.match(/[?&]aweme_id=(\d+)/);
|
||||
if (m0) videoId = m0[1];
|
||||
}
|
||||
if (!videoId) {
|
||||
var m2 = pageUrl.match(/\/(?:video|note)\/(\d+)/);
|
||||
if (m2) videoId = m2[1];
|
||||
}
|
||||
|
||||
// === 方案一:从 RENDER_DATA 里精确找当前视频的播放地址 ===
|
||||
var renderVideoUrl = "";
|
||||
var renderAudioUrl = "";
|
||||
try {
|
||||
var rd = document.getElementById("RENDER_DATA");
|
||||
if (rd && rd.textContent) {
|
||||
var decoded = decodeURIComponent(rd.textContent);
|
||||
// 在 JSON 里找 aweme_id 等于 videoId 的节点,提取其 video.play_addr 或 play_addr 列表
|
||||
// 用正则粗匹配,避免完整 JSON 解析的复杂性
|
||||
var idx = decoded.indexOf(videoId);
|
||||
while (idx >= 0) {
|
||||
// 在这个 ID 附近找 playApi / play_addr / url_list
|
||||
var chunk = decoded.substring(Math.max(0, idx - 200), idx + 5000);
|
||||
// 找 DASH 格式的视频轨和音频轨
|
||||
var vMatches = chunk.match(/https?:\/\/[^"\\]+media-video[^"\\]*/gi);
|
||||
var aMatches = chunk.match(/https?:\/\/[^"\\]+media-audio[^"\\]*/gi);
|
||||
if (vMatches && vMatches.length) {
|
||||
renderVideoUrl = vMatches[vMatches.length - 1];
|
||||
if (aMatches && aMatches.length) {
|
||||
renderAudioUrl = aMatches[aMatches.length - 1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
// 找普通 mp4 直链
|
||||
var mp4Matches = chunk.match(/https?:\/\/[^"\\]*\.mp4[^"\\]*/gi);
|
||||
if (mp4Matches && mp4Matches.length) {
|
||||
renderVideoUrl = mp4Matches[mp4Matches.length - 1];
|
||||
break;
|
||||
}
|
||||
idx = decoded.indexOf(videoId, idx + 1);
|
||||
}
|
||||
}
|
||||
} catch (e) { /* RENDER_DATA 解析失败就走嗅探兜底 */ }
|
||||
|
||||
// === 方案二:选正在播放的 <video> 元素 ===
|
||||
var vids = Array.prototype.slice.call(document.querySelectorAll("video"));
|
||||
var best = null;
|
||||
for (var i = 0; i < vids.length; i++) {
|
||||
var v = vids[i];
|
||||
if (v.videoWidth > 0 || !isNaN(v.duration)) {
|
||||
best = v;
|
||||
break;
|
||||
if (!v.paused && v.currentTime > 0) { best = v; break; }
|
||||
}
|
||||
if (!best) {
|
||||
for (var j = 0; j < vids.length; j++) {
|
||||
var v2 = vids[j];
|
||||
if (v2.videoWidth > 0 || (!isNaN(v2.duration) && v2.duration > 0 && v2.currentTime > 0)) {
|
||||
best = v2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!best) best = vids[0];
|
||||
@@ -20,33 +77,48 @@
|
||||
var s = best.querySelector && best.querySelector("source");
|
||||
if (s) current = s.src || s.getAttribute("src") || "";
|
||||
}
|
||||
if (best.networkState === 0 || (best.msKeySystemLoaded && !best.src))
|
||||
playable = false;
|
||||
if (best.networkState === 0) playable = false;
|
||||
}
|
||||
|
||||
// === 方案三:嗅探列表兜底 ===
|
||||
var all = window.__mediaUrls || [];
|
||||
var videoTracks = [];
|
||||
var audioTracks = [];
|
||||
var otherMedia = [];
|
||||
for (var k = 0; k < all.length; k++) {
|
||||
var u = all[k];
|
||||
if (/media-video/i.test(u)) videoTracks.push(u);
|
||||
else if (/media-audio/i.test(u)) audioTracks.push(u);
|
||||
else otherMedia.push(u);
|
||||
}
|
||||
|
||||
function pickLast(arr) {
|
||||
return arr.length ? arr[arr.length - 1] : "";
|
||||
}
|
||||
|
||||
var dashVideo = pickLast(videoTracks);
|
||||
var dashAudio = pickLast(audioTracks);
|
||||
|
||||
// 如果 RENDER_DATA 找到了,优先用它
|
||||
if (renderVideoUrl) {
|
||||
dashVideo = renderVideoUrl;
|
||||
if (renderAudioUrl) dashAudio = renderAudioUrl;
|
||||
}
|
||||
|
||||
var title = document.title || "";
|
||||
var h1 = document.querySelector("h1");
|
||||
if (h1 && h1.innerText) title = h1.innerText;
|
||||
|
||||
var anchors = [];
|
||||
var links = document.querySelectorAll("a[href]");
|
||||
for (var j = 0; j < links.length; j++) {
|
||||
var h = links[j].href;
|
||||
if (
|
||||
window.__reportMedia &&
|
||||
/\.(mp4|flv|m3u8|mov|mkv|webm|ts)(\?|#|$)/i.test(h)
|
||||
)
|
||||
anchors.push(h);
|
||||
}
|
||||
|
||||
return JSON.stringify({
|
||||
current: current || "",
|
||||
playable: playable,
|
||||
usesMse: !!window.__usesMse || /^blob:/i.test(current),
|
||||
title: title,
|
||||
pageUrl: location.href,
|
||||
sniffed: (window.__mediaUrls || []).slice(-60),
|
||||
anchors: anchors.slice(-20),
|
||||
pageUrl: pageUrl,
|
||||
videoId: videoId,
|
||||
sniffed: otherMedia.slice(-60),
|
||||
dashVideo: dashVideo,
|
||||
dashAudio: dashAudio,
|
||||
m3u8Blobs: (window.__m3u8Blobs || []).slice(-1),
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
Reference in new issue
Block a user