[{"badge":"动态","content":"有空了解下这个开源项目 GitHub ↗ GitHub - leiz56638111-create/puppy-store-cast: 小狗便利店投屏：轻量 Android TV DLNA 视频接收端，基于 Media3，采用 GPL-3.0-only。 小狗便利店投屏：轻量 Android TV DLNA 视频接收端，基于 Media3，采用 GPL-3.0-only。 - leiz56638111-create/puppy-store-cast","date":"2026年10月29日 09:04","description":"有空了解下这个开源项目 GitHub ↗ GitHub - leiz56638111-create/puppy-store-cast: 小狗便利店投屏：轻量 Android TV DLNA 视频接收端，基于 Media3，采用 …","permalink":"http://blog.880508.xyz/moments/#moment-20261029090418","title":"有空了解下这个开源项目 GitHub ↗ GitHub - …","type":"moments"},{"badge":"","content":"如今在家里装一两个网络摄像头，几乎成了许多家庭的刚需——有人为了看家防盗，有人为了随时看一眼熟睡的婴儿，还有人为了在上班时抓拍家里宠物的搞笑日常。\n市面上的智能摄像头硬件往往几十到一百出头就能买到，性价比看似极高。但真正用上之后，许多人都会遇到几道躲不开的“坎”：\n无休止的云存储订阅套路：不买云存储，历史录像就只能看十几秒甚至只有缩略图；如果家里装了三四个摄像头，一年光是交云存会员费就比摄像头本身还要贵。 挥之不去的隐私安全隐忧：家里的客厅、卧室、大门口实时画面，全部通过第三方厂商的云端中转和存储，隔三岔五爆出的“云端漏洞”或“监控泄露”新闻，让人心里总是不踏实。 传统开源 NVR 又重又繁琐：想在自己的 NAS 或软路由上自建 NVR（网络视频录像机）？市面上的传统方案要么配置复杂得像工业视频工程软件，要么对 CPU 和显卡性能要求苛刻，家里几十瓦的小主机跑上去风扇狂转、发热剧增，实在经不起长期 7×24 小时折腾。 正是出于**“想要一个极简、省电、好用且 100% 掌握在自己手中”**的初衷，我打磨了这款轻量级自托管 NVR——CamKeep。\n今天这篇文章不聊晦涩的底层音视频编解码算法，就单纯从家庭用户和 HomeLab 爱好者的日常视角，聊聊它是如何帮我们轻松接管家庭安防的。\n什么是 CamKeep？ 简单来说，CamKeep 是一个专为家庭 NAS、迷你主机和小服务器设计的轻量级自建网络视频录像系统。\n它的核心任务非常纯粹：\n接入流：把家里各个品牌（海康、大华、TP-Link、各种海思/雄迈方案等）摄像头的视频流统一聚合起来； 录下来：按照你设定的时间规则，安静无感地把视频持久化存到你的 NAS 硬盘上； 查得到：提供一个清爽易用的 Web 网页端，让你随时随地像刷短视频一样顺滑地拖动时间轴回看录像。 它没有庞杂的企业级安防架构，也不强求高昂的硬件配置。只要你的设备支持运行 Docker（无论是群晖、威联通、Unraid、TrueNAS，还是装了 Linux 的小主机、N1 盒子、树莓派），一条命令就能轻松跑起来。\n为什么选择 CamKeep？日常使用中的几大亮点 1. 100% 局域网本地优先，彻底告别云端与订阅 CamKeep 在设计之初就确立了**“内网安全、本地优先”**的原则：\n零外部依赖：它不需要注册任何外部云端账号，不依赖厂商的云服务中转，更不会向外界上传你的任何视频片段与设备信息； 免订阅费：你的存储空间有多大，录像就能存多久。硬盘满了？系统会自动按设定的天数循环清理最旧的片段，全程全自动； 本地权限可控：系统内置了本地用户与权限管理，可以为家人创建只读账号，甚至单独限制某个账号只能看门口摄像头，兼顾便利与隐私。 2. 极致的低功耗设计，老旧小主机也能轻松常开 对于 24 小时开机的家庭设备，电耗和发热是必须考虑的现实问题。很多传统 NVR 动辄在后台对视频进行二次转码，导致 CPU 占用率居高不下。\nCamKeep 深度复用了开源流媒体项目 go2rtc 的流处理能力，录制时默认采用**“直接流拷贝（Stream-Copy）”**技术——摄像头推过来什么格式，系统就原汁原味地分片写入磁盘，CPU 几乎只需要处理基础的 I/O 写入。这意味着即便是在几瓦功耗的软路由、老款 ARM 设备或低配 J4125 / N100 小主机上接入多路 2K/4K 摄像头，CPU 占用通常也仅有个位数，设备完全不会发烫。\n3. 像商用 App 一样好用的 24 小时时间轴回放 以前很多简陋的自建录像方案，回放时往往是一堆零碎的 .mp4 文件列表，想找一段昨天下午 3 点的画面得翻好几页、挨个点开试看，体验极其糟糕。\nCamKeep 在网页控制台里内置了可拖拽的 24 小时连续时间轴：\n支持鼠标滚轮缩放、移动端双指手势缩放，可以在“全天视图”与“分钟精细视图”之间随意平滑缩放； 点到哪里，画面直接秒级定位播放； 更贴心的是动检事件高亮标记：即便你是 24 小时全天候连续录像，系统也能在检测到画面有人或车走过时，在时间轴上叠加不同颜色的小色块。回看时扫一眼时间轴，哪里有动静一清二楚，再也不用快进几小时“大海捞针”。 4. 丰富的事件录像策略：帧差与 ONVIF 联动 除了常规的“定时录像”与“全天录像”，家庭监控经常需要“动检录像”（只录有动静的时刻，极度节省磁盘空间）。\nCamKeep 支持多种事件触发源：\n内置轻量帧差检测：针对普通的纯 RTSP 摄像头，后台用极低的采样率检测画面变化； ONVIF PullPoint 硬件直通：如果摄像头本身支持 ONVIF 事件上报，CamKeep 可以直接接收摄像头的硬件动检信号，完全不耗费宿主机的计算资源； Time-Shift 时光倒流缓存：很多时候画面出现变化时，往往“关键动作”已经发生了。CamKeep 支持预录缓存引擎，在事件触发时能连同发生前几秒的缓冲画面一起打包成事件视频，完整捕捉来龙去脉。 5. 统一的设备控制与超低延迟直播 如果你的摄像头支持机械云台旋转（PTZ）、对焦或光学变焦，CamKeep 在 Web 控制台就能直接进行遥控操作，免去在手机上翻找各家私有 App 的繁琐。同时得益于 go2rtc 的加持，实时预览时延能压到几十毫秒以内的 WebRTC 级别，点开即看，几乎感觉不到延迟。\n3 分钟快速上手 部署 CamKeep 非常简单，推荐直接使用 Docker 或 Docker Compose。\n第一步：准备存储目录 在你的 NAS、硬盘阵列或服务器上找一个空间充足的路径，建立好配置目录和录像目录。例如：\nmkdir -p /vol1/CamKeep/config mkdir -p /vol1/CamKeep/records 第二步：编写 docker-compose.yml 在同级目录下新建一个 docker-compose.yml 文件：\nservices: camkeep: image: ghcr.io/r0n9/camkeep:latest container_name: camkeep restart: unless-stopped network_mode: \"host\" # 推荐 host 模式，便于 WebRTC 低延迟直播与局域网设备探测 shm_size: \"512m\" # 预录缓存共享内存建议设为 512MB 以上 environment: - TZ=Asia/Shanghai - CAMKEEP_AUTH_PASSWORD=admin # 设置你的初始管理员密码 volumes: - ./config:/app/config # 存放配置文件与系统状态 - ./records:/app/records # 存放历史录像与最新抓拍封面 然后在终端执行启动命令：\ndocker compose up -d 第三步：添加摄像头，开始录制 启动完成后，打开浏览器访问 http://\u003c你的NAS IP\u003e:9110； 输入默认用户名 admin 和上面配置的初始密码登录系统； 进入**「配置管理」**页面，系统提供了非常友好的图形化表单，只需填入摄像头 ID 与对应的 RTSP 地址（例如 rtsp://admin:password@192.168.1.100:554/stream），选择开启录像即可； 回到首页的**「实时节点」**看板，稍等几秒就能看到摄像头的实时画面、当前状态和自动录制进度。 结语 折腾家庭 HomeLab 和自建服务的乐趣，往往不在于堆砌多么宏大复杂的架构，而在于用最轻巧、可控的技术，切实解决生活中的实际需求。\nCamKeep 并不是一个试图去和海康、大华企业级安防云相抗衡的重型软件，它更像是一个守候在家庭角落里默默耕耘的“数字录像管家”：它安安静静，只消耗极低的资源，不打扰你，也不向任何云端上传哪怕一帧画面；但当你想回顾某一天某个时间点的院子、门口或是小猫小狗的小插曲时，它总能清晰、顺畅地为你呈现出来。\n如果你家里正好有一台闲置的 NAS 或小主机，也有几个正在使用的网络摄像头，不妨把 CamKeep 跑起来体验一下。\n项目主页与源码：\nGitHub 仓库：https://github.com/r0n9/camkeep Docker 镜像：ghcr.io/r0n9/camkeep:latest / r0n9/camkeep:latest 欢迎在 GitHub 上提出你的使用反馈与想法！","date":"2026年10月26日","description":"厌倦了昂贵的摄像头云存订阅与隐私顾虑？介绍一款专为家庭 NAS、软路由和边缘设备设计的轻量级自托管 NVR 系统 CamKeep，单容器部署、极低资源占用、顺滑 24H 时间轴回放，把家庭监控的主动权牢牢拿回自己手中。","permalink":"http://blog.880508.xyz/2026/10/26/camkeep%E4%B8%93%E4%B8%BA%E5%AE%B6%E5%BA%AD-nas-%E4%B8%8E%E5%B0%8F%E4%B8%BB%E6%9C%BA%E6%89%93%E9%80%A0%E7%9A%84%E8%BD%BB%E9%87%8F%E7%BA%A7%E8%87%AA%E5%BB%BA%E8%A7%86%E9%A2%91%E7%9B%91%E6%8E%A7%E7%B3%BB%E7%BB%9F/","title":"CamKeep：专为家庭 NAS 与小主机打造的轻量级自建视频监控系统","type":"posts"},{"badge":"动态","content":"GitHub ↗ r0n9 - Overview 多年以后，面对已经觉醒的人工智能，人类将会想起那个第一次看见 token 流动的遥远夜晚。. r0n9 has 59 repositories available. Follow their code on GitHub.","date":"2026年10月25日 20:04","description":"GitHub ↗ r0n9 - Overview 多年以后，面对已经觉醒的人工智能，人类将会想起那个第一次看见 token 流动的遥远夜晚。. r0n9 has 59 repositories available. Follow their …","permalink":"http://blog.880508.xyz/moments/#moment-20261025200447","title":"GitHub ↗ r0n9 - Overview 多年以后，面对已经觉醒的人工智 …","type":"moments"},{"badge":"动态","content":"","date":"2026年10月25日 20:03","description":"","permalink":"http://blog.880508.xyz/moments/#moment-20261025200321","title":"","type":"moments"},{"badge":"动态","content":"CleanYourTV 👍","date":"2026年10月23日 17:53","description":"CleanYourTV 👍","permalink":"http://blog.880508.xyz/moments/#moment-20261023175341","title":"CleanYourTV 👍","type":"moments"},{"badge":"","content":"Gitea 自动备份到 MinIO 方案说明 为了防止服务器故障、磁盘损坏或误操作导致代码仓库丢失，可以将 Gitea 数据目录定时同步到 MinIO 对象存储，实现异地备份。\n本方案基于：\nGitea MinIO MinIO Client（mc） Linux Crontab 同步方式采用 mc mirror，支持增量同步，仅传输新增或变更文件。\n前置条件 0. docker compose 安装 MinIO services:\rminio-server: # 这里是正确的服务定义位置minio-server:\rimage: quay.io/minio/minio:RELEASE.2025-04-03T14-56-28Z\rcontainer_name: minio\rports:\r- \"9000:9000\" # API端口\r- \"9001:9001\" # 控制台端口\rvolumes:\r- /vol1/1000/docker/minio/data:/data # 挂载数据目录\renvironment:\rMINIO_ROOT_USER: username # 默认管理员用户名\rMINIO_ROOT_PASSWORD: password # 默认管理员密码\rcommand: server --console-address \":9001\" /data # 指定控制台端口和数据目录\rrestart: always\rhealthcheck:\rtest: [\"CMD\", \"curl\", \"-f\", \"http://localhost:9000/minio/health/live\"]\rinterval: 30s\rtimeout: 20s\rretries: 3 1. 安装 MinIO Client curl https://dl.min.io/client/mc/release/linux-amd64/mc \\ -o /usr/local/bin/mc chmod +x /usr/local/bin/mc 验证安装：\nmc --version 2. 配置 MinIO 连接 添加 MinIO 服务：\nmc alias set myminio \\ http://minio.example.com:9000 \\ ACCESS_KEY \\ SECRET_KEY 验证连接：\nmc ls myminio Gitea 数据目录 确认 Gitea 实际数据目录，例如：\n/home/rong/gitea 目录通常包含：\ngitea/\r├── repositories/ # Git 仓库\r├── lfs/ # Git LFS 文件\r├── data/ # 附件及其他数据\r├── conf/ # 配置文件\r└── log/ # 日志 手动执行备份 执行同步：\nmc mirror --overwrite \\ /home/rong/gitea \\ myminio/backup/gitea 同步完成后：\nmyminio\r└── backup\r└── gitea\r├── repositories\r├── lfs\r├── data\r└── conf 配置定时任务 编辑 Crontab：\ncrontab -e 添加：\n0 4 * * * /usr/local/bin/mc mirror --overwrite /home/rong/gitea myminio/backup/gitea \u003e\u003e /home/rong/gitea-backup.log 2\u003e\u00261 含义：\n配置项 说明 0 4 * * * 每天凌晨 4 点执行 mc mirror 目录镜像同步 –overwrite 覆盖已存在文件 /home/rong/gitea 本地 Gitea 数据目录 myminio/backup/gitea MinIO 备份目录 » log 记录执行日志 2\u003e\u00261 记录错误日志 查看日志：\ntail -f /home/rong/gitea-backup.log 关于 –remove 参数 可以使用：\nmc mirror --overwrite --remove \\ /home/rong/gitea \\ myminio/backup/gitea 但不建议用于备份场景。\n原因：\n如果本地误删仓库：\n/home/rong/gitea/repositories/project.git 下一次同步时，MinIO 中对应目录也会被删除。\n因此：\n-remove：适合灾备镜像 不加 -remove：适合长期备份 推荐使用：\nmc mirror --overwrite 数据恢复 从 MinIO 恢复：\nmc mirror \\ myminio/backup/gitea \\ /home/rong/gitea 恢复完成后启动 Gitea：\ndocker restart gitea 或：\ndocker compose restart gitea 最佳实践 推荐策略：\n每天凌晨自动同步 MinIO 开启版本控制（Versioning） 定期验证备份可恢复性 重要数据同时备份到另一台服务器或云存储 推荐保留：\n本地 Gitea\r↓\rMinIO 主备份\r↓\r异地存储（可选） 形成多副本备份体系，降低数据丢失风险。\n示例目录结构 MinIO\r└── backup\r└── gitea\r├── repositories\r├── lfs\r├── data\r├── conf\r└── log 该方案适用于 Docker 部署、NAS 部署以及传统 Linux 服务器部署的 Gitea 实例。","date":"2026年10月23日","description":"为了防止服务器故障、磁盘损坏或误操作导致代码仓库丢失，可以将 Gitea 数据目录定时同步到 MinIO 对象存储，实现异地备份。","permalink":"http://blog.880508.xyz/2026/10/23/gitea-%E8%87%AA%E5%8A%A8%E5%A4%87%E4%BB%BD%E5%88%B0-minio/","title":"Gitea 自动备份到 MinIO","type":"posts"},{"badge":"动态","content":"感谢 “赛博菩萨” CloudFlare Workers ！","date":"2026年10月23日 03:07","description":"感谢 “赛博菩萨” CloudFlare Workers ！","permalink":"http://blog.880508.xyz/moments/#moment-20261023030722","title":"感谢 “赛博菩萨” CloudFlare Workers ！","type":"moments"},{"badge":"动态","content":"博客专属的 Web 在线发布服务也不能少","date":"2026年10月23日 01:56","description":"博客专属的 Web 在线发布服务也不能少","permalink":"http://blog.880508.xyz/moments/#moment-20261023015646","title":"博客专属的 Web 在线发布服务也不能少","type":"moments"},{"badge":"动态","content":"⬆️ 上传图片支持前端 HTML5 Canvas 智能压制与 WebP 转码功能","date":"2026年10月23日 01:43","description":"⬆️ 上传图片支持前端 HTML5 Canvas 智能压制与 WebP 转码功能","permalink":"http://blog.880508.xyz/moments/#moment-20261023014307","title":"⬆️ 上传图片支持前端 HTML5 Canvas 智能压制与 WebP 转码功能","type":"moments"},{"badge":"动态","content":"趁热打铁，把刚才上线的「动态」随手记也全面打通并接入了全站搜索 🔍\n现在顶部的搜索不仅能搜技术长文，平时随手记录的碎片想法、折腾心得也能秒级检索。搜索结果里给动态加上了专属徽标标识，点击结果即可平滑直达对应的动态并自动高亮，这下不用担心碎碎念多了找不到之前的记录了～","date":"2026年10月23日 01:03","description":"趁热打铁，把刚才上线的「动态」随手记也全面打通并接入了全站搜索 🔍\n现在顶部的搜索不仅能搜技术长文，平时随手记录的碎片想法、折腾心得也能秒级检索。搜索结果里给动态加上了专属徽标标识，点击结果即可平滑直达对应的动态并自动高亮，这下不用担心碎碎 …","permalink":"http://blog.880508.xyz/moments/#moment-20261023010300","title":"趁热打铁，把刚才上线的「动态」随手记也全面打通并接入了全站搜索 🔍\n现在顶部的搜 …","type":"moments"},{"badge":"动态","content":"折腾了几天，博客全新改版正式上线啦 🎉\n重构对齐了极简纸质美学与轻量交互微动效，补齐了全站精准搜索、时间轴归档、GitHub 贡献日历，以及现在这个刚刚落地的随手记录「动态」专区。\n以后除了成体系的技术长文，一些零碎的代码折腾心得、HomeLab 日常和碎片想法也会随手丢在这里。\n欢迎常来逛逛，Stay curious, keep tinkering! ☕️","date":"2026年10月23日 00:30","description":"折腾了几天，博客全新改版正式上线啦 🎉\n重构对齐了极简纸质美学与轻量交互微动效，补齐了全站精准搜索、时间轴归档、GitHub 贡献日历，以及现在这个刚刚落地的随手记录「动态」专区。\n以后除了成体系的技术长文，一些零碎的代码折腾心得 …","permalink":"http://blog.880508.xyz/moments/#moment-20261023003000","title":"折腾了几天，博客全新改版正式上线啦 🎉\n重构对齐了极简纸质美学与轻量交互微动效， …","type":"moments"},{"badge":"","content":"功能说明： 使用 docker exec 调用 mysqldump，生成 .sql 备份文件； 文件名中包含当前时间，保存在 mysql_backup/ 目录； 自动清理： 删除 超过 7 天的备份文件； 保留每月 1 号的备份文件，不管时间多久。 脚本 mysql_backup.sh #!/bin/bash # ========== 配置 ========== CONTAINER_NAME=\"mysql\" MYSQL_USER=\"dbuser\" MYSQL_PASSWORD=\"dbpassword\" BACKUP_DIR=\"/home/ubuntu/mysql_backup\" # ========== 创建备份目录 ========== mkdir -p \"$BACKUP_DIR\" # ========== 生成备份文件名 ========== DATE=$(date '+%Y-%m-%d_%H-%M-%S') BACKUP_FILE=\"${BACKUP_DIR}/backup_${DATE}.sql\" # ========== 执行备份 ========== echo \"开始备份：$BACKUP_FILE\" docker exec \"$CONTAINER_NAME\" mysqldump -u \"$MYSQL_USER\" -p\"$MYSQL_PASSWORD\" --all-databases \u003e \"$BACKUP_FILE\" # ========== 清理逻辑 ========== echo \"清理旧备份...\" # 找出所有 .sql 文件 find \"$BACKUP_DIR\" -type f -name \"*.sql\" | while read file; do # 提取文件名中的日期 filename=$(basename \"$file\") date_str=$(echo \"$filename\" | grep -oP '\\d{4}-\\d{2}-\\d{2}') # 如果提取不到日期，跳过 if [[ -z \"$date_str\" ]]; then continue fi # 获取今天日期和文件日期的时间戳 file_ts=$(date -d \"$date_str\" +%s) today_ts=$(date +%s) # 计算文件和今天的天数差 age_days=$(( (today_ts - file_ts) / 86400 )) # 如果超过 7 天且不是每月 1 号 if [[ $age_days -gt 7 ]]; then day_of_month=$(date -d \"$date_str\" +%d) if [[ \"$day_of_month\" != \"01\" ]]; then echo \"删除过期备份：$file\" rm -f \"$file\" fi fi done echo \"备份完成。\" 设置定时任务 设置每天 12:00 和 20:00 备份一次，并将日志写入文件。\n0 12,20 * * * /home/ubuntu/mysql_backup.sh \u003e\u003e /home/ubuntu/mysql_backup.log 2\u003e\u00261","date":"2025年8月20日","description":"Docker安装的Mysql数据库定时备份脚本","permalink":"http://blog.880508.xyz/2025/08/21/Docker%E5%AE%89%E8%A3%85%E7%9A%84Mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%9A%E6%97%B6%E5%A4%87%E4%BB%BD%E8%84%9A%E6%9C%AC/","title":"Docker安装的Mysql数据库定时备份脚本","type":"posts"},{"badge":"","content":"📢 网站域名迁移公告 尊敬的用户朋友们：\n为进一步统一品牌形象、提升访问体验，我们的网站已完成域名迁移：\n🔗 新域名： https://boardrop.app\n🕒 生效时间：即日起\n原有域名 https://airclipbd.com 将继续通过 301 重定向自动跳转到新域名，无需用户手动操作。\n🌐 为什么更换为 boardrop.app？ 新域名的含义和愿景：\nBoard + Drop：灵感源自于“画板投放”、“内容投送”之意，寓意我们的平台是一个灵活、即时、沉浸式的“内容投放空间”。 简洁直观：相较旧域名，boardrop.app 更具可读性和可记忆性，方便用户输入与传播。 强调应用属性：.app 域名表明我们是一个工具型产品，为用户提供高效实用的功能服务。 面向未来：更贴合我们打造多人协作、远程共享与互动的长期愿景。 🔄 域名迁移影响说明 项目 说明 原有链接访问 将自动跳转到 boardrop.app，无需手动修改 浏览器书签 建议手动更新为新域名，以提升访问速度 接口/API调用 建议尽快更新为新域名，旧接口将逐步弃用 搜索引擎收录 已配置 301 重定向，权重将自动过渡至新域名 🔐 HTTPS 加密访问 新域名已部署完整 SSL 安全证书，支持 TLS1.3，确保所有用户访问安全可靠。\n感谢您的支持与理解！\nhttps://boardrop.app\n2025 年 7 月","date":"2025年7月8日","description":"📢 网站域名迁移公告尊敬的用户朋友们： 为进一步统一品牌形象、提升访问体验，我们的网站已完成域名迁移：  🔗 新域名： https://boardrop.app🕒 生效时间：即日起  原有域名 https://airclipbd.com 将继续通过 301 重定向自动跳转到新域名，无需用户手动操作。  🌐 为什么更换为 boardrop.app？新域名的含义和愿景：  Board + Dr","permalink":"http://blog.880508.xyz/2025/07/08/airclipbd-20250708/","title":"boardrop.app 网站域名迁移公告","type":"posts"},{"badge":"","content":"v2.4.1-20250611 版本更新 Airclipbd 隔空剪贴板 迎来了一个新版本，希望大家能够给予支持！\nChangelog\nUI 迎来了一个新设计，更加美观。\n局域网互传优化，设备的名称、图标Icon、设备类型展示更加清晰美观。\n文件、信息互传窗口优化。","date":"2025年6月25日","description":"v2.4.1-20250611 版本更新Airclipbd 隔空剪贴板 迎来了一个新版本，希望大家能够给予支持！ Changelog  UI 迎来了一个新设计，更加美观。  局域网互传优化，设备的名称、图标Icon、设备类型展示更加清晰美观。  文件、信息互传窗口优化。","permalink":"http://blog.880508.xyz/2025/06/25/airclipbd-20250625/","title":"Airclipbd 隔空剪贴板 v2.4.1-20250611 版本更新","type":"posts"},{"badge":"","content":"如何在 Quest 3 上安装 Parsec 串流 PC 或 MacOS 在这篇博客中，我们将详细介绍如何在 Meta Quest 3 上安装 Parsec 客户端，并通过远程串流连接到你的 PC 或 MacOS 设备。整个过程非常简单，通过在 APKPure 下载 Parsec 的 XAPK 文件，然后使用 SAI（Split APKs Installer）在 Quest 3 上进行安装，我们就能轻松实现远程桌面体验。\n第 1 步：下载 Parsec XAPK 文件 访问 APKPure 网站，搜索 Parsec 客户端，选择适合 arm64-v8a 架构的版本。通常，APKPure 会提供一个 XAPK 格式的下载链接。\n在我们的示例中，使用了这个链接：下载 Parsec XAPK。\n下载完成后，你会得到一个 .xapk 文件，这个文件实际上是一个压缩包，里面包含了多个 APK 文件。\n第 2 步：解压 XAPK 文件 将 .xapk 文件的扩展名改为 .zip，然后解压这个文件。\n解压后，你会看到两个 APK 文件：\ntv.parsec.client.apk（主程序） config.arm64_v8a.apk（针对 ARM64 架构的配置 APK） 这些文件必须一起安装，才能确保 Parsec 客户端正常运行。\n第 3 步：安装 SAI（Split APKs Installer） 使用 SideQuest 或 USB 将 SAI APK 安装到你的 Quest 3 上。可以在 SAI GitHub 页面 下载最新版本的 SAI 安装包。\n安装完成后，在 Quest 3 上打开 SAI 应用。\n第 4 步：使用 SAI 安装 Parsec 客户端 打开 SAI 后，点击界面中的 “安装 APKs” 按钮。\n浏览文件系统，选择你之前解压出的这两个 APK 文件：\ntv.parsec.client.apk（主程序） config.arm64_v8a.apk（配置 APK） 勾选这两个文件并点击 “安装”。安装过程中，SAI 会自动处理分包 APK，确保 Parsec 客户端能够在 Quest 3 上正常运行。\n安装完成后，返回 Quest 3 的 “未知来源” 页面，你会看到 Parsec 应用图标。\n第 5 步：连接到 PC 或 MacOS 在你的 PC 或 MacOS 上，下载并安装 Parsec 客户端。如果你还没有账户，可以创建一个免费账号。\n在 Parsec 应用中登录你的账户。\n在 Quest 3 上启动 Parsec 客户端，使用你的账号登录，并找到你要连接的设备。\n一旦连接成功，你就可以通过 Quest 3 享受高质量的远程桌面体验，无论是玩游戏、办公，还是使用其他 PC 或 Mac 应用。\n小贴士 网络要求：确保你的 PC/Mac 和 Quest 3 都连接到同一 Wi-Fi 网络，以获得更好的串流体验。 权限设置：首次使用 Parsec 时，可能需要授予应用网络、麦克风等权限。 控制方式：你可以通过 Quest 3 的虚拟桌面进行鼠标和键盘控制，甚至使用手柄进行游戏控制。 总结 通过这个简单的过程，你就能在 Quest 3 上安装 Parsec 客户端，并通过串流远程访问你的 PC 或 MacOS 设备。使用 SAI 安装分包 APK，使整个过程更加简便，无需复杂的命令行操作。\n享受你的 VR 串流体验吧！","date":"2025年4月24日","description":"如何在 Quest 3 上安装 Parsec 串流 PC 或 MacOS在这篇博客中，我们将详细介绍如何在 Meta Quest 3 上安装 Parsec 客户端，并通过远程串流连接到你的 PC 或 MacOS 设备。整个过程非常简单，通过在 APKPure 下载 Parsec 的 XAPK 文件，然后使用 SAI（Split APKs Installer）在 Quest 3 上进行安装，我们就能","permalink":"http://blog.880508.xyz/2025/04/24/%E5%A6%82%E4%BD%95%E5%9C%A8%20Meta%20Quest%203%20%E4%B8%8A%E5%AE%89%E8%A3%85%20Parsec%20%E4%B8%B2%E6%B5%81%20PC%20%E6%88%96%20MacOS/","title":"如何在 Quest 3 上安装 Parsec 串流 PC 或 MacOS","type":"posts"},{"badge":"","content":"Share Extension 分享扩展 在项目中添加新的 Share Extension target\nNSExtensionActivationRule 扩展的 Info.plist\n\u003ckey\u003eNSExtensionAttributes\u003c/key\u003e \u003cdict\u003e \u003ckey\u003eNSExtensionActivationRule\u003c/key\u003e \u003cdict\u003e \u003ckey\u003eNSExtensionActivationSupportsText\u003c/key\u003e \u003ctrue/\u003e \u003ckey\u003eNSExtensionActivationSupportsImageWithMaxCount\u003c/key\u003e \u003cinteger\u003e9\u003c/integer\u003e \u003ckey\u003eNSExtensionActivationSupportsWebURLWithMaxCount\u003c/key\u003e \u003cinteger\u003e1\u003c/integer\u003e \u003c/dict\u003e \u003c/dict\u003e Share Extension 分享扩展，分享发布后直接跳转主应用APP class ShareViewController: SLComposeServiceViewController\ndidSelectPost 方法实现，点击默认的发布按钮后的处理\n原本打算尝试点击发布后，打开主应用app，这里一直失败。\n主应用URL设置，涉及 URL Types in Info.plist，这里不展开。\n排除了主应用的URL错误，尝试在safari中输入url，例如”testProject://“，可以打开主应用。\n通过URL打开应用代码，直接使用extension的open方法：\nif let url = URL(string: \"testProject://\") { print(\"URL: \\(url)\") self.extensionContext?.open(url) { success in print(\"URL \\(success ? \"opened\" : \"failed to open\")\") self.extensionContext?.completeRequest(returningItems: [], completionHandler: nil) } } else { print(\"URL 格式错误\") return } 问题原因：\nhttps://stackoverflow.com/questions/24297273/openurl-not-work-in-action-extension\nNSExtensionContext only support openURL function in today extension ,this is described in apple’s documents about NSExtensionContext.The original words is “Each extension point determines whether to support this method, or under which conditions to support this method. In iOS 8.0, only the Today extension point supports this method.”\n译: 在 iOS 中，NSExtensionContext 的 openURL:completionHandler: 方法仅在 Today 扩展中可用。 根据苹果官方文档的描述：“每个扩展点决定是否支持此方法，或在何种条件下支持此方法。在 iOS 8.0 中，只有 Today 扩展点支持此方法。” 这意味着，除 Today 扩展外，其他类型的扩展（如 Share、Action 等）无法使用 openURL:completionHandler: 方法来打开 URL。 因此，您需要根据扩展的类型，选择适合的方式来处理 URL 打开操作。\n因此，想通过扩展组件，直接打开某个APP，应该是做不到了，出于安全考虑吧。\n参考了一下其他APP的做法，有大致思路了：\n放弃在分享发布后打开主应用APP，在 Share Extension 中直接实现功能，也就是修改 Share Extension 中默认的分享页面实现。\n使用 App Group 通过 UserDefaults 实现数据共享 为了在主App和Share Extension之间共享数据，需要启用 App Groups：\n在Xcode中，选择主App和Share Extension的Target。 在 Signing \u0026 Capabilities 中，点击 “+” 添加 App Groups。 设置一个唯一的App Group ID，例如group.com.yourcompany.app，并在两个Target中启用。","date":"2025年2月27日","description":"Share Extension 分享扩展在项目中添加新的 Share Extension target NSExtensionActivationRule扩展的 Info.plist 123456789101112NSExtensionAttributes NSExtensionActivationR","permalink":"http://blog.880508.xyz/2025/02/27/ios%20swift%20%E5%BC%80%E5%8F%91%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%E5%85%B3%E4%BA%8EShare%20Extension%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95/","title":"iOS swift 开发学习笔记：关于Share Extension遇到的问题记录","type":"posts"},{"badge":"","content":"在 Ubuntu 系统中使用 firewalld 时，默认情况下，firewalld 不会对 Docker 容器的网络流量生效。这是因为 Docker 在启动时会自动创建自己的 iptables 规则来管理网络，绕过了 firewalld 的规则。这种行为可以确保 Docker 容器的网络功能正常，但也会导致 firewalld 的规则无法控制 Docker 端口。\n具体原因有以下几点：\n1. Docker 使用 iptables Docker 默认会直接操作 iptables 来管理网络连接，而不是通过 firewalld。因此，firewalld 中的规则不会影响 Docker 创建的容器的网络流量。\n2. Docker 配置覆盖 firewalld Docker 会修改 iptables 规则，以确保容器能够进行网络连接和端口转发。这些规则可能与 firewalld 的设置发生冲突，导致 firewalld 对 Docker 的流量无效。\n解决方案 如果你希望 firewalld 可以控制 Docker 容器的网络流量，可以尝试以下几种方法。\n方法 1: 配置 Docker 使用 firewalld 管理规则 可以通过修改 Docker 的配置，禁用 Docker 自己管理 iptables，让 firewalld 接管。\n打开 Docker 配置文件（如果文件不存在，可以新建一个）：\nsudo nano /etc/docker/daemon.json 添加以下配置，禁用 Docker 自动修改 iptables：\n{ \"iptables\": false } 重启 Docker 服务：\nsudo systemctl restart docker 通过禁用 Docker 的 iptables 规则，网络流量将由 firewalld 进行控制。\n注意：禁用 iptables 后，你需要手动管理网络规则，确保容器仍然可以正常访问外部网络。\n方法 2: 使用 iptables 自定义规则 如果你不希望禁用 Docker 的 iptables 管理，你可以通过手动添加 iptables 规则来配合 firewalld。\n确认 Docker 的网络桥接接口（通常是 docker0）：\nifconfig 在 firewalld 中允许或限制该接口的流量。例如：\nsudo firewall-cmd --zone=trusted --add-interface=docker0 --permanent sudo firewall-cmd --reload 这样可以将 docker0 接口添加到 firewalld 的 trusted 区域，允许其网络流量。\n总结 firewalld 对 Docker 容器的端口没有生效，是因为 Docker 默认直接操作 iptables，绕过了 firewalld 的规则。你可以通过禁用 Docker 的 iptables 管理功能，或手动配置 iptables 来使 firewalld 生效。","date":"2024年10月10日","description":"在 Ubuntu 系统中使用 firewalld 时，默认情况下，firewalld 不会对 Docker 容器的网络流量生效。这是因为 Docker 在启动时会自动创建自己的 iptables 规则来管理网络，绕过了 firewalld 的规则。这种行为可以确保 Docker 容器的网络功能正常，但也会导致 firewalld 的规则无法控制 Docker 端口。 具体原因有以下几点： 1. D","permalink":"http://blog.880508.xyz/2024/10/10/Firewalld%E9%98%B2%E7%81%AB%E5%A2%99%E7%9A%84%E8%A7%84%E5%88%99%E6%97%A0%E6%B3%95%E6%8E%A7%E5%88%B6Docker%E7%AB%AF%E5%8F%A3%E7%9A%84%E9%97%AE%E9%A2%98/","title":"Firewalld防火墙的规则无法控制Docker端口的问题","type":"posts"},{"badge":"","content":"v2.3.1-20240926 版本更新 Changelog\n移除了客户端离线时消息的显示。\nRemoved the display of messages when the client is offline.\n修复了部分剪贴板ID异常获取的问题。\nFixed issues with abnormal retrieval of some board IDs.\n区分了大屏与小屏的显示适配，突出了点对点传输功能。\nDifferentiated the display adaptation for large and small screens, highlighting the point-to-point transmission feature.\n大屏显示现支持折叠与展开功能。\nLarge screen display now supports collapse and expand functionality.\n大屏展示\n小屏展示","date":"2024年9月26日","description":"v2.3.1-20240926 版本更新Changelog  移除了客户端离线时消息的显示。 Removed the display of messages when the client is offline.  修复了部分剪贴板ID异常获取的问题。   Fixed issues with abnormal retrieval of some board IDs.  区分了大屏与小屏的显示适配，","permalink":"http://blog.880508.xyz/2024/09/26/airclipbd-0926/","title":"Airclipbd 隔空剪贴板 v2.3.1-20240926 版本更新","type":"posts"},{"badge":"","content":"背景 当使用 expect 登入你的虚拟主机的时候，你会发现使用 vim，会经常出现行错乱的问题。\n原因 expect 脚本自动 ssh 登陆，当终端窗口发生变化时，默认 expect 不会将终端窗口大小改变的信号传送到远程的服务器上，因此在使用上会出现很不方便的地方，比如 vim 打开文件时出现串行，要是含有中文的文件可能根本无法编辑。\n解决 #!/usr/bin/env expect #trap sigwinch spawned trap { set rows [stty rows] set cols [stty columns] stty rows $rows columns $cols \u003c $spawn_out(slave,name) } WINCH #... 结果你发现完全OK ，不再乱行了","date":"2024年9月3日","description":"背景当使用 expect 登入你的虚拟主机的时候，你会发现使用 vim，会经常出现行错乱的问题。 原因expect 脚本自动 ssh 登陆，当终端窗口发生变化时，默认 expect 不会将终端窗口大小改变的信号传送到远程的服务器上，因此在使用上会出现很不方便的地方，比如 vim 打开文件时出现串行，要是含有中文的文件可能根本无法编辑。 解决12345678#!/usr/bin/env expect","permalink":"http://blog.880508.xyz/2024/09/03/%E9%80%9A%E8%BF%87expect%E7%99%BB%E5%BD%95linux,%20vim%E8%A1%8C%E9%94%99%E4%B9%B1%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/","title":"通过expect登录linux, vim行错乱问题解决方案","type":"posts"},{"badge":"","content":"什么是 WebRTC？ WebRTC（Web Real-Time Communication）是一种允许网页和应用程序进行实时通信（RTC）的技术。它支持点对点的视频、音频和数据传输，无需安装额外的插件或应用程序。WebRTC 的主要特点如下：\n实时通信：WebRTC 允许用户通过浏览器直接进行语音和视频通话，以及数据共享。 点对点连接：WebRTC 可以直接在两个用户间建立连接，实现数据的直接传输，而非通过中心服务器。这样做可以减少延迟和提高通信效率。 兼容性：它是一个开放标准，被大多数现代浏览器支持，包括 Chrome、Firefox、Safari 和 Edge。 安全性：所有 WebRTC 组件都要求使用安全的起点（HTTPS），并对所有数据进行加密传输。 多功能性：除了音视频通话，WebRTC 还支持各种数据传输，包括文件共享和实时文本聊天。 NAT 穿透：WebRTC 使用 STUN/TURN 服务器来处理 NAT（网络地址转换）和防火墙穿透，确保不同网络环境下的设备可以相互连接。 媒体捕获和处理：WebRTC 提供了捕获本地媒体（如摄像头和麦克风输入）、处理和播放远程媒体的能力。 标准化 API：提供了一套标准的 API，方便开发者在网络应用中集成实时通信功能。 总之，WebRTC 是一种强大的实时通信技术，使得在不同平台和设备之间的音视频通话和数据共享变得简单和高效。\nWebRTC 的 NAT 穿透 WebRTC 中的 NAT（网络地址转换）穿透是一个关键技术，用于在两个位于不同网络（例如家庭或企业网络）的设备之间建立直接的通信连接。NAT 穿透对于保证 WebRTC 能够在各种网络环境下正常工作至关重要。以下是 WebRTC NAT 穿透的详细介绍：\n1. NAT 问题的背景 NAT 的作用：NAT 使多个设备能够共享一个公共 IP 地址，同时保持它们的内部（私有）IP 地址。这是家庭和企业网络常用的一种方法。 NAT 对 P2P 的影响：NAT 使得点对点（P2P）通信变得复杂，因为外部网络无法直接访问内部网络中的设备。 2. WebRTC 的 NAT 穿透技术 WebRTC 使用几种技术来解决 NAT 问题：\na. ICE（Interactive Connectivity Establishment） 功能：ICE 是一种框架，用于收集设备的多种网络地址（候选者），并尝试通过这些地址建立连接。 候选者类型：包括本地地址、反射地址（通过 STUN 获得）和中继地址（通过 TURN 获得）。 b. STUN（Session Traversal Utilities for NAT） 用途：STUN 服务器帮助设备发现其公共 IP 地址和端口，这对于穿越 NAT 是必需的。 工作原理：设备向 STUN 服务器发送请求，服务器回应设备的公共 IP 地址和端口。 c. TURN（Traversal Using Relays around NAT） 场景：在某些复杂的 NAT 情况下，STUN 无法实现穿透，此时需要 TURN。 功能：TURN 服务器充当中继，转发两个尝试连接的设备之间的流量。 影响：虽然有效，但使用 TURN 会增加延迟和带宽消耗。 3. NAT 穿透过程 收集候选者：设备使用 ICE 框架来收集其所有可能的网络地址（本地、反射和中继）。 候选者交换：通信双方通过信令通道交换他们的 ICE 候选者信息。 连接尝试：双方尝试使用收集到的候选者信息来建立直接的 P2P 连接。 选择最佳路径：在成功建立连接后，将选择最有效的路径进行数据传输。 4. 重要性 保证连通性：NAT 穿透使得位于不同 NAT 后面的设备可以建立直接的通信连接。 提高效率：虽然使用 TURN 会增加资源消耗，但大多数情况下，ICE 和 STUN 足以成功穿越 NAT，确保通信的高效性。 5. 实践中的挑战 复杂的 NAT 类型：对于对称型 NAT，仅靠 STUN 可能无法成功穿越，需要依赖 TURN。 资源和成本：维护 TURN 服务器可能涉及额外的资源和成本。 WebRTC 通过这些 NAT 穿透技术，确保了在不同网络环境下都能够实现可靠和高效的实时通信。\n搭建基于 WebRTC 的视频通话系统 搭建基于 WebRTC 的视频通话系统涉及多个步骤，主要包括信令、NAT 穿透、媒体捕获与渲染等。下面是搭建这种系统的基本指南，假设你想在两个不同的家庭网络中实现视频通话：\n1. 准备工作 了解 WebRTC: 需要基本的了解关于 WebRTC 的工作原理。 编程技能: 熟悉至少一种编程语言，如 JavaScript（对于 Web 应用程序）。 2. 信令服务器 作用: 用于交换 WebRTC 通信双方的元数据，如 ICE 候选者、会话描述协议（SDP）信息等。 搭建方式: 可以使用 WebSocket、REST API 等技术搭建一个简单的信令服务器。这可以使用 Node.js、Python 等后端技术实现。 3. STUN/TURN 服务器 STUN: 使用公共 STUN 服务器（如 Google 的 STUN 服务器: stun:stun.l.google.com:19302）或自建 STUN 服务器。 TURN: 对于更复杂的 NAT 穿透情况，可能需要 TURN 服务器。可以使用开源解决方案如 coturn。 4. 媒体捕获和处理 API 使用: 利用 WebRTC 提供的 API 如 getUserMedia 来捕获音频和视频媒体流。 显示媒体: 使用 HTML 的 \u003cvideo\u003e 标签来显示捕获的视频流。 5. 前端实现 编写客户端代码: 使用 HTML/CSS/JavaScript 创建用户界面。 集成 WebRTC: 在客户端代码中集成 WebRTC API，实现视频通话的建立、维持和结束。 6. 建立连接 交换 SDP: 通过信令服务器交换双方的 SDP 描述。 交换 ICE 候选者: 通过信令服务器交换 ICE 候选信息以建立连接。 7. 测试和调试 本地测试: 首先在本地网络环境中测试视频通话功能。 跨网络测试: 然后在两个不同的家庭网络中测试，确保 NAT 穿透有效。 8. 部署 信令服务器部署: 将信令服务器部署到云服务或公共服务器上。 客户端访问: 确保用户可以通过互联网访问前端应用。 9. 安全性和隐私 使用 HTTPS: 确保应用使用 HTTPS，这是 WebRTC 的一个要求。 数据加密: WebRTC 本身就提供端到端加密。 10. 可扩展性和性能优化 适应不同带宽: 实现适应不同网络条件的逻辑。 优化用户体验: 根据需要优化界面和用户交互。 搭建基于 WebRTC 的视频通话系统需要对网络编程、前端开发和后端服务有一定的了解。这个过程涉及到多个技术点，但 WebRTC 提供了大多数必要的工具来简化这个过程。成功实现后，你将拥有一个能够在不同家庭网络间进行视频通话的系统。","date":"2024年7月15日","description":"什么是 WebRTC？WebRTC（Web Real-Time Communication）是一种允许网页和应用程序进行实时通信（RTC）的技术。它支持点对点的视频、音频和数据传输，无需安装额外的插件或应用程序。WebRTC 的主要特点如下：  实时通信：WebRTC 允许用户通过浏览器直接进行语音和视频通话，以及数据共享。 点对点连接：WebRTC 可以直接在两个用户间建立连接，实现数据的直接传","permalink":"http://blog.880508.xyz/2024/07/15/%E5%85%B3%E4%BA%8EWebRTC%E7%9A%84%E4%B8%80%E4%BA%9B%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93%E5%92%8C%E8%AE%B0%E5%BD%95/","title":"关于WebRTC的一些技术总结和记录","type":"posts"},{"badge":"","content":"独立开发者必看，cloudflare worker 其实也能发邮件，而且是比较优雅地发邮件\nhttps://web.okjike.com/originalPost/65203d2205145f31e56e0707\n什么是 DKIM ？ https://www.cloudflare.com/zh-cn/learning/dns/dns-records/dns-dkim-record/\n参考1\nCloudflare Email Routing 免费邮件发送服务\nhttps://eleduck.com/posts/4lfxE0\n参考2\nCloudflare Email Routing 免费邮件发送（作为 Service 服务）用于 Workers/Pages 项目中。****\nhttps://github.com/willin/cloudflare-send-email-service\n参考3\nCloudflare + MailChannels 使用 DKIM 发送电子邮件\nhttps://github.com/r0n9/mail\n终于搞定！！！记录一下步骤，如下： 1. CloudFlare 添加域名 yourdomain.com 2. 启用Email路由： [Enable Email Routing · Cloudflare Email Routing docs](https://developers.cloudflare.com/email-routing/get-started/enable-email-routing/) 3. 本地安装 wrangler 以部署 cf worker。注意 node 版本。 sudo npm install wrangler@latest -g 在开始之前，请确保按照此处的说明设置 Wrangler。 here\n4. 生成私钥 Generate the Private Key openssl genrsa 2048 | tee priv_key.pem | openssl rsa -outform der | openssl base64 -A | wrangler secret put DKIM_PRIVATE_KEY 此命令的各个部分： - openssl genrsa 2048 生成 2048 位 RSA 密钥 - tee priv_key.pem 将密钥写入 priv_key.pem 文件 - openssl rsa -outform der | openssl base 64 -A 将密钥从 PEM 格式转换为 DER 格式，然后对其进行 base64 编码（这实质上是从 PEM 格式的密钥中删除标头） - wrangler secret put DKIM_PRIVATE_KEY 将它作为秘密添加到我们的 Cloudflare Worker 中\n5. CloudFalare DNS 管理页面，创建 4 个 DNS TXT 记录 创建第一个 TXT 解析记录 运行以下命令，这将从私钥 priv_key.pem 创建一个公钥，编码为 base64，最后将其写入 record.txt 文件。 echo -n \"v=DKIM1;p=\" \u003e record.txt \u0026\u0026 openssl rsa -in priv_key.pem -pubout -outform der | openssl base64 -A \u003e\u003e record.txt 复制 record.txt 文件的内容，并将其作为 TXT 记录添加到您的域中。 - Name: mailchannels._domainkey 创建第二个 TXT 解析记录 Name: yourdomain.com Value: v=spf1 a mx include:relay.mailchannels.net ~all - 创建第三个 TXT 解析记录，设置cfid，否则会报无权限调用。 参考：Secure your domain name against spoofing with Domain Lockdown™ Name: _mailchannels.yourdomain.com Value: v=mc1 cfid=yourdomain.workers.dev \u003e cfid 会在你测试的报错信息中看到，注意不是workder全url，而是子域名。解析后等待生效大约需要半天 \u003e - 创建第四个 TXT 解析记录，DMARC 记录来强制使用DKIM签名 参考：Adding a DKIM Signature Name: _dmarc.yourdomain.com Value: v=DMARC1; p=reject; adkim=s; aspf=s; rua=mailto:YYY; ruf=mailto:YYY pct=100; fo=1; 6. 验证DKIM解析，有可能需要等待几个小时，DNS 记录才会更新。 https://dmarcly.com/tools/dkim-record-checker 正常显示如下： 7. 代码解压，wrangler 部署到 cf worker cloudflare-send-email-service.zip\nwrangler deploy --name mail 8. 验证，邮件发送成功，返回状态码 202 curl --location 'https://mail.yourdomain.workers.dev' \\ --header 'Content-Type: application/x-www-form-urlencoded' \\ --data-urlencode 'sender_email=admin@yourdomain.com' \\ --data-urlencode 'sender_name=xxx' \\ --data-urlencode 'recipient_email=xxx@gmail.com' \\ --data-urlencode 'subject=测试' \\ --data-urlencode 'message=111' \\ --data-urlencode 'recipient_name=user'","date":"2024年7月5日","description":"独立开发者必看，cloudflare worker 其实也能发邮件，而且是比较优雅地发邮件  https://web.okjike.com/originalPost/65203d2205145f31e56e0707 什么是 DKIM ？https://www.cloudflare.com/zh-cn/learning/dns/dns-records/dns-dkim-record/  参考1","permalink":"http://blog.880508.xyz/2024/07/05/Cloudflare%20+%20MailChannels%20%E4%BD%BF%E7%94%A8%20DKIM%20%E5%8F%91%E9%80%81%E7%94%B5%E5%AD%90%E9%82%AE%E4%BB%B6/","title":"Cloudflare + MailChannels 使用 DKIM 发送电子邮件","type":"posts"},{"badge":"","content":"Snapdrop + Clipboard + ChatGPT = boardrop.app 隔空剪贴板\nSnapDrop 局域网内点对点传输 Snapdrop: local file sharing in your browser. Inspired by Apple’s Airdrop.\nhttps://github.com/RobinLinus/snapdrop\n同一网络内设备自动发现 设备间文件点对点传输 Peer2Peer Clipboard 在线剪切板 支持剪切板空间 /${board_name} 公开读写，寄存简单方便 剪贴板复制内容直接粘贴，支持文字、图片、各种文件。 限制粘贴内容最大20MB，每个剪切板空间暂存最新20条记录。 暂存6小时 ChatGPT 提供强大的技术支持 前端支持 HTML, CSS, Javascript 后端支持 Golang, Gin, Redis, Websocket 开发过程与当前进展 2024/07/05","date":"2024年7月5日","description":"Snapdrop + Clipboard + ChatGPT = boardrop.app 隔空剪贴板  SnapDrop 局域网内点对点传输Snapdrop: local file sharing in your browser. Inspired by Apple’s Airdrop. https://github.com/RobinLinus/snapdrop  同一网络内设备自","permalink":"http://blog.880508.xyz/2024/07/05/airclipbd-0705/","title":"boardrop.app 隔空剪贴板","type":"posts"}]