实时数据流处理入门:从Kafka到Flink的架构实践与核心机制解析

1. 为什么要把数据处理搬到“实时”这条轨道上

先说个我自己的经历。去年帮某电商平台做营销大屏的数据链路,最初方案完全是批处理:每五分钟调度一次脚本,把当天的订单、点击、支付流水汇总到报表库。结果上线第一天晚上,运营指着屏幕问我:“这里显示今日成交额250万,但后台订单实际已经到300万了,差得有点多吧?”我看了看任务日志,发现凌晨高峰时段那个批处理脚本因为上游接口抖动重跑了三趟,加上本身处理耗时,数据整整延迟了近二十分钟。

后来我把整条链路迁移到实时数据流处理,同样的大屏,数据延迟从“分钟级”压到“秒级”,而且再没出现过因为重跑导致的断档式跳变。这件事让我意识到一个问题:很多场景不是不需要实时,而是团队还没搞清“批处理”和“流处理”的边界,就急着选型了。

实时数据流处理,通俗讲就是数据在产生的同时就被处理、被消费,而不是攒一批再统一算。它解决的核心矛盾是“业务决策对时效性的要求”和“数据处理链路固有延迟”之间的冲突。适合它的场景一般有三个特征:数据持续产生、单条数据价值随时间快速衰减、对异常或趋势需要尽快感知。典型的像交易风控、库存预警、实时监控告警、直播间在线人数统计、IoT设备状态上报,都是这类。

这篇文章不是给你堆概念,而是从一个真实可跑的Demo出发,把实时数据流处理的架构拆开讲清楚:核心组件选什么、为什么这样选、跑通之后会遇到哪些坑、以及几个绕不开的底层机制(水位线、背压、时间语义)到底是什么。内容同样适合刚接触流计算、想在团队里引入实时链路的开发同学参考。

2. 实时管道的基础架构与核心组件选型

2.1 一条实时链路到底由哪几块拼起来

实时数据流处理,本质上是一条“数据管道”,从数据产生到最终被使用,中间经历四个环节:数据源、传输层、处理引擎、数据落地与消费。

用一个生活化的类比:数据源是水龙头,传输层是自来水主管道,处理引擎是净水厂,数据落地就是你家水龙头接出来的水。水龙头一直在开,净水厂不能等水攒满一缸再处理,必须边流边处理,这就是“流式”的核心含义。

我见过不少团队的第一版实时方案,是把批处理脚本的调度周期从“每小时”改成“每分钟”,以为这就是实时的。其实那只是“更频繁的批处理”,真正的流式处理强调的是“事件驱动”:每来一条数据,都触发一次处理逻辑,而不是等一批数据凑齐再统一跑。这背后的资源模型、容错方式、延迟表现完全不同。

2.2 选型对比:自研、开源框架还是云托管

处理引擎是整条链路的大脑,选型上通常绕不开这几个选项:

方案延迟表现运维成本适用规模我的建议
自研消息队列+消费者秒级~分钟级高小规模、逻辑极简单不推荐作为长期方案,适合验证概念
Kafka + Flink毫秒~秒级中高大流量、复杂计算生产环境的主流选择
Kafka + Spark Streaming秒级中中大规模、微批可接受已有Spark体系时可复用
云托管流计算服务毫秒~秒级低中小规模、不想管集群快速交付时优先考虑

我自己的习惯是:如果团队已经有Kafka,且计算逻辑涉及多流join、窗口聚合、状态管理,直接上Flink;如果只是把A系统的数据简单过滤后丢给B系统,完全没有复杂计算,用Kafka加一个轻量消费者就够了,没必要引入重计算引擎。选型永远为业务复杂度服务,而不是为技术栈的“高大上”服务。

这里必须强调传输层的角色。很多人觉得Kafka只是一个“消息队列”,其实在实时链路里,它真正解决的是“削峰填谷”和“多消费者解耦”。比如大促瞬时流量是平时的十倍,如果没有Kafka缓冲,下游计算引擎直接被打挂是必然结果。Kafka通过分区机制把吞吐量摊开,配合消费者的提交位移机制,保证每条数据至少被处理一次,这是整条链路可靠性的基石。

3. 从零搭建一个可运行的实时流处理Demo

说再多理论,不如亲手跑通一个最小系统。这个Demo的场景设定为:模拟某平台用户点击事件流,实时统计每秒钟各页面的点击量,并把超过阈值的结果输出到控制台和文件。

