ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
Join LingDaily to practice English through real-time AI conversations and daily news podcasts customized for learners.
EducationJavaScript · SwiftGitHub @JackYinpeiOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Talk News 是一款创新的语言学习应用,它将实时新闻阅读与互动式对话相结合,帮助用户在真实语境中学习和练习外语。
Translation pending
Loading the full README.
Read the full README ↗LingDaily 是一个以新闻和真实场景为素材的多语言口语学习应用。它使用 Next.js App Router、NextAuth、Supabase 与 Gemini Live,支持双向实时语音、学习记录、生词、进度和双语新闻播客。
record_language_correction 工具调用),在对话流内展示。flowchart LR
Browser[Next.js UI] --> Auth[NextAuth]
Browser --> APIs[App Router APIs]
Browser <-->|WebSocket + ephemeral token| GeminiLive[Gemini Live]
APIs --> Gemini[Gemini HTTP / TTS]
APIs --> Supabase[(Supabase Auth + Postgres/PostgREST)]
Cron[Server crontab] -->|POST /api/podcast/generate| APIs
APIs --> News[News feeds]
APIs --> COS[Tencent COS]
APIs --> Volume[Persistent podcast volume]
主要边界如下:
| 层 | 目录/入口 | 职责 |
|---|---|---|
| 页面 | app/ | 首页、对话、历史、进度、生词、场景管理和播客页面 |
| API | app/api/ | 鉴权后的令牌、翻译、历史、学习项、场景和播客接口 |
| Gemini Live | app/lib/GeminiLiveService.js | WebSocket 生命周期、麦克风输入和流式音频调度 |
| 业务模块 | app/lib/ | 语言模型、历史存储、场景提示和播客流水线 |
| 数据库 | supabase/migrations/ | RLS、索引、RPC、兼容升级与系统场景 seed |
| 部署 | Dockerfile、docker-compose.yml | 8000 端口应用与持久化播客目录 |
Gemini Live 的浏览器连接先向 POST /api/realtime-token 申请一次性令牌,再建立 WebSocket。旧的 /api/gemini-token 暂时保留为带弃用响应头的兼容别名。旧的 /api/learning/unfamiliar-english 同样继续代理到统一的学习项接口。
播客生成链路为:服务器 cron → 生成接口 → 新闻源 → Gemini 结构化脚本 → 多说话人 TTS → MP3 → COS → Supabase → 本地 manifest/RSS 镜像。Supabase 暂时不可用时,生成接口会退回已有的本地 manifest/feed 兼容路径。
要求:Node.js 20.19+、npm,以及一个可用的 Supabase 项目和 Gemini API Key。
cp .env.example .env.local
npm ci
npm run dev
开发服务器地址是 http://localhost:8000。
首次运行前,应按下一节将数据库迁移应用到目标 Supabase 项目。生产构建与启动:
npm run build
npm start
完整模板见 .env.example。本地开发使用 .env.local;服务器上的 docker-compose.yml 从 .env 读取运行时变量。
关键约定:
GEMINI_API_KEY 是服务端标准变量;GOOGLE_API_KEY 仅作为旧部署别名。GEMINI_BASE_URL 是可选的服务端 Gemini HTTP/TTS 代理;GOOGLE_GEMINI_BASE_URL 是旧别名。NEXT_PUBLIC_GEMINI_BASE_URL 是浏览器 Gemini Live/WebSocket 代理。若整套请求都需要代理,服务端和 NEXT_PUBLIC_ 两项应指向同一受控代理。NEXT_PUBLIC_SUPABASE_URL 与 NEXT_PUBLIC_SUPABASE_ANON_KEY 可以公开;SUPABASE_SERVICE_ROLE_KEY 必须只存在于服务端。PODCAST_SECRET、COS Secret 和 OAuth Secret 只能放在服务端环境,不得提交到仓库。NEXT_PUBLIC_GEMINI_API_KEY。任何 NEXT_PUBLIC_* 值都会进入浏览器包。NEXT_PUBLIC_* 在镜像构建时写入前端包,修改后必须重新构建镜像。GitHub 部署工作流已经把站点 URL、Supabase 公共配置和 Gemini 公共代理作为 build args;其余密钥由服务器 .env 在运行时注入。
生产库是早期手工建表的 Supabase 库,当前没有
supabase_migrations.schema_migrations。因此本次升级使用 SQL Editor 手工、
逐文件执行;在为远端建立 migration baseline 前,不要再混用
supabase db push,否则会无法判断哪些迁移已执行。
生产执行顺序:
No limit,执行
scripts/preflight-production.sql。只有所有
BLOCKER 都为零时才能继续;REVIEW 项需人工确认。BEGIN/COMMIT;不要去掉事务边界,也不要只执行其中一段。scripts/postflight-production.sql,确认
所有非 INFO 项均为 PASS,并将各表行数与 preflight 结果对比。九个迁移为:
202607110001_create_user_preferences.sql:语言偏好;兼容旧的 text user_id 和缺列,异常重复行会中止。202607110002_create_unfamiliar_english.sql:学习项事件表与 RLS。202607110003_upgrade_podcast_pipeline.sql:播客状态、生成租约、公开读取策略。202607110004_upgrade_chat_history.sql:历史修订号、并发保存 RPC、来源类型。202607110005_multilingual_learning_items.sql:学习项和偏好的多语言升级。202607110006_multilingual_scenarios.sql:兼容旧两表/新单表的多语言场景升级。202607110007_seed_scenarios.sql:幂等系统场景 seed;发现相同语言对的重复场景时中止,不自动删除或合并。202610050002_ai_usage.sql:iOS AI token 用量表 ai_usage(owner 只读 RLS、Live 上报幂等唯一键)与汇总 RPC ai_usage_summary;只新增对象。202610050001_native_practice_sync.sql:iOS 云同步复用现有表——chat_history 新增 practice 来源(含 key 约束与 RPC 校验),scenarios 新增可空 practice_plan;发现未知来源时中止。迁移不会自动删除重复偏好、重复场景或非数组对话正文;发现这些
异常时显式事务会使整个文件回滚并要求先人工处理。失败后不要单独执行该文件的
COMMIT。不要把这些 SQL 指向机器上
其他项目正在使用的 PostgreSQL。
仓库提供完全隔离的迁移测试:
./scripts/test-migrations.sh
脚本只会启动名称以 lingdaily-pgsql- 开头的临时 PostgreSQL 容器和数据库,不发布任何宿主端口,并在退出时删除自己的容器。它验证 fresh schema、旧 text 偏好表、最早的标量播客图片/非唯一索引、旧场景两表结构、真实生产 catalog fixture、RLS/ACL、两个 RPC、重跑幂等性,以及异常聊天/重复场景必须回滚且不丢数据。它不会连接、停止或复用宿主机已有的 PostgreSQL 进程。
GitHub 的播客定时工作流已禁用,正式任务继续由服务器 crontab 触发。现有请求契约保持不变:
POST http://localhost:8000/api/podcast/generate
x-podcast-secret: <PODCAST_SECRET>
无请求体,无必需 query 参数
等价的安全示例(不要把真实密钥提交到脚本或仓库):
curl -s -X POST 'http://localhost:8000/api/podcast/generate' \
-H "x-podcast-secret: $PODCAST_SECRET" \
--max-time 350
兼容行为:
PODCAST_TIMEZONE 的当天日期生成;默认 Asia/Shanghai。error 的字段,以兼容旧 cron 对响应文本的判断。error 字段,旧脚本会按原逻辑重试。date=YYYY-MM-DD 和 force=true 只是运维用可选参数,正式 cron 不需要添加。如果服务器脚本中曾直接写入过密钥,密钥暴露后应在服务器环境与应用环境中同时轮换,但接口 path/header 不需要改变。
生产 docker-compose.yml 只启动应用,不包含 PostgreSQL,因此不会占用或修改宿主机 5432。应用数据库是外部 Supabase;本地 SQL 验证使用上一节的隔离临时容器。
推荐发布顺序:
.env,确认 PODCAST_SECRET 和 COS 配置仍在。docker compose up -d。/podcasts/feed.xml,再用原 path/header 手动触发一次跳过或生成验证。./podcasts 会挂载到容器 /app/public/podcasts,用于保留旧 manifest、RSS 和本地音频镜像。不要在更新镜像时删除这个目录。
发布前的本地质量检查:
npm run check
Sitemap 只包含真实公开页面:首页、播客列表和已完成的播客详情。生成过程使用 Supabase anon key 和播客公开 RLS,不读取 chat_history,也不会把用户 ID、对话 key、后台或登录后页面写进公开 sitemap。
可选 Nginx 示例位于 nginx/gemini-proxy.conf。上线时应替换示例域名、启用 HTTPS、限制访问并设置合理的速率/连接数上限,避免把代理暴露成不受控的公共转发服务。
原生客户端位于 ios/,最低支持 iOS 15。已有免登录的 SwiftUI AI 体验版:真实 Gemini 对话、明日预演、一句话重来、本机记录与表达收藏。先运行 npm run ios:dev,再在 Xcode 运行 iPhone 模拟器;自己的真机改用 npm run ios:dev -- --device 并重新安装 Debug 版。已支持 Gemini Live 实时语音;正式认证与云同步仍待接入。
后续按“新闻/场景 → 语音练习 → 历史与学习项”完成首版,播客与进度后置。
设计语言、页面模板、架构、数据契约、实施计划与产品创意见 iOS 重构方案。