[MF]实验室对应添加fetch劫持
This commit is contained in:
parent
a746d54993
commit
54d3e5798f
BIN
fetch/speech-commands/group1-shard1of2
Normal file
BIN
fetch/speech-commands/group1-shard1of2
Normal file
Binary file not shown.
BIN
fetch/speech-commands/group1-shard2of2
Normal file
BIN
fetch/speech-commands/group1-shard2of2
Normal file
Binary file not shown.
1
fetch/speech-commands/metadata.json
Normal file
1
fetch/speech-commands/metadata.json
Normal file
@ -0,0 +1 @@
|
||||
{"words": ["_background_noise_", "_unknown_", "down", "eight", "five", "four", "go", "left", "nine", "no", "one", "right", "seven", "six", "stop", "three", "two", "up", "yes", "zero"], "frameSize": 232}
|
1
fetch/speech-commands/model.json
Normal file
1
fetch/speech-commands/model.json
Normal file
File diff suppressed because one or more lines are too long
BIN
game/橘子/models/knn-model-juzi.bin
Normal file
BIN
game/橘子/models/knn-model-juzi.bin
Normal file
Binary file not shown.
1
game/橘子/models/knn-model-juzi.json
Normal file
1
game/橘子/models/knn-model-juzi.json
Normal file
@ -0,0 +1 @@
|
||||
{"dataset":{"0":{"start":0,"length":38400},"1":{"start":38400,"length":38400}},"classList":[{"id":"class-1","name":"青橘子","images":[]},{"id":"class-2","name":"黄橘子","images":[]}],"k":3,"featureDim":1280,"date":"2025-08-25T09:39:56.187Z","dataFile":"knn-model-juzi.bin"}
|
128
姿态分类/index.html
128
姿态分类/index.html
@ -64,6 +64,134 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- !!!!!! 核心劫持代码:确保在任何 TF.js 库之前加载 !!!!!! -->
|
||||
<script>
|
||||
(function() {
|
||||
// 定义你的镜像服务器的公共前缀,用于存放 MoveNet 模型文件
|
||||
// 例如:'https://goood-space-assets.oss-cn-beijing.aliyuncs.com/public/movenet-mirror/'
|
||||
// 重要:确保你的镜像服务器的目录结构与原始模型文件的路径部分匹配。
|
||||
// 举例:
|
||||
// 如果原始是 https://tfhub.dev/deepmind/movenet/singlepose-lightning/4/model.json
|
||||
// 那么在你的CDN上,你需要部署为:
|
||||
// https://goood-space-assets.oss-cn-beijing.aliyuncs.com/public/movenet-mirror/tfhub.dev/deepmind/movenet/singlepose-lightning/4/model.json
|
||||
//
|
||||
// 如果你的CDN就是直接放了 model.json, group1-shard*of*.bin,那么 MIRROR_BASE_URL 将不含后续路径。
|
||||
//
|
||||
// **** 根据你前一个回复的镜像路径,我们假设你的镜像结构是: ****
|
||||
// https://goood-space-assets.oss-cn-beijing.aliyuncs.com/public/fetch/snake_game/model.json
|
||||
// https://goood-space-assets.oss-cn-beijing.aliyuncs.com/public/fetch/snake_game/group1-shard1of2.bin
|
||||
// https://goood-space-assets.oss-cn-beijing.aliyuncs.com/public/fetch/snake_game/group1-shard2of2.bin
|
||||
//
|
||||
// 那么,我们需要将匹配的原始URL路径重写为 MIRROR_SPECIFIC_FILENAME_PREFIX
|
||||
// 也就是将类似 "https://tfhub.dev/.../model.json..."
|
||||
// 替换为 "https://goood-space-assets.oss-cn-beijing.aliyuncs.com/public/fetch/snake_game/model.json"
|
||||
const MIRROR_SPECIFIC_FILENAME_PREFIX = 'https://goood-space-assets.oss-cn-beijing.aliyuncs.com/public/fetch/snake_game/';
|
||||
|
||||
// 定义需要被劫持的原始 URL 的域名模式
|
||||
const INTERCEPT_DOMAINS = [
|
||||
'https://tfhub.dev/',
|
||||
// 如果实际的最终模型文件仍然解析到 storage.googleapis.com,也需要包含
|
||||
// 例如:'https://storage.googleapis.com/tfjs-models/'
|
||||
// 或者你观察到的实际的最终 Google Storage 域名
|
||||
];
|
||||
|
||||
// 备份原始的 fetch 函数
|
||||
const originalFetch = window.fetch;
|
||||
|
||||
window.fetch = function(input, init) {
|
||||
let url = input;
|
||||
if (input instanceof Request) {
|
||||
url = input.url;
|
||||
}
|
||||
|
||||
let newUrl = url;
|
||||
let isIntercepted = false;
|
||||
|
||||
// 检查 URL 是否以我们关注的域名开头
|
||||
for (const domain of INTERCEPT_DOMAINS) {
|
||||
if (url.startsWith(domain)) {
|
||||
// 尝试从 URL 中提取文件名 (不包含查询参数)
|
||||
// 匹配 model.json 或 group1-shardXofY.bin
|
||||
const fileNameMatch = url.match(/(model\.json|group1-shard\dof\d\.bin)/);
|
||||
if (fileNameMatch) {
|
||||
const fileName = fileNameMatch[0]; // 获取匹配到的文件名
|
||||
newUrl = MIRROR_SPECIFIC_FILENAME_PREFIX + fileName; // 拼接新的镜像 URL
|
||||
isIntercepted = true;
|
||||
break; // 找到匹配的域名和文件,停止循环
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isIntercepted) {
|
||||
console.warn(`[TFJS Fetch Intercepted] Original: ${url}`);
|
||||
console.warn(`[TFJS Fetch Intercepted] Redirecting to: ${newUrl}`);
|
||||
|
||||
if (input instanceof Request) {
|
||||
input = new Request(newUrl, {
|
||||
method: input.method,
|
||||
headers: input.headers,
|
||||
body: input.body,
|
||||
referrer: input.referrer,
|
||||
referrerPolicy: input.referrerPolicy,
|
||||
mode: 'cors',
|
||||
credentials: input.credentials,
|
||||
cache: 'default',
|
||||
redirect: 'follow',
|
||||
integrity: undefined, // 移除 integrity 属性以避免校验失败
|
||||
signal: input.signal,
|
||||
});
|
||||
} else {
|
||||
input = newUrl;
|
||||
}
|
||||
}
|
||||
|
||||
return originalFetch(input, init).catch(error => {
|
||||
console.error(`[TFJS Fetch Intercepted Error] Failed to load ${url} (redirected to ${newUrl || url || input}):`, error);
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
// -------------------- 劫持 XMLHttpRequest API (备用安全网) --------------------
|
||||
// 尽管 TF.js 主要用 fetch,但安全起见保留 XHR 劫持
|
||||
const originalXHR = window.XMLHttpRequest;
|
||||
window.XMLHttpRequest = function() {
|
||||
const xhr = new originalXHR();
|
||||
const originalOpen = xhr.open;
|
||||
xhr.open = function(method, url, async = true, user = null, password = null) {
|
||||
let newUrl = url;
|
||||
let isIntercepted = false;
|
||||
|
||||
for (const domain of INTERCEPT_DOMAINS) {
|
||||
if (url.startsWith(domain)) {
|
||||
const fileNameMatch = url.match(/(model\.json|group1-shard\dof\d\.bin)/);
|
||||
if (fileNameMatch) {
|
||||
const fileName = fileNameMatch[0];
|
||||
newUrl = MIRROR_SPECIFIC_FILENAME_PREFIX + fileName;
|
||||
isIntercepted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isIntercepted) {
|
||||
console.warn(`[TFJS XHR Intercepted] Original: ${url}`);
|
||||
console.warn(`[TFJS XHR Intercepted] Redirecting to: ${newUrl}`);
|
||||
url = newUrl; // 修改传入 open 的 URL
|
||||
}
|
||||
|
||||
return originalOpen.apply(this, arguments);
|
||||
};
|
||||
|
||||
for (const key in originalXHR) {
|
||||
if (originalXHR.hasOwnProperty(key)) {
|
||||
window.XMLHttpRequest[key] = originalXHR[key];
|
||||
}
|
||||
}
|
||||
return xhr;
|
||||
};
|
||||
|
||||
})();
|
||||
</script>
|
||||
<!-- 引入所有依赖库 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@4.20.0/dist/tf.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/pose-detection@2.1.3/dist/pose-detection.min.js"></script>
|
||||
|
@ -4,6 +4,130 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>KNN 图像分类器 - TensorFlow.js</title>
|
||||
|
||||
<!-- !!!!!! 核心劫持代码:确保在任何 TF.js 库之前加载 !!!!!! -->
|
||||
<script>
|
||||
(function() {
|
||||
// 定义你的镜像服务器的公共前缀,用于存放 MobileNet 模型文件
|
||||
// 根据你提供的最新路径进行更新。
|
||||
// 确保这些文件就命名为 model.json, group1-shardXof4.bin,并直接在此目录下
|
||||
const MOBILENET_MIRROR_BASE_URL = 'https://goood-space-assets.oss-cn-beijing.aliyuncs.com/public/fetch/mobilenet/';
|
||||
|
||||
// 定义需要被劫持的原始 URL 的域名模式
|
||||
// 我们观察到最终请求来自 storage.googleapis.com
|
||||
const INTERCEPT_DOMAINS = [
|
||||
'https://storage.googleapis.com/tfjs-models/', // tfjs 官方模型常用的 CDN
|
||||
'https://storage.googleapis.com/', // 更宽泛的匹配 Google Storage
|
||||
'https://tfhub.dev/', // 如果 MobileNet 也会通过 tfhub.dev 间接加载
|
||||
];
|
||||
|
||||
// 备份原始的 fetch 函数
|
||||
const originalFetch = window.fetch;
|
||||
|
||||
window.fetch = function(input, init) {
|
||||
let url = input;
|
||||
if (input instanceof Request) {
|
||||
url = input.url;
|
||||
}
|
||||
|
||||
let newUrl = url;
|
||||
let isIntercepted = false;
|
||||
|
||||
// 检查 URL 是否以我们关注的域名开头
|
||||
for (const domain of INTERCEPT_DOMAINS) {
|
||||
if (url.startsWith(domain)) {
|
||||
// 尝试从 URL 中提取文件名 (不包含查询参数)
|
||||
// 匹配 model.json 或 group1-shardXofY.bin
|
||||
const fileNameMatch = url.match(/(model\.json|group1-shard\dof\d\.bin)/);
|
||||
if (fileNameMatch) {
|
||||
const fileName = fileNameMatch[0]; // 获取匹配到的文件名
|
||||
newUrl = MOBILENET_MIRROR_BASE_URL + fileName; // 拼接新的镜像 URL
|
||||
isIntercepted = true;
|
||||
break; // 找到匹配的域名和文件,停止循环
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isIntercepted) {
|
||||
console.warn(`[TFJS Fetch Intercepted] Original: ${url}`);
|
||||
console.warn(`[TFJS Fetch Intercepted] Redirecting to: ${newUrl}`);
|
||||
|
||||
// 如果 input 是 Request 对象,需要创建新的 Request 对象来修改 URL
|
||||
if (input instanceof Request) {
|
||||
try {
|
||||
input = new Request(newUrl, {
|
||||
method: input.method,
|
||||
headers: input.headers,
|
||||
body: input.body,
|
||||
referrer: input.referrer,
|
||||
referrerPolicy: input.referrerPolicy,
|
||||
mode: 'cors', // 总是使用 CORS 模式
|
||||
credentials: input.credentials,
|
||||
cache: 'default',
|
||||
redirect: 'follow',
|
||||
integrity: undefined, // 移除 integrity 属性以避免校验失败
|
||||
signal: input.signal,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`[TFJS Fetch Intercepted Error] Failed to create new Request object: ${e.message}. Falling back to URL string.`, input);
|
||||
// 如果创建 Request 对象失败,回退到直接使用 URL 字符串
|
||||
input = newUrl;
|
||||
}
|
||||
} else {
|
||||
// 如果 input 是 URL 字符串,直接替换
|
||||
input = newUrl;
|
||||
}
|
||||
}
|
||||
|
||||
return originalFetch(input, init).catch(error => {
|
||||
console.error(`[TFJS Fetch Intercepted Error] Failed to load ${url} (redirected to ${newUrl || url || input}):`, error);
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
// -------------------- 劫持 XMLHttpRequest API (备用安全网) --------------------
|
||||
const originalXHR = window.XMLHttpRequest;
|
||||
window.XMLHttpRequest = function() {
|
||||
const xhr = new originalXHR();
|
||||
const originalOpen = xhr.open;
|
||||
xhr.open = function(method, url, async = true, user = null, password = null) {
|
||||
let newUrl = url;
|
||||
let isIntercepted = false;
|
||||
|
||||
for (const domain of INTERCEPT_DOMAINS) {
|
||||
if (url.startsWith(domain)) {
|
||||
const fileNameMatch = url.match(/(model\.json|group1-shard\dof\d\.bin)/);
|
||||
if (fileNameMatch) {
|
||||
const fileName = fileNameMatch[0];
|
||||
newUrl = MOBILENET_MIRROR_BASE_URL + fileName;
|
||||
isIntercepted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isIntercepted) {
|
||||
console.warn(`[TFJS XHR Intercepted] Original: ${url}`);
|
||||
console.warn(`[TFJS XHR Intercepted] Redirecting to: ${newUrl}`);
|
||||
url = newUrl; // 修改传入 open 的 URL
|
||||
}
|
||||
|
||||
// 调用原始的 open 方法
|
||||
return originalOpen.apply(this, arguments);
|
||||
};
|
||||
|
||||
// 将原始 XMLHttpRequest 的所有静态属性和方法复制到劫持后的 XMLHttpRequest 构造函数
|
||||
// 这样像 XHR.UNSENT 等常量仍然可用
|
||||
for (const key in originalXHR) {
|
||||
if (typeof originalXHR[key] !== 'function' && originalXHR.hasOwnProperty(key)) {
|
||||
window.XMLHttpRequest[key] = originalXHR[key];
|
||||
}
|
||||
}
|
||||
return xhr;
|
||||
};
|
||||
|
||||
})();
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet@latest"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/knn-classifier@latest"></script>
|
||||
|
117
音频分类/voice.html
117
音频分类/voice.html
@ -181,7 +181,124 @@
|
||||
<div id="predictionResult">
|
||||
等待模型训练完成并开始识别...
|
||||
</div>
|
||||
<!-- !!!!!! 核心劫持代码:确保在任何 TF.js 库之前加载 !!!!!! -->
|
||||
<!-- 如果你有其他模型的劫持代码,请确保它们都先于 TF.js 库 -->
|
||||
<script>
|
||||
(function() {
|
||||
// 定义你的镜像服务器的公共前缀,用于存放 Speech Commands 模型文件
|
||||
// 根据你提供的最新路径进行更新。
|
||||
const SPEECH_COMMANDS_MIRROR_BASE_URL = 'https://goood-space-assets.oss-cn-beijing.aliyuncs.com/public/fetch/speech-commands/';
|
||||
|
||||
// 定义需要被劫持的原始 URL 的域名模式
|
||||
// 明确指出是 tfjs-models 下的 speech-commands 模型
|
||||
const INTERCEPT_DOMAINS = [
|
||||
'https://storage.googleapis.com/tfjs-models/tfjs/speech-commands/',
|
||||
// 如果实际请求路径更短,也可以包含更宽泛的匹配
|
||||
// 'https://storage.googleapis.com/tfjs-models/',
|
||||
// 'https://storage.googleapis.com/',
|
||||
];
|
||||
|
||||
// 备份原始的 fetch 函数
|
||||
const originalFetch = window.fetch;
|
||||
|
||||
window.fetch = function(input, init) {
|
||||
let url = input;
|
||||
if (input instanceof Request) {
|
||||
url = input.url;
|
||||
}
|
||||
|
||||
let newUrl = url;
|
||||
let isIntercepted = false;
|
||||
|
||||
// 检查 URL 是否以我们关注的域名开头
|
||||
for (const domain of INTERCEPT_DOMAINS) {
|
||||
if (url.startsWith(domain)) {
|
||||
// 尝试从 URL 中提取文件名 (不包含查询参数)
|
||||
// 匹配 metadata.json, model.json, group1-shardXofY (注意这里没有.bin后缀)
|
||||
const fileNameMatch = url.match(/(metadata\.json|model\.json|group1-shard\dof\d)/);
|
||||
if (fileNameMatch) {
|
||||
const fileName = fileNameMatch[0]; // 获取匹配到的文件名
|
||||
newUrl = SPEECH_COMMANDS_MIRROR_BASE_URL + fileName; // 拼接新的镜像 URL
|
||||
isIntercepted = true;
|
||||
break; // 找到匹配的域名和文件,停止循环
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isIntercepted) {
|
||||
console.warn(`[TFJS Fetch Intercepted] Speech Commands - Original: ${url}`);
|
||||
console.warn(`[TFJS Fetch Intercepted] Speech Commands - Redirecting to: ${newUrl}`);
|
||||
|
||||
if (input instanceof Request) {
|
||||
try {
|
||||
input = new Request(newUrl, {
|
||||
method: input.method,
|
||||
headers: input.headers,
|
||||
body: input.body,
|
||||
referrer: input.referrer,
|
||||
referrerPolicy: input.referrerPolicy,
|
||||
mode: 'cors',
|
||||
credentials: input.credentials,
|
||||
cache: 'default',
|
||||
redirect: 'follow',
|
||||
integrity: undefined, // 移除 integrity 属性以避免校验失败
|
||||
signal: input.signal,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`[TFJS Fetch Intercepted Error] Speech Commands - Failed to create new Request object: ${e.message}. Falling back to URL string.`, input);
|
||||
input = newUrl;
|
||||
}
|
||||
} else {
|
||||
input = newUrl;
|
||||
}
|
||||
}
|
||||
|
||||
return originalFetch(input, init).catch(error => {
|
||||
console.error(`[TFJS Fetch Intercepted Error] Speech Commands - Failed to load ${url} (redirected to ${newUrl || url || input}):`, error);
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
// -------------------- 劫持 XMLHttpRequest API (备用安全网) --------------------
|
||||
const originalXHR = window.XMLHttpRequest;
|
||||
window.XMLHttpRequest = function() {
|
||||
const xhr = new originalXHR();
|
||||
const originalOpen = xhr.open;
|
||||
xhr.open = function(method, url, async = true, user = null, password = null) {
|
||||
let newUrl = url;
|
||||
let isIntercepted = false;
|
||||
|
||||
for (const domain of INTERCEPT_DOMAINS) {
|
||||
if (url.startsWith(domain)) {
|
||||
const fileNameMatch = url.match(/(metadata\.json|model\.json|group1-shard\dof\d)/);
|
||||
if (fileNameMatch) {
|
||||
const fileName = fileNameMatch[0];
|
||||
newUrl = SPEECH_COMMANDS_MIRROR_BASE_URL + fileName;
|
||||
isIntercepted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isIntercepted) {
|
||||
console.warn(`[TFJS XHR Intercepted] Speech Commands - Original: ${url}`);
|
||||
console.warn(`[TFJS XHR Intercepted] Speech Commands - Redirecting to: ${newUrl}`);
|
||||
url = newUrl;
|
||||
}
|
||||
|
||||
return originalOpen.apply(this, arguments);
|
||||
};
|
||||
|
||||
for (const key in originalXHR) {
|
||||
if (typeof originalXHR[key] !== 'function' && originalXHR.hasOwnProperty(key)) {
|
||||
window.XMLHttpRequest[key] = originalXHR[key];
|
||||
}
|
||||
}
|
||||
return xhr;
|
||||
};
|
||||
|
||||
})();
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/speech-commands@latest/dist/speech-commands.min.js"></script>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user