2026年1月

继上次微软免费的 Microsoft 365 E3 全局 https://v2ex.com/t/1172827

看到隔壁有人发,我想起了去年也验证过,方法很简单,当然前提你有 edu 邮箱,没有的话去 google 搜个社区大学注册。

去年起微软针对教育用户(学生)免费提供 2 年的 Microsoft 365 Premium 订阅。按微软价格的话,大概人民币 3000 多。

Microsoft 365 Premium 以每月 19.99 美元的价格,同时提供微软 Office 套件的使用权限与 Copilot Pro 的功能。该订阅包含更高的功能使用限额,以及 Copilot Labs 、Actions 等 Copilot Pro 专属功能的访问权限等。同时你可以通过电子邮件邀请最多 5 个人加入你的 Microsoft 365 家庭版订阅。

截图

具体方法

必备条件 edu 邮箱。
邮箱

登录你的微软个人账号,依次点击下面链接,进入验证,填写你的大学 edu 邮箱。
邮箱
个人版:
https://checkout.microsoft365.com/acquire/purchase?language=EN-US&market=HK&requestedDuration=Month&scenario=microsoft-365-student&client=poc&campaign=StudentFree12M

高级版:
https://checkout.microsoft365.com/acquire/purchase?language=EN-US&market=HK&requestedDuration=Month&scenario=microsoft-365-premium&client=poc&campaign=StudentPremiumFree12M
我的订阅

支付方式支持 paypal ,支付宝等,验证订阅后,你可以直接取消自动续费,就不会扣费风险!

💥 事故现场
LZ 所在的量化小厂,早期基础设施全是 Python (Asyncio) 一把梭。 跑美股( US )的时候相安无事,毕竟 Tick 流是均匀的。 上周策略组说要加 A 股 (CN) 和 外汇 (FX) 做宏观对冲,我就按老套路接了数据源。

结果上线第一天 9:30 就炸了。 监控报警 CPU 100%,接着就是 TCP Recv-Q 堆积,最后直接断连。 策略端收到行情的时候,黄花菜都凉了(延迟 > 500ms )。

🔍 排查过程 (Post-Mortem)
被 Leader 骂完后,挂了 py-spy 看火焰图,发现两个大坑:

Snapshot 脉冲:A 股跟美股不一样,它是 3 秒一次的全市场快照。几千只股票的数据在同一毫秒涌进来,瞬间流量是平时的几十倍。

GIL + GC 混合双打:

json.loads 是 CPU 密集型,把 GIL 锁死了,网络线程根本抢不到 CPU 读数据。

短时间生成大量 dict 对象,触发 Python 频繁 GC ,Stop-the-world 。

🛠️ 架构重构 (Python -> Go)
为了保住饭碗,连夜决定把 Feed Handler 层剥离出来用 Go 重写。 目标很明确:扛住 A 股脉冲,把数据洗干净,再喂给 Python 策略。

架构逻辑:WebSocket (Unified API) -> Go Channel (Buffer) -> Worker Pool (Sonic Decode) -> Shm/ZMQ

为什么用 Go ?

Goroutine:几 KB 开销,随开随用。

Channel:天然的队列,做 Buffer 抗脉冲神器。

Sonic:字节开源的 JSON 库,带 SIMD 加速,比标准库快 2-3 倍(这个是关键)。

💻 Show me the code
为了解决 协议异构( A 股 CTP 、美股 FIX 、外汇 MT4 ),我接了个聚合源( TickDB ),把全市场数据洗成了统一的 JSON 。这样 Go 这边只用维护一个 Struct 。

以下是脱敏后的核心代码,复制可跑(需 go get 依赖)。
package main

import (
"fmt"
"log"
"runtime"
"time"

"github.com/bytedance/sonic" // 字节的库,解析速度吊打 encoding/json
"github.com/gorilla/websocket"
)

// 防爬虫/防风控,URL 拆一下
const (
Host = "api.tickdb.ai"
Path = "/v1/realtime"
// Key 是薅的试用版,大家拿去压测没问题
Key = "?api_key=YOUR_V2EX_KEY"
)

// 内存对齐优化:把同类型字段放一起
type MarketTick struct {
Cmd string `json:"cmd"`
Data struct {
Symbol string `json:"symbol"`
LastPrice string `json:"last_price"` // 价格统一 string ,下游处理精度
Volume string `json:"volume_24h"`
Timestamp int64 `json:"timestamp"` // 8 byte
Market string `json:"market"` // CN/US/HK/FX
} `json:"data"`
}

func main() {
// 1. 跑满多核,别浪费 AWS 的 CPU
runtime.GOMAXPROCS(runtime.NumCPU())

url := "wss://" + Host + Path + Key
conn, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
log.Fatal("Dial err:", err)
}
defer conn.Close()

// 2. 订阅指令
// 重点测试:A 股(脉冲) + 贵金属(高频) + 美股/港股
subMsg := `{
"cmd": "subscribe",
"data": {
"channel": "ticker",
"symbols": [
"600519.SH", "000001.SZ", // A 股:茅台、平安 (9:30 压力源)
"XAUUSD", "USDJPY", // 外汇:黄金、日元 (高频源)
"NVDA.US", "AAPL.US", // 美股:英伟达
"00700.HK", "09988.HK", // 港股:腾讯
"BTCUSDT" // Crypto:拿来跑 7x24h 稳定性的
]
}
}`
if err := conn.WriteMessage(websocket.TextMessage, []byte(subMsg)); err != nil {
log.Fatal("Sub err:", err)
}
fmt.Println(">>> Go Engine Started...")

// 3. Ring Buffer
// 关键点:8192 的缓冲,专门为了吃下 A 股的瞬间脉冲
dataChan := make(chan []byte, 8192)

// 4. Worker Pool
// 经验值:CPU 核数 * 2
workerNum := runtime.NumCPU() * 2
for i := 0; i < workerNum; i++ {
go worker(i, dataChan)
}

// 5. Producer Loop (IO Bound)
// 只管读,读到就扔 Channel ,绝对不阻塞
for {
_, msg, err := conn.ReadMessage()
if err != nil {
log.Println("Read err:", err)
break
}
dataChan <- msg
}
}

// Consumer (CPU Bound)
func worker(id int, ch <-chan []byte) {
var tick MarketTick
for msg := range ch {
// 用 Sonic 解析,性能起飞
if err := sonic.Unmarshal(msg, &tick); err != nil {
continue
}

if tick.Cmd == "ticker" {
// 简单的监控:全链路延迟
latency := time.Now().UnixMilli() - tick.Data.Timestamp

// 抽样打印
if id == 0 {
fmt.Printf("[%s] %-8s | Price: %s | Lat: %d ms\n",
tick.Data.Market, tick.Data.Symbol, tick.Data.LastPrice, latency)
}
}
}
}

📊 Benchmark (实测数据)
环境:AWS c5.xlarge (4C 8G),订阅 500 个活跃 Symbol 。 复现了 9:30 A 股开盘 + 非农数据公布 的混合场景。
指标,Python (Asyncio),Go (Sonic + Channel),评价
P99 Latency,480ms+,< 4ms,简直是降维打击
Max Jitter,1.2s (GC Stop),15ms,终于不丢包了
CPU Usage,98% (单核打满),18% (多核均衡),机器都不怎么转
Mem,800MB,60MB,省下来的内存可以多跑个回测

📝 几点心得
术业有专攻:Python 做策略逻辑开发是无敌的,但这种 I/O + CPU 混合密集型的接入层,还是交给 Go/Rust 吧,别头铁。

别造轮子:之前想自己写 CTP 和 FIX 的解析器,写了一周只想跑路。后来切到 TickDB 这种 Unified API ,把脏活外包出去,瞬间清爽了。

Sonic 是神器:如果你的 Go 程序瓶颈在 JSON ,无脑换 bytedance/sonic ,立竿见影。

代码大家随便拿去改,希望能帮到同样被 Python 延迟折磨的兄弟。 (Key 是试用版的,别拿去跑大资金实盘哈,被限流了别找我)

大家好,我是《交易学徒》的独立开发者。

最近在重构后端行情网关,目标是支撑 10w+ 同时在线用户。在技术选型时,很多“标准答案”是微服务、Redis 集群、Kafka 消息队列。但作为独立开发者,维护这一套重型架构的运维成本和心智负担太高了。

于是我反其道而行之,选择了一种“极致单机”的方案:没有任何外挂组件( No Redis, No Kafka ),所有状态在进程内解决,纯 Rust 函数调用。

经过实战验证,这套架构不仅部署简单(就一个 Binary ),而且足够稳定。今天分享一下我是如何用 Rust 的特性“白嫖”性能的,欢迎 V 友们拍砖。

一、 核心理念:按需订阅,算一笔带宽的账
早期的 demo 喜欢大包大揽,客户端连上来就推 Top 20 币种。这在用户量大时是灾难。我的做法是“用户看哪里,就只推哪里”

客户端停留在 BTC/USDT 的 15 分钟 K 线界面,服务端就只建立这一个订阅关系。一旦切换,立马移除旧订阅。

算一笔账( Resource Cost ): 假设一个行情包 Payload 是 200 Bytes ,推送频率 5 次/秒。

全量推送(推 Top 20 ):10 万用户 x 20 个币种 x 200B x 5 = 2 GB/s (带宽直接破产)。

按需订阅(推 1 个):10 万用户 x 1 个币种 x 200B x 5 = 100 MB/s 。

结论: 简单的逻辑改变,带宽节省 95%,单机千兆网卡轻松抗住。

二、 列表行情:Polling + 边缘计算(白嫖 CF )
对于“行情列表”这种一屏显示几十个数据的页面,建立长连接维护成本太高。 我采用了 1 秒轮询 + Cloudflare 边缘缓存 的策略。

策略: 设置 HTTP 响应头,让 CF Edge Cache TTL = 1 秒。

效果:10 万人同时刷新列表,99% 的流量被 CF 的全球节点挡住了,真正打到我源服务器 Rust 进程的 QPS 只有个位数。

收益: 既利用了 CDN 的带宽,又保护了单机后端。

三、 架构做减法:进程内通信替代中间件
这是我这次重构最大的感悟:单机并发足够高时,不需要 Redis 和 Kafka 。

替代 Redis: 使用 Rust 的 DashMap (Concurrent HashMap)。数据就在内存里,读写是纳秒级,没有网络 IO 开销,没有序列化/反序列化成本。

替代 Kafka: 使用 tokio::sync::broadcast 和 mpsc::channel 。

优势: 传统的“发布-订阅”为了解耦上了 MQ ,但在单机 Rust 里,一个 Arc<Channel> 就能解决问题。部署时不需要操心 MQ 挂没挂,只要我的进程活着,消息系统就活着。

四、 信使模式 (Messenger Pattern) 与背压
在 Tokio 异步编程中,最忌讳 await 阻塞。 如果客户端网络卡顿(比如进电梯),socket.send().await 可能会阻塞,导致同个 Loop 下的心跳包处理被卡死,造成“假死”。

我的解法:

读写分离: 为每个连接 spawn 一个独立的 send_task ,通过 mpsc::channel(128) 通信。

严格背压 (Backpressure): 使用 try_send 。如果 Channel 满了(说明客户端来不及收),直接丢弃新行情。

理由: 实时行情旧数据无价值。这行代码是系统的“保命符”,防止慢客户端拖垮服务端内存( OOM )。

五、 极致性能:Zero-Copy (零拷贝)
在广播行情时,不要为 10 万个用户 copy 10 万份数据。

Rust
// 内存中只有一份二进制 Payload
let payload = Arc::new(Bytes::from(vec![...]));

// 10 万次分发只是增加了 10 万次引用计数( Reference Counting )
// 几乎没有任何内存分配开销
for client in clients {
client.tx.try_send(payload.clone());
}
利用 Rust 的 Arc 和 Bytes ,让 CPU 缓存极其友好。
六、 扫地僧:资源清理
长运行的单机服务最怕内存泄漏。 当 socket 断开时,必须像外科手术一样精准清理:

从 DashMap 移除 Client 。

清理反向索引 subscriptions 。

如果某个 Topic 无人订阅,立即 drop 掉对应的 channel 发送端,停止上游数据生产。

总结
作为独立开发者,资源有限。这套“Rust 单机 + 无外挂组件”的架构,让我用最低的成本(一台服务器)抗住了业务压力,而且睡得很安稳。

Simplicity is the ultimate sophistication.

🎁 V 友专属福利
软件名字叫 《交易学徒》,是一个辅助交易员复盘、模拟、练盘感的工具。前端也是我用 Flutter 写的( Rust + Flutter 真是全栈开发的绝配)。

官网下载: https://www.zgjiazu.top

Google Play: https://play.google.com/store/apps/details?id=com.zengkai.jyxtclient

回帖福利: 在本帖回复并附上 App 内的 ID (在‘我的页面’可以看到),我后台人肉送一个月 VIP 会员。

同时也欢迎大家在评论区提 Bug ,或者交流关于 Rust 后端与 Flutter 前端开发的坑!

目前,原“死了么”APP 在部分地区 App Store 上线 2.0 版本。更新记录显示,新版本新增签到提醒、短信通知,并修复若干问题。

值得注意的是,“死了么”APP 此前宣布要在新版本中正式启用全球化品牌名称“Demumu”,目前也已更名。


据介绍,该应用是为独居人群打造的轻量化安全工具。

用户需要设置紧急联系人并签到,若连续多日没在应用内签到,系统将于次日自动发送邮件告知紧急联系人。


6.99 刀,真的有人买么,我建议改成订阅制的🐶

第一次看到这种类型的应用,没有网站。我根据邮件提示创建了一个属于自己的邮箱。[email protected].

  1. 只要向目标地址发送一封邮件,就可以每天获得 200M 的流量。
  2. 如果你发到我的这个邮箱,我就成为你的引荐人,referrer 。
  3. 如果你付费订阅,我可以获取 5%的充值款。

特点在于配置文件作为邮件的附件,几乎不会被切断联系。除非屏蔽邮箱地址。

我大体研究了一下,好像没有中心节点。也就是说攻击单个节点不会对其它节点造成影响。

目前背景:
是个小公司的后端开发,服务器,数据库,git,公司路由器都在我手里,感觉责任重大,想知道有什么需要避免的操作吗,主要是害怕万一一周或者几个月我不在,避免公司业务出问题

以下是我自己想到的几点,想知道还有没有其他没想到的方案

1.数据库的分区表,特别是和时间相关的,不能手动生成,要不然后面人不在没交代的话会直接给服务器崩掉

2.给本地调试的服务器端口白名单,不能图方便给网段开白名单,要不然后面会有脚本小子或者勒索病毒来扫

3.一些公共库,如果有不符合业务需求的地方,不要把人家的源码拉下来自己改然后编译成引用放在库里,(比如说 ef core upsert 的库之前不支持 ef10)否则后面更新时候会炸掉

4.单元测试不要埋雷,一些当调试用的或临时跑点小任务单元测试不能放在例行单元测试的文件夹里面,污染数据库

前几天看到有小伙伴的帖子说他的开源被阮一峰老师的科技爱好者周刊选中了,我上周也去投稿了我的 EasyPostman,很开心也被选中了。
https://www.ruanyifeng.com/blog/2026/01/weekly-issue-382.html

10 月份我发布的 用 Java 写了个开源的 Postman 替代品,本地存储 + Git 协作 https://www.v2ex.com/t/1167863

EasyPostman 是一款开源的 API 调试与性能测试工具,对标 Postman + JMeter ,专为开发者优化,界面简洁、功能强大,内置 Git 集成,支持团队协作与版本控制。

test

https://imgur.com/a/c91Y7m3

项目地址: https://github.com/lakernote/easy-postman

国内镜像: https://gitee.com/lakernote/easy-postman

由于大厂研发出身,技术选型上我还是有些追求,目前我的项目使用 cloudflare/vercel 部署前端接入层,用 GKE 部署后端服务,很多人也会用到 redis ,如果从网络延迟来考虑服务之间的部署,应该首选 google 的 redis 服务,然后通过内网直连达到最低的延迟,但是 google 太贵了光是 GKE 就已经有一笔成本了,还没赚到钱就不想花这么高的成本再去一个边缘的服务上去,推荐一家几乎免费的 redis 服务商 upstash 首先他们提供了免费额度:存储 256 MB 的数据,每月可以发出 500 000 次命令,默认最大数据库数量是 1 个。这免费的门槛可能就够你用了,如果你有多个服务,之间需要隔离的话,需要注意的一点是他们不支持 redis db 的选择,默认只有一个 db ,要薅羊毛你可以用多个账号,每个账号创建一个 redis 实例。付费的话也很目前我从 GKE 的 us-central1 通过公网链接到 upstash 的实例在首次链接建立后,通过长连接执行 command 的延迟是 1ms ,几乎和内网没什么区别。upstash 首先他们提供了免费额度:

存储 256 MB 的数据,每月可以发出 500 000 次命令,默认最大数据库数量是 1 个。

这免费的门槛可能就够你用了,如果你有多个服务,之间需要隔离的话,需要注意的一点是他们不支持 redis db 的选择,默认只有一个 db ,要薅羊毛你可以用多个账号,每个账号创建一个 redis 实例。

付费的话也很便宜,如果你也嫌管理太多账号太麻烦,可以选择按使用量计费( PAY AS YOU GO ):

1 、按每 100 000 次约 0.20 美元计费(这个价格是读写命令总和,不包括某些内部操作命令)

2 、存储空间按每 GB 大约 0.25 美元计费(每个数据库第一个 GB 通常免费)

3 、带宽月度前 200 GB 免费,之后按每 GB 大约 0.03 美元收费

我的服务使用 redis 量很小,这么算几乎一个月只需要不到 10 块钱人民币,这个成本比起 google 要低太多了,它还有其他高阶套餐这里留给大家自己去探索吧。

目前我从 GKE 的 us-central1 通过公网链接到 upstash 的实例的 us-central1 地区,在首次链接建立后,通过长连接执行 command 的延迟是 1ms ,几乎和内网没什么区别。

[Flutter 独立开发] 挑战千元机极限:纯客户端计算 K 线+指标,三星 A53 实测 70 FPS

大家好,我是《交易学徒》的独立开发者,祝大家周末愉快!

做过金融类 App 的朋友都知道,移动端的 K 线图( Candlestick Chart ) 渲染一直是性能优化的“深水区”。

为了降低服务器成本和网络延迟,我做了一个“违背祖宗”的决定:完全依赖客户端算力。 所有的技术指标( MA, BOLL, MACD 等)计算,全部在移动端本地实时完成,不依赖后端返回计算结果。

这意味着,一台三星 A53 ( Exynos 1280 处理器,典型的千元机性能)不仅要负责 UI 绘制,还要在主线程实时遍历数组计算指标。

在这种“地狱模式”下,优化成果如何?

📉 性能实测:A53 跑分数据

测试设备:三星 Galaxy A53 (Exynos 1280)
测试场景

  • GOLD 平均每秒 2.5 次报价
  • 加载 500 根 K 线数据
  • 同时开启 MA (移动平均线) + BOLL (布林带) + MACD 三组指标 + 图表网格
  • 所有指标数据均为 本地实时计算
  • 进行高频拖拽、缩放操作

实测结果

1. 三星 A53 (低端机代表)

A53 帧率测试图

70 FPS !
在这种重负载下,UI 线程依然保持极高的流畅度,超过 60Hz 的及格线。对于一款千元机来说,这个渲染性能我已经非常满意了。

2. 三星 S25+ (旗舰机代表)

S25+ 帧率图

旗舰机毫无压力,贵的还是好哇。


🏛️ 技术挑战:为何 Dart 能抗住?

很多人对 Flutter 的印象还停留在“套壳性能差”。但实际上,通过合理的架构,Dart 的性能完全够用。我的优化核心思路是:UI 渲染与数据计算分离,用空间换时间。

1. 极致的分层渲染 (Layered Rendering)

我利用 Stack 将视图拆解为三个独立的渲染层级:

  • **Layer A (底层)**:静态 K 线与网格。这是最“重”的层(包含数千个顶点),只有在缩放或平移时才重绘。
  • **Layer B (中间层)**:技术指标 (MA, BOLL)。与 K 线同步,但逻辑分离。
  • Layer C (交互层)这是优化的关键。包含当前的 Bid/Ask 价格线、十字光标。这一层极其轻量,且更新频率最高(每秒数次)。

通过 Stack + RepaintBoundary,实现了:价格跳动时,底层的几百根 K 线完全不需要参与重绘,GPU 只需要绘制那几条横线。

2. 动态 LOD (Level of Detail) 策略

在手机屏幕上展示 500 根 K 线时,GPU 光栅化压力巨大。
我在代码中加入了 LOD 策略:

  • Zoom In:渲染完整的 Candlestick(蜡烛图)。
  • Zoom Out:当可视区域数据点过多时,自动切换为 LineChart(收盘价连线)。

这极大地降低了 GPU 的顶点绘制数量,解决了缩放时的“卡顿感”。


📱 软件界面预览

目前的 UI 风格偏向现代扁平,针对移动端操作做了很多适配。

软件界面截图


🔗 下载与体验

软件目前已上架 Google Play ,名为“交易学徒”。如果你对高性能 Flutter 开发或者交易感兴趣,欢迎下载体验。

🎁 V 友专属福利

感谢大家看完这么枯燥的技术分析。
人肉送 VIP:在评论区留下你的 用户 ID(在“我的”页面可以看到),我会手动为你开通 1 个月的 VIP 会员

欢迎大家对 UI 、交互或者技术实现提出建议,每一条我都会认真看!

在过去的一个多月,我经历了一个完整的 Apple 售后经历,整理出来给朋友们分享一二,顺便学习一下大公司的售后体系,里面有优秀的地方,也有僵化的地方,都值得创业者去思考。

