用 requestAnimationFrame 测量屏幕刷新率:事件循环与帧间隔的实践
几天前我在调试一个列表滚动卡顿的问题顺手把开发者工具的性能面板拖出来看了几眼。就在那堆密密麻麻的任务之间我注意到主线程上的空隙几乎像被尺子量过一样每隔十六七毫秒就出现一次。这个间隔我太熟了60Hz屏幕的一帧。也就是在那会儿我冒出一个念头——既然事件循环的每一步都踩在屏幕刷新节奏上那我是不是可以用纯JavaScript写一个demo直接把设备的刷新率给测出来于是就有了这篇文章里的这个小项目。这个demo本质上做的事情很简单监听requestAnimationFrame的回调时间统计相邻两帧之间的时间差再从这些时间差里反推出当前设备的刷新率。它顺带还会跑一个实时fps计数器、画一张帧间隔直方图甚至能用setTimeout跟你开个玩笑让你看清“事件循环的空闲度”和“屏幕刷新率”到底是不是一回事。适合觉得自己事件循环学得差不多、想找个好玩角度加深理解的开发者也适合单纯想知道自己笔记本或手机浏览器实际跑在多少Hz的普通用户。1. 事件循环里的“节拍器”为什么刷新率能和事件循环挂钩1.1 浏览器绘制一帧的完整流程要理解这个demo的测量逻辑得先把事件循环里“渲染帧”的位置讲清楚。现代浏览器在管理页面时主线程的事件循环大致是这样的从宏任务队列里取出一个任务执行比如处理输入事件、执行定时器回调、跑完一段脚本任务执行完后清空微任务队列比如Promise的then回调接下来浏览器会判断“这一帧是否需要渲染”如果需要就依次执行requestAnimationFrame回调、样式计算、布局、绘制最后把合成好的画面交给显卡。关键在于最后这个渲染步骤并不是随意触发的它通常会被浏览器调度到和显示器刷新节奏对齐的位置。显示器每刷新一次浏览器就获得一次机会去生成新帧如果页面没有变化也没有动画它可以跳过渲染但如果页面上有rAF驱动的动画浏览器就尽量保证每个刷新周期都执行一次rAF回调。这个机制很像教室里的打铃制度。显示器是那个打铃的人每隔固定时间响一次浏览器是班主任听到铃响后宣布“大家站起来”执行rAF回调然后迅速整理队列布局和绘制。如果班主任有事耽误了那这一帧可能就错过了铃声学生只能在下一轮铃声响起时再站起来。1.2 常见刷新率和帧间隔对照表我们需要测量的就是“两个铃声之间的实际时间”。屏幕刷新率用赫兹Hz表示60Hz就是一秒刷新60次换算成单帧时间就是1000 / 60 ≈ 16.67ms。下面是一张常用对照表屏幕刷新率单帧间隔一秒钟内的帧数60Hz16.67ms60帧90Hz11.11ms90帧120Hz8.33ms120帧144Hz6.94ms144帧注意很多屏幕并不是整数的60、120比如某些笔记本面板是59.94Hz帧间隔会落在16.68ms附近还有的屏幕会在不同刷新率之间自动切换。所以检测的时候不能拿着标准值去死板比对而是要容忍一小段误差区间我后面会讲到具体怎么处理。1.3 为什么选rAF而不是setTimeout测量刷新率的第一步是选对探针。setTimeout虽然也是事件循环的一部分但它走的是宏任务队列浏览器并不保证定时器回调跟显示器刷新对齐。你就算设置setTimeout(fn, 0)它也只是说“尽快插入下一个宏任务”具体晚多少取决于当前主线程忙不忙。但requestAnimationFrame不一样。浏览器在调度rAF时会尽量把它放在渲染之前让回调里的改动在下一帧画面上体现出来。rAF回调收到的时间戳就是浏览器认为“这一帧应当开始”的时刻。把连续两个rAF回调的时间戳相减得到的就是浏览器实际执行渲染帧的节奏这正是我们要测的东西。这也是为什么说“事件循环demo”而不是“动画demo”——整个测量过程完全是在事件循环的渲染步骤上做文章所有数据都来自浏览器自身的调度信号。2. 测刷新率的核心算法记录帧间隔找出主频输出置信度2.1 rAF时间戳的含义requestAnimationFrame的回调函数会收到一个DOMHighResTimeStamp类型的参数很多同学习惯叫它now。这个时间戳和performance.now()同源但语义上更特殊它表示的是这一帧的开始时间也就是浏览器决定开始渲染这一帧的时刻。在大多数情况下主线程忙碌程度不高时回调实际执行时间几乎等于这个帧开始时间如果主线程忙到炸回调会迟到但入参时间戳依然保留着“应该开始渲染”的时刻。因此我们优先用回调入参去计算相邻帧间隔而不是在回调里去调performance.now()重新取当前时间那样会把主线程的排队延迟也算进去鬼知道中间隔了多久。2.2 采集样本收集相邻rAF回调的间隔测量逻辑第一步是连续采样。我习惯采样240帧左右也就是大约4秒的数据量太少容易受偶然掉帧影响太多会让页面看起来像卡住了一样。下面是核心采集函数async function collectFrameIntervals(frameCount 240) { const samples []; await new Promise(resolve { let lastStartTime -1; let frames 0; function tick(startTime) { if (lastStartTime 0) { const gap startTime - lastStartTime; const busyDelay performance.now() - startTime; // 过滤掉明显不合理的间隔 if (gap 2 gap 100) { samples.push({ gap, // 记录主线程迟到时间后面用于剔除“被阻塞的假帧” busy: busyDelay }); } } lastStartTime startTime; frames; if (frames frameCount) resolve(); else requestAnimationFrame(tick); } requestAnimationFrame(tick); }); return samples; }有几个过滤条件需要解释一下。间隔小于2ms的数据基本可以扔掉正常情况下浏览器不可能在2ms内完成一整套渲染流程出现这种数多半是同帧重复回调、时间戳抖动或者别的怪异情况。间隔大于100ms的样本同样没有意义那往往来自用户切走标签页、系统休眠、或者长时间卡死混进统计里会把结果彻底带偏。busyDelay是我顺手记的一个诊断字段。它等于当前真实时间和rAF入参时间戳的差用来判断这一帧回调是不是“迟到”。如果页面主线程被长任务霸占rAF回调只能在长任务结束后才执行这个差值就会很大。后面我专门讲它怎么用。2.3 为什么取众数而不是平均拿到几百个帧间隔之后最自然的想法是算平均值。但平均值恰恰是个坑。拿一台60Hz屏幕来说正常情况下帧间隔稳定在16.7ms左右。可一旦浏览器出现一次掉帧就会产生一个33.4ms的间隔如果掉两帧就是50.1ms。假设我们采到10个样本其中8个是16.7ms2个是33.4ms那么平均数是(8 × 16.7 2 × 33.4) / 10 20.0ms换算出来居然只有50Hz和真实的60Hz差了整整10Hz。平均值对离群值极其敏感而掉帧在浏览器里又太常见了。正确做法是找“众数”也就是出现次数最多的那个间隔。还是上面那组数据16.7ms出现了8次众数就是16.7ms对应60Hz完美还原真实刷新率。这背后的原理其实很简单一个稳定在60Hz的屏幕最频繁出现的间隔必然是一帧的标准间隔偶尔的掉帧只不过是在整数倍位置多出一些零星样本不会影响主峰的位置。2.4 量化和主频判定代码拿到众数之后还得把它映射到具体的刷新率。这里可以直接用候选目标值去投票。我准备了一份候选表包含144Hz、120Hz、90Hz、60Hz这四档最常见刷新率然后对每个样本做最近邻匹配落在某个候选值附近的就给它投一票function estimateRefreshRate(gaps) { const targets [ { hz: 144, interval: 1000 / 144 }, { hz: 120, interval: 1000 / 120 }, { hz: 90, interval: 1000 / 90 }, { hz: 60, interval: 1000 / 60 } ]; const votes {}; for (const gap of gaps) { for (const t of targets) { if (Math.abs(gap - t.interval) 1.6) { votes[t.hz] (votes[t.hz] || 0) 1; break; } } } let best null; for (const [hz, count] of Object.entries(votes)) { if (!best || count best.count) { best { hz: Number(hz), count }; } } return best ? { hz: best.hz, confidence: best.count / gaps.length } : { hz: 0, confidence: 0 }; }容差1.6ms是我实测后的折中值。60Hz和90Hz之间差着5.5ms90Hz和120Hz之间差着2.8ms1.6ms的容差完全能分开但144Hz和120Hz只差1.4ms用这个容差就会出现重叠有可能把部分样本投错票。所以这个demo只会输出一个相对可信的整数结果真到144Hz和120Hz纠缠不清的情况我建议用直方图肉眼看主峰位置或者多采几百帧让数据更干净。3. 实测会翻车后台标签页、省电模式、可变刷新率和系统抢占3.1 第一个坑标签页一隐身节奏就没了按理说代码没问题就能跑出结果但我第一次真机测试就翻车了。当时我在电脑上开着三四个标签页测试页面只在其中一个标签页里。采样中途我点了一下另一个标签页看网页回来一看结果居然测出个15Hz。原因很简单标签页一旦进入后台浏览器为了省资源会直接暂停或大幅度限制rAF回调。有些浏览器在页面不可见时干脆完全不调用rAF有些则是降到1帧每秒意思一下。无论哪种情况采样数据里混入了超长间隔众数直接失效。解决办法有两个。一是在开始采样之前检查document.visibilityState必须等于visible才能动手二是采样过程中监听visibilitychange事件用户一切走就立即中止回到页面后再重采。我最后写了个自动重试机制这样即使测试中切了标签页回来时也会自动重新测量不至于显示一个离谱的数字。3.2 第二个坑省电模式和自适应刷新率直方图会出现双峰第二个坑来自设备本身的省电策略。我在一台标称120Hz的笔记本上测试插电时测出来是120Hz拔掉电源再测结果变成了60Hz。不是因为代码错了是系统在电池模式下把刷新率降到了60Hz以延长续航。这种情况下测出来的60Hz其实是设备在当前状态下的真实表现但容易让人误以为屏幕本身只有60Hz。更复杂的自适应刷新率屏幕也差不多。所谓自适应就是屏幕可以在一个范围内动态调整刷新率比如显示静态图片时降到几十Hz滚动或播放动画时升到最高档。这类屏幕的直方图往往会出现“双峰结构”——8.3ms和16.7ms各自攒起一个小高峰看起来像60Hz和120Hz在打架。处理思路是不要只看单一峰值而是同时报告“最短主簇间隔”和“当前主簇间隔”。最短主簇间隔才能反映设备想跑的最高速率。如果你的屏幕测出双峰看到的第一反应不应该是代码坏了而应该是“这块屏支持可变刷新率”。3.3 第三个坑主线程被占满时帧是真的会迟到刷新率测量还有一个非常隐蔽的干扰因素主线程繁忙。如果你的页面里跑着很多重型动画或者其他标签页在后台疯狂占CPUrAF回调本身可能被推迟。前面tick函数里我记录的busyDelay字段就是用来处理这个场景的。假设弹出一个200ms的同步长任务在这200ms里所有rAF回调都不会执行。等任务结束浏览器会立刻补一次rAF但这次回调的入参时间戳还是“它原本应该出现”的时刻而回调真正执行时已经隔了200多毫秒。如果不管这个问题这组数据里就会出现一个巨大的异常间隔又会把平均值捣乱。我采用的方案是过滤掉busyDelay超过6ms的样本。超过这个阈值说明这一帧已经实际错过了窗口期不值得参与主频统计。这里的6ms是根据浏览器帧调度习惯拍的一个经验值不是科学常数。笔记本配置差一点、后台占用高一点可能需要调整阈值否则过滤太严反而样本不够。3.4 第四个坑窗口跑到哪块屏结果就是哪块屏的刷新率最后这个坑和代码无关但坑过不少人。如果你外接了显示器浏览器窗口落在哪块屏幕上rAF的节奏就跟哪块屏幕走。比如主屏是60Hz外接屏是120Hz把浏览器窗口从主屏拖到外接屏同一段代码测出来的结果会从60Hz变成120Hz。所以想测哪块屏就把窗口拖到哪块屏再重新跑一遍。别边测边拖采样中切换显示器会导致帧间隔剧烈抖动出来一个谁都不认识的结果。4. 把demo做成一个可以玩的“设备体检”页面4.1 页面布局和交互设计光有一堆数字不够直观我把它做成了一个小页面包含三个模块。第一块是大号刷新率数字和状态徽标几秒自动刷新一次第二块是帧间隔直方图用canvas画出来每个毫秒桶的样本数量一目了然第三块是一个跑圈小球用rAF驱动做往返运动方便眼睛直接感受当前帧率是否顺滑。页面的核心逻辑是每3秒自动重测一轮。自适应刷新率屏幕在静止时可能会降频自动重测能捕捉到屏幕频率切换的过程。直方图只画最近的采样结果不保留历史这样每一轮都像是给屏幕做了一次即时体检。4.2 完整代码实现下面是一份完整的可运行页面保存成HTML文件直接打开就行!DOCTYPE html html langzh-CN head meta charsetUTF-8 / meta nameviewport contentwidthdevice-width, initial-scale1.0 / titleEvent Loop Refresh Rate Meter/title style body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; background: #f4f5f7; color: #222; margin: 0; padding: 24px; display: grid; gap: 16px; } .card { background: #fff; border-radius: 14px; box-shadow: 0 4px 14px rgba(0,0,0,.06); padding: 20px 24px; } .big-number { font-size: 56px; font-weight: 800; letter-spacing: -1px; } .badge { display: inline-block; margin-left: 8px; padding: 2px 10px; border-radius: 99px; background: #e6f4ff; font-size: 13px; font-weight: 600; color: #0b57d0; } canvas { width: 100%; height: 180px; display: block; } .runway { position: relative; height: 80px; border-radius: 12px; background: #eee; overflow: hidden; } .ball { position: absolute; top: 24px; left: 12px; width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(135deg, #4361ee, #9d4edd); box-shadow: 0 2px 6px rgba(0,0,0,.18); } .hint { color: #666; font-size: 14px; line-height: 1.6; } /style /head body div classcard div span classbig-number idhz--/span span classbadge idstate采样中/span /div div classhint iddetail请保持页面在前台不要切换标签页。/div /div div classcard b帧间隔直方图ms/b canvas idhist width600 height180/canvas /div div classcard b跑圈动画观察流畅度/b div classrunwaydiv classball idball/div/div div classhint如果看到小球一顿一顿说明当前帧率不太高丝滑移动说明至少在高刷新率区间。/div /div script const hzEl document.getElementById(hz); const stateEl document.getElementById(state); const detailEl document.getElementById(detail); const ball document.getElementById(ball); const canvas document.getElementById(hist); const ctx canvas.getContext(2d); function drawHistogram(gaps) { if (!gaps.length) return; const maxGap Math.min(50, Math.max(...gaps)); ctx.clearRect(0, 0, canvas.width, canvas.height); const bins new Array(Math.ceil(maxGap)).fill(0); for (const g of gaps) { if (g 0 g maxGap) bins[Math.floor(g)]; } const maxCount Math.max(...bins); const barW canvas.width / bins.length; ctx.fillStyle #0b57d0; for (let i 0; i bins.length; i) { const h (bins[i] / maxCount) * (canvas.height - 20); ctx.fillRect(i * barW, canvas.height - h, barW - 1, h); } ctx.fillStyle #666; ctx.font 11px monospace; ctx.fillText(0ms, 4, canvas.height - 6); ctx.fillText(maxGap.toFixed(0) ms, canvas.width - 46, canvas.height - 6); } function estimateRefreshRate(gaps) { const targets [ { hz: 144, interval: 1000 / 144 }, { hz: 120, interval: 1000 / 120 }, { hz: 90, interval: 1000 / 90 }, { hz: 60, interval: 1000 / 60 } ]; const votes {}; for (const gap of gaps) { for (const t of targets) { if (Math.abs(gap - t.interval) 1.6) { votes[t.hz] (votes[t.hz] || 0) 1; break; } } } let best null; for (const [hz, count] of Object.entries(votes)) { if (!best || count best.count) best { hz: Number(hz), count }; } return best ? { hz: best.hz, confidence: best.count / gaps.length } : { hz: 0, confidence: 0 }; } async function measure() { const stateEl document.getElementById(state); const detailEl document.getElementById(detail); if (document.visibilityState ! visible) { stateEl.textContent 不可见; detailEl.textContent 标签页隐藏了切回前台后3秒内会自动重测。; return; } const samples []; await new Promise(resolve { let last -1; let frames 0; function tick(now) { if (last 0) { const gap now - last; const busy performance.now() - now; if (gap 2 gap 100) samples.push({ gap, busy }); } last now; frames; if (frames 240) resolve(); else requestAnimationFrame(tick); } requestAnimationFrame(tick); }); const cleanGaps samples.filter(s s.busy 6).map(s s.gap); if (!cleanGaps.length) { stateEl.textContent 无数据; detailEl.textContent 采样失败可能是页面被持续阻塞。; return; } const { hz, confidence } estimateRefreshRate(cleanGaps); hzEl.textContent hz || --; stateEl.textContent confidence 0.35 ? 可信 : 混杂; detailEl.textContent 采样 ${cleanGaps.length} 个有效帧间隔主频 ${hz}Hz置信度 ${(confidence * 100).toFixed(0)}%; drawHistogram(cleanGaps); } let start 0; function loop(t) { if (!start) start t; const elapsed (t - start) / 1000; const period 2; const phase (elapsed % period) / period; const x 12 phase * (document.querySelector(.runway).clientWidth - 56); ball.style.transform translateX(${x}px); requestAnimationFrame(loop); } requestAnimationFrame(loop); measure(); setInterval(measure, 3000); /script /body /html4.3 页面逻辑的执行流程页面的核心逻辑藏在measure()函数里。第一步检查页面是否可见不可见就直接放弃这一轮第二步采样240帧把有效间隔和忙碌标记一起存进数组第三步用busy 6过滤掉那些主线程迟到的样本第四步调用estimateRefreshRate算出主频和置信度最后把结果绘制到页面上。为什么我会把置信度阈值设在0.35因为自适应刷新率屏幕会把票分散到多个档位即使真实主频是120Hz它的票占比也可能只有40%到50%。如果阈值设太高很多自适应屏幕会被误判成“混杂”设成0.35既能覆盖这种情况又不至于让只有零星几票的结果冒充可信。4.4 如何手动核验测量结果想确认页面测得准不准有两个不怎么费事的办法。一是打开开发者工具的性能面板录制一小段时间线然后看“渲染”或“绘制”相关任务的间距。如果这些任务在时间轴上的间距均匀分布在16.7ms左右那和页面上测出来的60Hz就是吻合的。二是打开操作系统自带的显示设置页在高级显示信息里找到当前刷新率和页面结果做一次交叉对比。顺带提一句如果你的浏览器支持requestVideoFrameCallback也可以把它当作第二个探针。它会在视频帧实际呈现时触发比rAF更接近“真正显示出去”的时刻但受片源帧率的限制直接用视频帧间隔不够准确更适合用来观察视频播放有没有掉帧。5. 顺带实验用 setTimeout 测到的“假刷新率”5.1 一个反直觉的小脚本标题里的“顺便”主要体现在这个重量轻但很有意思的实验上。把事件循环玩明白之后我不禁好奇如果用setTimeout(0)去高频计数会不会也得到一个跟屏幕刷新率接近的数字于是写了下面这段脚本let count 0; const startTime performance.now(); function loop() { count; if (performance.now() - startTime 1000) { setTimeout(loop, 0); } else { console.log(1秒内执行了, count, 次定时器回调); } } setTimeout(loop, 0);这个脚本让setTimeout(0)循环触发跑一秒后打印次数。我原以为会得到一个几百上千的大数字结果在多数浏览器里它只有240到250次左右。换算下来每次回调间隔大约是4ms。5.2 这4ms是哪来的答案在浏览器的嵌套定时器节流规则里。当页面里的定时器处于“嵌套”状态也就是前一个定时器回调里又创建了下一个定时器时浏览器会强制把最小间隔限制到约4ms防止脚本用setTimeout循环把页面拖垮。因为我们的脚本是嵌套调用所以每秒最多跑250次左右。4ms这个数字和屏幕刷新率没有半毛钱关系。60Hz屏幕的帧间隔是16.7ms120Hz是8.3ms它们都不是4ms。所以如果你用这类方法去测“刷新率”得到的只是一个由事件循环调度规则决定的假结果。它能说明事件循环至少还有多快的调度余量但说明不了屏幕实际在跑多少Hz。5.3 把主线程堵死看看会怎样再做一个更直观的破坏性实验。在页面运行时往主线程里塞一个同步长任务const blockUntil performance.now() 200; while (performance.now() blockUntil) {}这段代码会让主线程空闲200ms。期间rAF回调全部排队等待setTimeout回调也全部堆积动画直接卡住。等长任务结束后所有积压的回调会集中冒出来帧间隔直方图会出现一个巨大的异常尖峰跑圈小球则表现为明显停顿。这个实验解释了一件事无论是rAF还是setTimeout它们都依赖主线程这个“单车道”。一旦车道被堵所有节拍器都会一起晚点。所以测量刷新率之前最好把页面放到干净环境里关掉其他重型动画别拿一个正在直播或滚动新闻的页面当测试床否则数据里会掺进去大量不属于屏幕节奏的噪声。最后分享一点实操体会这个demo我后来一直留着每次拿到一台新设备就点开测一下。测的次数多了总结出两条经验第一如果直方图上出现两个明显高峰别急着怀疑代码出了问题那大概率是可调刷新率屏幕在省电和满血模式之间自动切换取较短的那个峰才是设备想跑的最快速度第二测量时别开着视频网站或有动画的页面我实际遇到过开着直播页面时怎么测都只有30Hz关掉后才看到真实的120Hz差异全来自主线程被抢。如果你也打算在自己的设备上试建议把页面存成本地文件放在空白标签页里运行。几秒出一个结果还能顺便看看那个跑圈小球丝滑不丝滑。这种把浏览器机制变成小实验的玩法确实比单纯背八股文有意思得多。

相关新闻

YOLOv10焊缝质量检测:模型、数据集与C++推理实战

YOLOv10焊缝质量检测:模型、数据集与C++推理实战

简介:本资源面向工业质检与计算机视觉方向的开发者、学生及研究人员,提供一套基于YOLOv10的焊缝质量好坏检测完整方案,可直接用于钢材焊缝缺陷识别与质量分级任务。压缩包共约2000个文件,大小154.15MB,包含312张jpg图像…

2026/10/11 19:59:51 阅读更多 →
关系数据库范式设计:从函数依赖到BCNF工程落地

关系数据库范式设计:从函数依赖到BCNF工程落地

简介:本资源是西南交通大学《数据库原理》课程第六章‘关系数据库设计理论’的配套作业详解文档,面向计算机专业本科生及数据库初学者,聚焦函数依赖分析、ERM反向建模与3NF规范化分解等核心难点。文档完整呈现了含40分简答题、50分设计题与10…

2026/10/11 19:59:51 阅读更多 →
银行排队系统实验报告核心指南:M/M/c建模与仿真验证

银行排队系统实验报告核心指南:M/M/c建模与仿真验证

简介:银行排队系统实验报告是一份面向计算机专业学生的C语言数据结构课程设计资料,以队列为核心模拟银行多窗口排队场景,帮助学习者掌握如何将离散事件仿真转化为可运行的程序,并理解平均逗留时间的计算逻辑。资源为单个doc文档&a…

2026/10/11 19:58:50 阅读更多 →

最新新闻

闪学it-手把手教你掌握新一代AI工具

闪学it-手把手教你掌握新一代AI工具

AI 工具实战指南:从提问技巧到成品输出全流程拆解一、认知基线:把大模型当作“概率推理引擎”多数人使用 AI 工具的挫败感,源于把它当成搜索引擎或万能助理,而忽略了它的本质:一个基于上下文进行概率续写的推理引擎。它…

2026/10/11 20:56:42 阅读更多 →
CNN+Transformer运动想象脑电分类实战:从预处理到跨被试调参

CNN+Transformer运动想象脑电分类实战:从预处理到跨被试调参

简介:这份毕业设计资源面向电子信息、生物医学工程及人工智能方向的本科生与研究生,聚焦运动想象脑电信号分类任务,采用CNNTransformer混合框架:CNN负责提取局部时空特征,Transformer捕捉全局依赖关系,并创…

2026/10/11 20:56:42 阅读更多 →
如何快速上手Hope Agent:从安装到首次对话的10分钟完整教程(macOS/Windows/Linux)

如何快速上手Hope Agent:从安装到首次对话的10分钟完整教程(macOS/Windows/Linux)

【免费下载链接】hope-agent 🦭 A cross-device desktop AI agent with memory, autonomous goals, dynamic workflows, and headless deployment | 会记忆、能持续推进目标、会动态编排多 Agent 的跨端桌面 AI 助手,也可服务化常驻 NAS / 云端 项目地址…

2026/10/11 20:56:42 阅读更多 →
Avocado Examples案例深度解析:从滑动条到聊天应用,18个交互原型实战拆解

Avocado Examples案例深度解析:从滑动条到聊天应用,18个交互原型实战拆解

【免费下载链接】avocado An interaction design toolbox 项目地址: https://gitcode.com/gh_mirrors/avocado11/avocado 点击查看 免费下载 Avocado 是一个零代码的交互设计工具箱(interaction design toolbox),其 Examples/ 目…

2026/10/11 20:56:42 阅读更多 →
GPS轨迹纠偏与地图匹配:从最近邻投影到隐马尔可夫模型的Python实现

GPS轨迹纠偏与地图匹配:从最近邻投影到隐马尔可夫模型的Python实现

简介:面向需要处理GPS轨迹与路网数据对齐的开发者,这份地图匹配资源提供了完整的Python实现方案。项目围绕真实定位数据漂移问题,涵盖数据预处理、最近邻/HMM等多种匹配算法,并配以可视化验证脚本,适合从事交通监控、导…

2026/10/11 20:56:42 阅读更多 →
HyperQwen int8 张量核实战:修复 Marlin W4A8 负缩放 bug 并逐层选择激活量化

HyperQwen int8 张量核实战:修复 Marlin W4A8 负缩放 bug 并逐层选择激活量化

HyperQwen int8 张量核实战:修复 Marlin W4A8 负缩放 bug 并逐层选择激活量化 【免费下载链接】HyperQwen Serve large Qwen models fast on the GPUs you actually own. Qwen3.8-27B on a single 24 GB card with vLLM: 127 tok/s single-user (381 when the answe…

2026/10/11 20:55:42 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →