VBFS视频块文件系统:突破通用文件系统存储瓶颈的设计与实践
1. 从一个真实需求说起为什么我们需要重新审视视频存储做视频相关项目的朋友大概率都经历过这样的场景监控系统跑了大半年硬盘里堆了几十万个视频文件每个文件几分钟到几小时不等想按时间段检索一段录像文件系统遍历目录就要几十秒或者做视频编辑协作一个项目拆成几百个片段文件素材服务器上小文件多到ls都卡再或者做流媒体点播用户拖动进度条时后端要从一个大MP4里做字节范围读取随机IO把磁盘拖得死去活来。这些问题的根子其实不在应用层而在存储层——我们一直用通用文件系统ext4、XFS、NTFS这些去装视频这种大块、连续、时序性强、元数据相对简单的数据。通用文件系统是为海量小文件、随机读写、复杂权限模型设计的拿它装视频就像用快递分拣中心去运煤炭能用但效率不对路。VBFSVideo Block File System视频块文件系统就是冲着这个错配来的。它把视频当作块而不是文件来管理用一套专门为视频数据特征优化的索引和存储结构把检索、随机访问、空间回收这几件事重新做了一遍。这篇博文我不打算写成产品说明书而是按一个实际做过视频存储系统的人的角度把VBFS的设计思路、核心机制、落地要点和踩过的坑掰开揉碎讲清楚。不管你是做安防、做媒资、做点播还是做边缘视频盒子只要你的系统里视频数据占了存储的大头这套思路都值得参考。2. 视频数据的本质特征与通用文件系统的错配2.1 视频数据到底特殊在哪先把视频数据的物理特征摆出来后面所有设计决策都是从这些特征推导的。第一单块体积大且边界清晰。一段1080P、25帧、H.264编码的视频码率按4Mbps算一小时就是大约1.8GB。视频天然是按段产生的——摄像头一次录像、一次导出、一次转码都是一个完整的逻辑单元。这个逻辑单元内部是连续的单元之间是独立的。第二写入基本是顺序追加。视频录制场景下数据是源源不断往后写的几乎不会回头改中间某个字节。这跟数据库那种频繁原地更新的负载完全不同。第三读取以时间段为单位。用户要的是昨天下午3点到3点15分的录像而不是第12345个字节到第67890个字节。检索维度是时间不是文件名或inode号。第四冷热分层极其明显。最近几天的视频被频繁回看一个月前的视频可能永远不会被访问但又不允许删除合规留存要求。这就要求存储层能低成本地管理海量冷数据。第五元数据简单但量大。每个视频块的元数据无非是时间范围、通道号、码率、编码格式、存储位置这几项结构固定。但块的数量可能是千万级甚至亿级元数据本身的检索效率就成了瓶颈。2.2 通用文件系统为什么水土不服拿ext4举例一个视频文件在磁盘上对应一个inodeinode里存着数据块的extent树。文件数量到百万级时目录项查找、inode分配、extent树的维护都会成为开销。更麻烦的是这几个点目录遍历成本高按时间检索录像通用做法是用文件名编码时间戳然后遍历目录匹配O(n)的目录扫描在千万文件级别完全不可接受。小文件放大问题如果为了检索方便把视频切成小片段比如每10秒一个文件文件数量爆炸每个文件至少占一个inode和一个块元数据占比飙升磁盘空间利用率反而下降。随机读性能差从大文件中间读取一段通用文件系统要经过页缓存、预读、extent查找路径长延迟不可控。空间回收碎片化视频有生命周期过期要删。通用文件系统删除大文件后留下的空洞在持续写入场景下会逐渐碎片化需要定期整理。VBFS的核心思路就是放弃文件这个抽象直接用块作为存储和检索的基本单位把时间索引做进存储层。下面拆开讲。3. VBFS的核心设计块、索引与存储布局3.1 视频块这个抽象怎么定义VBFS里最基本的单位叫视频块Video Block它不是文件系统意义上的block扇区而是一个逻辑概念一段连续时间、同一通道、同一编码参数的视频数据加上它的元数据构成一个视频块。一个视频块的典型结构是这样的组成部分内容说明块头魔数、版本、块ID固定长度用于快速识别和校验元数据区起始时间、结束时间、通道号、码率、编码、时长定长结构便于批量扫描索引区关键帧偏移表支持块内快速定位数据区实际视频码流连续存放不做二次切分块的大小是可以配置的常见取值是按时间切比如每5分钟一个块或按大小切比如每256MB一个块。按时间切的好处是检索直观按大小切的好处是空间管理均匀。实际项目里我一般建议按时间切因为视频检索的天然维度就是时间按大小切会导致块的时间边界不规则检索时还要额外算。提示块大小一旦定下来后期调整成本很高因为它影响索引结构和空间分配策略。建议在项目初期就根据码率和检索粒度需求算清楚。比如码率4Mbps、要求检索粒度到分钟那5分钟一块就是约150MB这个粒度比较舒服。3.2 时间索引VBFS的灵魂通用文件系统按路径检索VBFS按时间检索。所以它的核心索引结构是一棵以时间为键的索引树通常用B树或者时间分片的多级索引来实现。索引项的结构大致是(通道号, 起始时间, 结束时间, 块物理地址, 块长度)。这棵索引树常驻内存或者放在高速存储上检索时给定通道时间段直接定位到覆盖这个时间段的若干视频块拿到物理地址后顺序读取即可。这里有个关键设计点索引和数据分离。索引很小每条几十字节可以全部放进内存数据很大放在磁盘上顺序存放。检索时先查内存索引再按地址读磁盘避免了通用文件系统那种先查目录再查inode再查extent的多级跳转。我实测过一个对比千万级视频块、按时间段检索通用文件系统方案平均耗时在秒级VBFS方案在毫秒级。差距主要就来自索引结构的不同。3.3 存储布局顺序写、分区管理VBFS在磁盘上的布局通常是分段segment式的磁盘被划分成若干个固定大小的段视频块顺序写入段内写满一个段再写下一个。这种布局借鉴了日志结构文件系统的思想好处是写入永远是顺序的磁盘吞吐能跑满段内数据物理连续读取时预读效率高空间回收以段为单位避免碎片化。段的回收用引用计数后台整理每个段记录被多少索引项引用当段内所有视频块都过期后整段回收。如果段内还有有效块后台整理任务会把有效块搬到新段然后回收旧段。这个过程对上层透明。注意段的大小要权衡。段太小整理频繁写放大严重段太大回收粒度粗空间利用率低。经验值是段大小设为单块大小的10到50倍比较合适。4. 关键机制拆解写入、检索与回收怎么落地4.1 写入路径从码流到视频块写入是VBFS最考验工程实现的环节因为视频写入是持续的、高吞吐的任何一次卡顿都可能导致丢帧。完整的写入路径大致分四步接收与缓冲上层应用录像服务把码流按通道推给VBFSVBFS先在内存缓冲区里攒数据。缓冲区大小要能扛住一次磁盘抖动一般设几秒的码流量。块封装当缓冲区里的数据达到一个块的时长或大小阈值就封装成一个视频块生成块头和元数据同时提取关键帧偏移写入索引区。索引更新把新块的索引项插入时间索引树。这一步要在内存里完成保证低延迟。落盘把块数据顺序写入当前活跃段写完后更新段的元信息。索引的持久化可以异步做因为即使索引丢了也能通过扫描块头重建。这里有个容易踩的坑索引更新和落盘的顺序。如果先落盘再更新索引中间崩溃会导致数据在盘上但检索不到如果先更新索引再落盘崩溃会导致索引指向不存在的块。常见做法是先落盘、再更新内存索引、最后异步持久化索引崩溃后通过扫描块头重建索引保证最终一致。4.2 检索路径时间段查询怎么做到毫秒级检索的输入是(通道号, 起始时间, 结束时间)输出是覆盖这个时间段的视频块列表。流程是在时间索引树里做范围查询找到所有与目标时间段有交集的块对每个块根据索引里的物理地址和长度构造读取请求如果请求跨越多个块按时间顺序拼接如果只需要块内某一段比如用户拖动进度条到块中间利用块内的关键帧索引定位到最近的关键帧从那里开始解码。关键帧索引是块内随机访问的关键。视频编码里关键帧I帧是独立可解码的从关键帧开始解码才能正确还原画面。VBFS在封装块时就把关键帧的偏移记录下来检索时直接跳到目标时间之前最近的关键帧避免从头解码整个块。实操心得关键帧索引的粒度直接影响拖动响应速度。如果块内关键帧间隔是2秒那最坏情况下要解码2秒的数据才能到目标位置。对于点播场景建议关键帧间隔控制在1到2秒对于纯存储场景可以放宽到5秒以上省码率。4.3 空间回收过期视频怎么优雅地删视频有留存周期过期数据要回收。VBFS的回收机制分三层逻辑删除先把索引项标记为过期检索时不再返回。这一步很快只是改内存状态。段级回收当某个段内所有块都过期整段直接回收不需要搬数据。这是最高效的情况。段内整理如果段内还有有效块后台任务把有效块读到内存写入新的活跃段然后回收旧段。整理任务要限速避免影响正常写入。回收策略上我建议用惰性回收后台整理的组合逻辑删除立即生效物理回收交给后台低优先级任务慢慢做。这样既保证了检索的正确性又不会因为回收动作影响写入性能。5. 实操落地从零搭一个VBFS原型5.1 环境与依赖准备要验证VBFS的核心思路不需要一上来就写内核模块用用户态程序模拟完全够用。我建议的技术栈是语言C或Rust需要精细控制内存和IO存储一块裸盘或者一个大文件模拟块设备索引内存B树可以用现成库也可以自己写个简化版测试数据用ffmpeg生成不同码率的测试视频流。先明确几个核心参数我按一个中等规模安防场景来设定参数取值依据通道数16中小型场景单通道码率4Mbps1080P主流码率块时长5分钟检索粒度与块大小的平衡单块大小约150MB4Mbps × 300秒 ÷ 8段大小4GB约27个块回收粒度合适留存周期30天常见合规要求按这个配置算一下总容量16通道 × 4Mbps × 30天 × 86400秒 ÷ 8 ÷ 1024³ ≈ 19.3TB。这个量级用单机多盘或者小规模集群都能扛。5.2 核心数据结构定义先用伪代码把关键结构定下来这是整个系统的骨架// 视频块元数据定长便于批量扫描 struct BlockMeta { uint64_t block_id; uint32_t channel_id; uint64_t start_time_ms; // 块起始时间 uint64_t end_time_ms; // 块结束时间 uint32_t bitrate; uint32_t codec; uint64_t data_offset; // 数据在磁盘上的偏移 uint32_t data_length; uint32_t keyframe_count; }; // 索引项时间索引树的节点 struct IndexEntry { uint32_t channel_id; uint64_t start_time_ms; uint64_t end_time_ms; uint64_t data_offset; uint32_t data_length; }; // 段描述 struct Segment { uint64_t segment_id; uint64_t start_offset; uint64_t size; uint32_t ref_count; // 被多少有效块引用 bool is_active; };这几个结构定下来后写入、检索、回收三条路径就都有据可依了。5.3 写入流程的代码骨架写入的核心是把码流攒成块、写盘、更新索引。简化后的流程void write_stream(uint32_t channel, const uint8_t* data, size_t len) { // 1. 追加到通道缓冲区 channel_buffer[channel].append(data, len); // 2. 判断是否达到块阈值 if (channel_buffer[channel].duration() BLOCK_DURATION_MS) { // 3. 封装块 BlockMeta meta build_block_meta(channel, channel_buffer[channel]); // 4. 顺序写入活跃段 uint64_t offset active_segment.append(channel_buffer[channel].data(), channel_buffer[channel].size()); meta.data_offset offset; meta.data_length channel_buffer[channel].size(); // 5. 更新内存索引 index_tree.insert(meta); // 6. 更新段引用计数 active_segment.ref_count; // 7. 清空缓冲区 channel_buffer[channel].clear(); // 8. 段满则切换 if (active_segment.is_full()) { switch_active_segment(); } } }这段代码里最关键的是第4步的顺序写入和第5步的内存索引更新。顺序写入保证了吞吐内存索引保证了检索延迟。索引的持久化可以每隔几秒批量刷一次崩溃后靠扫描块头重建。5.4 检索流程的代码骨架检索就是查索引、拼结果std::vectorBlockMeta query(uint32_t channel, uint64_t start_ms, uint64_t end_ms) { // 1. 时间索引树范围查询 auto entries index_tree.range_query(channel, start_ms, end_ms); // 2. 按时间排序 std::sort(entries.begin(), entries.end(), [](const IndexEntry a, const IndexEntry b) { return a.start_time_ms b.start_time_ms; }); // 3. 构造读取请求 std::vectorBlockMeta result; for (auto e : entries) { result.push_back(load_block_meta(e)); } return result; }如果要做块内定位就在拿到BlockMeta后再读块内的关键帧索引找到目标时间之前最近的关键帧偏移从那里开始读数据。5.5 回收流程的代码骨架回收分逻辑删除和物理整理两步// 逻辑删除标记过期 void mark_expired(uint64_t current_time_ms) { auto expired index_tree.query_expired(current_time_ms - RETENTION_MS); for (auto e : expired) { index_tree.remove(e); segment_of(e).ref_count--; } } // 物理整理后台任务 void background_compact() { for (auto seg : segments) { if (seg.ref_count 0 !seg.is_active) { // 整段回收 free_segment(seg); } else if (seg.ref_count THRESHOLD !seg.is_active) { // 段内整理搬有效块 compact_segment(seg); } } }整理任务一定要限速我一般用令牌桶控制每秒搬运的数据量避免和正常写入抢IO。6. 常见问题与排查技巧实录6.1 写入丢帧怎么排查丢帧是视频存储最要命的问题。排查思路按这个顺序走看缓冲区水位如果缓冲区经常被打满说明磁盘写入跟不上要么是磁盘本身慢要么是写入路径有阻塞。看段切换开销段切换时要关闭旧段、打开新段、更新元信息如果这个动作太重切换瞬间会卡。优化方法是预分配下一个段切换时只改指针。看索引更新锁竞争多通道并发写入时如果索引树用了全局锁会成为瓶颈。改成按通道分片加锁或者用无锁结构。我踩过的一个坑是索引持久化用了同步fsync每写一个块就fsync一次直接把吞吐打下来了。后来改成批量异步刷丢帧问题消失。6.2 检索结果时间对不上怎么办检索出来的视频段时间和预期对不上通常是这几个原因时间戳基准不一致写入端用的是本地时间检索端用的是UTC差了几个时区。统一用UTC毫秒时间戳显示时再转本地。块边界处理错误查询时间段跨越块边界时如果只查了起始块没查结束块会漏数据。范围查询要用start query_end AND end query_start这种重叠判断而不是包含判断。关键帧定位偏差块内定位时如果找的是目标时间之后的关键帧会跳过一段画面。要往前找最近的关键帧。6.3 空间回收后容量没释放逻辑删除后磁盘空间没降这是正常的因为物理回收是后台异步的。但如果长时间不释放要检查后台整理任务是不是被限速限得太狠几乎没跑段引用计数是不是算错了导致段一直被认为有有效块是不是有索引项泄漏删了数据但索引没删导致段一直被引用。提示建议加一个监控指标统计已逻辑删除但未物理回收的数据量这个值持续增长就说明回收跟不上。6.4 常见问题速查表现象可能原因排查方向写入丢帧磁盘慢/锁竞争/同步刷盘看缓冲区水位、索引锁、fsync频率检索慢索引未命中/索引树退化看索引是否常驻内存、树是否平衡检索漏数据时间边界判断错误检查范围查询的重叠逻辑空间不释放后台整理未跑/引用计数错看整理任务速率、段引用计数块内定位慢关键帧间隔太大调整编码关键帧间隔崩溃后数据丢失索引未持久化实现块头扫描重建索引7. 一些设计取舍上的个人体会VBFS这套思路不是银弹它有明确的适用边界。我在实际项目里总结了几条取舍原则供参考。块大小宁大勿小。块太小会导致块数量爆炸索引内存占用上升段内碎片增多。块太大又会导致检索粒度粗、回收不灵活。我的经验是单块控制在100MB到500MB之间对应5到15分钟的录像这个区间在检索精度和存储效率之间比较平衡。索引一定要能重建。不管索引持久化做得多好都要假设它会丢。块头里存足够的元信息让系统能从裸盘扫描重建索引。这个能力在灾难恢复时价值巨大我见过不止一次因为索引损坏导致整个存储不可用的案例。回收策略要保守。物理回收是不可逆的一旦搬错数据就永久丢失。整理任务要做严格的校验搬运前后对比校验和确认无误再回收旧段。宁可回收慢一点也不要出错。监控比功能重要。视频存储系统跑起来后最怕的是静默故障——数据在丢但没人知道。要监控写入速率、丢帧数、索引命中率、回收进度、磁盘健康度这些指标任何一个异常都要能告警。别急着上分布式。单机VBFS能扛到几十TB级别很多场景根本不需要分布式。分布式带来的复杂度一致性、网络分区、数据迁移远超收益。先把单机做扎实真到容量瓶颈再考虑扩展。最后分享一个我在调试阶段常用的小技巧写一个离线校验工具定期扫描所有视频块校验块头完整性、索引一致性、数据校验和。这个工具在开发期能快速发现逻辑错误在运维期能提前发现磁盘坏道导致的数据损坏。投入不大但省下的排查时间非常可观。

相关新闻

基于Hadoop+Spark+Hive的美食推荐系统毕业设计实战解析

基于Hadoop+Spark+Hive的美食推荐系统毕业设计实战解析

做大数据方向的毕业设计,最怕的就是选题又大又空,最后交付一个没有实际业务闭环的Demo。而“基于HadoopSparkHive的美食推荐系统”这个题目,恰好把经典的大数据技术栈和贴近日常生活的场景结合在了一起。它不仅要你用分布式存储和计算&#x…

2026/10/17 5:04:17 阅读更多 →
OpenWAM世界-动作模型:开源预训练权重与微调实战指南

OpenWAM世界-动作模型:开源预训练权重与微调实战指南

1. 具身模型这条赛道,为什么突然被一个叫 OpenWAM 的东西搅动了第一次看到“OpenWAM”这个名字,是在一个做机器人学习的朋友群里。有人甩了张截图,说“世界-动作模型这块终于有人把预训练权重放出来了”,底下立刻炸出一堆人问“真…

2026/10/17 5:04:17 阅读更多 →
XSS-labs靶场实战:从原理到绕过,系统掌握XSS漏洞利用

XSS-labs靶场实战:从原理到绕过,系统掌握XSS漏洞利用

1. 靶场到底在练什么:先看懂XSS-labs的关卡地图XSS-labs(也有人叫XSS挑战靶场)是我接触过的Web安全练习环境里,最适合用来系统刷一遍XSS技能树的平台。界面确实朴素——一排带序号的关卡,每条输入框构造出不同的过滤场…

2026/10/17 5:04:17 阅读更多 →

最新新闻

XSS常用语句、绕过思路与场景化防御实战指南

XSS常用语句、绕过思路与场景化防御实战指南

说到XSS,不少人脑子里第一反应就是弹窗alert。我以前带新人时,总有人背了一堆payload,真到测试环境全被拦下来,就开始怀疑人生。这篇就是我从日常工作中沉淀出来的XSS常用语句和绕过思路,不讨论宏大的攻击链&#xff0…

2026/10/17 5:39:28 阅读更多 →
Aspose.Words 21.11 JDK17 实战:Word转PDF避坑指南

Aspose.Words 21.11 JDK17 实战:Word转PDF避坑指南

简介:本资源面向需要在Java项目中实现Word转PDF的开发者,提供aspose-words-21.11-jdk17.jar及配套调用示例,帮助快速完成文档格式转换功能的集成与验证。压缩包共2个文件,包含1个jar与1个java源码,整体约13.7MB&#x…

2026/10/17 5:39:28 阅读更多 →
自托管云开发结合AI编码代理:用Coder构建可重建的工作区环境

自托管云开发结合AI编码代理:用Coder构建可重建的工作区环境

1. 自托管云开发解决什么问题:环境漂移和AI代理的落户问题Coder 这个名字听起来像是一个通用编程工具的代称,但它的实际定位是:一个能把自托管云开发环境和 AI 编码代理组合在同一套工作区体系里的平台。简单说,你在浏览器里打开一…

2026/10/17 5:39:28 阅读更多 →
DYT到Derf转换全攻略:取消归一化与量化误差避坑指南

DYT到Derf转换全攻略:取消归一化与量化误差避坑指南

前一段时间我在处理一批传感器数据时,碰到一个特别典型的场景:上游为了压缩存储和计算方便,把原始数值归一化后写入DYT 格式;下游的图表平台却需要真实量纲的数据,也就是Derf 格式。二者之间隔的就是这一步"取消归…

2026/10/17 5:39:28 阅读更多 →
工作记忆如何同时记住多件事?大脑用的是高速轮转而非并行存储

工作记忆如何同时记住多件事?大脑用的是高速轮转而非并行存储

如果你有过一边听播客回消息、一边还要惦记着出门前拿钥匙和快递的经历,那你一定想过一个问题:脑子里明明同时装着好几件事,为什么有时候一样没落下,有时候连话到嘴边都忘干净?这个“临时存放几件事”的窗口&#xff0…

2026/10/17 5:39:28 阅读更多 →
SPIRAL方法解析:自博弈与多智能体强化学习如何提升推理能力

SPIRAL方法解析:自博弈与多智能体强化学习如何提升推理能力

最近看到一套叫 SPIRAL 的训练方法,全称是 Self-Play on Zero-Sum Games Incentivizes Reasoning via Multi-Agent Multi-Turn Reinforcement。直译过来很拗口:在零和博弈上做自我对弈,通过多智能体多轮强化学习去激励推理能力。但我盯着这个…

2026/10/17 5:38:28 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →