forked from 77media/video-flow
性能优化
This commit is contained in:
parent
c6a7889b43
commit
96e5630b7c
@ -29,8 +29,137 @@ import { TextCanvas } from "../common/TextCanvas";
|
||||
import { fetchSubscriptionPlans, SubscriptionPlan } from "@/lib/stripe";
|
||||
import { useCallbackModal } from "@/app/layout";
|
||||
|
||||
/** 视频预加载系统 - 后台静默运行 */
|
||||
function useVideoPreloader() {
|
||||
/** 预加载单个视频 */
|
||||
const preloadVideo = (src: string): Promise<void> => {
|
||||
return new Promise((resolve) => {
|
||||
const video = document.createElement('video');
|
||||
video.muted = true;
|
||||
video.preload = 'auto';
|
||||
|
||||
// 设置超时,避免某个视频卡住整个预加载过程
|
||||
const timeout = setTimeout(() => {
|
||||
console.warn(`视频预加载超时: ${src}`);
|
||||
resolve();
|
||||
}, 10000); // 10秒超时
|
||||
|
||||
video.onloadeddata = () => {
|
||||
clearTimeout(timeout);
|
||||
resolve();
|
||||
};
|
||||
|
||||
video.onerror = () => {
|
||||
clearTimeout(timeout);
|
||||
console.warn(`视频预加载失败: ${src}`);
|
||||
resolve(); // 即使失败也继续,不影响其他视频
|
||||
};
|
||||
|
||||
video.src = src;
|
||||
video.load();
|
||||
});
|
||||
};
|
||||
|
||||
/** 预加载所有视频 */
|
||||
const preloadAllVideos = async () => {
|
||||
const allVideos = [
|
||||
// HomeModule1 - 首屏视频(最高优先级)
|
||||
"https://cdn.qikongjian.com/videos/home.mp4",
|
||||
// HomeModule2 - 核心价值视频(高优先级)
|
||||
"https://cdn.qikongjian.com/videos/module2 (1).mp4",
|
||||
"https://cdn.qikongjian.com/videos/module2 (2).mp4",
|
||||
"https://cdn.qikongjian.com/videos/module2 (3).mp4",
|
||||
// HomeModule4 - 制作工序视频(中优先级)
|
||||
"https://cdn.qikongjian.com/videos/module4 (3).mp4",
|
||||
"https://cdn.qikongjian.com/videos/module4 (1).mp4",
|
||||
"https://cdn.qikongjian.com/videos/module4 (4).mp4",
|
||||
"https://cdn.qikongjian.com/videos/module4 (2).mp4",
|
||||
// HomeModule3 - 案例展示视频(低优先级,数量多)
|
||||
"https://cdn.qikongjian.com/videos/show (1).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (2).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (3).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (4).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (5).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (6).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (7).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (8).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (9).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (10).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (11).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (12).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (13).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (14).mp4",
|
||||
"https://cdn.qikongjian.com/videos/show (15).mp4",
|
||||
];
|
||||
|
||||
try {
|
||||
// 分阶段预加载:先加载关键视频,再加载其他视频
|
||||
const criticalVideos = allVideos.slice(0, 8); // 前8个是关键视频
|
||||
const otherVideos = allVideos.slice(8);
|
||||
|
||||
// 第一阶段:预加载关键视频
|
||||
for (let i = 0; i < criticalVideos.length; i += 2) {
|
||||
const batch = criticalVideos.slice(i, i + 2);
|
||||
await Promise.all(batch.map(preloadVideo));
|
||||
}
|
||||
|
||||
// 第二阶段:后台预加载其他视频
|
||||
if (otherVideos.length > 0) {
|
||||
// 使用 requestIdleCallback 在浏览器空闲时预加载
|
||||
const preloadRemaining = () => {
|
||||
let index = 0;
|
||||
const processBatch = () => {
|
||||
if (index >= otherVideos.length) return;
|
||||
|
||||
const batch = otherVideos.slice(index, Math.min(index + 3, otherVideos.length));
|
||||
batch.forEach(preloadVideo);
|
||||
index += batch.length;
|
||||
|
||||
if (index < otherVideos.length) {
|
||||
requestIdleCallback(processBatch, { timeout: 1000 });
|
||||
}
|
||||
};
|
||||
|
||||
requestIdleCallback(processBatch, { timeout: 1000 });
|
||||
};
|
||||
|
||||
// 如果浏览器不支持 requestIdleCallback,使用 setTimeout
|
||||
if (typeof requestIdleCallback !== 'undefined') {
|
||||
preloadRemaining();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
for (let i = 0; i < otherVideos.length; i += 3) {
|
||||
const batch = otherVideos.slice(i, i + 3);
|
||||
batch.forEach(preloadVideo);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('视频预加载过程中出现错误:', error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// 使用 requestIdleCallback 在浏览器空闲时开始预加载
|
||||
// 如果浏览器不支持,则使用 setTimeout 延迟执行
|
||||
if (typeof requestIdleCallback !== 'undefined') {
|
||||
requestIdleCallback(() => preloadAllVideos(), { timeout: 2000 });
|
||||
} else {
|
||||
setTimeout(() => preloadAllVideos(), 100);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 这个 hook 不需要返回任何值,它只是后台静默运行
|
||||
return;
|
||||
}
|
||||
|
||||
export function HomePage2() {
|
||||
// 后台静默预加载视频,不显示任何加载界面
|
||||
useVideoPreloader();
|
||||
const [hPading, setHPading] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
// 获取当前窗口尺寸
|
||||
const currentWidth = window.innerWidth;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user