3.1 环境准备与数据模拟

先准备环境。这里我用Python模拟数据生产者,用Kafka做传输层,用Flink做计算引擎。如果你本机没有Flink,直接跑一个Flink standalone集群即可,不需要依赖任何真实公司的基础设施。

# 下载并启动Kafka(简化版,实际使用需配置broker和zookeeper) bin/kafka-server-start.sh config/server.properties # 创建主题,分区数设为3,副本因子设为1(单机环境) bin/kafka-topics.sh --create --topic click-events --partitions 3 --replication-factor 1

数据生产者模拟代码,每0.5秒发送一条点击事件,字段包含页面ID、用户ID、时间戳:

import json import time import random from kafka import KafkaProducer producer = KafkaProducer( bootstrap_servers='localhost:9092', value_serializer=lambda v: json.dumps(v).encode('utf-8') ) pages = ['home', 'detail', 'cart', 'search'] while True: event = { 'page': random.choice(pages), 'user_id': random.randint(10000, 99999), 'ts': int(time.time() * 1000) } producer.send('click-events', value=event) print(f'produced: {event}') time.sleep(0.5)

这段代码本身没有多复杂,但有一个细节值得注意:时间戳字段ts用的是事件产生时的客户端时间,而不是当前处理时间。为什么?因为后续我们要做窗口聚合,如果依赖处理时间,一旦数据在传输过程中发生积压,统计结果就会失真。这个点后面讲时间语义时还会展开。

3.2 Flink作业的核心计算逻辑

接来下是Flink侧的作业。假设我们统计每5秒内各页面的点击量,并且只保留点击量超过10次的页面:

package demo.realtime; import org.apache.flink.api.common.eventtime.WatermarkStrategy; import org.apache.flink.api.common.serialization.SimpleStringSchema; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.api.windowing.time.Time; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; import org.apache.flink.util.Collector; import java.time.Duration; import java.util.Properties; public class ClickMetricJob { public static void main(String[] args) throws Exception { StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(3); Properties kafkaProps = new Properties(); kafkaProps.setProperty("bootstrap.servers", "localhost:9092"); kafkaProps.setProperty("group.id", "click-metric-group"); DataStream<String> source = env.addSource( new FlinkKafkaConsumer<>("click-events", new SimpleStringSchema(), kafkaProps) ); source.map(line -> { // 简单解析JSON,生产环境建议使用POJO或AVRO String[] parts = line.replace("{", "").replace("}", "").split(","); String page = parts[0].split(":")[1].replace("\"", "").trim(); long ts = Long.parseLong(parts[2].split(":")[1].trim()); return new ClickEvent(page, ts, line); }) .assignTimestampsAndWatermarks( WatermarkStrategy.<ClickEvent>forBoundedOutOfOrderness(Duration.ofSeconds(3)) .withTimestampAssigner((event, timestamp) -> event.ts) ) .keyBy(event -> event.page) .timeWindow(Time.seconds(5)) .process((key, context, elements, out) -> { long count = 0; for (ClickEvent e : elements) { count++; } if (count > 10) { out.collect(new Tuple2<>(key, count)); } }) .print(); env.execute("click-metric-job"); } public static class ClickEvent { public String page; public long ts; public String raw; public ClickEvent() {} public ClickEvent(String page, long ts, String raw) { this.page = page; this.ts = ts; this.raw = raw; } } }

注意这行代码:assignTimestampsAndWatermarks。它做的事情是告诉Flink,事件的时间戳从哪个字段提取,以及允许数据最多迟到多久。这里设置的是3秒的乱序容忍度,意思是事件时间比当前水位线晚超过3秒的数据,会被判定为迟到,不再参与窗口计算。

3.3 跑通观察点:如何确认管道真的在实时运转

启动Flink作业后,在生产者已经有数据的前提下,你会看到类似这样的输出:

(click-metric-group) 2> (detail,12) (click-metric-group) 1> (home,15)

如果你仔细观察,会发现结果不是每5秒整齐地输出一批,而是窗口触发时间可能略有前后。这是因为窗口的触发依赖于水位线推进,而水位线取决于上游数据的时间戳分布。数据产生速度不均匀、网络抖动、Kafka消费积压,都会影响水位线到达下游的时间。

初学阶段判断管道是否健康,我习惯盯三个指标:Kafka消费者组的Lag(积压量)、Flink作业的延迟水位(currentWatermark)、以及输出结果的连续性。只要Lag保持平稳或下降、水位线持续推进、结果持续输出,这条管道就算“活着”了。

4. 水位线、背压和时间语义:实时计算绕不开的三个核心机制

4.1 时间语义:处理时间和事件时间为什么必须分清

这是整个流处理里最容易踩坑、也最影响正确性的地方。处理时间(Processing Time)指数据到达计算引擎时的机器时间;事件时间(Event Time)指数据真实发生时自带的时间戳。

如果只用处理时间做窗口聚合,遇到数据延迟到达就全乱了。举个例子:用户凌晨0点0分1秒点击了页面,因为网络抖动,这条数据3分钟后才被Flink处理。如果按处理时间开窗口,这条点击就被归到3分钟后那个窗口里,当天的统计口径直接出偏差。所以实时管道的正确姿势,是优先使用事件时间,配合水位线来管理乱序数据。

理解这个逻辑,你就能明白为什么我在生产者的模拟代码里专门加了ts字段,并且要求在Flink侧显式指定它作为事件时间戳。

4.2 水位线:数据迟到多少,窗口才敢关闭

水位线可以理解为“事件时间的进度条”。它的核心逻辑是:如果一个事件时间戳为T的数据已经到达,那么比T晚超过允许偏移量的数据大概率不会再来了,可以放心关闭T之前的窗口。

我用一个容易懂的类比来解释:去车站赶火车,检票口规定了“发车前5分钟停止检票”。水位线就是那个“发车时刻”,而允许乱序的3秒就是“停止检票前的缓冲时间”。水龙头一直在流水,窗口计算不可能永远等所有数据到齐再算,必须有一个“差不多等到了”的信号,这就是水位线存在的意义。

实际设置时,forBoundedOutOfOrderness(Duration.ofSeconds(3))里的3秒不是拍脑袋定的,它应该基于你对上游链路延迟的真实观测。如果Kafka到Flink的端到端延迟通常在1秒内,设置3秒的容忍度是合理的;如果经常出现5秒以上的乱序,就需要调大,否则统计结果会漏数据。当然容忍度调大也有代价——窗口触发变慢,结果输出延迟变高。这是一个需要根据业务容忍度取平衡的参数。

4.3 背压:当下游扛不住时,系统怎么保证不崩

背压(Backpressure)是流处理系统最重要的自我保护机制。当Flink的某个算子处理速度跟不上数据流入速度时,背压会把这种“处理不过来”的状态向上游传递,让上游放慢发送速度,而不是无限积压导致内存溢出。

如果你用Flink的Web UI观察过作业,会发现蓝色、黄色、红色的背压告警色块。曾经有个线上作业,某个join算子因为状态膨胀导致处理变慢,上游Kafka消费者的拉取速率自动降了下来,数据积压在Kafka里等待恢复。因为背压机制的存在,整条链路没崩,只是结果延迟变大了。等到状态清理后,积压数据很快追平。

这里有个常见误解:以为背压是“系统故障”,需要立刻排查。其实背压只是系统的减压信号,真正要做的是找出背压的源头算子,看它是CPU密集、状态过大、还是遇到了数据倾斜。不同原因的处理方式完全不同。

5. 生产环境踩坑记录与排查思路

跑通Demo只是开始,我把线上环境遇到过的几个高发问题整理出来,每个都附上完整的排查链路,而不是直接给结论。

5.1 重复消费导致统计翻倍

某次流量活动数据对不上,经排查发现统计结果是预期的两倍。顺着链路排查,先看Kafka消费者组的提交位移策略,发现作业配置了enable.auto.commit=true,并且提交间隔设置过长。作业在处理一批数据后、还没提交位移时发生重启,恢复时Kafka把同一批数据又发了一遍,Flink的窗口计算里就把重复数据也算进去了。

这类问题的根治方案是变更幂等化:要么关闭自动提交、改用处理完成后再手动提交;要么在计算逻辑里按事件ID去重。Flink的checkpoint机制本身就提供了“精确一次”的语义保证,前提是正确启用checkpoint并把Kafka消费者的位移也纳入状态管理。我当时的修复路径是:开启checkpoint,设置语义为EXACTLY_ONCE,同时关闭Kafka的自动提交,问题随即消失。

5.2 上游时间戳格式不规范

这个坑出在对接第三方数据源时。对方给的时间戳是字符串格式且不带时区信息,我直接按本地时区解析,结果夜里高峰时段跨天的数据全部被分到了前一天。排查链路是:先看窗口输出结果,发现每天的00:00~00:05窗口数据异常偏大,往前翻原始数据,才发现是解析时区错位。

修复并不复杂,统一在数据接入层把时间戳规范化为UTC毫秒值,并在Flink侧用带时区的解析器处理。但这个过程暴露了一个更通用的教训:接入层必须做数据治理,不能在计算层临时救火。时间戳、ID类型、枚举值,这些字段的规范化应该在数据进入Kafka之前就完成。

5.3 状态后端导致的内存问题

某个长窗口的聚合作业频繁Full GC,伴随背压持续告警。初步怀疑是内存配置不足,但调大堆内存后问题依旧。后来用Flink Web UI查看状态大小,发现单个算子的状态已经膨胀了几十GB,才意识到是状态后端的选择问题。

这个场景里我用的是RocksDB状态后端而非堆内存状态后端。对于长时间窗口、大key数量的作业,RocksDB把状态存储在磁盘,避免了堆内存持续增长导致的GC压力。但RocksDB也有代价——读写性能比纯内存状态后端慢一些,调优时需要关注block大小、write buffer数量等参数。具体调到了多少、效果如何,会直接体现在背压指标和响应时间上。这属于同一类问题的两种表象:状态膨胀和高频GC,根源都在状态管理策略,而不仅是一句“内存不够”的笼统提示。

6. 优化思路与后续扩展:从“能跑”到“跑得稳跑得快”

6.1 并行度与Kafka分区数的匹配

很多人的第一版Flink作业,并行度要么是默认值,要么随便设了个数。并行度设小了,数据倾斜时单算子处理不过来;设大了,资源浪费,还会导致小文件过多、checkpoint耗时变长。

一个实用的经验法则是:Flink作业中消费Kafka的source并行度,应该和Kafka主题的分区数保持匹配。Kafka每个分区同一时刻只能被同一个消费组里的一个消费者消费,如果source并行度大于分区数,多出来的并行度空转;如果小于分区数,一个消费者就要消费多个分区,吞吐受限。比如主题有3个分区,source并行度设为3或6都是合理选择。

6.2 窗口聚合的优化经验

窗口聚合是最容易出性能问题的点。曾经有个按用户维度统计的作业,状态里要保留每个用户的明细数据,窗口一开就是30分钟,导致状态无限膨胀。优化的思路是反推业务需求:如果下游只需要聚合后的计数,就不该保留明细。

改进方案是做两层聚合,第一层在keyBy用户后先做局部计数,第二层再按更大的维度汇总。这样细粒度状态只保留在局部,上游数据到达第一层后就能及时压缩状态,整体状态量下降显著。类似的思路也可以用在去重计数场景上。

6.3 数据落地到下游存储时的幂等设计

实时计算结果要被业务使用,落地方式直接影响可用性。如果你把Flink的sink直接写MySQL,作业重启后重复执行sink,就可能导致重复更新或计数翻倍。更稳妥的方式是,在sink里以事件ID或窗口ID作为唯一键,配合upsert语义,保证同一批数据无论写几次,最终结果一致。

ClickHouse这类分析型数据库在实时场景里也很常见,但要注意写入的batch大小和buffer刷新策略。设置不当容易因为小批次高频写入导致合并任务过载,进而引发查询性能恶化。这部分经验需要结合实际集群规格自行调整,不同量级下的最优参数差异很大。

回看整条链路的演进,从最初五分钟一跑的批处理脚本,到现在基于Kafka和Flink的实时管道,最本质的变化不是技术栈换了,而是看待数据的角度变了:数据不再是等着被处理的静态文件,而是持续流动、边产生边决策的“活水”。把握住“事件时间优先、水位线管理延迟、背压保护稳定、sink幂等保一致”这四条主线,你在实时数据流处理上就算真正入门了。

相关新闻

粮库AI控温干燥系统实战:从传感器布点到干燥曲线整定

粮库AI控温干燥系统实战:从传感器布点到干燥曲线整定

我是在粮库里泡了十几年的设备工程师&#xff0c;干过烘干塔、平房仓通风、浅圆仓充氮&#xff0c;也在不少粮机改造项目上踩过坑。前两年参与了一套“AI控温干燥”系统的设计与调试&#xff0c;就是把粮食的粮温、水分这些信号统一送进控制器&#xff0c;按预设的干燥曲线自动…

2026/10/20 21:05:05 阅读更多 →
REA模型原理与供应链事件溯源实践

REA模型原理与供应链事件溯源实践

我无法基于当前输入生成符合要求的博文。原因如下&#xff1a;项目标题为单个字母组合“rea”&#xff0c;无明确语义指向&#xff0c;不属于任何可识别的技术术语、产品名、工具名、方法论或常见缩写&#xff08;如REA在不同领域可能指代“Resource-Event-Agent”建模、Real E…

2026/10/20 21:05:05 阅读更多 →
多智能体协同与自主决策AI代理系统:从架构到实战

多智能体协同与自主决策AI代理系统:从架构到实战

做自主决策AI代理系统这件事&#xff0c;我前前后后折腾了将近一年。从最初只是给大模型套一层工具调用&#xff0c;到后来做成能自主规划、自我纠错、甚至多个代理之间互相协作的完整系统&#xff0c;踩过的坑比写过的代码还多。这个项目不是某个课程作业&#xff0c;也不是论…

2026/10/20 21:05:05 阅读更多 →

最新新闻

分账平台哪个好?商户功能对比参考

分账平台哪个好?商户功能对比参考

分账平台哪个好&#xff0c;是商户问得最多的问题&#xff0c;但答案没有统一标准&#xff0c;因为每个商户的需求不同。判断平台好不好&#xff0c;要先看它能否覆盖自己的核心场景&#xff1a;多方分成、比例调整、固定金额分配、批量结算&#xff0c;这些功能是否都支持&…

2026/10/20 21:46:22 阅读更多 →
rea模块设计实战:实时数据读取与处理的核心技术解析

rea模块设计实战:实时数据读取与处理的核心技术解析

1. 从“rea”这个标题说起&#xff1a;一个被低估的通用缩写第一次看到“rea”这个标题的时候&#xff0c;我脑子里蹦出来的第一反应是——这大概率又是一个被缩写玩坏的项目名。做技术的人都有个习惯&#xff0c;喜欢把长名字砍成三四个字母&#xff0c;图省事、图好记、图在命…

2026/10/20 21:46:22 阅读更多 →
Flutter animations库在OpenHarmony的共享轴过渡适配

Flutter animations库在OpenHarmony的共享轴过渡适配

设计师拿着交互稿找到我&#xff0c;第一句就是“这几个页面切换必须用Material Design 3的共享轴过渡”。我当时第一反应倒是挺轻松——Flutter生态里不是有现成的animations库吗&#xff1f;拿过来直接引用就行。结果真在 OpenHarmony 工程里跑了一遍&#xff0c;编译报错、运…

2026/10/20 21:46:22 阅读更多 →
OpenHarmony上Flutter animations库适配:共享轴过渡实现指南

OpenHarmony上Flutter animations库适配:共享轴过渡实现指南

最近有朋友问我在 OpenHarmony 上做 Flutter 移植时&#xff0c;animations 这个三方库该怎么处理。这个包在 pub.dev 上一直很火&#xff0c;官方维护&#xff0c;里面包含共享轴过渡、容器变形、淡入淡出切换这几套页面动效&#xff0c;尤其是 SharedAxisTransition&#xff…

2026/10/20 21:46:22 阅读更多 →
Ollama本地大模型部署实战:从入门到API服务调优

Ollama本地大模型部署实战:从入门到API服务调优

我先把结论放在前面&#xff1a;2026年想在本地跑一个大模型&#xff0c;Ollama基本是绕不开的那个工具。我第一次用它是在某台16GB内存的旧笔记本上&#xff0c;没有独立显卡&#xff0c;装完驱动之后从官网下了个安装包&#xff0c;两条命令下去&#xff0c;一个7B模型就能正…

2026/10/20 21:46:22 阅读更多 →
服务器时间同步详解:NTP与chrony核心原理及故障排查

服务器时间同步详解:NTP与chrony核心原理及故障排查

1. 时间不同步的真实代价&#xff1a;几个让人头疼的业务场景如果你还没把时间同步当回事&#xff0c;觉得"服务器时间差个几秒无伤大雅"&#xff0c;那我建议你先停下来想想这几个场景。我遇到过最典型的一次事故是这样的。某天晚上&#xff0c;某公司的订单系统突然…

2026/10/20 21:45:14 阅读更多 →

日新闻

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/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

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

如果你的信息流最近也天天刷到“机器人大脑”这个词&#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 阅读更多 →