轻量级H264解码库实战:从NAL解析到宏块重建

简介:这份资源面向在C# WinForm环境下开发视频监控或播放类应用的开发者,提供海思H264解码库的完整调用素材,帮助解决原生解码库与.NET平台对接的问题。压缩包共9个文件,约839KB,包含2个lib静态库、1个dll动态库、2个h头文件、1个c示例源码、1个exe可执行程序以及2个pdf开发文档,覆盖从接口定义到实际调用的完整链路。其中头文件与API参考文档可用于梳理解码器初始化、单帧解码、资源释放等函数原型,示例源码展示了NAL单元读取、YUV数据获取与解码流程组织方式,开发指南则补充了参数配置与错误处理说明。目前已有364人学习下载,适合具备一定C#基础、需要借助P/Invoke集成海思解码能力的中高级开发者参考,可减少接口封装与调试环节的摸索成本。

1. 从播放器卡顿说起:这个 H264 解码库到底能干什么

如果你做过音视频相关的开发,大概率遇到过这样的场景:从某处拿到一段 H264 裸流,想在自己的程序里解出 YUV 或者 RGB 帧,结果发现 FFmpeg 太重、依赖太多,编译一次要等半天,移植到嵌入式设备上更是各种水土不服。这时候一个轻量级的 H264 解码库就显得特别实用。思 H264 解码库就是冲着这个需求去的——它把 H264 的解析和解码逻辑封装成一套相对独立的模块,不依赖庞大的多媒体框架,适合需要把解码能力嵌进自己项目里的开发者。你可以用它来解码本地 H264 文件、处理实时流中的 NAL 单元,或者把它当成学习 H264 解码流程的参考实现。适合谁?做嵌入式音视频的、写播放器内核的、想搞清楚 H264 帧内帧间预测到底怎么落地的,以及需要一套可裁剪解码方案的工程师。它不追求大而全,追求的是能看懂、能改、能塞进你自己的工程里跑起来。

2. 工程结构与核心模块:从码流到图像的完整链路

2.1 目录组织与模块划分

拿到一个解码库,我习惯先看目录结构,因为目录往往比文档更能说明作者的设计意图。思 H264 解码库的源码组织通常遵循“解析—解码—输出”三段式划分,常见做法是分成以下几个核心目录:

  • src/或source/:存放解码器主体实现,包括 NAL 解析、SPS/PPS 处理、切片解码、宏块重建等。
  • include/:对外暴露的头文件,定义解码器句柄、配置结构体、回调接口。
  • utils/或common/:比特流读取、内存管理、错误码定义等公共设施。
  • examples/或test/:最小可运行示例,通常是一个读文件、解码、写 YUV 的控制台程序。
  • build/或根目录下的 Makefile/CMakeLists.txt:构建脚本。

这种划分的好处是解码核心和平台相关代码分离得比较干净。你移植的时候,主要改的是内存分配和文件 IO 那几处,解码逻辑本身不用动。

2.2 NAL 解析与参数集处理

H264 码流的基本单位是 NAL 单元。解码的第一步,就是把连续的字节流切分成一个个 NAL,然后根据 NAL 类型决定是送进参数集解析器还是切片解码器。下面这段代码展示了一个典型的 NAL 切分逻辑:

// 从码流缓冲区中查找起始码 0x000001 或 0x00000001 static int find_start_code(const uint8_t *buf, int size, int offset) { for (int i = offset; i < size - 3; i++) { if (buf[i] == 0 && buf[i+1] == 0 && buf[i+2] == 1) { return i; // 返回起始码位置 } if (i < size - 4 && buf[i] == 0 && buf[i+1] == 0 && buf[i+2] == 0 && buf[i+3] == 1) { return i; } } return -1; // 没有找到 } // 解析 NAL 头,取出 nal_unit_type static int parse_nal_header(const uint8_t *nal, int len, NalHeader *hdr) { if (len < 1) return -1; hdr->forbidden_zero_bit = (nal[0] >> 7) & 0x01; hdr->nal_ref_idc = (nal[0] >> 5) & 0x03; hdr->nal_unit_type = nal[0] & 0x1F; return 0; }

这里的逻辑说明:find_start_code负责在缓冲区里定位 NAL 的起始位置,H264 的起始码有两种形式,三位和四位,四位形式多一个零字节,通常出现在流的开头或者某些特殊位置。parse_nal_header从 NAL 的第一个字节里提取nal_unit_type,这个字段决定后续走哪条解析路径——类型 7 是 SPS,类型 8 是 PPS,类型 5 是 IDR 切片,类型 1 是非 IDR 切片。参数说明:nal_ref_idc表示该 NAL 是否被参考,非零表示后续帧可能依赖它,解码时不能随便丢弃。

我一般会在 NAL 解析层加一个环形缓冲区,因为实时流里 NAL 可能跨包到达,直接对整块内存做起始码扫描容易漏掉边界情况。这个库的常见做法是提供一个nal_buffer_feed接口,你往里喂数据,它内部维护状态,凑齐一个完整 NAL 再回调给你。

2.3 切片解码与宏块重建

切片解码是整个库最核心也最复杂的部分。H264 的切片由切片头、切片数据和宏块数据组成。解码器需要根据切片头里的slice_type判断这是 I 切片、P 切片还是 B 切片,然后逐个宏块进行预测、变换、量化反变换和重建。

下面是一个宏块重建的简化流程代码:

// 解码一个宏块,mb 是宏块上下文,包含预测模式、残差等信息 static int decode_macroblock(Decoder *dec, Macroblock *mb) { // 1. 根据 mb_type 确定预测方式 if (mb->mb_type == MB_TYPE_I_16x16) { // 帧内 16x16 预测,读取预测模式 mb->intra_pred_mode = read_ue(dec->bs); intra_predict_16x16(dec, mb); } else if (mb->mb_type == MB_TYPE_P_16x16) { // 帧间预测,读取运动矢量差 read_motion_vector_diff(dec->bs, &mb->mvd); // 根据参考帧和运动矢量做运动补偿 motion_compensate(dec, mb); } // 2. 读取残差系数,做反量化和反变换 if (mb->coded_block_pattern > 0) { read_residual_coeffs(dec->bs, mb); dequantize(mb); inverse_transform(mb); } // 3. 预测块 + 残差 = 重建块 reconstruct_block(mb); // 4. 去块滤波(如果启用) if (dec->deblocking_enabled) { deblock_macroblock(dec, mb); } return 0; }

逻辑说明:这段代码把宏块解码拆成四步——预测、残差解析、重建、滤波。read_ue是读取无符号指数哥伦布码,H264 的很多语法元素都用这种编码。motion_compensate根据运动矢量和参考帧计算预测块,这是 P/B 切片解码的关键。dequantize和inverse_transform把残差系数还原成像素域的残差。最后reconstruct_block把预测值和残差值相加得到重建像素。参数说明:coded_block_pattern指示哪些 8x8 子块有非零残差系数,为零时可以跳过残差解析,这是 H264 的一个优化点。

实际解码时,宏块之间的依赖关系很重——帧内预测要用到左边和上边的已重建像素,帧间预测要用到参考帧。所以解码顺序不能乱,而且参考帧管理必须正确。这个库通常用一个 DPB(解码图像缓冲区)来管理参考帧,你需要在初始化时指定 DPB 大小。

2.4 输出 YUV 与帧管理

解码完一帧后,你需要把重建像素从内部格式转成 YUV 或 RGB 输出。这个库一般提供两种输出方式:一种是直接给你 YUV420P 的平面指针,你自己拷贝;另一种是注册回调,解码器每解完一帧就调你的函数。

// 解码一帧并输出 YUV420P int decoder_decode_frame(Decoder *dec, Frame *out) { int ret = decode_one_frame(dec); if (ret < 0) return ret; // 从 DPB 中取出当前解码帧 FrameBuffer *fb = dpb_get_current(dec->dpb); if (!fb) return ERR_NO_FRAME; // 填充输出结构体 out->width = dec->sps.width; out->height = dec->sps.height; out->data[0] = fb->y; // Y 平面 out->data[1] = fb->u; // U 平面 out->data[2] = fb->v; // V 平面 out->linesize[0] = fb->stride_y; out->linesize[1] = fb->stride_uv; out->linesize[2] = fb->stride_uv; return 0; }

逻辑说明:decode_one_frame内部会循环解析 NAL 直到解出一帧完整图像。dpb_get_current从解码图像缓冲区取出当前帧的像素数据。输出结构体里的linesize是行跨度,可能大于宽度,因为内存对齐的原因。参数说明:width和height来自 SPS,如果 SPS 里有裁剪信息,实际显示尺寸可能略小,需要根据frame_cropping字段调整。

提示:YUV 输出时注意 UV 平面的行数是 Y 平面的一半,linesize 也可能不同,拷贝时别搞混。

3. 编译与运行:从源码到可执行文件

3.1 构建环境与依赖

这个库的设计目标之一就是依赖少,所以通常只需要一个 C99 编译器和一个 make 工具就能编。常见做法是提供 Makefile 和 CMakeLists.txt 两套构建脚本,你用哪个顺手就用哪个。我一般先用 Makefile 快速验证,因为改起来直观。

