先说是什么:上传两张人脸照片,选一个场景模板,生成一段两人说唱的视频。 不是文生视频——照片是必须输入。 做的过程中撞了几件挺有共性的事,记一下,也算给后面的人省点时间。 一、Next.js 的 .env.local 优先级高于 .env.production 这个坑最阴。构建成功、部署成功、健康检查全绿,网站打开是坏的。 原因是 Next 的加载顺序: .env.local > .env.production > .env .env.local 是给本地开发用的(官方文档也写了测试环境应忽略它), 但生产构建照样读它,而且优先级最高,会盖掉 .env.production 。 我本机的 .env.local 里 NEXT_PUBLIC_API_BASE 指向 localhost:5001 , 结果构建产物里烧的就是 localhost——线上用户打开页面,浏览器去请求 他自己的 localhost 。 因为 NEXT_PUBLIC_ 是构建期内联进 JS 的,运行时改不了,所以要重新 build 。 后来在部署脚本里加了一道闸:构建前扫描产物,发现 localhost 直接让部署失败。 不然这个错每次都可能再犯,而且每一步看起来都是对的。 二、视频要 90 秒才返回,用户以为页面卡死 一开始 POST /tasks 是同步的:预处理(约 90 秒)+ 提交上游 + 返回。 实测那条请求 cost=93158ms 。按钮转圈一分半,什么都不显示。 改成"扣积分 → 建任务行 → 入队 → 立刻返回",真实生成在后台线程跑。 用户亚秒级拿到 task_no ,前端开始倒计时。 有两个细节值得说: 顺序很重要。校验和扣分必须在入队之前,不然失败时账本里会多出 spend/refund 两行噪音,用户看到余额没变但流水很脏。 后台线程随进程重启而消失,会留下"积分已扣 + 任务永远 pending"。 这个必须补偿——不是加个 atexit 就够( kill -9 时钩子不跑), 而是取任务时自愈:卡太久且没有上游 id 的,判失败并退款。 四、没有 migrate 工具,create_all 不改已有表 项目用的是 db.create_all(),它只建缺失的表,不管已有表的结构。 我加了几个字段,本地测试全绿,上线直接炸 Unknown column 。 而且 MySQL 遇到第一个不存在的列就报错,不会一次告诉你全部缺哪些—— 得补一个跑一次。 后来写了个脚本,拿代码模型和线上库逐表比对,把缺表/缺列/多余列列出来。 这类项目建议第一天就加这个,比手动 DESC 靠谱。 五、Stripe 的 Managed Payments 会强制要产品税码 这个账号默认开了 Managed Payments ,它要求价格来自后台预建的、 带 tax_code 的 Price 。但我的套餐价格存在自己数据库里,结账时用内联 price_data 传——直接被拒: Invalid line_items[0]: the product tax code is missing. Stripe 给了按会话覆盖的官方参数,加上就能用内联价格: managed_payments[enabled]=false 不用去后台建一堆产品。代价是价格只有一处(自己的库),改价不用同步两边。 局限也说一下,免得点进去发现不对: 场景是固定的 9 个模板,不能自定义 必须两张人脸照片,产物就是两个人在场景里说唱;没有空镜、产品片 每段视频成本不低,所以免费额度只够一条 5 秒 站在这: https://hotellobbyaiapp.com 有在做类似东西的,欢迎交流上面几个坑的其它解法。


  • 情报分类:技术学习与提效
  • 分类依据:内容涉及技术、AI、软件工具或工程实践
  • 信息来源:服务器 / V2EX
  • 发布时间:2026/10/14 09:39:52