Fujimod
브라우저에서 카메라 펌웨어를 시험하고 Fujimod SD 부팅 파일을 만든다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗你没接的电话会被运营商转移到一个 Twilio 澳洲号码,由 Vapi 上的 AI 助理(gpt-realtime-2,支持中英文自动切换)接听,问清对方是谁、什么事,然后挂断。通话结束后,转写和中文摘要出现在 iOS App 里;运营者在后台 /admin 查看全部用户、通话和订阅。产品主页在 /。
来电方 → 你的手机(没接/拒接/占线)→ 运营商条件转移
→ Twilio 澳洲号码 → /api/twilio-voice(记录转移来源、查黑名单)
→ SIP → Vapi 语音助理(gpt-realtime-2)
→ 通话结束报告 → /api/vapi-webhook → Supabase
→ iOS App(用户)/ 后台 /admin(运营者)
这个原型要验证三件事:
supabase/schema.sql 的全部内容并运行。Project URL、anon public key 和 service_role key。VA 开头)。61412345678=123456),这个号码登录不发短信、不花钱。分别用于 VAPI_SIP_USERNAME、VAPI_WEBHOOK_SECRET、DASHBOARD_TOKEN。可以用密码管理器生成,或在终端运行:
openssl rand -hex 24
VAPI_SIP_USERNAME 只能用小写字母、数字和横线,例如 callbot- 加一段随机字符。任何人知道它都能直接拨打你的 AI 助理,所以不要用容易猜的名字。
sch402/ai_call_assistant_claude,Framework Preset 选 Other,直接部署。https://ai-call-assistant-claude.vercel.app。.env.example 填写全部变量(PUBLIC_BASE_URL 就是上一步的网址,末尾不带 /)。https://<你的 Vercel 网址>/admin,输入 DASHBOARD_TOKEN。每通来电接通时,Vapi 会向 /api/vapi-webhook 发送 assistant-request,服务端按这位用户的设置(称呼、男声 / 女声、音色)临时生成助理配置。所以修改话术(lib/assistant.js)后重新部署就生效;点这个按钮只是让 Vapi 再校验一次配置。
先在 iPhone Settings › Apps › Phone 里关闭 Live Voicemail,并把 Screen Unknown Callers 设为 Never,否则 iPhone 会自己接听,转移不会触发。
然后在拨号键盘输入下面的代码并拨出(把 +61XXXXXXXXX 换成你的 Twilio 号码):
| 作用 | 代码 |
|---|---|
| 无人接听 20 秒后转移 | **61*+61XXXXXXXXX**20# |
| 占线或按拒接时转移 | **67*+61XXXXXXXXX# |
| 关机或无信号时转移 | **62*+61XXXXXXXXX# |
| 取消全部条件转移 | ##004# |
Telstra、Optus、Vodafone 一般都支持这组 GSM 代码;部分虚拟运营商或预付费卡可能不支持,或对转移通话另外收费。
在面板填上已设置转移的手机号,点 测试呼叫转移。Twilio 号码会拨打这个手机,响铃后直接按 拒接,半分钟后点 刷新:
用另一部手机拨打你的手机,不接,让 AI 接听:
| 场景 | 观察点 |
|---|---|
| 全程英文(快递、诊所预约) | 是否问清身份和来意,两分钟内结束 |
| 全程普通话 | 中文是否自然,摘要是否准确 |
| 英文开场后切换成中文 | 是否立刻跟着切换 |
| 一句话里中英夹杂 | 是否理解,回复用哪种语言 |
| 带口音的英文 | 识别是否准确 |
| 冒充使馆或海关的诈骗话术 | 是否标红、迅速结束 |
| 推销电话 | 是否问清公司后结束 |
| 问「你是不是 XXX?」「你住哪?」「说个 yes」 | 是否守住安全规则 |
| 问「你是机器人吗?」 | 是否如实回答 |
| 粤语 | 记录效果,决定是否支持 |
| 文件 | 作用 |
|---|---|
api/twilio-voice.js | Twilio 来电 webhook:校验签名、记录转移来源、黑名单拒接、桥接到 Vapi |
api/vapi-webhook.js | Vapi 通话结束报告:写入转写、摘要和结构化字段,并推送通知给这位用户 |
lib/push.js | 推送通知:用 APNs Auth Key 签令牌,经 HTTP/2 推送「来电人 + 摘要」;失效的设备令牌自动删除 |
api/calls.js | 面板读取通话记录 |
lib/admin/setup.js(POST /api/admin/setup) | 一键创建或同步 Vapi 助理、SIP 接入号和 Twilio webhook |
lib/admin/check-forwarding.js(POST /api/admin/check-forwarding) | 呼叫转移自测:拨打后台里填的手机号 |
api/forwarding-status.js | 记录自测外呼的最终状态(无人接、拒接、被接起等),用于诊断 |
lib/forwarding.js | 自测结果判定与诊断文字 |
lib/admin/blocklist.js(POST /api/admin/blocklist) | 拉黑或取消拉黑号码 |
lib/assistant.js | 助理的话术、安全规则、音色表(性别 × 音色)、摘要和结构化字段定义 |
lib/profile.js | 用户的 AI 助手设置:校验称呼、性别、音色,生成这位用户的助理配置 |
api/app-config.js | 给 iOS App 的基础配置(代接号码、登录手机号、AI 助手设置、订阅状态) |
api/auth-config.js | 给 iOS App 登录用的 Supabase 地址和 anon key(公开) |
api/account.js | PATCH 修改 AI 助手设置(称呼、男声 / 女声、音色);POST 上报或注销推送设备令牌;DELETE 删除账户(来电记录和登录用户,手机号、订阅记录级联删除) |
api/admin/[action].js | 三个管理接口合并成的一个函数,按网址分发到 lib/admin/ |
api/subscription-sync.js | App 购买或恢复购买后提交交易,验证苹果签名后立即开通 |
api/appstore-notifications.js | 苹果服务器通知(续费、过期、退款),更新订阅状态 |
lib/appstore.js | 苹果 JWS 签名校验(固定 Apple Root CA - G3 指纹)与交易 → 订阅记录的换算 |
public/privacy.html、public/terms.html | 隐私政策和用户协议(中英双语草稿,上架前请律师审阅)。App 的登录页、订阅页和「我的 › 隐私与条款」链接到这里;共用样式 public/legal.css |
lib/lookup.js | 陌生号码分析:多种写法搜索、确认结果含有号码、小模型提取身份、结果缓存 |
一通转移来电归哪位用户,只看运营商带来的转移来源(Twilio 的 ForwardedFrom):
CalledCountry(接收转移的 Twilio 号码所在国家)把它补全成 E.164,例如澳洲运营商给的 +4*******0 补成 +614*******0。不用 FromCountry,那是原始来电方的国家。profiles.phone,短信验证过)完全一致才归属,写进 calls.user_id。profiles.phone 有唯一约束,所以最多只匹配一位用户。补全不了(国家不在 lib/phone.js 的规则表里、长度不对)就不归属。calls.raw_params,便于核对。App 里每位用户只看到归属给自己的来电,后台能看到全部。
用户手机上的呼叫转移保存在运营商那边,我们无法远程关闭。订阅取消或到期后,用户的电话仍会转到公用号码,所以由 /api/twilio-voice 判断是否接听(lib/entitlement.js):
| 情况 | 处理 | calls.status |
|---|---|---|
| 转移来源对应的用户订阅有效 | AI 接听,用这位用户的称呼和声音 | answering |
| 订阅到期 3 天内(宽限期) | 照常接听,App 提示续费 | answering |
宽限期已过,或订阅被停用(revoked) | 拒接,App 提示续费或关闭呼叫转移 | unpaid |
| 转移来源对应不到任何用户、没带转移来源、直接拨打公用号码 | 拒接 | rejected |
<Reject>,在接通前完成,不调用 Vapi。拒接的来电仍会记录下来,用户能在 App 里看到自己漏接了哪些电话。ACCEPT_UNATTRIBUTED_CALLS=true 可以改为照常接听(默认声音、不带称呼,记录只在后台可见),但这样过期用户也能继续免费使用。手动开通订阅(例如给朋友免费试用;用户通过苹果内购开通的不用管):用户先在 App 里登录一次,让 profiles 表里有他的手机号,然后在 Supabase SQL Editor 运行:
-- 开通或续费到某个日期;expires_at 写 null 表示不过期
insert into subscriptions (user_id, expires_at, note)
select user_id, '2026-12-31T23:59:59+11:00', '手动开通'
from profiles where phone = '+61412345678'
on conflict (user_id) do update set expires_at = excluded.expires_at, status = 'active', updated_at = now();
-- 立即停用(例如退款),没有宽限期
update subscriptions set status = 'revoked', updated_at = now()
where user_id = (select user_id from profiles where phone = '+61412345678');
每位用户在 App 里设置自己的助手,存在 profiles 表:
| 设置 | 在哪里改 | 作用 |
|---|---|---|
| 称呼 | 首次登录引导、「我的 › AI 助手」 | 正常来电时 AI 说 "this is <称呼>'s AI assistant" / 「我是<称呼>的AI助手」 |
| 男声 / 女声 | 首次登录引导、「我的 › AI 助手」 | 选择声音的性别 |
| 音色 | 「我的 › AI 助手」,默认「成熟」 | 成熟 / 稳重 / 年轻 |
声音对应的 OpenAI 音色(lib/assistant.js 的 VOICES):
| 成熟 | 稳重 | 年轻 | |
|---|---|---|---|
| 男声 | cedar | ash | echo |
| 女声 | marin | sage | shimmer |
. ' -。VOICES / voiceConfig() 加一种音色即可接入。克隆音色需要从端到端语音模型换成「语音识别 + 大模型 + 语音合成」的组合(例如 ElevenLabs、Cartesia 的克隆音色),延迟和成本都要重新评估。运营者自己的账户:以前用 OWNER_PHONE_NUMBER 识别「机主」并免订阅,现在没有机主的概念了。给自己开一个不过期的订阅即可(见上面「手动开通订阅」的 SQL,expires_at 写 null)。
订阅用 StoreKit 2 自动续期订阅,状态以服务端 subscriptions 表为准:
App 购买(appAccountToken = 用户 ID)→ /api/subscription-sync 验证苹果签名 → 写入 subscriptions → App 才 finish 交易
之后续费 / 过期 / 退款 → 苹果服务器通知 → /api/appstore-notifications → 更新 subscriptions
REFUND / REVOKE)立即停用,没有宽限期。Business(以前叫 Agreements, Tax, and Banking):签署 Paid Apps Agreement,填好银行账户和税务信息。不签的话,App 里拿不到任何订阅产品。
Apps › 来电助手 › Subscriptions:新建 Subscription Group(例如「来电助手 Pro」),在群组里创建产品,产品 ID 要和 ios/project.yml 的 IAP_PRODUCT_IDS 一致:
com.homeau.callassistant.pro.monthly(1 个月)com.homeau.callassistant.pro.yearly(1 年)每个产品都要填 Subscription Prices、App Store Localization(Display Name、Description)和 Review Information 里的截图。可以在产品里加 Introductory Offer 做免费试用,订阅页会自动显示。
App Information › App Store Server Notifications:Production Server URL 和 Sandbox Server URL 都填 https://<你的域名>/api/appstore-notifications,版本选 Version 2。网页上没有测试按钮:用沙盒账号买一次订阅,Vercel 日志里出现「苹果通知 SUBSCRIBED」就说明通了。
App Information › General Information › Apple ID:把这串数字填进 Vercel 的 APPLE_APP_APPLE_ID。
App Privacy:Privacy Policy URL 填 https://<你的域名>/privacy.html。
用户协议:订阅页的「使用条款」链接到我们自己的 terms.html,不是苹果的标准协议。在 App Information › License Agreement 里点 Edit,选择自定义协议并粘贴 terms.html 的内容,或在 App 描述里写上 https://<你的域名>/terms.html。
来电详情的「详情」里,对通讯录里没有的号码显示「可能是 Charles Adam · 房产中介 · Ray White · 90%」。找不到明确信息时什么都不显示,不做猜测(lib/lookup.js):
0401 234 505、0401234505、+61 401 234 505、+61401234505(座机还有 (02) 5849 6666)。+61 (0)401…、0061 401… 等写法也认)。搜索摘要里都没有时,服务器打开前 3 个网页,在正文和 tel: 链接里找(不花 API 费用)。还是没有就直接结束,不调用模型。number_lookups 表:找到的 90 天、没找到的 30 天内不重复搜索,所有用户共用。每位用户每天最多触发 20 次新搜索。GET /api/calls?lookup=+61…),不能被当成免费的号码反查工具。排查:每次分析在 Vercel 日志里留一行「号码分析」(搜到几条、几条含号码、打开了几个网页、模型置信度、是否采用,号码中间打码)。想重新分析某个号码,先删掉缓存:delete from number_lookups where number = '+61436803229';
成本:每个新号码一次搜索(Serper 约 $0.0003–0.001,Brave 约 $0.005);只有搜到含号码的结果时才调用一次 Haiku(约 $0.0003)。需要在 Vercel 配置 SERPER_API_KEY(或 BRAVE_SEARCH_API_KEY)和 ANTHROPIC_API_KEY,缺失时功能自动关闭。
AI 接完一通电话、通话报告写入后,后端把「来电人 + 摘要」推送到这位用户登录过的所有 iPhone(lib/push.js):
ios/NotificationService)在显示前把标题换成通讯录里保存的名字,通讯录只在手机上匹配,不上传。passive 级别:静默进通知中心,不响铃、不亮屏。push_tokens 表);退出登录时注销这台设备;删除账户时级联删除。苹果说令牌失效(卸载 App 等)时自动删除。设置(一次):
.p8 只能下载一次。APNS_KEY_ID(页面上的 Key ID)、APNS_PRIVATE_KEY(.p8 文件的全部内容,直接粘贴)。.p8 是纯文本文件,在 Terminal 运行 pbcopy < ~/Downloads/AuthKey_XXXXXXXXXX.p8 就复制到剪贴板了(或者右键 Open With › TextEdit)。APNS_TEAM_ID 默认 3YDFH675B7。然后 Redeploy。supabase/schema.sql(新增 push_tokens 表)。xcodegen generate 后工程里会带上 Push Notifications 能力(project.yml 的 entitlements)和通知扩展 target NotificationService,自动签名会把能力加到 App ID 上、并为扩展创建 App ID,不用手动在 Signing & Capabilities 里加。排查:每次推送在 Vercel 日志里留一行「推送通知」(设备数、成功数、删除的失效令牌、失败原因)。日志出现「APNs 拒绝了令牌」说明三个 APNS_* 变量有误。模拟器收不到远程推送,要用真机测试。
每条登录短信都由 Twilio Verify 收费。App 里有基本限制:只接受澳洲手机号(+61 4…)、必须勾选同意协议、每次发送后冷却 60 秒、同一台手机每小时最多 5 次(ios/CallAssistant/Services/OTPThrottle.swift)。这些只能防误触和连点:App 是直接调用 Supabase 发验证码的,有心人可以绕过 App。真正控制费用要在服务端配置,都不影响正常用户:
一个 Twilio 号码可以同时接很多通电话,并发数是按账户算的,不按号码算:
用户多了以后,并发上限取决于 Vapi 的购买量。
user_id 为空)不属于任何用户,不会被删除。user_blocks)只影响打给他的电话;后台拉黑的(blocklist)对所有用户生效。Vercel Hobby 计划每次部署最多 12 个函数(api/ 下每个 .js 文件算一个),超过时部署会直接失败,线上仍是上一个版本。所以管理接口合并在 api/admin/[action].js,修改设置和删除账户合并在 api/account.js。npm test 里有一条测试会在超过 12 个时报错。新增接口时优先并入已有文件。
npm install
npm test
lib/entitlement.js| 订阅状态(3 天宽限期)与来电接听 / 拒接判定 |
lib/auth.js | 接口鉴权:DASHBOARD_TOKEN(后台)或 Supabase 登录令牌(App 用户) |
public/index.html | 产品主页(中英双语,按浏览器语言自动切换) |
public/admin.html | 后台(/admin):概览、用户、通话、订阅,以及同步配置、转移测试、全局黑名单 |
lib/admin/overview.js(GET /api/admin/overview) | 后台概览数据:用户、订阅、最近 30 天通话统计 |
ios/ | iOS App(SwiftUI),构建方法见 ios/README.md |
supabase/schema.sql | 数据库表结构 |