# 查看目录下有没有 Makefile ls # 常见输出:Makefile CMakeLists.txt src/ include/ examples/ # 直接用 make 编译 make # 如果报错找不到头文件,检查 include 路径 make CFLAGS="-I./include -O2 -Wall"

逻辑说明:make会读取 Makefile,按规则编译src/下的源文件,链接成静态库或可执行文件。CFLAGS里的-I./include告诉编译器头文件在哪,-O2开优化,-Wall开警告。参数说明:如果你的平台是 ARM 嵌入式,需要把CC换成对应的交叉编译器,比如make CC=arm-linux-gnueabihf-gcc。

3.2 最小可运行示例

examples/目录下通常有一个decode_file.c或者类似名字的文件,功能是读一个 H264 文件,解码,把 YUV 写到输出文件。编译和运行方式如下:

# 编译示例程序 make examples/decode_file # 运行:输入 H264 文件,输出 YUV 文件 ./examples/decode_file input.h264 output.yuv # 如果程序支持打印信息,会看到类似输出: # SPS: 1920x1080, profile 100, level 40 # Decoded frame 0, type I # Decoded frame 1, type P # ...

逻辑说明:示例程序的主循环一般是打开文件、读一块数据、喂给解码器、取帧、写文件。input.h264是 Annex-B 格式的裸流,每个 NAL 前面有起始码。output.yuv是解码后的 YUV420P 数据,可以用 YUV 播放器打开验证。参数说明:如果输入文件是 AVCC 格式(长度前缀而不是起始码),需要先做格式转换,这个库可能不直接支持,你得自己加一层。

3.3 集成到自己的工程

如果你要把解码库嵌进现有项目,通常只需要把src/下的源文件和include/下的头文件加入你的构建系统,然后调用几个对外接口。常见做法是:

#include "h264_decoder.h" Decoder *dec = decoder_create(); decoder_set_output_callback(dec, my_frame_callback, NULL); // 喂数据 decoder_feed(dec, buf, len); // 解码循环 while (decoder_has_frame(dec)) { Frame frame; decoder_decode_frame(dec, &frame); // 处理 frame } decoder_destroy(dec);

逻辑说明:decoder_create分配解码器上下文,decoder_set_output_callback注册回调,decoder_feed往解码器里送码流数据,decoder_decode_frame取出一帧。参数说明:my_frame_callback的签名通常是void (*)(Frame *frame, void *userdata),你在回调里做渲染或存盘。注意回调里不要做太耗时的操作,否则会阻塞解码线程。

注意:多线程使用时,一个解码器实例只能被一个线程操作,多个线程解码要创建多个实例。

4. 避坑与常见问题:解码失败时先查这几处

4.1 解码花屏或绿屏

现象:解出来的 YUV 图像大面积绿色或者块状花屏。原因:最常见的是参考帧丢失或者 DPB 管理出错。H264 的 P 帧和 B 帧依赖前面的参考帧,如果参考帧被错误地释放或者覆盖,运动补偿就会取到错误数据。解决:检查 DPB 的分配和释放逻辑,确保参考帧在不再被依赖之前不被回收。另外检查nal_ref_idc,非零的 NAL 对应的帧要标记为参考帧。

4.2 首帧解码失败

现象:第一个 I 帧就解不出来,报错找不到 SPS 或 PPS。原因:SPS 和 PPS 必须在 IDR 切片之前到达解码器。有些码流把 SPS/PPS 放在文件头,有些则每个 IDR 前都重复发送。如果你的喂数据逻辑把 SPS 和 IDR 分到了不同的缓冲区,解码器可能还没收到参数集就开始解切片了。解决:在喂数据之前先扫描一遍,确保 SPS/PPS 先于 IDR 进入解码器。或者用带外方式把 SPS/PPS 直接设置给解码器。

4.3 内存泄漏

现象:长时间运行后内存持续增长。原因:每解码一帧都会分配帧缓冲区,如果输出回调里没有正确释放或者 DPB 只增不减,内存就会涨。解决:检查decoder_decode_frame之后是否需要调用decoder_release_frame。有些库的设计是帧缓冲区由解码器内部管理,你不需要释放;有些则需要你显式释放。看头文件里的注释,别想当然。

4.4 性能不达预期

现象:解码 1080p 流时 CPU 占用很高,帧率上不去。原因:可能是没开编译优化,或者去块滤波、运动补偿这些热点函数没有针对平台优化。解决:先确认编译时加了-O2或-O3。如果还不行,看热点函数能不能用 SIMD 指令重写。这个库通常把可优化的部分单独放在一个文件里,方便你替换成 NEON 或 SSE 版本。

