news 2026/9/10 7:33:12

PHP内存溢出排查与优化:从报错定位到分批处理实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PHP内存溢出排查与优化:从报错定位到分批处理实战

平时在群里看PHP开发者问得最多的问题,除了"这个报错啥意思",大概就是内存溢出了。尤其像批量Excel处理、远程接口拉取大数据、图片压缩、视频处理这类脚本,跑着跑着突然弹出一句:

PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate ... bytes)

脚本直接中断,数据没处理完,日志还不好查。这个问题我在生产环境踩过很多次,也在不同的项目里试过各种方案,今天把这几年积累的定位思路、排查工具、实战解法一次性聊透。无论你是刚入门还在用宝塔面板跑PHP,还是在搞队列消费、容器打包,这篇文章应该都能给你省不少时间。

1. 内存溢出的常见场景与报错解读

很多初学者一看到内存溢出就觉得很玄学,其实它就是一个非常直白的问题:PHP程序运行时,需要申请的内存大小超过了当前环境允许的上限。要理解它,先看两件事:报错长什么样,以及它通常出现在哪些业务里。

1.1 典型的报错形态以及含义

拿最常见的报错来说:

PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /www/wwwroot/project/task.php on line 56

这里面的134217728 bytes,换算一下正好是128M,就是php.inimemory_limit的默认值。后边的tried to allocate 20480 bytes表示程序在尝试申请20KB额外内存时失败了。实际情况往往是内存已经满了,哪怕你再申请1KB都拿不到,报错里的数字只是最小的一次申请记录而已。

我见过不少新手看到这串报错,第一反应就是调大memory_limit,从128M调到256M,还不行就调到1024M,好像只要把天花板掀了问题就没了。但这是治标不治本。如果脚本本身在无限循环里积累数据,或者一次性把一个超大文件读进了内存,你就算把memory_limit改成-1(不限制),最终也会把服务器的物理内存耗尽,甚至把机器拖死,连MySQLNginx都跟着遭殃。

1.2 哪几类项目最容易触发内存溢出

根据我实际接触过的项目,下面这几种业务场景是内存溢出的"高发区":

  • 批量数据处理:Excel批量导入、批量更新数据库、定时拉取第三方接口数据。比如用PHPExcel读取一个几十MB的Excel,因为库的特性会把所有行都载入内存,几百行还行,几万行直接爆。
  • 图片/视频处理GD库或Imagick处理大尺寸图片,图片像素越高,内存消耗呈指数级上涨。视频压缩、转码也类似,码流数据全在内存里跑。
  • 队列消费者:常驻内存的PHP进程,比如用ThinkPHPLaravel写的队列脚本。如果业务代码里有累积型变量或全局缓存,跑的时间越长,内存越大,直到溢出。
  • 复杂计算或代码审计类脚本:递归算法没写退出条件、foreach循环里不停往数组里丢数据、正则回溯次数爆炸,都会在不知不觉中吃满内存。

我自己有一次印象很深的经历:帮客户排查一个PHP脚本,功能是用GD库给商品图片加水印,图不算大,但脚本跑几十张就崩。后来用工具一量,发现每次循环里创建的图片对象都没有销毁,一张2MB的图片在内存里以像素数组形式存在时能膨胀到几十MB,循环累积下来必炸。

1.3 PHP内存限制的机制和初衷

PHP设置memory_limit并不是故意找茬,而是为了避免单个请求把服务器资源耗尽。对于Web请求来说,每个请求是短生命周期进程,加上内存限制可以防止恶意或错误的脚本消耗掉整个FPM进程池的资源。但对于CLI命令行脚本来说,生命周期可能很长,内存限制依然有效,这就导致了很多通过命令行跑批量任务时频繁报错。

理解了这个机制,你就能明白:调大memory_limit是一种临时手段,而让程序在有限内存下跑完任务才是核心目标。下面我们从原理开始,一步步拆解内存为什么会涨上去。

2. 深入理解PHP内存管理的底层逻辑

想真正解决内存溢出,只改配置是不够的,你得清楚PHP内部是怎么管理内存的。这一节我会用比较通俗的方式讲一下引用计数、垃圾回收和常见的内存累积写法,这是后面所有排查手段的理论基础。

2.1 变量的生命周期与引用计数机制

PHP脚本里的每个变量,内部都通过一个zval结构体来存储,这个结构体里有一个字段叫refcount,用来记录这个变量被多少个符号引用。当refcount变为0时,这个变量的内存就能被释放了。

