OwnTone Sync

Smart Playlists Guide

Dynamic playlists that update automatically based on your listening habits

OwnTone's smart playlists are text files that define rules for automatically selecting tracks from your library. Unlike static playlists, they update dynamically—add new music that matches the criteria, and it appears automatically. Skip a song too many times, and it can drop out of rotation.

When combined with OwnTone Sync's playback tracking feature, smart playlists become even more powerful. The app reports your play and skip events back to OwnTone, which means your playlists can adapt to how you actually listen—prioritizing songs you love and resting ones you've heard recently.

💡 The Sync Advantage

Enable playback tracking in OwnTone Sync to feed your listening data back to the server. Your smart playlists will then reflect what you play on your phone, not just what you stream at home.

Key Concepts

Smart playlists filter your library using fields, operators, and values. Here are the most useful ones for building listening-aware playlists:

Rating

Filter by star rating. OwnTone uses a 0-100 scale: rating = 0 (unrated), rating = 20 (1 star), up to rating = 100 (5 stars). Use ratings to prioritize favorites or exclude tracks you don't want in shuffle.

Play & Skip Counts

Track engagement with play_count and skip_count. Surface unplayed tracks, identify overplayed ones, or exclude songs you frequently skip.

Time Fields

Use time_played, time_skipped, and time_added with relative dates like 3 days ago or last week to create rotation and freshness rules.

Genre & Metadata

Filter by genre, artist, album, and more. Use includes for partial matches or is for exact matches.

📖 Full syntax reference on owntone.github.io →

Example Playlists

🔀 Smart Shuffle

A weighted rotation system that surfaces higher-rated songs more frequently while giving everything appropriate rest periods. This replaces basic shuffle with something that respects both your preferences and listening fatigue.

How it works

The playlist divides your library into rating tiers (5-star, 4-star, etc.) and applies different rules to each:

  • Higher-rated songs (4-5 stars) return to rotation sooner and tolerate more plays before needing a longer rest
  • Lower-rated songs (2-3 stars) need longer gaps between plays and have stricter skip limits
  • Unplayed tracks in any tier are always eligible, helping you discover music you haven't heard yet

For example, a 5-star song might reappear after 3 days, while a 3-star song waits 25 days. If you skip a song repeatedly, it drops out of rotation until enough time passes.

The result: your favorites appear often enough to enjoy but not so often they become stale, while deeper cuts still surface occasionally.

View full playlist code
"Smart Shuffle" { data_kind is file and media_kind is music and not (genre is "Folk" or genre is "World" or genre includes "Holiday" or genre is "Children" or genre is "Speech" or genre is "Humor" or genre is "Jazz" or genre is "Classical") and rating > 20 and ( (rating > 90 and (play_count = 0 or (play_count < 10 and skip_count < 3 and time_played before 3 days ago and time_skipped before 5 days ago) or (play_count < 20 and skip_count < 6 and time_played before 13 days ago and time_skipped before 15 days ago) or (play_count < 30 and skip_count < 10 and time_played before 18 days ago and time_skipped before 20 days ago) or (skip_count < 15 and time_played before 20 days ago and time_skipped before 25 days ago))) or (rating > 80 and rating <= 90 and (play_count = 0 or (play_count < 10 and skip_count < 5 and time_played before 8 days ago and time_skipped before 10 days ago) or (play_count < 20 and skip_count < 8 and time_played before 15 days ago and time_skipped before 17 days ago) or (play_count < 30 and skip_count < 12 and time_played before 21 days ago and time_skipped before 23 days ago) or (skip_count < 20 and time_played before 30 days ago and time_skipped before 35 days ago))) or (rating > 70 and rating <= 80 and (play_count = 0 or (play_count < 10 and skip_count < 5 and time_played before 13 days ago and time_skipped before 15 days ago) or (play_count < 20 and skip_count < 10 and time_played before 18 days ago and time_skipped before 20 days ago) or (play_count < 30 and skip_count < 15 and time_played before 23 days ago and time_skipped before 25 days ago) or (skip_count < 25 and time_played before 45 days ago and time_skipped before 50 days ago))) or (rating > 60 and rating <= 70 and (play_count = 0 or (play_count < 10 and skip_count < 7 and time_played before 15 days ago and time_skipped before 17 days ago) or (play_count < 20 and skip_count < 12 and time_played before 21 days ago and time_skipped before 23 days ago) or (play_count < 30 and skip_count < 18 and time_played before 25 days ago and time_skipped before 27 days ago) or (skip_count < 30 and time_played before 60 days ago and time_skipped before 65 days ago))) or (rating > 50 and rating <= 60 and (play_count = 0 or (play_count < 10 and skip_count < 8 and time_played before 21 days ago and time_skipped before 25 days ago) or (play_count < 20 and skip_count < 15 and time_played before 28 days ago and time_skipped before 32 days ago) or (play_count < 30 and skip_count < 20 and time_played before 33 days ago and time_skipped before 37 days ago) or (skip_count < 35 and time_played before 45 days ago and time_skipped before 55 days ago))) or (rating > 40 and rating <= 50 and (play_count = 0 or (play_count < 10 and skip_count < 10 and time_played before 25 days ago and time_skipped before 30 days ago) or (play_count < 25 and skip_count < 18 and time_played before 35 days ago and time_skipped before 40 days ago) or (play_count < 30 and skip_count < 22 and time_played before 38 days ago and time_skipped before 43 days ago) or (skip_count < 40 and time_played before 45 days ago and time_skipped before 55 days ago))) or (rating > 30 and rating <= 40 and (play_count = 0 or (play_count < 10 and skip_count < 12 and time_played before 25 days ago and time_skipped before 30 days ago) or (play_count < 20 and skip_count < 20 and time_played before 35 days ago and time_skipped before 40 days ago) or (play_count < 30 and skip_count < 25 and time_played before 43 days ago and time_skipped before 48 days ago) or (skip_count < 45 and time_played before 50 days ago and time_skipped before 65 days ago))) or (rating > 20 and rating <= 30 and (play_count = 0 or (play_count < 10 and skip_count < 15 and time_played before 25 days ago and time_skipped before 30 days ago) or (play_count < 20 and skip_count < 25 and time_played before 35 days ago and time_skipped before 40 days ago) or (play_count < 30 and skip_count < 30 and time_played before 33 days ago and time_skipped before 37 days ago) or (skip_count < 50 and time_played before 60 days ago and time_skipped before 65 days ago))) ) }
📱 Sync tip: This playlist benefits most from playback tracking. Without it, only plays from your home setup count toward the rotation logic.

🆕 Recently Added

New music from the last 3 weeks, excluding tracks you've rated as "don't shuffle" (1-star). Great for evaluating new additions to your library.

"Recently Added" { media_kind is music and data_kind is file and time_added after 21 days ago and (rating = 0 or rating > 20) order by time_added desc }
Understanding the rating filter

The condition rating = 0 or rating > 20 includes:

  • Unrated tracks (rating = 0) — new music you haven't evaluated yet
  • 2-star and above (rating > 20) — tracks you've decided to keep in rotation

It excludes 1-star tracks (rating = 20), which you can use as a "don't include in shuffle" marker without deleting the file from your library.

📱 Sync tip: Sync this playlist to quickly evaluate new music on the go, then rate tracks to sort them into your other playlists.

🔁 Rediscover

Songs you used to play but haven't heard in over 6 months. Resurface forgotten favorites from your library.

"Rediscover" { media_kind is music and data_kind is file and play_count > 5 and time_played before 180 days ago and rating > 20 order by time_played asc }
📱 Sync tip: With playback tracking enabled, songs you rediscover on your phone will update their time_played and eventually rotate out of this list.

😴 Overplayed Cool-down

Tracks you've played heavily that might benefit from a rest. Review these periodically—if you're tired of a song, this helps you notice.

"Overplayed" { media_kind is music and data_kind is file and play_count > 30 and time_played after 14 days ago order by play_count desc }
Tuning the thresholds

Adjust these values based on your library size and listening habits:

  • play_count > 30 — Lower this if your library is newer or you want to catch songs earlier
  • time_played after 14 days ago — The recency window; songs drop off this list naturally as time passes

This playlist is diagnostic rather than for playback—use it to spot songs that might need a break or a rating adjustment.

🎸 Genre Shuffle (Soul/R&B Example)

A genre-focused playlist with basic rotation logic to avoid immediate repeats.

"Soul" { data_kind is file and media_kind is music and ( genre includes "Soul" or genre is "R&B" ) and not rating = 20 and ( play_count = 0 or (time_played before 1 days ago and time_skipped before 3 days ago) ) }
Adapting for other genres

Replace the genre conditions with your own. Note the difference between operators:

  • genre includes "Soul" — matches "Soul", "Neo-Soul", "Soul/Funk", etc.
  • genre is "R&B" — matches only the exact string "R&B"

Use includes for broader matching when your tags might have variations.

🎄 Holiday Music

A simple seasonal playlist. Enable sync only when you want holiday music on your device.

"Holiday Music" { media_kind is music and genre includes "Holiday" }
📱 Sync tip: In OwnTone Sync, you choose which playlists to sync. Add this one in December, remove it in January—your storage stays clean the rest of the year.

Creating Your Own

Smart playlists are plain text files with a .smartpl extension, placed anywhere in your OwnTone music library folder.

1. Create the file

Create a text file like my-playlist.smartpl in your music library folder. The filename doesn't matter—only the playlist name inside the file.

2. Write the rules

Use the format "Name" { conditions }. Combine conditions with and, or, and not. Use parentheses to group logic.

3. Rescan library

Trigger a library rescan in OwnTone (or wait for automatic scan). Your new playlist will appear alongside your regular playlists.

📖 Complete syntax documentation →

Ready to sync smarter playlists?

Enable playback tracking to make your smart playlists truly adaptive.

Download on Google Play