4.5 时间戳错乱

现象:解码出来的帧顺序对,但时间戳不对,导致播放时音视频不同步。原因:H264 的 POC(图像顺序计数)计算错误,或者解码器没有正确输出 POC。解决:检查 POC 的计算逻辑,尤其是pic_order_cnt_type为 1 或 2 的情况。如果库不直接输出 POC,你可能需要自己根据帧类型和frame_num推算显示顺序。

5. 二次开发:裁剪、加速与接口改造

5.1 裁剪不需要的功能

这个库的一个好处是模块化程度还可以,你可以按需裁剪。比如你的场景只解 I 帧和 P 帧,不需要 B 帧,那就可以把 B 帧相关的运动补偿和参考帧管理代码去掉,能省不少空间。常见做法是用宏开关控制:

// 在配置头文件里定义 #define ENABLE_B_FRAME 0 #define ENABLE_DEBLOCKING 1 #define ENABLE_ERROR_CONCEALMENT 0

逻辑说明:ENABLE_B_FRAME关掉后,解码器遇到 B 切片直接跳过,不报错。ENABLE_DEBLOCKING关掉后,重建帧不做去块滤波,画质会差一点但速度快。ENABLE_ERROR_CONCEALMENT关掉后,遇到错误直接返回,不做隐藏处理。参数说明:裁剪之前先确认你的码流里确实没有 B 帧,否则关掉会解不出图像。

5.2 热点函数加速

解码的性能瓶颈通常在运动补偿、反变换和去块滤波。如果你在 ARM 平台上,可以用 NEON 重写这几个函数。我一般会先做 profiling,确认哪个函数占用时间最多,再针对性优化。比如运动补偿里的像素插值,用 NEON 一次处理 16 个像素,比 C 循环快好几倍。

// NEON 版本的 6 抽头插值滤波示例(简化) void interpolate_halfpel_neon(uint8_t *dst, uint8_t *src, int stride) { // 加载源像素 uint8x16_t s0 = vld1q_u8(src - 2); uint8x16_t s1 = vld1q_u8(src - 1); // ... 加载更多 // 加权求和 // 存储结果 vst1q_u8(dst, result); }

逻辑说明:这段代码用 NEON 指令并行处理多个像素的插值计算。vld1q_u8一次加载 16 个字节,vst1q_u8一次存储 16 个字节。参数说明:stride是行跨度,NEON 加载时要注意内存对齐,不对齐会降低性能甚至崩溃。

5.3 接口改造与封装

如果你要把这个库封装成 C++ 类或者给其他语言调用,建议在include/外面再包一层。比如封装成 C++ 的H264Decoder类,内部持有 C 的解码器句柄,析构时自动释放。这样上层业务代码不用关心 C 接口的细节。

class H264Decoder { public: H264Decoder() { dec_ = decoder_create(); } ~H264Decoder() { decoder_destroy(dec_); } bool feed(const uint8_t *data, int len) { return decoder_feed(dec_, data, len) == 0; } bool decode(Frame *out) { return decoder_decode_frame(dec_, out) == 0; } private: Decoder *dec_; };

逻辑说明:这个 C++ 封装用 RAII 管理解码器生命周期,构造时创建,析构时销毁。feed和decode直接转发给 C 接口。参数说明:如果要在多线程环境使用,记得给feed和decode加锁,或者每个线程一个实例。

5.4 验证改造效果

改完之后怎么验证?我一般用三组数据:一组标准测试流,一组实际业务流,一组边界情况(比如只有一帧、分辨率特别小、码流有错误)。标准测试流看解码正确性,实际业务流看性能和稳定性,边界情况看容错。对比改造前后的 YUV 文件,用md5sum或者逐像素比较,确保没有引入回归。

从那以后我每次改解码器,都强制走一遍“标准流 + 业务流 + 边界流”的验证流程,宁可多花半小时,也不想在线上看到花屏。希望帮到你。

本文还有配套的精品资源,点击获取

相关新闻

谱哈希实战:从谱方法到二进制编码的ANN召回方案

谱哈希实战:从谱方法到二进制编码的ANN召回方案

先说一个我实际碰到过的场景&#xff1a;一批短文本向量&#xff0c;维度不算高&#xff0c;128维左右&#xff0c;但要支持五百万条数据的近邻召回。暴力算距离不可能&#xff0c;单条查询全表扫描要算上亿次浮点乘加&#xff0c;就算优化到极致也扛不住高并发&#xff1b;倒排…

