跳转到内容

ChronoFrame - 一款优雅的瀑布流相册系统

更新于: 2026-04-05
LiuShen
10 分钟
3,850 字
PV --
UV --

这里是清羽AI,这篇文章由清羽飞扬介绍了一款名为ChronoFrame的开源瀑布流相册系统。该项目灵感源自Afilmory,但与之不同的是,ChronoFrame是一个可在线管理的动态照片系统,支持自动解析EXIF信息、展示拍摄位置、地图足迹回溯以及自动生成缩略图等功能,相比静态相册更具交互性。作者柳神对比了TimePlus、PicImpact等竞品,认为ChronoFrame在长期使用体验和视觉呈现上更符合个人需求。文章还提供了Docker部署方案和存储配置建议,六神分享了自己使用天翼云盘结合OpenList和CDN的免存储桶方案以降低成本。全文详细阐述了从静态主题到动态系统的相册搭建历程,为读者提供了完整的项目评估和部署参考。

碎碎念

一个月没有更新文章啦,不过放心,煮啵不是似了,煮啵只是染上了Arch瘾在捣鼓新系统呢!虽然过程不是很顺利,结果也不是很顺利,但是起码也是玩过的人了,本来打算玩明白了写一个对应的教程,但是玩明白之后,自己先逃离了,倒不是说没配置好,主要是很多软件都没有,维护也不太行,比如腾讯视频,网易邮箱大师……诸如此类的应用还有很多,Arch确实很漂亮,也很符合我的开发习惯,但是,还有很大的进步空间哦~

(等煮啵研究一下能不能刷个MacOS,这个总不缺生态了吧,哼哼)

新系统

这一个月,虽然一直在研究新系统,但也不是一点没碰网站,由于嫖上了群友的ChatGPT组织,反倒写代码更多了,比如前面的兰空图床美化,还有煮啵自己的临时邮箱,再就是新相册,相册是我最喜欢的网站之一,他承载了我之前的记忆,之前的相册由于玩崩了,所以干脆没迁移,从头开始新整了一个相册,尽可能将之前的一些照片搬了上来,全新的系统有了更大的维护需求,原来的Typecho只需要填写直链即可,现在的相册主要手动上传原图,他会自动生成缩略图,虽然说更加的系统化,但是对于存储的要求也更高啦,最后煮啵找到了一个更好的方案,基本摆脱了未来的存储焦虑!

介绍

首先放上项目地址,项目的配置较多,如果看到这里溜了的小伙伴要自己看好哦!

站外引用 · 引用站外地址,不保证站点的可用性和安全性ChronoFrame: 丝滑的照片展示和管理应用github.com@HoshinoSuzumi

原作者说,这个项目的灵感来自一个同样很优秀的开源项目 —— Afilmory

Afilmory更偏向于“静态相册”的思路:通过预处理照片生成清单文件,然后以静态站点的形式进行展示。这种方式部署简单、成本低,非常适合纯展示类需求。

ChronoFrame在此基础上走向了另一个方向:它不是一个“生成好的相册”,而是一个真正可以在线管理的动态照片系统

相比传统相册项目,ChronoFrame不仅可以上传、整理和浏览照片,还能自动解析EXIF、展示拍摄位置、在地图上回溯足迹,虽然说我目前对这个功能不太满意,由于它支持自动生成缩略图,所以在大尺寸图片下依然保持非常丝滑的浏览体验。

下面是俺自己的地址:

本站链接 · 来自本站,本站可确保其安全性,请放心点击跳转清羽飞扬の时光相册LiuShen's Blog

如果你只是想做一个静态展示站,Afilmory可能已经足够,但如果你希望拥有一个可以长期使用、持续管理、并且体验优秀的个人相册系统,那 ChronoFrame会是一个更值得尝试的选择。

竞品

竞品?实则是项目介绍!

在刚开始建立相册的时候,我找了很多相册程序,那时候的相关程序远没有现在这么丰富,所以我甚至研究了博客程序的相册主题,比如洪哥的TimePlus,地址如下:

站外引用 · 引用站外地址,不保证站点的可用性和安全性TimePlus: 洪墨时光。由Heo维护的Time主题版本,基于Typechogithub.com@zhheo

对于之前的我来说,这款主题十分合适,只需要填写图片直链和对应信息即可完美的实现展示的功能,虽然说精度不是很高,但是对于只想展示照片的我已经是够够的啦,配合piclist和自建的兰空图床,可以做到存储的极致轻量化。