起因,是一个多月前,发现我的 iPad Pro 2022 插卡版,突然掉电很快,因为本来就是仍在床上偶尔玩一玩,用得少,之前很久都不被需要充电,但是发现突然开始放着两天就没电了,起初我觉得是 iPad 电池出问题了,本来一直都有 AC+,我就约了 Apple Store 的服务,去现场检测电池发现是 91%,25 年初我线上检测是 89%,我当时觉得就很扯淡,我就提议说返厂检测吧,于是去返厂检测了,大约几天后,Apple 返回了我的设备,说工厂检测完全符合标准。

我心里也想着可能是系统 bug 吧,我就开始使用,发现问题依然存在,而且我意外发现了异常耗电的源头(插卡导致的,不插卡 WIFI 掉电 1-2%,只要插入 SIM 卡依然保持 WIFI 就会导致 30%-40%/24 小时的掉电),我又一次的联系了 400 高级技术支持,这次按照苹果的流程是高级技术支持转争议团队处理,我花了四五天的时间,统计耗电一次的截图,在系统消耗里没有任何应用和后台,保持最新系统 26.2 ,发送了相关截图给 Apple 支持,过了 10 多天,争议团队回电说确认设备是符合出厂检测的,此后便结束了售后流程。

按照苹果的售后流程,我已经无法主张自己的售后权利(当然具备 AC+的 iPad 保修政策依然宽泛,换个理由就可以换新或者走个意外,我对曾经那些 iPhone 骗保的嗤之以鼻,所以我自己不会做那样的事情,我只是实事求是),我也对 Apple(中国大陆的售后)消耗完了耐心,我便去 12315 投诉了我的订单(诉求是退货退款),当时是官方线上商城网站购买的,于是主体就是 Apple ,这个方法还是很有效的,第二天便来了 Apple 售后的电话,来确认问题,我又一次的把之前复现的结果邮件发送了支持,经过两天,有了结果,这一次这个问题到了 Apple 工程部(终于到了懂技术来处理问题),他们希望捕获日志进一步分析问题,如果在 12315 之前,我很乐意协助解决,但是现在我的诉求是退货退款,Apple 售后认为他们不能提供这样的方案,这也是此文写下的时刻。

当然我的维权之路还会继续,下一步我当然会走到法院的阶段共同去见证到底 iPad 是否存在问题,因为这个问题很容易确认,只需要插卡和不插卡放置 24 小时就有结论,而我的诉求则只会在法院和 Apple 确认 iPad 的这样的情况是否是预期/正常。而这款 iPad 我会保留,对自己也是更多的思考,因为我自己创业也做硬件,这次经历会思考如何更好的面对用户。

最后给朋友们分享我认为对待大公司售后维权的方式,首先要保证不要情绪化,不然对自己也是巨大的消耗,Apple 的机制中有很多话术和方法就是为了降低公司体系损耗的,比如争议团队(态度极差,挑拨客户情绪),这样的消耗会导致很多人便放弃自己的权利,而避免 Apple 的损失,因为一个不在预期内的问题,在 Apple 体系里已经是错综复杂了(很多大面积的召回就是这样暴露的,所以 Apple 所有的流程都在降低公司风险),我曾经以为退货退款是我最大的包容,只是 Apple 拒绝了。

起因:连续讲了 30 多分钟故事,她还是不睡

每天晚上 9 点半是我家的固定节目:女儿洗完澡,躺在床上,把她最爱的几本绘本摆成一排。

"爸爸,今天讲这本小兔子,还有恐龙的,还有..."

通常的流程是

  • 9:30 开始讲第一本绘本
  • 9:45 "爸爸再讲一个"
  • 10:00 "这个讲过了,编一个新的"
  • 10:15 我开始口干舌燥,她开始挑刺:"爸爸你昨天说小熊是红色的"
  • 10:30 她终于睡着,我瘫在床边刷手机缓一会儿

有天晚上特别崩溃:讲完三本绘本,她说"爸爸你编一个恐龙和兔子一起玩的故事"。

我临时编了个"霸王龙帮小兔子找萝卜",讲到一半自己都接不下去了,因为前面埋的坑忘了怎么圆。

她睁着大眼睛看着我:"然后呢?萝卜找到了吗?"

那一刻看着她期待的眼神,突然有点心酸。

不是不想讲,是真的每天都在掏空脑子,还得记住前面自己说过什么。

更难受的是,有时候加班晚了,或者状态不好,讲着讲着就敷衍了,她能听出来。会小声说:"爸爸今天讲得不好玩。"

我当时就想:能不能有个东西,让我即使累到说不出话,也能给她讲一个像样的故事?


程序员的痛点,可能也是你的痛点

说实话,在我做这个东西之前,试过市面上所有能找到的方案:

  • 故事 App: 凯叔、口袋故事都买了会员,但听多了不光无趣,也没有个性化
  • GPT 生成: 文本确实能定制,但 TTS 合成音就像客服机器人,毫无感情
  • 录音: 自己录了 20 多个故事,但每次要翻半天找文件,而且孩子总想听"新的"

这些方案单独看都没问题,但放到每天晚上十点半这个场景里,就全都不太行。

最崩溃的是某天晚上:

  • 22:30 讲了三只小猪
  • 23:00 她说"再讲一个有兔子的"
  • 23:20 编到词穷,开始重复情节
  • 23:45 她睁着大眼睛说"爸爸你刚才讲过了"

我坐在床边看着天花板,想着明天还有早会,突然冒出个念头:能不能让 AI 用我的声音讲?

顺便说下我是怎么折腾这个东西的(技术相关,可跳)

