/**
|
* 视频预下载缓存:用 wx.downloadFile 提前把转场 mp4 落地为本地临时文件,
|
* 转场时改用本地路径作 <video src>,消除首帧网络缓冲导致的黑帧。
|
*
|
* ## 背景
|
* wx.preloadAssets 仅支持 image / font,**不支持视频**。派单转场 mp4 直接用 CDN URL 作
|
* <video src> 时,首帧需先经网络请求 + 缓冲,「加载完成 → 首帧绘制」间会露出约一帧黑屏。
|
* 方案:进入下单流程(发布中/呼叫中)即 downloadFile 把 mp4 下到本地临时路径,转场时用本地
|
* 路径播放——本地文件无网络缓冲,首帧秒出。
|
*
|
* ## 使用
|
* - preloadVideo(url):幂等发起下载,成功后缓存 `CDN URL → 本地 tempFilePath`。
|
* - getPreloadedVideoSrc(url):取本地路径;未就绪(下载中/失败/非 weapp)则回退原 CDN URL,不阻塞。
|
*
|
* 参考:https://developers.weixin.qq.com/miniprogram/dev/api/network/download/wx.downloadFile.html
|
*/
|
|
/** 判断当前是否为微信小程序环境。 */
|
const isWeapp = (): boolean => process.env.TARO_ENV === 'weapp';
|
|
/** CDN URL → 本地临时文件路径(下载成功后写入)。 */
|
const localPathCache: Record<string, string> = {};
|
|
/** 已发起下载的 URL(下载中/已完成均登记,避免重复请求;失败时移除以允许重试)。 */
|
const pendingSet = new Set<string>();
|
|
/**
|
* 幂等预下载视频。已缓存或正在下载则直接返回;非 weapp / 低版本无 downloadFile 时静默跳过。
|
* 下载失败不报错、不缓存,转场时自动回退 CDN URL。
|
*
|
* @param url 视频 CDN 地址
|
*/
|
export const preloadVideo = (url: string): void => {
|
try {
|
if (!isWeapp() || !url) return;
|
if (localPathCache[url] || pendingSet.has(url)) return;
|
// @ts-ignore 微信小程序全局 API,低版本走 typeof 兜底跳过
|
if (typeof wx === 'undefined' || typeof wx.downloadFile !== 'function') return;
|
|
pendingSet.add(url);
|
// @ts-ignore
|
wx.downloadFile({
|
url,
|
success: (res: any) => {
|
if (res && res.statusCode === 200 && res.tempFilePath) {
|
localPathCache[url] = res.tempFilePath;
|
} else {
|
// 非 200:不缓存,允许后续重试
|
pendingSet.delete(url);
|
}
|
},
|
fail: () => {
|
// 下载失败:不缓存、允许后续重试,转场时回退 CDN URL(不影响功能)
|
pendingSet.delete(url);
|
},
|
});
|
} catch (e) {
|
console.error('[preloadVideo] 视频预下载异常:', e);
|
// 兜底:绝不抛出
|
}
|
};
|
|
/**
|
* 取预下载好的本地视频路径;未就绪则回退原 CDN URL。
|
*
|
* @param url 视频 CDN 地址
|
* @returns 本地临时路径(已就绪)或原 CDN URL
|
*/
|
export const getPreloadedVideoSrc = (url: string): string => localPathCache[url] || url;
|