
我们做文物保护的客户提了个需求野外文物采集地点在山区没信号3DGS 重建能不能纯离线跑。我们一开始拍胸脯说能——Spatial Recon Kit 是端侧重建端侧就是离线。真到山里测才发现端侧重建的某些环节偷偷要联网特征提取用的模型默认从云端拉离线时直接失败。这篇文章记录我们把重建流程的联网依赖摸清楚做离线兜底以及离线模式下质量和功能掉多少。能力面哪些环节要联网哪些不要3DGS 端侧重建的五个阶段采集/特征提取/点云初始化/优化/导出我们逐个测了断网情况下的行为。阶段默认是否联网联网用途离线能否跑采集否无能特征提取是拉特征提取模型默认不能需预置模型点云初始化否无能优化否无能导出否无能质量评估可选是拉评估模型默认不能需预置模型只有特征提取和可选的质量评估要联网。其他阶段纯端侧计算断网不影响。问题出在特征提取——它用的 SfM 特征提取模型默认从云端拉第一次使用时下载到本地缓存之后用缓存。但第一次使用时断网就直接失败不会等有网再试。// entry/src/main/ets/offline/OfflineReconSetup.etsimport{spatialRender}fromkit.SpatialReconKit;import{fileIo}fromkit.FileKit;exportclassOfflineReconSetup{// 检查离线重建所需的本地资源是否就绪staticasynccheckReadiness():PromiseOfflineReadiness{constchecks:OfflineReadiness{featureModel:false,assessModel:false,storageSpace:false};// 1. 特征提取模型是否已缓存到本地// 路径在应用沙箱 files/recon/models/feature.binconstmodelPath:string${getContext().filesDir}/recon/models/feature.bin;try{conststatawaitfileIo.statSync(modelPath);// 模型文件约 12 MB小于 1 MB 认为未下载完整checks.featureModelstat.size1*1024*1024;}catch(e){checks.featureModelfalse;}// 2. 质量评估模型如果用端侧 NRQAconstassessPath:string${getContext().filesDir}/recon/models/assess.bin;try{conststatawaitfileIo.statSync(assessPath);checks.assessModelstat.size1*1024*1024;}catch(e){checks.assessModelfalse;}// 3. 存储空间是否够重建结果 中间张量至少 500 MBconstfreeBytes:numberawaitgetFreeStorage();checks.storageSpacefreeBytes500*1024*1024;returnchecks;}// 在有网时预拉模型之后离线可用staticasyncprefetchModels():Promisevoid{// 触发一次特征提取Kit 会自动下载并缓存模型// 用一张 1x1 占位图触发目的是拉模型不是真重建constplaceholder:stringOhosRawFile://placeholder/1x1.png;constsessionawaitspatialRender.ReconSession.create({offline:true// 标记预拉模式失败不抛异常});awaitsession.warmupModels();awaitsession.release();}}prefetchModels要在有网时调一次之后离线就能跑。我们把它放在应用首次启动时用户有网时静默预拉用户无感。野外采集前要确认这一步跑过否则到了山里第一次重建就失败。约束面离线模式的功能缺失离线不只是能不能跑还有跑起来和在线有没有差。我们对比了离线和在线模式下重建结果的质量和功能。维度在线模式离线模式差异原因特征提取模型最新版云端拉缓存版可能旧模型更新滞后重建质量SSIM 0.88SSIM 0.84旧模型特征点少 15%重建耗时6320 ms6800 ms离线模型未做端侧算子优化质量评估可用不可用模型未预置评估模型大没默认预置模型更新自动需有网时手动触发离线无法拉新模型错误恢复可查云端诊断只看本地日志无远程协助离线模式重建质量降一档——SSIM 从 0.88 降到 0.84。原因是离线用的特征提取模型是缓存版可能不是最新。云端模型迭代更新离线缓存停在最后一次有网时的版本。我们测的范围内最新模型比缓存版特征点多 15%重建质量更好。质量评估在离线模式下不可用。第 36 篇说的 SSIM/PSNR 评估需要 holdout 帧对比这部分纯端侧不联网。但如果用端侧 NRQA 模型无参考评估那个模型要单独预置默认不预置模型 8 MB占空间。我们的选择是离线时只用 SSIM/PSNR不用 NRQA够用。场景落地野外文物采集我们跟文物保护客户去了一趟山区采集一尊露天石佛。地点确实没信号全程离线。真机数据离线 vs 在线重建对比指标离线重建山区现场在线重建回办公室重跑采集时长42 秒42 秒同素材特征提取耗时1620 ms1380 ms点云初始化耗时880 ms780 ms优化耗时4100 ms3800 ms导出耗时360 ms320 ms重建总耗时6960 ms6280 msSSIM0.830.87PSNR27.2 dB28.8 dB文件体量14.2 MB13.8 MB离线重建总耗时多 11%SSIM 低 0.04PSNR 低 1.6 dB。质量差异肉眼可辨——离线重建的石佛表面纹理略糊在线重建的更清晰。客户问能不能接受我们说能——野外采集的目的是留档不是展示质量差一档但够用。如果要做展陈级展示回办公室用在线模式重跑一遍。真机数据模型版本对质量的影响我们测了三个版本的特征提取模型看版本差异多大。模型版本发布时间特征点数SSIM离线可用v2.1最新2026-0941000.88需有网拉v2.02026-0638000.86已缓存v1.92026-0335000.83旧设备缓存模型版本差一档SSIM 差 0.02-0.05。野外采集那次离线用的是 v2.0比最新 v2.1 差 0.02可接受。但如果设备缓存停在 v1.9差 0.05 就比较明显了。离线模式的质量取决于上次有网时拉的是哪个版本这不可控。我们的处理是应用启动时如果有网静默检查模型版本并更新。这样保证离线时用的是最新缓存版。但用户如果长期不联网比如山区驻留一周期间模型有更新也拿不到。踩坑与取舍坑一以为全离线可用结果特征提取要联网模型这是开头说的痛。我们以为端侧重建就是离线重建没做联网依赖排查。到了山区第一次重建直接失败错误信息是feature model download failed才知道特征提取要联网拉模型。教训端侧 ≠ 离线。端侧指的是计算在设备上完成离线指的是不依赖网络。端侧重建的某些环节模型加载可能依赖网络要逐环节排查。排查方法就是断网跑一遍看哪步失败。坑二离线模式质量降一档客户预期没对齐我们跟客户说端侧重建可以离线跑客户理解成离线跑和在线跑一样好。实际离线质量降一档客户看到结果觉得你们说能离线怎么质量差了。问题出在沟通没区分能跑和跑得好。能跑是功能问题跑得好是质量问题。离线模式能跑但质量降一档。后来我们改成离线可跑质量约为在线的 95%展陈级需回在线重跑客户接受。坑三模型预拉时机错了最初把prefetchModels放在用户点开始采集时调结果用户在山区点采集时触发预拉没网直接失败。预拉要在用户有网时做不是要用了才拉。改成应用首次启动时静默预拉但有用户首次启动时也没网开箱即用场景预拉失败。最后加了预拉失败时的引导“本次采集需要离线模型请先在有网环境打开应用一次”。引导跳转到模型下载页等有网时下载。坑四被放弃的方案——把模型打进 APK想过把特征提取模型直接打进 APK省去预拉步骤。模型 12 MBAPK 从 80 MB 涨到 92 MB。问题是模型更新要发版——云端模型迭代更新打进 APK 就只能跟版本走用户不更新 APK 就用旧模型。权衡后放弃了。预拉方案虽然要用户有网时打开一次但模型能自动更新长期看模型版本更新。APK 打包模型适合模型不更新的场景3DGS 特征提取模型还在迭代不适合。坑五存储空间检查漏了中间张量离线采集时用户会连续重建多个文物。我们只检查了重建结果存储空间没算中间张量临时占用。中间张量一个重建约 300 MB连续重建 5 个就是 1.5 GB 临时占用加上结果文件存储爆了。修复是重建完立刻释放中间张量Kit 提供session.releaseIntermediate()并检查剩余空间不足 500 MB 时提示用户清理。这个坑在离线场景特别容易踩因为离线用户倾向一次性多采集几个。离线重建的完整流程把上面的坑都填了离线重建的完整流程是这样// entry/src/main/ets/offline/OfflineReconFlow.etsexportclassOfflineReconFlow{staticasyncrun(videoUri:string):PromiseReconResult{// 1. 离线就绪检查constreadiness:OfflineReadinessawaitOfflineReconSetup.checkReadiness();if(!readiness.featureModel){thrownewError(特征提取模型未就绪请先在有网环境打开应用);}if(!readiness.storageSpace){thrownewError(存储空间不足需至少 500 MB 可用空间);}// 2. 创建离线 sessionconstsessionawaitspatialRender.ReconSession.create({offline:true,// 强制离线不尝试联网config:AdaptiveReconConfig.build(/* frameCount */90,/* coverage */0.8)});try{// 3. 执行重建各阶段耗时埋点constprofilernewReconProfiler();profiler.attach(session);constresultawaitsession.start(videoUri);// 4. 离线质量评估仅 SSIM/PSNR不用 NRQAconstqualityawaitQualityAssessor.assess(result.gsNode,result.holdoutFrames);console.log(offline recon SSIM:${quality.ssim});// 5. 立刻释放中间张量避免连续重建存储爆awaitsession.releaseIntermediate();return{result,quality,timings:profiler.getReport()};}finally{awaitsession.release();}}}注意offline: true这个参数。不传或传 false 时Kit 会尝试联网拉模型离线场景下这次联网尝试会超时默认 30 秒才失败用户等 30 秒看到错误体验差。传 true 时直接走本地缓存不尝试联网失败立刻返回。离线链路和在线链路的第一个岔口是有没有网。把判定画出来才能看出预拉为什么必须提前做。有网络无网络已预拉未预拉发起重建请求当前是否有网络拉取最新特征模型执行在线重建在线评估并上传诊断特征模型是否已预拉创建 offline 为 true 的 session执行离线重建 质量降一档只用 SSIM 和 PSNR 评估重建完释放中间张量提示先在有网环境打开应用引导跳转模型下载页图里最容易被忽略的是未预拉分支。它不报错只是提示用户联网避免线上 30 秒超时。离线/在线能力对比能力在线模式离线模式重建支持支持质量降一档质量评估 SSIM/PSNR支持支持质量评估 NRQA支持不支持模型未预置模型自动更新支持不支持错误远程诊断支持不支持多次连续重建支持支持需主动释放中间张量首次使用直接可用需先在有网环境预拉模型离线模式的能力缺失主要在模型更新和远程诊断重建本身能力完整。如果接受质量降一档离线模式可用。小注意下哦端侧 ≠ 离线特征提取默认要联网拉模型离线前要预置模型模型预拉要在有网时做不能等要用了才拉应用首次启动静默预拉离线模式重建质量约为在线的 95%SSIM 差 0.02-0.05肉眼可辨离线模式 SSIM/PSNR 评估可用NRQA 不可用NRQA 模型默认不预置offline: true要显式传不传时 Kit 会尝试联网超时 30 秒才失败连续重建要主动释放中间张量单次重建中间张量 300 MB不释放会爆存储模型打进 APK 不适合迭代场景特征提取模型还在更新预拉方案更灵活离线存储空间检查要算中间张量不能只算结果文件单次重建需 500 MB 余量