Versun

对待生命,不妨大胆一点,因为我们终将失去它



DiffRhythm 模型

2025-03-06
国内的 ASLP-Lab 推出的开源音乐生成模型 DiffRhythm,只需提供歌词和音乐风格片段,就可以生成一首完整带人声的音乐,支持中英文,虽然人声还有点电音感,但整体效果相当可以了。
官网下方有Demo,我的音乐梦指日可待了!

我的英语学习之旅小结

2025-03-06
为什么要写这篇博文呢?
因为我在连续学习了66天后,学习的动力和欲望开始降低,且进步效果并不明显(毕竟只有66天,才刚刚开始)
所以我需要给自己一个交代,记录下学习的痕迹,否则真的要交代在这了。

我的学习方法其实很简单,那就是大量的英语阅读和听力,使用的软件是 LingQ,以下是我的学习进度统计:
LingQ Stats

总共阅读了 20.4 万字,其中认识的单词有 7501 个,标记了 3174 个新单词,学习了 51 个新单词。
阅读时间总共是 71 小时,平均每天 1 小时。
听力时间总共是 22.7 小时,平均每天半小时。

综上,看似学习了 66 天,其实时间也就 71 + 22.7 = 93.7 小时,也就近 4 天左右的时间,也难怪效果不明显。
但值得表扬的是,2025年到目前为止,每天都抽出时间学习英语,包括周末,慢慢养成了这个习惯。

所以我接下来应该要做的事:
1. 争取每天 2 小时在英语学习上
2. 要多听,最好能每天 1 小时的听力时间
3. 尽量少“坚持”,多样化去学习,多找些有趣的文章去看

期待下一次小结能有所进步

填坑记: Active Storage 图片在邮件中的显示问题

2025-03-05
今天在发送 Newsletter 时,发现邮件中的图片破损无法显示,很奇怪,因为相关代码是照搬 rss 的生成代码的:
article.content.to_s
content 是富文本,所以 to_s 是 html 代码,但 rss 阅读器就可以显示图片,但邮件里却无法显示图片。

于是,我打开浏览器的开发者工具查看,发现了端倪:
rss 阅读器的图片地址是绝对地址,所以能正确解析:
rss-img

邮件里的地址是相对地址,所以解析到了邮箱服务商的主机:
newsletter-img

但代码一样,为什么结果不一样呢,随即我查看了博客生成的 feed 文件,发现生成的 img 地址也是相对地址:
feed-xml

所以,结果很明显,众多的 rss 阅读器自动对相对地址补充了主机信息,避免了类似的问题。

既然找到了问题,那么解决方案就是,直接修改 active storage blob 的 html 模版代码,添加主机信息即可:
# 修改前:
<%= image_tag url_for(blob) %>
# 修改后:
<%= image_tag "#{site_settings[:url]}#{url_for(blob)}" %>
完成。

给博客添加网站分析功能

2025-03-05
前两天刚说要给博客加功能,这不就来了嘛,内置了基础的网站分析功能,并可公开访问
大部分博主几乎都是使用第三方的网站分析,比如 Google Analytics、 Plausible、Umami、Posthog、Matomo 等。
但有几个问题比较难解决:
1. 需要加载第三方的 js 代码
2. 如果安装了类 uBlock 插件,则脚本会被阻止
3. 隐私和维护问题

综上,在VersunCMS上集成该功能刻不容缓,所幸有一个针对 Rails 编写的网站分析包:ankane/ahoy,非常简易好用,步骤如下:
1. 添加包到 Gemfile
gem "ahoy_matey"
然后执行命令安装
bundle install
rails generate ahoy:install
rails db:migrate
2. 添加事件跟踪代码到 app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  after_action :track_action
 #.....
  protected

  def track_action
    ahoy.track "Viewed", request.path_parameters
  end
3. 添加 Analytics 控制器
rails g controller analytics index
控制器代码如下
class AnalyticsController < ApplicationController
  def index
    @total_visits = Ahoy::Visit.count
    events = Ahoy::Event.where(name: "Viewed").where("properties->>'slug' IS NOT NULL")

    # 统计访问量并按数量排序,只取前10篇
    visits_count = {}
    events.each do |event|
      visits_count[event.properties] ||= 0
      visits_count[event.properties] += 1
    end
    @visits_by_path = visits_count.sort_by { |_, count| -count }.first(10).to_h

    @referrers = Ahoy::Visit.group(:referrer)
                            .count
                            .reject { |k, _| k.nil? }
                            .sort_by { |_, count| -count }
                            .to_h

    @browsers = Ahoy::Visit.group(:browser)
                           .count
                           .sort_by { |_, count| -count }
                           .to_h

    @operating_systems = Ahoy::Visit.group(:os)
                                    .count
                                    .sort_by { |_, count| -count }
                                    .to_h

    @devices = Ahoy::Visit.group(:device_type)
                          .count
                          .sort_by { |_, count| -count }
                          .to_h
  end
end
4. 修改视图文件 app/views/analytics/index.html.erb
<h3>Website Analytics</h3>
<div class="total-visits">
  <h4>Total Views: <%= @total_visits %></h4>