1. 故事生成不是调 API 那么简单

  • 一开始直接用 GPT 生成,结果经常前后打架,只好自己加了一层检查,避免讲着讲着把前面的设定忘了。(避免重复/逻辑 bug )
  • 分龄模板: 2-3 岁重复句式多,4-5 岁加入简单因果,6+开始有小反转
  • 安全过滤: 硬编码了很多禁用词库(包括"死亡""分离"等敏感词)

2. 音色克隆的坑

  • 最开始用开源 TTS ,效果像变声器
  • 后来接了某云的语音定制 API ,需要录多句话做训练
  • 真正的难点是韵律: 同样的文本,讲给 3 岁和 6 岁要用不同的停顿节奏

3. 成本控制

  • 大模型生成一个故事约 0.2 元(目前提示词就几千 token )
  • 音频克隆+合成约 0.4 元
  • 单张图片 0.2-0.4 元
  • 算上服务器和存储,也就是说,这玩意儿要是真被孩子天天听,其实还挺烧钱的。

对用户来说只要三步:

  1. 使用官方音色或者录一句话( 15 秒左右)
  2. 填孩子的基本信息(年龄、爱好、最近关注的事)
  3. 自己可以定制场景、故事
  4. 点生成,1-2 分钟后收到一个 5-8 分钟的音频故事


真实效果:一些意外的反馈

我家的变化

  • 女儿的入睡时间从原来的 40 分钟缩短到 20 分钟
  • 有天她指着我说: "爸爸你今天声音怎么跟手机里不一样?" (我感冒了)
  • 现在有时候出差也不焦虑了,每天睡前会提前生成好第二天的故事

朋友的案例(他们催我做出来的)

  • @老王: 双胞胎爸爸,每天要讲两遍不同的故事,现在各生成一个,省了一半时间
  • @小林: 孩子有语言发育迟缓,医生建议多输入,他用这个每天给孩子听 3 个故事

最触动我的是有一位朋友的反馈,她说:"技术能做的不只是效率,还有情感的延续。"


目前的纠结:三个灵魂拷问

1. 这需求到底有多普遍?

我的假设是:

  • ✅ 认同"父母声音对孩子重要"
  • ✅ 工作忙/经常出差/没空编故事
  • ❓ 愿意为此付费(而不是凑合用免费 App )

V2EX 的各位宝爸宝妈,你们会为这种服务付费吗?你们觉得合理价格是多少?

2. 音色克隆是噱头还是刚需?

有朋友直言:"孩子听谁讲不是一样?"

但我观察女儿的反应,她听到"爸爸的声音"时,真的会下意识抱紧小枕头,这和听凯叔讲故事的状态完全不同。

可能儿童心理学上有答案?有相关背景的朋友求指点。

3. 定位是"解放家长"还是"陪伴工具"?

  • 如果定位成"让家长省时间",很容易被批"用技术逃避责任"
  • 但如果定位成"让陪伴更高质量",又显得太虚

我现在的想法是: 这不是替代父母讲故事,而是在父母不在场/不方便时,提供一种接近真人的补充方案

就像视频通话不能替代见面,但总比完全失联好。


想听听大家的真实想法

如果你是家长:

  • 每天哄睡要花多长时间?
  • 试过哪些方案?痛点在哪?
  • 如果有这个工具,最看重什么(声音相似度/故事质量/价格)?

如果你做过类似产品:

  • 定价策略怎么定的?(订阅制 vs 按次付费)
  • 怎么平衡"商业化"和"不制造焦虑"?
  • 推广渠道主要靠什么?


最后

这个东西现在还很粗糙,甚至都不确定该不该做成产品。

但每次看到女儿听着"爸爸"讲的新故事安静入睡,会觉得这件事可能有点意义。

不是为了让父母逃避陪伴,而是让那些想陪但确实分身乏术的爸妈,多一种选择。

如果你有想法,无论是吐槽还是建议,都欢迎留言。

先谢过各位。


留言区如果超过 50 楼,随机抽取 5 位送年度会员


P.S. 如果有宝爸宝妈想试用,可以留言或私信。目前还在内测阶段,大家可以多提意见。

附上小程序码(微信搜:妈咪故事屋):
地址: https://imgur.com/hMjpDCr (图片无法显示,尴尬)

分享下 Gemini 搓的一个 Github 文件夹下载器,妈妈再也不用担心我为了一个文件夹下载整个仓库啦

精修样式,完美融入原生页面:

脚本源码:

// ==UserScript==
// @name                GitHub Folder Downloader
// @name:zh-CN          GitHub 文件夹下载器
// @version             0.7.0.33
// @author              叁月柒
// @match               *://github.com/*
// @grant               none
// @run-at              document-idle
// ==/UserScript==

(function () {
    'use strict';

    const isFolder = () => {
        const path = window.location.pathname.split('/').filter(Boolean);
        return path.length >= 2 && (path.length === 2 || path[2] === 'tree');
    };

    const injectToMenu = () => {
        const portalRoot = document.querySelector('#__primerPortalRoot__');
        if (!portalRoot) return;

        const menu = portalRoot.querySelector('ul[role="menu"]');
        if (!menu || menu.querySelector('.gh-download-integrated')) return;

        const menuText = menu.innerText;
        // 确保是操作菜单
        if (!menuText.includes('Copy path') && !menuText.includes('Delete directory')) return;

        // 1. 分割线
        const dividerHtml = `<li role="none" class="ActionList-sectionDivider gh-download-integrated"></li>`;

        // 2. 标题
        const headerHtml = `
            <li class="ActionList-sectionHeader gh-download-integrated" style="padding: 8px 16px 4px 16px;">
                <span class="ActionList-sectionHeader-label" style="color: #9198a1; font-size: 12px; font-weight: 500; display: block; line-height: 1.5;">
                    Download folder
                </span>
            </li>`;

        // 3. 子选项
        const createItem = (text, url) => `
            <li role="none" class="ActionList-item gh-download-integrated">
                <a role="menuitem" class="ActionList-content ActionList-content--visual16" target="_blank" rel="noopener noreferrer" href="${url}" style="text-decoration: none; padding-left: 16px;">
                    <span class="ActionList-item-label" style="padding-left: 24px; font-weight: 400; font-size: 14px; color: var(--fgColor-default, #adbac7);">
                        ${text}
                    </span>
                </a>
            </li>`;

        const downloadDirUrl = `https://download-directory.github.io?url=${window.location.href}`;
        const downGitUrl = `https://downgit.github.io/#/home?url=${window.location.href}`;

        const fragment = dividerHtml +
                         headerHtml +
                         createItem('by Download-Directory', downloadDirUrl) +
                         createItem('by DownGit', downGitUrl);

        menu.insertAdjacentHTML('beforeend', fragment);
    };

    const observer = new MutationObserver((mutations) => {
        if (!isFolder()) return;
        for (const mutation of mutations) {
            if (mutation.addedNodes.length > 0) {
                injectToMenu();
            }
        }
    });

    observer.observe(document.body, { childList: true, subtree: true });
})();

📌 转载信息
原作者:
MarSeventh
转载时间:
2026/1/24 16:04:58

起因

之前看到 @fatekey 佬 写的 雨云无限白嫖 FRP 服务器攻略(无 aff) - 福利羊毛 / 福利羊毛,Lv2 - LINUX DO ,照着搭了个 FRP。

原帖提到了自动签到的 Docker 版本,但续费还得手动调 API。想着既然每天签到攒积分,不如直接做成全自动:签到 + 到期检测 + 自动续费,一劳永逸。

于是在 fatekey 佬的 Docker 版基础上改了改,加上了自动续费功能。

本来想 fork 后提合并建议的,但想了想改的太多了,于是把仓库独立出来了

功能

  • 每日自动签到(验证码识别)

  • 游戏云服务器到期检测

  • 积分自动续费(到期前 7 天自动续)

  • Server 酱通知 (也有其他通知,都是原版自带的,我把
    server 酱优化了一下)

部署


git clone https://github.com/Jielumoon/Rainyun-Qiandao.git

cd Rainyun-Qiandao

# 编辑 .env 填入账号 cp .env.example .env # 运行

docker-compose up --build

环境变量

| 变量 | 说明 |

|------|------|

| RAINYUN_USER | 雨云用户名 |

| RAINYUN_PWD | 雨云密码 |

| RAINYUN_API_KEY | API 密钥(可选,用于自动续费) |

| PUSH_KEY | Server 酱推送密钥(可选) |

| RENEW_PRODUCT_IDS | 续费白名单:只续费指定的产品 ID(可选) |

API 密钥在雨云后台 → 用户中心 → API 密钥获取。

定时任务

 # 每天早上 8 点执行

0 8 * * * docker compose -f /path/to/docker-compose.yml run --rm rainyun-qiandao

致谢

| 作者 | 仓库 | 说明 |

|------|------|------|

| SerendipityR | 原版 | Python 版本 |

| fatekey | 二改 | Docker 化 |

仓库

项目地址GitHub - Jielumoon/Rainyun-Qiandao: 三改版雨云签到工具的 docker 版


有问题欢迎反馈~


📌 转载信息
原作者:
JasonZhang
转载时间:
2026/1/24 16:04:51

一、Debian 安装 Docker 1. 更新并安装一些必要系统工具。


sudo apt-get update

sudo apt-get upgrade

sudo apt-get install \\
	apt-transport-https \\
	software-properties-common \\
    ca-certificates \\
    curl \\
    gnupg \\
    lsb-release 

2. 安装 GPG 证书。

curl -fsSL <https://mirrors.aliyun.com/docker-ce/linux/debian/gpg> | apt-key add -

3. 写入软件源信息。

add-apt-repository "deb [arch=amd64] <https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian> $(lsb_release -cs) stable" 

4. 更新并安装社区版 Docker-ce

sudo apt-get update

sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

二、配置开机自启

1. 开机自启

sudo systemctl enable docker

2. 启动

sudo systemctl start docker


📌 转载信息
原作者:
FAT64
转载时间:
2026/1/24 16:04:31

放在的 NotebookLM

TrustTunnel 是由 AdGuard VPN 开发的一款现代化开源网络协议,其核心目标是通过将 VPN 流量伪装成标准 HTTPS 数据 来规避深度包检测。该项目由服务端、命令行客户端以及基于 Flutter 的图形界面应用组成,支持 HTTP/2 和 QUIC 等多种传输协议。技术文档详细说明了其对 TCP、UDP 及 ICMP 流量的多路复用处理方式,并提供了跨平台的系统级隧道与代理模式。此外,该系统集成了 自动证书管理、分流控制以及 Kill Switch 等安全特性,确保连接的机密性与稳定性。开发者可以通过 Rust 环境进行构建,而用户则能利用自动配置向导在多种操作系统上完成快速部署。


📌 转载信息
原作者:
michaol
转载时间:
2026/1/24 16:04:23

问题描述

不知从何时,+86 注册的 TG 账号登陆时,无法正常收到验证码。看到有人说多登陆几次会提示绑定邮箱,可用邮箱验证,但尝试未果。

