构建 SkyMoment:使用 Python、Skyfield 和天文数据的 4K 个性化星图生成器
发布: (2025年12月7日 GMT+8 04:47)
4 min read
原文: Dev.to
Source: Dev.to
The idea
大多数在线的 “星图海报” 并不是基于真实的天空数据,它们使用近似值、虚构星座或预渲染的视觉效果。我想要更准确、更科学的方案:
- 真正的星体位置
- 正确的坐标转换
- 合适的视场角
- 看起来自然的银河系
- 简洁的极简布局
……并把它做成一个小型自动化产品:输入一个时刻 → 获得 PDF/PNG → 完成。
Tech stack overview
- Python – 主渲染管线
- Skyfield – 行星星历 & 星体计算
- Hipparcos catalog – 星体位置 & 亮度
- Astropy – 坐标转换
- Matplotlib – 最终 4K 渲染
- Django – 后端 & API
- Lemon Squeezy – 支付 + webhook
- SMTP – 邮件发送最终海报
前端故意保持极简;真正的 “魔法” 在渲染管线中完成。
Astronomical calculations step‑by‑step
当用户输入日期、时间和位置(纬度/经度)时,管线会:
- Convert local time to UTC – Skyfield 需要精确的 UTC 时间戳。
- Load planetary ephemeris – 使用 DE421 / DE422(取决于构建版本)。
- Load Hipparcos star catalog – 提供 RA/Dec、星等、自行运动。
- Transform everything into the user’s sky coordinates – 使用
Astropy的 AltAz 转换,基于观测者位置。 - Filter stars – 只渲染亮度高于某阈值的星星。
- Split bright/faint stars – 明星使用 8‑点样式标记;暗星使用普通点。
- Render the Milky Way – 自定义多噪声层(低频形状、中频云结构、平滑 alpha 衰减、抑制 “沙粒” 人工痕迹)。这一步调试时间最长。
- Render at 4000 × 4000 resolution – 只要小心使用,Matplotlib 能很好地完成。
总渲染时间: 约 35–40 秒(服务器硬件)。
Rendering performance challenges
4K 分辨率 + 成千上万颗星星 + 银河噪声层 = 计算量大。部分优化措施:
- 每个 worker 只加载一次目录
- 重用 figure 对象
- 避免昂贵的 Python 循环
- 限制透明度的使用
- 跳过低于某星等的星星
- 尽可能缓存静态层
即使是微小的改动也能节省 10–20 % 的时间。
Backend architecture (Django)
SkyMoment 使用了一个简易管线:
- User configures their moment – 选择日期/时间/地点并预览。
- User is redirected to Lemon Squeezy checkout。
- After payment, LS sends a webhook to Django – 包含订单 ID、自定义字段(标题、地点、日期时间)以及产品变体。
- Django creates a generation job – 状态流转:
pending→generating→ready。 - A worker process runs the Python renderer。
- The final 4K poster is saved to disk。
- Django sends an email with a download link。
重要细节: webhook 必须立即响应;渲染在后台异步进行,以避免 LS 超时。
Example of what the system produces
Reduced‑size preview of a generated poster (insert image URL if desired).
4K 版本包含:
- 精确的星体位置
- 星座连线
- 极简排版
- 自定义标题 & 副标题
- 干净的暗色主题
What’s next
Roadmap items:
- 多种海报模板
- 更快的渲染(缓存或部分复用)
- 更多精心策划的着陆页
- 详细的生成日志与分析
如果你想为自己的时刻生成星图:
🔗
欢迎随时提问关于天文数据、渲染或后端架构的技术细节!