</div>
<div style="display: flex; justify-content: space-between;">
  <div>
    <p>Pages</p>
    <% @visits_by_path.each do |path_data, count| %>
        <%= count %> <>
        <%= path_data['slug'] %><br>
    <% end %>
  </div>
  <div>
    <p>Referrers</p>
    <% @referrers.each do |referrer, count| %>
        <%= count %> <>
        <%= referrer %><br>
    <% end %>
  </div>
</div>
<hr>
<div style="display: flex; justify-content: space-between;">
  <div>
    <p>Browsers</p>
    <% @browsers.each do |browser, count| %>
        <%= count %> <>
        <%= browser %><br>
    <% end %>
  </div>
  <div>
    <p>OS</p>
    <% @operating_systems.each do |os, count| %>
      <%= count %> <>
      <%= os %><br>
    <% end %>
  </div>
  <div>
    <p>Devices</p>
    <% @devices.each do |device, count| %>
      <%= count %> <>
      <%= device %><br>
    <% end %>
  </div>
</div>
最后将 analytics 的路径添加到 routes 文件里即可
get "/analytics" => "analytics#index"
效果如下,非常简朴,但个人使用,就不追求样式了
https://versun.me/analytics

Nothing Phone 3a

2025-03-05
Nothing Phone 推出 3a 系列手机,不得不说,颜值依旧非常在线,包括标准版和Pro版两款机型。
Phone 3a
最大的亮点是添加了一个专属 AI 功能的 EssentialKey 按键,类似 iPhone 的 Action Button,但看起来比 Action Button 要好用一些,比如原生支持短按捕捉内容并发送到EssentialSpace,长按录制语音笔记,双击访问EssentialSpace 等。
标准版售价SGD 549, 大约CNY 2976
标准版售价SGD 649, 大约CNY 3518

官方介绍:Introducing Phone (3a) Series | Nothing TV
评测视频:Nothing Phone 3a/Pro: Now Do a Flagship!
暴力拆解视频:Nothing (3a) Pro Durability Test - I know the Secret... (强迫症者勿看)

博客开通Newsletter啦

2025-03-04
我的博客新增了"邮件订阅"功能!现在除了 RSS 订阅,还可以用邮件接收我的更新。更新频率和博客更新的节奏一样,可能天天更新,也可能一周一次,如果不怕我扰民的话,欢迎订阅~

这功能本来是给我的"54321周刊"准备的。以前每次发周刊,我都得手动复制内容到 listmonk 上发邮件,太麻烦了。所以这几天我给 VersunCMS 加了 Newsletter 功能,后端直接用 listmonk 实现,省了不少事。

其实我一开始想用 Rails 的 Action Mailer 从头做,但发现要做的东西太多了,还是直接对接成熟且可自部署的 listmonk 更实际。

现在 VersunCMS 基本上已经很接近我理想中的集中式发布平台了,接下来就是优化一些细节,也许会再添加几个交叉发布的功能,然后再加个媒体页?再加些 AI 功能?再加个网页分析功能?。。。。。。。


crosspost and newsletter

最后,不要忘记订阅我的博客哈:RSS 或者 Newsletter

大模型代码逻辑测试:o3-mini独胜,其他主流模型全军覆没

2025-03-01
早上,我在优化VersunCMS关于邮件发送的逻辑时,突发奇想,想测试下主流的几个大模型的代码逻辑能力,结果有点出乎我的意料。 TLDR 测试平台:Perplexity 和 X 测试模型:o3-mini、claude-3.7-sonnect、 deepseek-r1、 Grok3(Think模式) 测试结果:只有o3-mini没有掉入陷阱,其它模型均失败 ...

红色警戒源代码

2025-02-28
EA 开源了游戏 红色警戒 的源代码,但代码库当前状态并不能完全编译。。
而且就算你费了九牛二虎之力编译成功,要打开编译后的二进制文件时,你必须先在 EA App 或者 Steam 上购买该游戏才能继续游玩。。。

EA: 我警告你啊,你不要动手动脚的,想玩呀,给钱!

Hector Martin 将辞去 Asahi Linux 项目负责人职务

2025-02-28
Asahi Linux 项目负责人 Hector Martin 宣布辞职,该项目是一个致力于让 Linux 在苹果 M 系列芯片设备上运行的项目。
我一直在关注这个项目,一直在等它兼容雷电口,但没想到等来的却是这个消息,虽然该项目还会继续进行,但失去了创始人的引领,维护者的信心真的会大受打击。

他辞职的主要原因和大部分开源作者差不多,压力大,需求越来越多,捐款越来越少,以及与Linux内核社区的冲突,Rust Linux 的问题等等,这些问题也揭示了整个 Linux 开源社区乃至更广泛的开源生态系统亟需变革的现状

PS: Hector Martin 目前正在寻找远程工作机会

Groq正式加入OpenRouter

2025-02-28
Groq 的LPU引擎运行开源模型的速度飞快,现在可以在 OpenRouter 上调用啦!!
目前支持的模型可查看这里