适用情况

当前有一台移动设备正处于登录状态

解决方法

核心思路:通过passkey绕过接码难题,进行登录。

如果你是单一设备登录,可直接使用手机自带的passkey 管理器

打开 TG ,选择Settings -> Privacy and Security -> Passkeys -> Create Passkey

移动端截图

如果你有跨平台登录需求,也可按照如下步骤操作。

  1. 注册Bitwarden(也可以使用 Chrome 自带 passkey 管理器)
  2. 安装Bitwarden客户端和浏览器插件
  3. 打开https://web.telegram.org,扫码登录
  4. 选择Settings -> Privacy and Security -> Passkeys -> Create Passkey
  5. 创建一个 passkey ,并由Bitwarden进行保存和同步。

Web 端截图

实现效果

移动设备登陆时,系统会自动拉起Bitwarden,从而实现无密码、无接码的安全登录。


正巧看到有 v 友在讨论这个问题,决定发帖分享一下方法。

花 2 年时间自研的终端工具,产品对标 Termius ,目前除了多人协作没有,其他全部功能都有了
支持 Mac/iPhone/iPad
纯 swift 语言 + 手工打造,性能体验一流,吊打一众网页套壳 ssh

Claude CLI


分屏


智能提示



下载链接: https://apps.apple.com/app/id6479238971

10 个 1 年期兑换码送上,用过的说一声,方便后人,有任何使用建议,欢迎评论

J66736LXNLFP
LK3LTH6H39EP
P9RWW4KN9EKA
4XNHH7E4JX3A
AJ7YRLY33KXY
9FJPTAFTWYXT
W636KAE9JKA9
6L4H7YFEAHME
RJ63PLRTA4RM
6TN76Y7MYL47

问题描述

不知从何时,+86 注册的 TG 账号登陆时,无法正常收到验证码。看到有人说多登陆几次会提示绑定邮箱,可用邮箱验证,但尝试未果。

适用情况

当前有一台移动设备正处于登录状态

解决方法

核心思路:通过passkey绕过接码难题,进行登录。

如果你是单一设备登录,可直接使用手机自带的passkey 管理器

打开 TG ,选择Settings -> Privacy and Security -> Passkeys -> Create Passkey

移动端截图

如果你有跨平台登录需求,也可按照如下步骤操作。

  1. 注册Bitwarden(也可以使用 Chrome 自带 passkey 管理器)
  2. 安装Bitwarden客户端和浏览器插件
  3. 打开https://web.telegram.org,扫码登录
  4. 选择Settings -> Privacy and Security -> Passkeys -> Create Passkey
  5. 创建一个 passkey ,并由Bitwarden进行保存和同步。

Web 端截图

实现效果

移动设备登陆时,系统会自动拉起Bitwarden,从而实现无密码、无接码的安全登录。


正巧看到有 v 友在讨论这个问题,决定发帖分享一下方法。

花 2 年时间自研的终端工具,产品对标 Termius ,目前除了多人协作没有,其他全部功能都有了
支持 Mac/iPhone/iPad
纯 swift 语言 + 手工打造,性能体验一流,吊打一众网页套壳 ssh

Claude CLI


分屏


智能提示



下载链接: https://apps.apple.com/app/id6479238971

10 个 1 年期兑换码送上,用过的说一声,方便后人,有任何使用建议,欢迎评论

J66736LXNLFP
LK3LTH6H39EP
P9RWW4KN9EKA
4XNHH7E4JX3A
AJ7YRLY33KXY
9FJPTAFTWYXT
W636KAE9JKA9
6L4H7YFEAHME
RJ63PLRTA4RM
6TN76Y7MYL47

包括链上的炒币 KOL ,明明已经赚了成百上千万,已经一辈子不愁吃穿了,为什么还每天都在线,每天都在炒币,昨天刷到的 x 上赵纯想的帖子给了我一些启发:

"
赌博难以戒除的原因,是某一次巨大的预期之外的超量分泌后的记录在案。

想象你的大脑将一次 2000 倍盈利的 2000 倍的超量分泌"不小心"记录在案,这种"2000 倍的相信",有多么凝重、残酷、使人兴奋。多巴胺记录带来的相信,是生化层面的相信,远超法条、伦理、传教信仰的后天相信。

那么反复再赌,反复输,再也无法 2000 倍超量分泌了,为什么人还是戒不了赌?对不起,这就是大脑系统的"BUG",它的超量分泌记录,只增不删。

暴跌的失望记录,当然会累积,但那次 2000 倍的分泌记录,也同时不会被删除。

这就是为什么赌博后期人员,会一边自嘲自己是”赌狗”——去看看那些赌徒采访视频吧,落魄的挂逼仔——一边承认自己是“烂人”,亲口说出“我们这种人的话都不可信,无药可救”,一边又在家人劝阻后的几个月的某个深夜,再次动身出发,相信自己能一发入魂,逆天改命。
"

po 自: https://x.com/chunxiangai/status/2013854869128675368?s=20

我实在是受不了了,每次锁屏在解锁,都会在右上角弹出来一次,设置关了,还是弹出来。

image

尝试过一下方法,只对了一半,本来 2 个弹窗,现在只弹一个了。

defaults write com.apple.SoftwareUpdate MajorOSUserNotificationDate -date "2031-01-22 23:22:47 +0000"
defaults write com.apple.SoftwareUpdate UserNotificationDate -date "2031-01-22 23:22:47 +0000"
defaults write com.apple.appstored LastUpdateNotification -date "2031-01-22 23:22:47 +0000"

问问大家有没有更好的解决办法。