2026/10/20 12:15:09 阅读更多 →
Nano Banana API实测:低成本AI图像生成方案与批量调用优化指南

Nano Banana API实测:低成本AI图像生成方案与批量调用优化指南

最近AI图像生成这块动静不小&#xff0c;不少群里都在传一个叫Nano Banana API的服务。名字听着挺随意&#xff0c;但价格确实有点扎眼&#xff1a;官方同款品质&#xff0c;单张只要约0.10&#xff0c;不到官方价格的一半。我第一时间去试了试&#xff0c;也跟同行聊了一圈&am…

2026/10/20 12:14:08 阅读更多 →
SpringBoot+Vue3服装电商系统开发实战:从数据库到部署全解析

SpringBoot+Vue3服装电商系统开发实战:从数据库到部署全解析

做服装类电商系统一直是很多开发者练手的热门方向&#xff0c;一是业务链路完整&#xff0c;从前台展示到购物车、订单、支付模拟&#xff0c;一套流程下来基本覆盖了常见业务系统的核心场景&#xff1b;二是前后端分离模式在真实项目中用得最普遍&#xff0c;学完直接能对标公…

2026/10/20 12:14:08 阅读更多 →

最新新闻

Spring Boot社区在线问诊系统实战:从需求到部署的完整技术拆解

Spring Boot社区在线问诊系统实战:从需求到部署的完整技术拆解

最近后台经常有人问社区家庭医生在线问诊系统怎么做&#xff0c;正好我前阵子完整跟过一个类似项目&#xff0c;从需求梳理到部署上线走了不少弯路。我干脆把这套系统的技术拆解和踩坑记录整理成一篇长文&#xff0c;一方面给自己做个复盘&#xff0c;另一方面给正在做毕业设计…

2026/10/20 13:09:01 阅读更多 →
Git克隆Demo代码仓库实战:从地址到跑通全流程

Git克隆Demo代码仓库实战:从地址到跑通全流程

1. 拿到仓库地址后&#xff0c;先别急着敲命令很多同学第一次接触代码仓库时&#xff0c;最容易犯的毛病就是&#xff1a;复制了地址&#xff0c;打开终端&#xff0c;直接输入git clone&#xff0c;回车&#xff0c;然后开始疯狂刷新浏览器看着进度条发呆。如果仓库小&#xf…

2026/10/20 13:09:01 阅读更多 →
OpenHarmony设备上Flutter淡出过渡动画移植实战与性能优化

OpenHarmony设备上Flutter淡出过渡动画移植实战与性能优化

上个月我把一个原本跑在标准Flutter环境里的页面过渡动画方案移植到OpenHarmony设备上&#xff0c;遇到的第一个问题倒不是动画本身&#xff0c;而是animations 这个官方维护的三方动画库直接编译不过。项目里本来打算用它实现页面切换时的淡出过渡效果&#xff0c;想着省一笔自…

2026/10/20 13:09:01 阅读更多 →
轻量级技能管理方案:从零搭建可量化可组合的技能表

轻量级技能管理方案:从零搭建可量化可组合的技能表

1. 从“skills”这个词说起&#xff1a;它到底指什么“skills”这个词看起来简单&#xff0c;但放在不同语境里&#xff0c;指向完全不同。做招聘的人看到它&#xff0c;想到的是岗位能力模型&#xff1b;做在线教育的人看到它&#xff0c;想到的是课程标签体系&#xff1b;做开…

2026/10/20 13:09:01 阅读更多 →
企业级RAG问答系统实战:知识库、检索链路与大模型应用的完整落地指南

企业级RAG问答系统实战:知识库、检索链路与大模型应用的完整落地指南

做了将近半年的基于大模型的智能问答系统&#xff0c;上线之后我最大的感受是&#xff1a;**决定这套系统好不好用的&#xff0c;往往不是大模型本身&#xff0c;而是知识库和检索链路。**模型答得再聪明&#xff0c;检索不到对的资料&#xff0c;它也只能一本正经地编。我们做…

2026/10/20 13:09:01 阅读更多 →
GraphRAG工程实践:知识图谱如何补足向量检索的推理短板

GraphRAG工程实践:知识图谱如何补足向量检索的推理短板

向量检索失效的那一刻&#xff0c;我才决定认真搞GraphRAG年初做过一个企业内部制度问答系统&#xff0c;刚开始用的是经典的向量库RAG方案&#xff1a;文档切块、embedding、top-k召回、拼prompt喂给大模型。原型阶段跑得很顺&#xff0c;演示的时候领导问了一个问题——"…

2026/10/20 13:08:00 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →