Skip to content

feat: smart playlists - rule-based auto-updating collections #1052

Description

@LWWZH

简介与背景

目前 FeelUOwn 的收藏(collection)是静态的文本文件(.fuo 格式,TOML 头部 + URI 列表)。用户需要手动添加/删除歌曲。对于大型曲库来说,这不够高效。

同时,RecentlyPlayedfeeluown/player/recently_played.py)和 Playlist 已经在追踪播放历史和队列状态,但这些数据没有被充分利用来生成动态歌单。

Smart Playlists(智能歌单)是 iTunes/Apple Music、Spotify、Roon 等主流播放器的标配功能,能让用户基于规则自动生成和更新歌单。

方案概述

核心思路

在现有 Collection 体系上扩展,支持声明式规则(而非静态 URI 列表)。规则引擎在应用启动时和播放事件触发时重新评估,动态更新歌单内容。

规则设计

.fuo 文件的 TOML 头部中新增 rules 字段:

+++
title = "最近常听"
description = "过去 30 天播放次数最多的 50 首歌"
type = "smart"
rules = """
sort_by = "play_count_desc"
time_range_days = 30
limit = 50
"""
+++

支持的规则字段

规则 类型 说明
sort_by enum play_count_desc, last_played_desc, date_added_desc, title_asc
time_range_days int 仅统计最近 N 天的播放数据
limit int 最大歌曲数
sources list 仅包含指定来源(如 ["netease", "qqmusic"]
min_play_count int 最低播放次数
exclude_disliked bool 排除标记为不喜欢的歌曲

需要修改的模块

  1. Collectionfeeluown/collection.py

    • 识别 type = "smart" 标记
    • 新增 SmartCollection 子类,持有规则而非静态模型列表
    • load() 中解析 rules 字段
  2. 新增 SmartPlaylistEngine(建议 feeluown/collection.py 或新文件)

    • 接收规则,查询 RecentlyPlayed 和播放计数数据
    • 返回排序后的歌曲列表
    • 提供 evaluate() 方法供定时刷新
  3. CollectionManagerfeeluown/collection.py

    • 在加载完所有 collection 后,触发 smart collection 的首次评估
    • 监听播放完成事件,增量刷新受影响的 smart collection
  4. RecentlyPlayedfeeluown/player/recently_played.py

    • 新增 get_play_counts(time_range_days=None) 方法
    • 新增 get_most_played(limit, time_range_days) 方法
  5. GUI 集成

    • 在侧边栏和集合页面中区分 smart collection 和普通 collection(例如显示不同的图标)
    • Smart collection 不显示 "添加歌曲" 按钮
    • 在设置中提供 smart collection 的刷新频率选项

内置 Smart Playlists

提供几个预置的 smart playlist 模板,用户可以在设置中一键创建:

  • 最近播放:最近 7 天播放过的歌曲
  • 最常听:播放次数最多的 50 首
  • 新发现:最近添加但播放次数 < 3 的歌曲
  • 长曲目:时长 > 6 分钟的歌曲

不在本次范围内

  • 基于 AI 的推荐规则(可后续扩展)
  • 跨设备同步 smart playlist
  • 嵌套规则(AND/OR 逻辑组合)

参考

  • feeluown/collection.py — Collection 和 CollectionManager
  • feeluown/player/recently_played.py — 播放历史追踪
  • feeluown/player/playlist.py — 播放计数基础设施

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions