简介 本文记录了我在NAS上搭建家庭影音中心使用的各种服务和工具,以及它们之间的依赖关系,方便有需要的朋友参考。本系统不仅可以在家庭局域网内使用,还通过ZeroTier虚拟局域网和Cloudflare Tunnel实现了远程访问功能。 服务 以下是我在docker上部署的服务和群晖套件: 服务名称 类型 依赖关系 GitHub链接 iCloudphotos 群晖套件 - boredazfcuk/icloudphotos qBittorrent 群晖套件 - linuxserver/qbittorrent Alist 群晖套件 - alist-org/alist ANI-RSS 群晖套件 qBittorrent Sonarr/Sonarr Bazarr 群晖套件 Sonarr, Radarr morpheus65535/bazarr Prowlarr 群晖套件 Sonarr, Radarr Prowlarr/Prowlarr Radarr 群晖套件 qBittorrent, Prowlarr Radarr/Radarr Sonarr 群晖套件 qBittorrent, Prowlarr Sonarr/Sonarr Jellyseerr docker Emby Fallenbagel/jellyseerr MinIO docker - minio/minio Emby docker - emby/embyserver Sub-Store docker - sub-store-org/Sub-Store Homer docker - bastienwirtz/homer Nginx Proxy Manager docker - NginxProxyManager/nginx-proxy-manager MongoDB docker - mongodb/mongo ZeroTier 群晖套件 - zerotier/ZeroTierOne Cloudflare Tunnel 群晖套件 - cloudflare/cloudflared 服务功能说明 iCloudphotos: 从iCloud自动下载照片到NAS存储 qBittorrent: BT下载客户端,用于下载影视资源 Alist: 文件列表程序,支持多种存储,提供统一的访问接口 ANI-RSS: 动画RSS订阅服务 Bazarr: 字幕管理工具,自动下载匹配的字幕 Prowlarr: 索引器管理工具,为Sonarr和Radarr提供资源搜索 Radarr: 电影自动化下载管理工具 Sonarr: 电视剧自动化下载管理工具 Jellyseerr: 媒体请求系统,用户可以请求下载新的影视内容 MinIO: 对象存储服务,用于存储各种数据 Emby: 媒体服务器,用于管理和播放媒体内容 Sub-Store: 订阅管理工具 Homer: 个人仪表盘,集中展示和访问各种服务 Nginx Proxy Manager: 反向代理管理工具,用于管理各种服务的访问 MongoDB: 数据库服务,为其他服务提供数据存储支持 ZeroTier: 虚拟局域网服务,实现远程设备如同局域网内一样访问NAS Cloudflare Tunnel: 安全隧道服务,将内部服务如MinIO等安全地暴露到公网,无需公网IP和端口转发 对外服务 ZeroTier: 虚拟局域网服务,实现远程设备如同局域网内一样访问NAS Cloudflare Tunnel: 安全隧道服务,将内部服务如MinIO等安全地暴露到公网,无需公网IP和端口转发 网络架构 内网访问 家庭局域网内的设备可以直接通过内网IP访问NAS上的各项服务,通过Nginx Proxy Manager进行反向代理和域名解析。 ...
通过Yjs私有化部署一个支持协同和存储Excalidraw白板的思路
大家好呀,今天简单聊聊如何通过Yjs私有化部署一个支持协同和存储Excalidraw白板的思路 公司的需求,其实业务上还是蛮需要一个私有化的白板系统,miro买不起,drawio被嫌弃太丑,倒是excalidraw入了法眼,但是又不肯出什么钱,就给了两天时间研究一下 本身看到了大佬的文章 链接 再考虑是否可以跟着部署三个服务 但是试用了下来因为本身需要基于一个魔改版的excalidraw,本身和现在官方版本已经隔了很久了,样式上肯定是不符合需求 本身都已经开始考虑放弃这块方案,看看官方的discuss里通过clone一份修改对应环境变量了来通过elcalidraw-room来进行协同了,后端方案豆打算临时不管了 但是在浏览官方api文档的时候,倒是发现可以手动设置协同状态以及手动设置screen上的显示数据 那么如果我用官方的版本,配合上动态修改数据,也可以进行协同啊 本身项目组里的几个项目都是通过yjs进行协同的,那么就动手去github上搜了一下 好巧不巧的是,正好有人开源了 y-excalidraw 这个项目 简单起了一个demo之后,发现确实意外的好用,协同能力也有,唯一的缺憾就是,因为 y-excalidraw 是将资源也写进了yjs内,那么谁也不想如果有人传了点图之后,yjs的数据大小直接爆炸吧 然后考虑到协同目前还是采用websocket比较方便,如果要处理后续的 拓展/重连等场景的话 socketio 又是最好的 底层改为next.js手动添加文件上传下载和协同的api 协同改为本地用yjs-indexeddb做离线编辑,y-socketio做协同处理 将存储画板数据全权代理给了,y-socketio服务器,让这边进行持久化 这样做好处不少 可以使用最新的官方excalidraw,保证不会脱节 通过yjs实现的crdt协同,能够有效的实现离线编辑,多人协作 通过socketio实现的websocket服务,能够自动处理重连等场景,未来也方便通过redis等方案去对协同进行扩容 通过nextjs进行整合,一个服务能解决80%的问题(redis/mongo/minio-server之类的没办法) graph TD subgraph NextApp["Next.js 应用"] Server["自定义服务器"] API["Next.js API路由"] Excalidraw["Excalidraw组件"] MinioClient["MinIO客户端"] YExcalidraw["y-excalidraw"] end subgraph Cloud["云服务"] SocketIO["Socket.IO服务器"] YSocketIO["y-socketio提供者"] Auth["认证层"] end subgraph MongoDB YMongoDB["y-mongodb"] end subgraph MinIO["MinIO存储"] Resources["资源文件"] end Server -->|托管| SocketIO SocketIO -->|实现| YSocketIO YSocketIO -->|提供| Auth YSocketIO -->|通过持久化数据| YMongoDB YMongoDB -->|存储在| MongoDB Excalidraw -->|使用| YExcalidraw YExcalidraw -->|连接到| SocketIO API -->|包含| MinioClient MinioClient -->|存储资源在| MinIO Resources -->|存储在| MinIO 本身我也封装了一个仓库欢迎试用 excalidraw-yjs-starter ...
基于YJS和Excalidraw的本地部署的思路
大家好呀,今天简单聊聊如何通过Yjs私有化部署一个支持协同和存储Excalidraw白板的思路 公司的需求,其实业务上还是蛮需要一个私有化的白板系统,miro买不起,drawio被嫌弃太丑,倒是excalidraw入了法眼,但是又不肯出什么钱,就给了两天时间研究一下 本身看到了大佬的文章 链接 再考虑是否可以跟着部署三个服务 但是试用了下来因为本身需要基于一个魔改版的excalidraw,本身和现在官方版本已经隔了很久了,样式上肯定是不符合需求 本身都已经开始考虑放弃这块方案,看看官方的discuss里通过clone一份修改对应环境变量了来通过elcalidraw-room来进行协同了,后端方案豆打算临时不管了 但是在浏览官方api文档的时候,倒是发现可以手动设置协同状态以及手动设置screen上的显示数据 那么如果我用官方的版本,配合上动态修改数据,也可以进行协同啊 本身项目组里的几个项目都是通过yjs进行协同的,那么就动手去github上搜了一下 好巧不巧的是,正好有人开源了 y-excalidraw 这个项目 简单起了一个demo之后,发现确实意外的好用,协同能力也有,唯一的缺憾就是,因为 y-excalidraw 是将资源也写进了yjs内,那么谁也不想如果有人传了点图之后,yjs的数据大小直接爆炸吧 然后考虑到协同目前还是采用websocket比较方便,如果要处理后续的 拓展/重连等场景的话 socketio 又是最好的 底层改为next.js手动添加文件上传下载和协同的api 协同改为本地用yjs-indexeddb做离线编辑,y-socketio做协同处理 将存储画板数据全权代理给了,y-socketio服务器,让这边进行持久化 这样做好处不少 可以使用最新的官方excalidraw,保证不会脱节 通过yjs实现的crdt协同,能够有效的实现离线编辑,多人协作 通过socketio实现的websocket服务,能够自动处理重连等场景,未来也方便通过redis等方案去对协同进行扩容 通过nextjs进行整合,一个服务能解决80%的问题(redis/mongo/minio-server之类的没办法) graph TD subgraph NextApp["Next.js 应用"] Server["自定义服务器"] API["Next.js API路由"] Excalidraw["Excalidraw组件"] MinioClient["MinIO客户端"] YExcalidraw["y-excalidraw"] end subgraph Cloud["云服务"] SocketIO["Socket.IO服务器"] YSocketIO["y-socketio提供者"] Auth["认证层"] end subgraph MongoDB YMongoDB["y-mongodb"] end subgraph MinIO["MinIO存储"] Resources["资源文件"] end Server -->|托管| SocketIO SocketIO -->|实现| YSocketIO YSocketIO -->|提供| Auth YSocketIO -->|通过持久化数据| YMongoDB YMongoDB -->|存储在| MongoDB Excalidraw -->|使用| YExcalidraw YExcalidraw -->|连接到| SocketIO API -->|包含| MinioClient MinioClient -->|存储资源在| MinIO Resources -->|存储在| MinIO 本身我也封装了一个仓库欢迎试用 excalidraw-yjs-starter ...
搭建我的开发环境
通过react native开发vision os应用 因为我是一个前端,所以一开始决定还是使用一个自己比较熟悉的平台进行第一次开发 那么最优解当然还是react native了 好在react-native目前有一个startkits是支持visionos的 https://github.com/callstack/react-native-visionos 练手项目打算做一个简单的翻译工具 初始化 npx @callstack/react-native-visionos@latest init YourApp https://callstack.github.io/react-native-visionos-docs/
电视直播工具推荐
https://github.com/andandroidor/ourtv
HomeAssistant安装指南
HomeAssistant安装指南 安装hacs https://github.com/hacs-china 之后在页面安装hacs https://github.com/XiaoMi/ha_xiaomi_home/blob/main/doc/README_zh.md 根据小米的ai自动接入
SS规则配置
# 官方配置模板:https://github.com/Dreamacro/clash/wiki/Configuration # Meta配置模板:https://github.com/MetaCubeX/Clash.Meta/blob/Alpha/docs/config.yaml # 接管:部分参数不支持在此页面直接修改,请到全局设置页面进行修改 # Port of HTTP(S) proxy server on the local end port: 7890 # Port of SOCKS5 proxy server on the local end socks-port: 7891 # Transparent proxy server port for Linux and macOS (Redirect TCP and TProxy UDP) redir-port: 7892 # Transparent proxy server port for Linux (TProxy TCP and TProxy UDP) tproxy-port: 7893 # HTTP(S) and SOCKS4(A)/SOCKS5 server on the same port mixed-port: 7893 allow-lan: true bind-address: '*' mode: rule # RESTful web API listening address external-controller: 127.0.0.1:9090 proxy-providers: provider1: type: http url: "http://192.168.3.99:6080/download/batvpn?target=ClashMeta&d_token=" interval: 3600 path: ./nas.yaml health-check: enable: true interval: 600 # lazy: true url: http://www.gstatic.com/generate_204 proxy-groups: - {name: 手动选择, type: select , include-all-providers: true} - {name: PROXY, type: url-test, include-all-providers: true, interval: 300, lazy: true} rule-providers: reject: type: http behavior: domain url: "https://cdn.jsdelivr.net/gh/ACL4SSR/ACL4SSR@master/Clash/reject.txt" path: ./ruleset/reject.yaml interval: 86400 google-cn-proxy-ip: type: http behavior: classical format: text path: ./rules/GoogleCNProxyIP.list url: "https://cdn.jsdelivr.net/gh/ACL4SSR/ACL4SSR@master/Clash/GoogleCNProxyIP.list" interval: 86400 local-area-network: type: http behavior: classical format: text path: ./rules/LocalAreaNetwork.list url: "https://cdn.jsdelivr.net/gh/ACL4SSR/ACL4SSR@master/Clash/LocalAreaNetwork.list" interval: 86400 unban: type: http behavior: classical format: text path: ./rules/UnBan.list url: "https://cdn.jsdelivr.net/gh/ACL4SSR/ACL4SSR@master/Clash/UnBan.list" interval: 86400 china-domain: type: http behavior: classical format: text path: ./rules/ChinaDomain.list url: "https://cdn.jsdelivr.net/gh/ACL4SSR/ACL4SSR@master/Clash/ChinaDomain.list" interval: 86400 china-media: type: http behavior: classical format: text path: ./rules/ChinaMedia.list url: "https://cdn.jsdelivr.net/gh/ACL4SSR/ACL4SSR@master/Clash/ChinaMedia.list" interval: 86400 china-company-ip: type: http behavior: classical format: text path: ./rules/ChinaCompanyIp.list url: "https://cdn.jsdelivr.net/gh/ACL4SSR/ACL4SSR@master/Clash/ChinaCompanyIp.list" interval: 86400 china-ip: type: http behavior: classical format: text path: ./rules/ChinaIp.list url: "https://cdn.jsdelivr.net/gh/ACL4SSR/ACL4SSR@master/Clash/ChinaIp.list" interval: 86400 rules: - DOMAIN,clash.razord.top,DIRECT - DOMAIN,yacd.haishan.me,DIRECT - RULE-SET,google-cn-proxy-ip,PROXY - RULE-SET,local-area-network,DIRECT - RULE-SET,unban,DIRECT - RULE-SET,china-domain,DIRECT - RULE-SET,china-media,DIRECT - RULE-SET,china-company-ip,DIRECT - RULE-SET,china-ip,DIRECT - GEOIP,CN,DIRECT,no-resolve - MATCH,PROXY
我的第一台 3d 打印机
我的打印机 我的打印机买的是拓竹的 x1cc,其实也是一时心血来潮买下来的,9499 还是很贵的。。。 主要还是因为我作为一个 coser,实际上啥也不会啦,还是学学 3d 建模给之后自己打印大局积累一点点的相关经验吧 材料的区别 在这里我记录一下拓竹支持的材料 虽然不比光固化打印,拓竹是打印塑料件的,打印需要拆分零件 使用的材料目前我接触下来有 pla PLA 不是塑料,PLA又称为聚乳酸,是由植物淀粉所制造成的塑料,不同于传统塑胶,他的来源是可再生资源如玉米淀粉,也造就了其可被生物利用分解的特性。 大部分的传统塑胶来自不可再生的石油和天然气的蒸馏聚合。 而源自生物质(例如PLA)的塑料被称为“ 生物塑料”。 这个是送的材料,质感还行 1、不耐久 2、在大约140°F (60°C)时变软(可能弯曲或扭曲) 3、不耐UV光 petg 这个我还没接触过 看说明是 3D打印PETG材料属于干净透明的热塑性无定型塑料,是非结晶型共聚酯,它不仅仅具有PLA材料的光泽度,还具有ABS材料的强度,而且在打印的时候非常顺畅,不会堵住喷头,要比ABS材料更容易打印,打印出来的模型呈半透明,表面光滑,不容易破裂,是3D打印耗材中重要的打印材料。 耗材消耗 第一次打印没有太关注这个 耗材数量只能通过计算了 购买的话,可以通过拓竹的官网进行购买,戴 rfid 芯片比较方便 如果想买平价的话,我看推荐的是三绿家的耗材 获取模型的网站 url: https://makerworld.com/zh title: "MakerWorld" description: "社区驱动的通往 3D 模型世界门户" host: makerworld.com favicon: https://makerworld.com/favicon_new.png 这个是拓竹官方的一个网站,很多会在这个网站上进行开源 剩下的就是找 b 站大佬了 比如有个星穹铁道的垃圾桶就能够找 url: https://www.bilibili.com/video/BV1SD421J7uh/?spm_id_from=333.999.0.0 title: "【开源】王下一桶可动3D打印模型_哔哩哔哩_bilibili" description: "王下一桶的可动3D打印模型,我有这个想法后很快就在空闲时间做好了,之后对细节进行了优化,选择开源发布。up随缘更新,二创类的基本都会免费开源,第一次设计可动人偶,水平不咋滴,支持的话还请多多三连。原始模型来源:Mihoyo改模:bilibili@粮亦丰模型下载链接:https://pan.baidu.com/s/1X8wxy8BRSHQDdjb0U-fK7w?pwd=1919 提取码:1919Ma, 视频播放量 8007、弹幕量 40、点赞数 454、投硬币枚数 194、收藏人数 445、转发人数 107, 视频作者 粮亦丰, 作者简介 ,相关视频:VLOG 3D打印原神宝箱收纳盒,【开源】钟表小子可动3D打印模型,【模型分享】可以量产的猫猫糕,自制反光流麻‖ 流萤/萨姆:我将,点燃大海!!,10000块零件,UP自主设计,《崩坏:星穹铁道》——星穹列车,抽卡歪了!那就自己3D打印一个黄泉,【星穹铁道】做一套可爆甲的萨姆!!!,关于我在学校3D打印手办这件事,机械狗社区最受欢迎的5款3D打印图纸,猫猫糕量产啦!是谁要的芝麻酥!" host: www.bilibili.com image: https://i2.hdslb.com/bfs/archive/ede5a7b7272e94710b16e40414fe2deb4323b9b8.jpg@100w_100h_1c.png 材料区分 实际上我不是很懂什么弹簧/螺丝的区别,这个型号只能之后获取了 ...
通过 node 上传大文件
通过 node 上传大文件 背景 因为工作上的原因,开发了一个客户端文件,用来做数据迁移 实际上的流程很简单,下载,清洗,再调用接口导入到另一个网站上 出现问题 本地的上传其实是通过 const formData = new FormData(); formData.append('file', blob); axios.post(xxx, formdata) 通过在 nodejs 里边写 formdata 并且通过 axios 进行上传的 遇到的第一个问题是 Buffer问题,因为 formdata 需要使用 blob 作为 file 字段进行上传的 最开始的时候我们的 blob 是通过 fs.readFileSync()生成的 但是在 node 环境下,我们的 node 实际上对 buffer 是有大小限制的 所以我一开始采用的方案是通过流式获取所有的 buffer 之后一起生成一个 blob const blob = await new Promise((resolve, reject) => { const stream = fs.createReadStream(); const blobData = []; stream.on('data', chunk => blobData.push(chunk)) stream.on('end', () => resolve(new Blob(blobData))) }) 这样一开始解决了读取 buffer 过大的问题 实际问题解决 实际问题还是上传下载的时候,如果读取为 blob的话,也是需要占用一段内存的 这也就造成了在传输 2g 以上大文件的时候出现了闪退 这个时候其实应该会有好几种解决方案 通过分片进行上传,实际上因为后端采用 minio 这个也是天然支持的,但是经过询问之后,发现上传 minio 其实也是后端额外封装了一层接口实现的,但是后端没有实现分片合并的逻辑,所以通过分片的方案就不行了 流式上传,这样可以减少内存的占用 所以上传的时候其实是需要将整个上传流程的 form 也转换成一个 stream ...
opencv 编译
为啥要编译opencv 因为 opencv 是频域水印需要的一个功能 但是本体这个包实在是太大了 所以打算编译一个最多 2m 的包出来 编译参考 url: https://docs.opencv.org/4.x/d4/da1/tutorial_js_setup.html title: "OpenCV: Build OpenCV.js" host: docs.opencv.org 环境搭建 首先还得是安装 emsdk 通过万能的 homebrew 进行安装 brew install emscripten url: https://www.cnblogs.com/Wayou/p/webassembly_quick_start.html title: "WebAssembly 上手 - 刘哇勇 - 博客园" description: "安装 Mac 上最便捷的安装方式当然是通过 Homebrew: $ brew install emscripten 安装好之后讲道理就已经自动配置好一切,然后 emcc 命令便可用了。 下面看非 Homebrew 安装的方式。 通过官方 WebAssembly Developer’s Guide 提" host: www.cnblogs.com 构建基础版的 opencv 跟着教程 首先得复制一份到本地 git clone git clone https://github.com/opencv/opencv.git cd opencv emcmake python ./opencv/platforms/js/build_js.py build_wasm --build_wasm