后面,随着Typecho的更新和主题的更新,作为强迫症的我,势必要用上最新的系统,但是我又懒得去配置一些环境,并且由于PHP众所周知的特性,安全性也较差,再加上对接的数据库,内存占用也比较严重,已经工作了的我可没这么多闲时间耗,我直接一个雷霆大踹给项目踢飞了,找了一些同类型的竞品项目,如下:

站外引用 · 引用站外地址,不保证站点的可用性和安全性CloudImgs - 极简风格的云图库,支持NAS部署github.com@qazzxxx

这个项目并不算是一个真正意义上的的开放性展示相册,而像是一个个人备份相册,后台需要密码才能进入,虽然说可以分享相册对外展示,但是路径仍然不是根目录,如果没有途径获取到你的分享链接,也无法查看。是一个优秀的项目,但不是我想要的效果。

展示

下面我比较关注的项目就是PicImpact啦,这个是一个彻底的相册站,由NextJS开发,支持S3R2OpenList等多种存储方式,上传图像时会自动抓取EXIF进行信息获取,比如拍照位置,拍照设备,图像大小,并按照美观的展示方式进行展示。

站外引用 · 引用站外地址,不保证站点的可用性和安全性PicImpact - 自部署的摄影作品网站,支持多种功能特性。github.com@besscroft

从一个相册的角度来看,这个程序已经具有基本上所有的功能,但是不知道为什么,我看issue中的演示站,总感觉卡卡的,并且按照我个人的审美而言,我更喜欢瀑布流展示,PicImpact虽然也有瀑布流,但是只能在时光相册页面看到,整体页面很清爽,但是个人不太喜欢(纯主观),如下:

展示页面

下面就是Afilmory了,其实刚发现他的时候,我并不知道他只能通过获取列表展示,我还以为是后台上传显示,但是由于那时候还是学生的我没法负担起较高价格的存储,虽然说免费的少量存储很多,但是对于我来说,更在乎服务的持续性,我不想使用那种一眼看到头的服务,所以就一直搁置。

虽然我到最后也没使用过,但是这并不影响他是一个很优秀的相册程序,项目地址如下:

站外引用 · 引用站外地址,不保证站点的可用性和安全性Afilmory - Modern photo gallery for photographersgithub.com@Afilmory

注意,这个程序官方并没有提供Docker镜像,所以可能需要自己打包一个哦,当然官方也带托管,感兴趣可以去体验一下!

Afilmory

由于没有给docker镜像,所以我也不太清楚后台功能有多少,需要大家自行探索咯。

除了这个,我还发现了一个相册站,与其说是相册站,不如说是壁纸站,并且自带图源,可以直接搭建一个免维护,带登录功能的图片采集站,不仅可以自己上传图片,也可以实现自动聚合各类壁纸,比如每日一图Bing等等,项目如下:

站外引用 · 引用站外地址,不保证站点的可用性和安全性wallpaper-gallerygithub.com@IT-NuanxinPro

如果你想做一个偏商业化的壁纸站,或者用于展示自己的摄影作品作为壁纸,那么这个项目应该是很适合你!图片如下:

Wallpaper-Gallery

部署

OK聊了一大堆有的没的,现在进入正题,针对于ChronoFrame,为了更加方便,我将其适配到了我个人的应用商店,欢迎使用,当然也带上了正常的部署方式啦,按需选择!

Docker

首先就是我们最常见的Docker咯,其实项目是给了教程的,但是他喵的配置也忒多了,如下:

横向滚动
环境变量说明默认值必需
CFRAME_ADMIN_EMAIL初始管理员用户的邮箱admin@chronoframe.com
CFRAME_ADMIN_NAME初始管理员用户的用户名Chronoframe
CFRAME_ADMIN_PASSWORD初始管理员用户的密码CF1234@!
NUXT_PUBLIC_APP_TITLE应用标题ChronoFrame
NUXT_PUBLIC_APP_SLOGAN应用口号
NUXT_PUBLIC_APP_AUTHOR应用作者
NUXT_PUBLIC_APP_AVATAR_URL应用头像 URL
NUXT_PUBLIC_COLOR_MODE_PREFERENCE颜色模式偏好,可选 lightdarksystemsystem
NUXT_PUBLIC_MAP_PROVIDER地图提供者,可选 mapboxmaplibremaplibre
NUXT_PUBLIC_MAPBOX_ACCESS_TOKENMapbox 访问令牌(可限制 URL),用于地图服务NUXT_PUBLIC_MAP_PROVIDERmapbox 时必需
NUXT_NOMINATIM_BASE_URLNominatim 反向地理编码服务的基础 URLhttps://nominatim.openstreetmap.org
NUXT_MAPBOX_ACCESS_TOKENMapbox 访问令牌(无 URL 限制),用于位置信息服务
NUXT_STORAGE_PROVIDER存储提供者,支持 locals3openlistlocal
NUXT_PROVIDER_LOCAL_PATH本地存储路径/app/data/storage
NUXT_PROVIDER_LOCAL_BASE_URL本地存储的访问 URL/storage
NUXT_PROVIDER_S3_ENDPOINTS3 兼容存储服务的 EndpointNUXT_STORAGE_PROVIDERs3 时必需
NUXT_PROVIDER_S3_BUCKETS3 存储桶名称chronoframeNUXT_STORAGE_PROVIDERs3 时必需
NUXT_PROVIDER_S3_REGIONS3 存储桶区域autoNUXT_STORAGE_PROVIDERs3 时必需
NUXT_PROVIDER_S3_ACCESS_KEY_IDS3 访问密钥 IDNUXT_STORAGE_PROVIDERs3 时必需
NUXT_PROVIDER_S3_SECRET_ACCESS_KEYS3 访问密钥NUXT_STORAGE_PROVIDERs3 时必需
NUXT_PROVIDER_S3_PREFIXS3 存储前缀photos/
NUXT_PROVIDER_S3_CDN_URLS3 存储的 CDN 地址
NUXT_PROVIDER_OPENLIST_BASE_URLOpenList 服务器 URLNUXT_STORAGE_PROVIDERopenlist 时必需
NUXT_PROVIDER_OPENLIST_ROOT_PATHOpenList 根路径NUXT_STORAGE_PROVIDERopenlist 时必需
NUXT_PROVIDER_OPENLIST_TOKENOpenList API 令牌NUXT_STORAGE_PROVIDERopenlist 时必需(用于 OpenList 认证)
NUXT_PROVIDER_OPENLIST_ENDPOINT_UPLOADOpenList 上传端点/api/fs/put
NUXT_PROVIDER_OPENLIST_ENDPOINT_DOWNLOADOpenList 下载端点
NUXT_PROVIDER_OPENLIST_ENDPOINT_LISTOpenList 列表端点
NUXT_PROVIDER_OPENLIST_ENDPOINT_DELETEOpenList 删除端点/api/fs/remove
NUXT_PROVIDER_OPENLIST_ENDPOINT_METAOpenList 元数据端点/api/fs/get
NUXT_PROVIDER_OPENLIST_PATH_FIELDOpenList 路径字段名path
NUXT_PROVIDER_OPENLIST_CDN_URLOpenList CDN 地址
NUXT_PUBLIC_OAUTH_GITHUB_ENABLED是否启用 GitHub OAuth 登录false
NUXT_OAUTH_GITHUB_CLIENT_IDGitHub OAuth 应用的 Client ID否(可选,用于 GitHub 登录)
NUXT_OAUTH_GITHUB_CLIENT_SECRETGitHub OAuth 应用的 Client Secret否(可选,用于 GitHub 登录)
NUXT_SESSION_PASSWORD用于加密会话的密码,32 位随机字符串
NUXT_PUBLIC_GTAG_IDGoogle Analytics 追踪 ID
NUXT_PUBLIC_ANALYTICS_MATOMO_ENABLED是否启用 Matomo 分析追踪false
NUXT_PUBLIC_ANALYTICS_MATOMO_URLMatomo 实例 URL 地址(如: https://matomo.example.com)否(启用 Matomo 时必需)
NUXT_PUBLIC_ANALYTICS_MATOMO_SITE_IDMatomo 站点 ID否(启用 Matomo 时必需)
NUXT_UPLOAD_MIME_WHITELIST_ENABLED是否启用上传文件 MIME 类型白名单验证true
NUXT_UPLOAD_MIME_WHITELIST上传文件允许的 MIME 类型列表(逗号分隔)见下方说明
NUXT_UPLOAD_DUPLICATE_CHECK_ENABLED是否启用重复文件检测true
NUXT_UPLOAD_DUPLICATE_CHECK_MODE重复文件处理模式,可选 warnblockskipskip
ALLOW_INSECURE_COOKIE是否允许非安全 Cookie(仅在开发环境使用)false

而且需要在Docker配置或者Docker-compose.yaml写好,无法在后台进行设置,这个是缺点,希望后面作者可以支持在后台配置存储,而不是在应用拉起后硬编码。

回到正题,上面的配置项虽然多,但是也不是所有都得填写,我整理了一份比较完善的大部分可用的启动命令,首先是纯docker:

不会还真有人直接这样启动吧

docker run -d \
  --name chronoframe \
  -p 3000:3000 \
  -v /opt/chronoframe/data:/app/data \
  -e CFRAME_ADMIN_NAME=admin \
  -e CFRAME_ADMIN_EMAIL=admin@example.com \
  -e CFRAME_ADMIN_PASSWORD=StrongPassword123 \
  -e NUXT_SESSION_PASSWORD=$(openssl rand -base64 32) \
  -e NUXT_STORAGE_PROVIDER=local \
  -e NUXT_PROVIDER_LOCAL_PATH=/app/data/storage \
  -e NUXT_PROVIDER_LOCAL_BASE_URL=/storage \
  -e NUXT_UPLOAD_MIME_WHITELIST_ENABLED=false \
  --restart=always \
  ghcr.io/hoshinosuzumi/chronoframe:0.14.1

这里为本地存储,如果你打算将图片存到服务器本地,可以直接启动,修改账号密码和邮箱即可。

如果打算使用S3存储,可以替换下面几个配置为:

-e NUXT_STORAGE_PROVIDER=s3 \
-e NUXT_PROVIDER_S3_ENDPOINT=https://s3.amazonaws.com \
-e NUXT_PROVIDER_S3_BUCKET=my-bucket \
-e NUXT_PROVIDER_S3_REGION=us-east-1 \
-e NUXT_PROVIDER_S3_ACCESS_KEY_ID=xxx \
-e NUXT_PROVIDER_S3_SECRET_ACCESS_KEY=xxx \

如果打算使用OpenList,按照文档修改一下配置就可以啦!当然这里我还是推荐使用docker-compose,配置保存到本地之后会更好看一些,并且方便修改,直接使用docker命令总有点拉屎到服务器的感觉。

如果使用docker-compose,如下配置,我将一些无用配置筛掉了,大家自行选择即可,如果不需要可以留空,compose文件如下:

version: "3.8"

services:
  chronoframe:
    container_name: chronoframe

    image: registry.liiiu.cn/ghcr.io/hoshinosuzumi/chronoframe:0.14.1

    # 端口映射:宿主机 -> 容器
    ports:
      - "3000:3000" # 可改成 127.0.0.1:3000:3000 仅本机访问

    # 数据持久化
    volumes:
      - ./data:/app/data

    # 自动重启
    restart: always

    environment:
      ########################################
      # ===== 基础管理员配置(必须) =====
      ########################################
      CFRAME_ADMIN_NAME: admin
      CFRAME_ADMIN_EMAIL: admin@example.com
      CFRAME_ADMIN_PASSWORD: admin123

      ########################################
      # ===== 站点 UI 信息(可选) =====
      ########################################
      NUXT_PUBLIC_APP_TITLE: "ChronoFrame"
      NUXT_PUBLIC_APP_SLOGAN: "My Photo Timeline"
      NUXT_PUBLIC_APP_AUTHOR: "YourName"
      NUXT_PUBLIC_APP_AVATAR_URL: ""

      ########################################
      # ===== 地图(不用可以留空) =====
      ########################################
      NUXT_PUBLIC_MAP_MAPLIBRE_TOKEN: ""

      ########################################
      # ===== 存储方式(三选一) =====
      ########################################

      ## 👉 1. 本地存储(推荐)
      NUXT_STORAGE_PROVIDER: local
      NUXT_PROVIDER_LOCAL_PATH: /app/data/storage
      NUXT_PROVIDER_LOCAL_BASE_URL: /storage

      ## 👉 2. S3(不用可以不填)
      NUXT_PROVIDER_S3_ENDPOINT: ""
      NUXT_PROVIDER_S3_BUCKET: ""
      NUXT_PROVIDER_S3_REGION: ""
      NUXT_PROVIDER_S3_ACCESS_KEY_ID: ""
      NUXT_PROVIDER_S3_SECRET_ACCESS_KEY: ""
      NUXT_PROVIDER_S3_PREFIX: ""
      NUXT_PROVIDER_S3_CDN_URL: ""

      ## 👉 3. OpenList(不用可以不填)
      NUXT_PROVIDER_OPENLIST_BASE_URL: ""
      NUXT_PROVIDER_OPENLIST_ROOT_PATH: ""
      NUXT_PROVIDER_OPENLIST_TOKEN: ""
      NUXT_PROVIDER_OPENLIST_ENDPOINT_UPLOAD: ""
      NUXT_PROVIDER_OPENLIST_ENDPOINT_DOWNLOAD: ""
      NUXT_PROVIDER_OPENLIST_ENDPOINT_LIST: ""
      NUXT_PROVIDER_OPENLIST_ENDPOINT_DELETE: ""
      NUXT_PROVIDER_OPENLIST_ENDPOINT_META: ""
      NUXT_PROVIDER_OPENLIST_PATH_FIELD: ""
      NUXT_PROVIDER_OPENLIST_CDN_URL: ""

      ########################################
      # ===== 安全相关(必须) =====
      ########################################
      NUXT_SESSION_PASSWORD: "change_to_random_32_char_secret"

      ########################################
      # ===== 上传策略 =====
      ########################################
      NUXT_UPLOAD_MIME_WHITELIST_ENABLED: "false"

以上就是docker启动的方式啦,如果你使用的是1Panel,我更推荐使用应用商店安装!

应用商店

首先按照之前已经有的教程,添加站长的应用商店:

本站链接 · 来自本站,本站可确保其安全性,请放心点击跳转不同姿势部署Anheyu-App应用LiuShen's Blog

然后搜索Chronoframe即可直接安装啦!

自行修改!别用我的配置!

这样你就可以获得一个很完美的相册!

存储

我并不想多讲别的存储,这里我只讲一下我的存储,由于刚开始实在不想单开一个存储桶,维护起来也麻烦,市面上付费的存储桶也没有太多的额度,并且存储和流量都是费用,还得操心是否被打穿,众所周知,存储桶脆的跟纸一样……

ChronoFrame提供了OpenList存储,于是派生了一系列邪修操作,当然大家要注意封号风险哈。

世界没有密不透风的墙,各大网盘商其实都能被OpenList挂载,在这之中,天翼云盘,Onedrive,夸克加会员,都能做到无损的品质,夸克的会员之所以能塞进来,主要因为很便宜啊,可以使用88VIP,不过建议不要去某鱼上买,很容易掉号,夸克会不定期叫你验证,如果到期没验证,会直接停掉会员。

煮啵这里用的是天翼云盘,默认带了30GB存储,可以通过手机端签到实现无限增长存储,一天能领大概60MB,只要电信不封锁这条线路,那我可以一直使用,当然我也套了一层CDN,缓存十年,虽然可能不太准嘻嘻,但是也能大幅度减少回源的概率,希望电信别给我干掉了。

如果有想要开相册的,大家也可以参考一下我的使用方式哦~

总结

喵了个咪的这个文章写了七天才写完,上周天就开始写,这个周又开始玩鱼缸了,每天只动一点点,导致上个月就月初一篇文章,嘻嘻献丑了。

清明时节雨纷纷,这句话在上海彻底体现出来了,天天从公司回家都能赶上暴雨,最后要么淋雨回家,要么熬到十点半打车回,也是没招了,下雨一点征兆都没有。

坏了总结写成碎碎念了,进入正题,其实我最初的想法是,给我一个填写直链的位置即可,为此我甚至找过静态主题,hugo中也有一些很好看的静态相册,但是终究维护起来较难。后面使用了洪哥的TimePlus主题,直接填写直链即可,这个相册跟随了我很长的时间,从刚建站到我的学生生涯结束。

进入工作后,对于成本的控制开始变得松散,只想给网站做好,做精,价格上从之前的肉疼到现在的无感(咳咳,虽然现在依旧是免费的),至少服务器上升级了吧!写文章也佛系了很多,倒不是说没时间写,主要是天天工作后,回来只记得玩手机了,根本不想写嘻嘻,不过一个月一篇是基本的,我尽量做到之前的频率,一个月两三篇,感觉过几个月就能做到啦!目前的工作已经逐渐变平缓,后续应该能多一些个人时间干点自己喜欢的事情!

每日一图

图片来自哲风壁纸

克莱因蓝

Previous
黔山赴夏,清风入怀
Next
兰空图床深度美化