举个例子:

$a = str_repeat('x', 1024 * 1024); // 占用1MB内存 $b = $a; // 这里并没有复制1MB,而是refcount++,内存还是1MB unset($b); // refcount--,内存还是1MB,由$a继续持有 unset($a); // refcount归零,1MB内存被释放

很多初学者不理解为什么unset($b)没有释放内存,因为变量并没有真正独立复制一份,这其实是PHP内存优化的手段。在COW(Copy On Write,写时复制)机制下,只有当一个变量被修改时,才会真正分裂出一份副本。

但这套机制在某些写法下会失效,最常见的就是循环里"自己引用自己":

$arr = []; $arr['self'] = &$arr; // 写时复制在引用面前失效 unset($arr); // 变量没了,但内部引用计数还是1,内存释放不掉

这就是垃圾回收里常说的"循环引用泄漏",在简单的unset下无法靠引用计数归零来清理,只能等GC(垃圾回收器)的cycle collector定期扫描。

2.2 引用计数清零与垃圾回收机制

从PHP 5.3开始,引入了基于Concurrent Cycle Collection的垃圾回收器,专门处理循环引用。但GC不是实时执行的,它有自己的触发条件:当根缓冲区里的疑似垃圾节点数量达到一定阈值(默认10000)时,才会启动回收流程。

所以,如果你的脚本只是循环几百次,产生的垃圾不够触发阈值,内存可能一直挂在那;如果循环几万次,GC启动之后会有一波卡顿。很多人会手动调用gc_collect_cycles()来强制回收,但这不能滥用,因为GC本身也消耗CPU。

我做过一个测试:一个循环里不断创建匿名对象,并且让对象之间互相引用,如果不手动干预,跑10万次循环,内存峰值会达到50MB以上;如果每1000次调用一次gc_collect_cycles(),内存峰值可以控制在10MB以内,但CPU耗时增加了约15%。在CLI批处理脚本中,这个取舍很划算;在高频Web请求中,则不建议主动调用。

2.3 内存膨胀的真实原因:累积、持有与占用

抛开底层机制,从业务代码的角度看,内存溢出本质上是三类原因:

  • 累计型:循环里往数组或对象里不停添加数据,比如把所有查询结果都攒在一个数组里,最后才统一处理。
  • 持有型:变量被全局对象、静态属性、闭包长期引用,无法释放。比如Laravel事件监听器里绑定了大对象,整个请求生命周期内都释放不掉。
  • 占用型:单次操作本身就非常耗内存,比如读取一个1GB的日志文件用file_get_contents(),或把一张5000x5000的图片用imagecreatetruecolor()转换成真彩色画布,这部分内存是跳跃式增长的。

以下面这段代码为例,看似简短,内存却会爆得很迅速:

$data = []; $file = fopen('large_log.txt', 'r'); while ($line = fgets($file)) { $data[] = json_decode($line, true); // 每行JSON都存进数组 }

large_log.txt有50万行时,$data数组会持有50万行解析结果,即使每行只有1KB,累积起来也有500MB。正确做法应该是逐行处理完就释放,或者分批落库。

3. 定位内存溢出的排查工具与实践方法

遇到内存溢出,别急着改代码或改配置,先定位到底是谁在"吃内存"。这一节分享几个我常用的方法,从简单的打点到工具辅助,一步步缩小范围。

3.1 用memory_get_usage打点定位

PHP内置了memory_get_usage()memory_get_peak_usage()两个函数,分别返回当前内存使用量和峰值内存使用量。在关键节点打印这两个值,可以把问题缩小到某段代码。

我在排查脚本时经常这么干:

// task.php echo '初始内存: ' . memory_get_usage() / 1024 / 1024 . " MB\n"; $users = getUsers(); // 从数据库读取用户列表 echo '读取用户后: ' . memory_get_usage() / 1024 / 1024 . " MB\n"; foreach ($users as $user) { processUser($user); } echo '处理完用户后: ' . memory_get_usage() / 1024 / 1024 . " MB\n"; echo '峰值内存: ' . memory_get_peak_usage() / 1024 / 1024 . " MB\n";

如果发现"读取用户后"和"处理完用户后"内存几乎一样,说明$users数据量太大,或者processUser里并没有真正释放资源。如果内存是随着循环次数稳步上升,那基本就是累积型问题,比如循环里追加了数组或没有清理临时变量。

这种打点方式虽然"原始",但胜在简单可靠,尤其在生产环境不方便装扩展的时候,这是最快的一招。

3.2 二分法隔离嫌疑代码

如果脚本非常长,内存峰值又很高,逐行打断点效率太低。我的习惯是先按功能块划分,然后分批注释,用memory_get_peak_usage()对比前后差异。

  • 先注释掉一半代码,跑一次,看内存峰值是否下降。
  • 如果下降了,说明问题在被注释掉的那一半里,继续二分。
  • 如果没下降,说明问题在保留的这一半里,继续二分。

用这种方式,通常四到五次就能定位到一个几十行的函数。我在一次排查中遇到的是一个图片缩放库,所有图片先被base64_encode后放入数组等待批量上传,一次500张图,内存峰值直接飙升到1GB。定位到这一行后,改成每处理一张就上传一张,内存瞬间降到80MB以内。

3.3 借助Xdebug和日志分析工具

Xdebug除了调试断点外,也能输出内存分析报告。配置好xdebug.auto_trace=1xdebug.collect_params=1之后,它会生成一份非常详细的函数调用日志,能看到每个函数的参数和耗时,但内存信息还不够直观。

更推荐的是Xdebug+Webgrind的组合,或者直接用phpstormProfile功能,图形化界面能直观看到内存消耗最高的调用栈。但Xdebug在生产环境会大幅拖慢性能,不建议长期开启,我一般是在本地或测试环境复现问题后再开。

还有一个办法是利用error_log记录内存变化曲线:

register_shutdown_function(function () { $error = error_get_last(); if ($error && strpos($error['message'], 'Allowed memory size') !== false) { error_log(json_encode([ 'time' => date('Y-m-d H:i:s'), 'memory' => memory_get_peak_usage(true), 'file' => $error['file'], 'line' => $error['line'], ]), 3, '/tmp/php_memory.log'); } });

这样生产环境报错时,至少能记录下当时的峰值内存和出错文件行号,方便事后分析。

4. 针对不同原因的解决方案与优化实践

定位到原因之后,就是对症下药了。这一节我会按配置调整、代码优化、工具选型三个层面给出具体方案,都是我在实际项目中验证过的做法。

4.1 合理调整memory_limit与运行环境配置

先说说什么时候该调配置。如果你的脚本确实存在单次大内存操作的需求,比如解析一个几十MB的JSON文件,而机器内存又充足,适当提高memory_limit是合理的。

  • 临时提升:在脚本开头用ini_set('memory_limit', '512M'),只影响当前脚本。
  • 永久调整:修改php.iniphp-fpmphp_admin_value,对整个环境生效。
  • CLI脚本:可以通过命令行参数指定php -d memory_limit=512M task.php,不用改任何配置文件。

但我不建议把memory_limit设成-1。一旦去掉限制,程序真的失控时,服务器会被直接拖垮,连SSH都卡。线上环境我一般只允许CLI脚本临时设置,Web请求仍保持128M或256M。

另外,PHP-FPMpm.max_requests也值得关注,合理的设置能让进程在累计消耗过多内存后自动回收。

4.2 用生成器节省循环内存

如果瓶颈是数据量太大,比如从数据库读取50万行记录,传统写法是->get()一次性取出所有数据,这非常耗内存。推荐用**生成器(Generator)**配合游标或分页处理。

Laravel为例:

// 传统写法:一次性加载50万条到内存 $users = User::query()->get(); foreach ($users as $user) { // 处理逻辑 } // 推荐写法:每次只取一条,内存占用极低 foreach (User::query()->cursor() as $user) { // 处理逻辑 }

cursor()就是基于生成器实现的,它每次从数据库取出一条记录,用完即弃。用这种方式处理50万条用户数据,内存占用几乎恒定在几十MB级别。

如果你用的是原生PHPMySQL,也一样可以用unbuffered query

$pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', '123456'); $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); $stmt = $pdo->query('SELECT * FROM large_table'); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { // 逐行处理,而不是全部缓存到内存 }

4.3 大文件读取与Excel批处理的优化技巧

处理大文件时,千万别用file_get_contents()file()(后者会把每一行都存成数组元素),而是要逐行读取:

$handle = fopen('large_file.csv', 'r'); while (($row = fgetcsv($handle, 0, ',')) !== false) { // 逐行处理CSV数据 } fclose($handle);

fgetcsv是流式读取,内存占用基本是固定的。对于Excel文件,尽量用PhpSpreadsheetsetReadDataOnly(true)setReadFilter()组合,只读取需要的列和行,避免把样式、公式也加载进内存。不过更推荐把Excel转成CSV后再用fgetcsv处理,效率更高且内存更省。

如果数据量非常大,还可以配合分批落库,处理1000行就INSERT一次,处理完unset($batch),保证内存里面同时存在的只有当前批次的数据。

4.4 图片压缩与视频处理场景的内存控制

PHP处理图片时,最耗内存的操作是imagecreatetruecolor()。一张1920x1080的图片,每个像素需要4字节(RGBA),算下来就是192010804≈8.3MB,如果图片是5000x5000,那就是100MB。所以处理大图前,先压缩画布尺寸,或者先压缩源图尺寸再处理。

我常用的一个做法:

function resizeImage($source, $maxWidth = 800, $maxHeight = 600) { $info = getimagesize($source); $src = match($info['mime']) { 'image/jpeg' => imagecreatefromjpeg($source), 'image/png' => imagecreatefrompng($source), 'image/gif' => imagecreatefromgif($source), default => throw new RuntimeException('Unsupported image type'), }; $dst = imagecreatetruecolor($maxWidth, $maxHeight); imagecopyresampled($dst, $src, 0, 0, 0, 0, $maxWidth, $maxHeight, $info[0], $info[1]); imagedestroy($src); // 用完立即销毁 // 输出或保存 $dst ... imagedestroy($dst); // 最后也要销毁 }

注意imagecreatefrom*imagecreatetruecolor创建的图像资源,在不再需要时务必imagedestroy(),否则它们会一直占着内存直到请求结束。

视频处理场景通常不建议用纯PHP,而是直接调用外部工具如FFmpeg。用shell_execproc_open执行FFmpeg命令,PHP只负责发起和接收结果,内存占用极小。之前帮人优化一个视频压缩脚本,原本用PHP读取整个视频进内存,改造成exec("ffmpeg -i input.mp4 -vf scale=... output.mp4")之后,PHP侧的内存开销几乎可以忽略。

4.5 队列消费和常驻进程的防泄漏设计

对于队列消费者这类常驻进程,问题往往不是单个任务吃内存,而是任务间内存无法回收导致慢慢涨。我用Laravel队列时走过一个弯路:在handle()方法里用了static变量缓存数据,结果进程不退出,静态变量永远不清空,跑几百个任务后内存就上去了。

后来我总结了一套队列进程的内存控制规范:

  • 任务类里尽量不用static属性或全局变量来缓存数据,非用不可时在任务结束时手动清理。
  • 在循环处理任务的while里,每隔一定数量(比如1000个)主动调用gc_collect_cycles()
  • 给队列进程设置最大执行时间最大处理数量,超过后自动退出,由Supervisor或宝塔的进程守护重新拉起。比如Laravel队列可以通过--max-time=3600让进程每小时退出一次。
php artisan queue:work --tries=3 --max-time=3600

5. 框架与运维环境中的内存溢出问题排查

不同框架、不同运行环境下,内存溢出的表现和排查入口也有差异。这一节专门说一下我在LaravelThinkPHP、宝塔面板和Docker容器里遇到过的情况。

5.1 Laravel与ThinkPHP中的常见坑

Laravel里,最经典的内存坑是模型关联的懒加载。如果查询100条文章数据,再逐条访问$article->comments,模型关联会被重复查询,不但慢,还会在内存里堆积大量重复的模型对象。用with('comments')预加载可以避免,但预加载本身也会一次性把关联数据装入内存,数据量很大时仍需分批。

另一种情况是队列任务里捕获了异常却没有释放资源。比如日志类绑定了句柄,catch之后句柄还挂着,下次任务继续追加。我的建议是:在finally里显式关闭句柄、释放资源。

ThinkPHP的情况类似,我之前遇到过用Db::name('table')->select()不加分页,一下查10万条,直接把内存打满。解决办法是改用chunk方法分批处理,或者用游标查询。

5.2 宝塔面板下排查PHP进程内存

换到宝塔面板环境,排查思路也差不多,但操作入口有些不同。我常用的操作是:

  1. 在宝塔的软件商店里打开PHP扩展,确认是否安装了opcacheopcache会缓存编译后的文件,节省内存。
  2. 找到php.inimemory_limit的配置,如果需要调到512M或更高,建议只改CLI模式的,避免Web请求也放开限制。
  3. 用宝塔自带的终端功能,执行ps aux | grep php,看各个php-fpm进程的RSS内存占用。如果某个进程的RSS一直在涨,可能就是请求泄漏或队列进程泄漏。
  4. 配置文件写入临时路径时,如果磁盘不够也可能报其他错误,但内存溢出还是优先看/tmp目录是否被缓存文件塞满。

宝塔的网站监控报表功能也能看到每个站点的PHP-FPM状态,如果某个站点平均内存使用率持续走高,大概率是那个站点的代码有问题。

5.3 Docker容器中PHP应用的资源限制

如果是通过Docker部署的PHP应用,除了PHP自身的memory_limit,还有一层容器内存限制。docker run --memory=512m会在操作系统层面限制容器使用的内存,即使用户态PHP代码把memory_limit设成-1,超过512M依然会被OOM Killer杀掉。

我做过一次PHP应用容器化排查:明明PHP脚本设置的memory_limit已经调到1G,但进程跑到500多MB就崩溃,docker logs里看到Killed。后来才发现是docker-compose.ymlmem_limit: 512m起的作用,改成1G后问题解决。

如果你在打包镜像时遇到类似问题,建议在Dockerfile里用CMD指定内存参数,比如:

CMD ["php", "-d", "memory_limit=1G", "artisan", "queue:work"]

这样至少能让项目的内存配置跟镜像走,部署到哪台机器都一样。

6. 一次完整的内存溢出事故排查复盘

聊了这么多理论和方法,最后用一个我亲历的案例,把从报错到修复的完整过程串一遍,方便你直观感受整套排查思路。

6.1 事故现场

客户反馈:后台有一个"批量导出报表"功能,选一个月的数据量大概30万行,点击导出后,页面一直转圈,过一会儿Nginx返回502,查看PHP-FPM日志,发现报错:

WARNING: [pool www] server reached pm.max_children setting (5), consider raising it

继续看PHP错误日志,内存溢出的Fatal error一条接一条。初步判断是导出功能把当月所有数据SELECT *出来后存在数组里,再循环拼接CSV字符串,最后一次性输出。

6.2 排查过程

我直接在服务器上跑了一条模拟命令:

php -d display_errors=1 -r "require 'export.php';"

手动执行脚本,打印出memory_get_peak_usage(),峰值来到900MB+。于是进一步打点,发现在查询所有数据后内存就占了750MB,后面拼CSV反而没涨多少。确认瓶颈就是一次性取出30万行数据

接下来的修复思路很清晰:改成chunk分批查询,每批5000行,处理完就写文件,最终完美解决了内存问题。

6.3 最终修复方案

// 原写法 $rows = Db::name('orders')->where('create_time', '>=', $start) ->where('create_time', '<', $end) ->select(); // 一次性取30万行,直接爆炸 // 修复方案 $fp = fopen('php://output', 'w'); // 输出CSV头 fputcsv($fp, ['订单号', '金额', '时间']); Db::name('orders') ->where('create_time', '>=', $start) ->where('create_time', '<', $end) ->chunk(5000, function ($rows) use ($fp) { foreach ($rows as $row) { fputcsv($fp, [$row['order_no'], $row['amount'], $row['create_time']]); } }); fclose($fp);

chunk(5000)每次只查5000行,内存占用基本恒定,CSV用流式写入,也不会在内存中累积。改完之后内存峰值从900MB降到了60MB左右,导出速度还快了,因为PHP-FPM进程不再被大内存请求锁死。

6.4 防止再次出现的护城河

这次事故之后,我给项目加了几道防线:

  • 代码层面:凡是列表导出的方法,统一用chunk或游标方式;凡是读取远程接口或文件,统一做分批/流式处理。
  • 日志层面:全局注册了shutdown function,一旦发生内存溢出,自动记录峰值内存和所在文件行号。
  • 监控层面:给php-fpm进程加了一个简单的内存监控脚本,当某个php-fpm进程RSS超过300MB时自动告警。
  • 测试层面:把memory_limit降到32M进行本地自测,倒逼自己写出内存友好的代码。

这就是一套完整的护城河思路。内存管理不是"碰到问题再调大"的事,而是要养成构造代码时就有内存意识的习惯。

7. 常用工具与函数速查

最后放一个我在排查和优化内存问题时常用的函数/工具清单,方便你直接复制使用。

7.1 PHP内置函数速查

函数作用使用场景
memory_get_usage()获取当前已使用内存打点查看阶段性内存变化
memory_get_peak_usage()获取脚本运行以来峰值内存确认脚本整体内存消耗
ini_set('memory_limit','512M')动态调整内存上限临时提升单个脚本限制
gc_collect_cycles()强制触发垃圾回收常驻内存循环大任务
unset($var)解除变量引用释放大变量或数组
imagedestroy($img)销毁图像资源图片处理的循环中

7.2 命令行排查技巧

# 查看php.ini位置 php --ini # 临时提升内存执行脚本 php -d memory_limit=512M task.php # 查看php-fpm进程的内存占用,按RSS排序 ps aux --sort=-rss | grep php-fpm # 代码内存曲线打点 php -r "echo memory_get_peak_usage(true);"

7.3 一个通用监控脚本模板

如果项目里经常有定时任务,建议在crontab里每5分钟跑一次这个脚本,把内存异常提前揪出来:

#!/bin/bash # 监控php-fpm内存使用,超过400MB输出告警 threshold=409600 for pid in $(pgrep php-fpm); do rss=$(awk '/VmRSS/{print $2}' /proc/$pid/status) if [ "$rss" -gt "$threshold" ]; then echo "[$(date)] php-fpm pid $pid memory: ${rss}KB" >> /var/log/php_memory_alert.log fi done

这个脚本不用装任何额外软件,只要有/proc文件系统就能跑,很多集群服务器上我都是这么用的。

8. 最后想说的几句实在话

我在实际排查内存溢出问题时的感受是:80%的情况不是PHP本身的问题,而是代码写法的问题memory_limit只是告诉你"到此为止",真正要解决的是为什么程序在有限内存里活不下去。

如果你正被这个问题折磨,记住三步走:先用memory_get_peak_usage()打点确认位置,再用二分法缩小范围,最后用分批/流式/释放资源的方法修复。做完这三步,你至少能解决绝大多数场景下的内存溢出。

另外一个小技巧:优化内存时把memory_limit故意调小一些,比如32M,然后用php -l跑一遍脚本,看到报错就说明你的代码还是太"胖"了。用这种自虐的方式来写代码,后面线上你反而会轻松很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 7:32:52

2020电赛E题资料.zip深度解析:嵌入式实时信号处理实战指南

简介&#xff1a;本资源为2020年全国大学生电子设计竞赛E题&#xff08;无线充电器设计&#xff09;的完整实战资料包&#xff0c;面向电子类、自动化、通信等专业本科生及电赛备赛团队&#xff0c;聚焦高频功率变换、磁耦合谐振建模与闭环控制实现等核心难点。压缩包共200.77M…

作者头像 李华
网站建设 2026/9/10 7:32:31

Buzz 上手指南:本地离线转录,免费把录音转成文字和字幕

Buzz 上手指南&#xff1a;本地离线转录&#xff0c;免费把录音转成文字和字幕 【免费下载链接】buzz Buzz transcribes and translates audio offline on your personal computer. Powered by OpenAIs Whisper. 项目地址: https://gitcode.com/GitHub_Trending/buz/buzz …

作者头像 李华
网站建设 2026/9/10 7:32:01

2026大模型工程师实战路线:从本地部署到微调落地的技能地图

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

作者头像 李华
网站建设 2026/9/10 7:31:32

Flipper Zero 音乐播放器完整指南:从 RTTTL 到 FMF 的旋律改造

Flipper Zero 音乐播放器完整指南&#xff1a;从 RTTTL 到 FMF 的旋律改造 【免费下载链接】Flipper Playground (and dump) of stuff I make or modify for the Flipper Zero 项目地址: https://gitcode.com/GitHub_Trending/fl/Flipper 这个来自 fl/Flipper 仓库的 Mu…

作者头像 李华
网站建设 2026/9/10 7:31:20

DeepCode 部署 3 步上手:把多智能体编程助手跑起来

DeepCode 部署 3 步上手&#xff1a;把多智能体编程助手跑起来 【免费下载链接】DeepCode "DeepCode: Open Agentic Coding (Agent Harness & Loop Engineering & Multi-Agent Orchestration)" 项目地址: https://gitcode.com/GitHub_Trending/deepc/DeepC…

作者头像 李华
网站建设 2026/9/10 7:30:43

AI技能实操:npx skill add 安装 ponytail,把散乱信息扎成束

我第一次见到 ponytail 这个词&#xff0c;不是在某本发型杂志上&#xff0c;而是在同事发来的一行命令里&#xff1a;npx skill add dietrichgebert/ponytail。当时我第一反应是&#xff0c;这年头连扎马尾辫都要装个技能了&#xff1f;后来等我把这个技能真正装进本地环境、跑…

作者头像 李华