kukicha 0.1.0a1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. kukicha-0.1.0a1/LICENSE +21 -0
  2. kukicha-0.1.0a1/PKG-INFO +286 -0
  3. kukicha-0.1.0a1/README.md +272 -0
  4. kukicha-0.1.0a1/pyproject.toml +29 -0
  5. kukicha-0.1.0a1/setup.cfg +4 -0
  6. kukicha-0.1.0a1/src/kukicha/__init__.py +1 -0
  7. kukicha-0.1.0a1/src/kukicha/__main__.py +5 -0
  8. kukicha-0.1.0a1/src/kukicha/album_artists.py +113 -0
  9. kukicha-0.1.0a1/src/kukicha/app_metadata.py +7 -0
  10. kukicha-0.1.0a1/src/kukicha/cli.py +115 -0
  11. kukicha-0.1.0a1/src/kukicha/commands/__init__.py +2 -0
  12. kukicha-0.1.0a1/src/kukicha/commands/opensubsonic.py +25 -0
  13. kukicha-0.1.0a1/src/kukicha/commands/player.py +25 -0
  14. kukicha-0.1.0a1/src/kukicha/commands/tools.py +98 -0
  15. kukicha-0.1.0a1/src/kukicha/commands/youtube_audio.py +821 -0
  16. kukicha-0.1.0a1/src/kukicha/data/taxonomy.tsv +1914 -0
  17. kukicha-0.1.0a1/src/kukicha/discogs.py +155 -0
  18. kukicha-0.1.0a1/src/kukicha/display.py +11 -0
  19. kukicha-0.1.0a1/src/kukicha/file_metadata.py +23 -0
  20. kukicha-0.1.0a1/src/kukicha/models.py +105 -0
  21. kukicha-0.1.0a1/src/kukicha/opensubsonic_web_adapter.py +1125 -0
  22. kukicha-0.1.0a1/src/kukicha/player_common.py +88 -0
  23. kukicha-0.1.0a1/src/kukicha/player_config.py +873 -0
  24. kukicha-0.1.0a1/src/kukicha/player_errors.py +10 -0
  25. kukicha-0.1.0a1/src/kukicha/player_jobs.py +238 -0
  26. kukicha-0.1.0a1/src/kukicha/player_media.py +72 -0
  27. kukicha-0.1.0a1/src/kukicha/player_navigation.py +453 -0
  28. kukicha-0.1.0a1/src/kukicha/player_platform.py +25 -0
  29. kukicha-0.1.0a1/src/kukicha/player_playlists.py +275 -0
  30. kukicha-0.1.0a1/src/kukicha/player_presenters.py +1018 -0
  31. kukicha-0.1.0a1/src/kukicha/player_runtime.py +335 -0
  32. kukicha-0.1.0a1/src/kukicha/player_views.py +647 -0
  33. kukicha-0.1.0a1/src/kukicha/player_web_adapter.py +740 -0
  34. kukicha-0.1.0a1/src/kukicha/playlist_art.py +69 -0
  35. kukicha-0.1.0a1/src/kukicha/scanner.py +1114 -0
  36. kukicha-0.1.0a1/src/kukicha/search.py +82 -0
  37. kukicha-0.1.0a1/src/kukicha/static/favicon.svg +23 -0
  38. kukicha-0.1.0a1/src/kukicha/static/player.css +2867 -0
  39. kukicha-0.1.0a1/src/kukicha/static/player.js +4241 -0
  40. kukicha-0.1.0a1/src/kukicha/taxonomy_data.py +88 -0
  41. kukicha-0.1.0a1/src/kukicha/templates/player/_icons.html +111 -0
  42. kukicha-0.1.0a1/src/kukicha/templates/player/_page_title.html +33 -0
  43. kukicha-0.1.0a1/src/kukicha/templates/player/_track_table.html +176 -0
  44. kukicha-0.1.0a1/src/kukicha/templates/player/album.html +108 -0
  45. kukicha-0.1.0a1/src/kukicha/templates/player/album_edit.html +200 -0
  46. kukicha-0.1.0a1/src/kukicha/templates/player/artist_split_rules.html +25 -0
  47. kukicha-0.1.0a1/src/kukicha/templates/player/artists.html +23 -0
  48. kukicha-0.1.0a1/src/kukicha/templates/player/base.html +200 -0
  49. kukicha-0.1.0a1/src/kukicha/templates/player/cache.html +19 -0
  50. kukicha-0.1.0a1/src/kukicha/templates/player/help.html +72 -0
  51. kukicha-0.1.0a1/src/kukicha/templates/player/home.html +253 -0
  52. kukicha-0.1.0a1/src/kukicha/templates/player/index.html +167 -0
  53. kukicha-0.1.0a1/src/kukicha/templates/player/jobs.html +53 -0
  54. kukicha-0.1.0a1/src/kukicha/templates/player/musicbrainz_overrides.html +80 -0
  55. kukicha-0.1.0a1/src/kukicha/templates/player/not_found.html +14 -0
  56. kukicha-0.1.0a1/src/kukicha/templates/player/playlist.html +53 -0
  57. kukicha-0.1.0a1/src/kukicha/templates/player/queue.html +20 -0
  58. kukicha-0.1.0a1/src/kukicha/templates/player/roots.html +43 -0
  59. kukicha-0.1.0a1/src/kukicha/templates/player/simple_page.html +5 -0
  60. kukicha-0.1.0a1/src/kukicha/text.py +33 -0
  61. kukicha-0.1.0a1/src/kukicha/use_case/__init__.py +215 -0
  62. kukicha-0.1.0a1/src/kukicha/use_case/commands/__init__.py +99 -0
  63. kukicha-0.1.0a1/src/kukicha/use_case/commands/album_edits.py +1341 -0
  64. kukicha-0.1.0a1/src/kukicha/use_case/commands/jobs.py +361 -0
  65. kukicha-0.1.0a1/src/kukicha/use_case/commands/player.py +879 -0
  66. kukicha-0.1.0a1/src/kukicha/use_case/commands/playlists.py +229 -0
  67. kukicha-0.1.0a1/src/kukicha/use_case/commands/roots.py +586 -0
  68. kukicha-0.1.0a1/src/kukicha/use_case/commands/startup.py +10 -0
  69. kukicha-0.1.0a1/src/kukicha/use_case/coverartarchive.py +317 -0
  70. kukicha-0.1.0a1/src/kukicha/use_case/database.py +1697 -0
  71. kukicha-0.1.0a1/src/kukicha/use_case/itunes.py +382 -0
  72. kukicha-0.1.0a1/src/kukicha/use_case/library.py +1876 -0
  73. kukicha-0.1.0a1/src/kukicha/use_case/listening.py +1229 -0
  74. kukicha-0.1.0a1/src/kukicha/use_case/musicbrainz.py +727 -0
  75. kukicha-0.1.0a1/src/kukicha/use_case/queries/__init__.py +81 -0
  76. kukicha-0.1.0a1/src/kukicha/use_case/queries/artists.py +44 -0
  77. kukicha-0.1.0a1/src/kukicha/use_case/queries/filters.py +488 -0
  78. kukicha-0.1.0a1/src/kukicha/use_case/queries/library.py +1596 -0
  79. kukicha-0.1.0a1/src/kukicha/use_case/queries/models.py +358 -0
  80. kukicha-0.1.0a1/src/kukicha/use_case/queries/musicbrainz.py +11 -0
  81. kukicha-0.1.0a1/src/kukicha/use_case/queries/params.py +105 -0
  82. kukicha-0.1.0a1/src/kukicha/use_case/queries/sorting.py +135 -0
  83. kukicha-0.1.0a1/src/kukicha/use_case/queries/sql.py +41 -0
  84. kukicha-0.1.0a1/src/kukicha.egg-info/PKG-INFO +286 -0
  85. kukicha-0.1.0a1/src/kukicha.egg-info/SOURCES.txt +96 -0
  86. kukicha-0.1.0a1/src/kukicha.egg-info/dependency_links.txt +1 -0
  87. kukicha-0.1.0a1/src/kukicha.egg-info/entry_points.txt +2 -0
  88. kukicha-0.1.0a1/src/kukicha.egg-info/requires.txt +5 -0
  89. kukicha-0.1.0a1/src/kukicha.egg-info/top_level.txt +1 -0
  90. kukicha-0.1.0a1/tests/test_album_artists.py +52 -0
  91. kukicha-0.1.0a1/tests/test_library.py +4052 -0
  92. kukicha-0.1.0a1/tests/test_musicbrainz.py +69 -0
  93. kukicha-0.1.0a1/tests/test_opensubsonic.py +660 -0
  94. kukicha-0.1.0a1/tests/test_player.py +8596 -0
  95. kukicha-0.1.0a1/tests/test_playlist_art.py +23 -0
  96. kukicha-0.1.0a1/tests/test_scanner.py +652 -0
  97. kukicha-0.1.0a1/tests/test_search.py +718 -0
  98. kukicha-0.1.0a1/tests/test_tools.py +896 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 zanyoats
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,286 @@
1
+ Metadata-Version: 2.4
2
+ Name: kukicha
3
+ Version: 0.1.0a1
4
+ Summary: Scan and query a SQLite-backed music metadata database.
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Requires-Dist: Flask>=3.1.0
9
+ Requires-Dist: Jinja2>=3.1.0
10
+ Requires-Dist: mutagen>=1.47.0
11
+ Requires-Dist: Pillow>=10.0.0
12
+ Requires-Dist: yt-dlp[default]==2026.3.17
13
+ Dynamic: license-file
14
+
15
+ # kukicha
16
+
17
+ `kukicha` focuses on managing and streaming your audio library using a http server backed by single sqlite database file. It comes with a simple and fast builtin web UI.
18
+
19
+ Some noteworthy features:
20
+ - It supports both POSIX and Windows.
21
+ - Text/token based search & filters.
22
+ - Artist tag cloud page
23
+ - Albums grid page
24
+ - Easily sync library root paths
25
+ - Supports most audio formats
26
+ - Never transcodes audio streams
27
+ - Playlist are ordinary m3u, m3u8, pls files
28
+ - Genre/style taxonomy provides clean data
29
+ - Artist split patterns overrides (avoid artist names like `Brian Eno with Jon Hopkins & Leo Abrahams`)
30
+ - iTunes cover art lookup
31
+ - Musicbrainz release group & release IDs overrides
32
+ - Overwrite album-level audio tags for album artist, genre
33
+ - Overwrite track-level audio tags for artist, album title
34
+
35
+ Roadmap
36
+ - Mount remote library roots (S3, etc.)
37
+ - Support subset of Opensonic API to support different clients
38
+ - Live stream a playlist
39
+
40
+ ## Install With pipx
41
+
42
+ Kukicha is not published to PyPI yet. Install it from a checked-out project root with `pipx`:
43
+
44
+ ```bash
45
+ # from the project root
46
+ pipx ensurepath
47
+ pipx install .
48
+ ```
49
+
50
+ Verify the install:
51
+
52
+ ```bash
53
+ which kukicha
54
+ pipx list
55
+ kukicha --help
56
+ ```
57
+
58
+ Updates can be installed using force flag:
59
+
60
+ ```bash
61
+ # when we move to versions use `pipx upgrade kukicha`
62
+ pipx install --force .
63
+ ```
64
+
65
+ For contributor setup with an editable install and test commands, see
66
+ [DEVELOPMENT.md](DEVELOPMENT.md).
67
+
68
+ ## Configure The Player
69
+
70
+ By default the player reads its config from
71
+ `$XDG_CONFIG_HOME/kukicha/kukicha.toml` or `~/.config/kukicha/kukicha.toml`.
72
+ If that file is missing, Kukicha uses built-in defaults and stores the default
73
+ database at `kukicha.sqlite` in the same config directory.
74
+
75
+ Create the config directory and file:
76
+
77
+ ```bash
78
+ mkdir -p ~/.config/kukicha
79
+ $EDITOR ~/.config/kukicha/kukicha.toml
80
+ ```
81
+
82
+ Example config:
83
+
84
+ ```toml
85
+ LogLevel = "INFO"
86
+ Roots = ["/Users/YOUR_USERNAME/Music"]
87
+ YoutubeDownloadPath = "/Users/YOUR_USERNAME/Music/YouTube"
88
+ PreferMusicBrainzEnglishAliases = true
89
+ ```
90
+
91
+ Supported keys:
92
+
93
+ - `LogLevel`: Python logging level name, such as `DEBUG`, `INFO`, or `WARNING`.
94
+ - `DatabasePath`: SQLite database path. Relative paths are resolved from the
95
+ config file directory.
96
+ - `Roots`: music library folders to scan. Relative paths are resolved from the
97
+ config file directory. Roots can also be managed from the Roots page.
98
+ - `FFmpegPath`: optional path to an executable `ffmpeg`; leave empty to unset.
99
+ - `YoutubeDownloadPath`: folder where YouTube chapter audio downloads are
100
+ written. Relative paths are resolved from the config file directory.
101
+ - `PreferMusicBrainzEnglishAliases`: when writing MusicBrainz album tags, prefer
102
+ the first English artist alias from the MusicBrainz payload. Defaults to
103
+ `true`.
104
+ - `Host`: interface to bind, defaulting to `127.0.0.1`.
105
+ - `Port`: TCP port from `1` to `65535`, defaulting to `65042`.
106
+ - `OpenSubsonicUsername`: username for the OpenSubsonic API, defaulting to
107
+ `guest`.
108
+ - `OpenSubsonicPassword`: password for the OpenSubsonic API, defaulting to
109
+ `guest`.
110
+ - `OpenSubsonicHost`: interface for the OpenSubsonic API, defaulting to
111
+ `127.0.0.1`.
112
+ - `OpenSubsonicPort`: TCP port for the OpenSubsonic API, defaulting to `4533`.
113
+ - `AccentColor`: palette name or matching hex code. Run `kukicha --help` for the
114
+ full palette list.
115
+ - `Appearance`: `light`, `dark`, `dim`, or `system`. `system` follows the
116
+ browser's `prefers-color-scheme`, using `light` for light mode and `dim` for
117
+ dark mode. Defaults to `system`.
118
+ - `ToastTimeoutMs`: positive toast timeout in milliseconds.
119
+ - `AlbumArtistSplitPatterns`: strings used when splitting album artist names.
120
+
121
+ Run `kukicha --help` to print the active config path, current values, supported
122
+ keys, accent colors, and appearance names.
123
+
124
+ ## Run The Player
125
+
126
+ Launch the local browser player:
127
+
128
+ ```bash
129
+ kukicha
130
+ ```
131
+
132
+ Or point it at an explicit config file:
133
+
134
+ ```bash
135
+ kukicha -c /path/to/config/kukicha.toml
136
+ ```
137
+
138
+ The default player URL is:
139
+
140
+ ```text
141
+ http://127.0.0.1:65042
142
+ ```
143
+
144
+ The player runs as a foreground HTTP service so launchd, systemd, and similar
145
+ service managers can supervise it directly. Logs go to normal stdout/stderr (with
146
+ timestamps).
147
+
148
+ The player provides album browsing, playback, full-text search, and filters for
149
+ library roots, artists, genres, styles, and album properties. Search indexes
150
+ album titles, album artists, and track titles. Quoted terms match exact token
151
+ phrases, spaces mean AND, semicolons mean OR, and a leading `-` excludes a term.
152
+
153
+ ## Run The OpenSubsonic API
154
+
155
+ Launch the minimal OpenSubsonic-compatible API:
156
+
157
+ ```bash
158
+ kukicha opensubsonic
159
+ ```
160
+
161
+ The default OpenSubsonic URL is:
162
+
163
+ ```text
164
+ http://127.0.0.1:4533
165
+ ```
166
+
167
+ The API supports basic album and artist browsing, direct streaming, downloads,
168
+ cover art, password auth, salted token auth, JSON responses, and GET or form
169
+ POST parameters.
170
+
171
+ ## Bulk Tag Edit
172
+
173
+ Rewrite album-level tags for every supported music file under a folder:
174
+
175
+ ```bash
176
+ kukicha tools bulk-tag-edit \
177
+ --folder "/Users/YOUR_USERNAME/Library/Mobile Documents/com~apple~CloudDocs/music/downloaded2/Richard David James" \
178
+ --album-artist "Richard David James" \
179
+ --album "Soundcloud" \
180
+ --genre "Electronic"
181
+ ```
182
+
183
+ The command recurses with the same supported audio extensions used by the scanner
184
+ and only writes album artist, album title, and genre tags. It has been convenient for a bulk tag edit (album level) in some circumstances
185
+
186
+ ## YouTube Audio
187
+
188
+ Download audio-only YouTube media. Video URLs are split into chapter files:
189
+
190
+ ```bash
191
+ kukicha tools yt-download-audio "https://www.youtube.com/watch?v=VIDEO_ID"
192
+ ```
193
+
194
+ If yt-dlp does not report chapters, or you want to override them, provide a
195
+ manual chapter file:
196
+
197
+ ```bash
198
+ kukicha -c ~/kukicha.toml tools yt-download-audio \
199
+ --chapters-file chapters.txt \
200
+ "https://www.youtube.com/watch?v=VIDEO_ID"
201
+ ```
202
+
203
+ The chapter file uses one chapter per nonblank line. Lines starting with `#`
204
+ are ignored:
205
+
206
+ ```text
207
+ 0:00 Intro
208
+ 03:12 - Track Two
209
+ 1:02:03.5 Finale
210
+ ```
211
+
212
+ Playlist URLs are downloaded as one audio file per playlist item. Chapters
213
+ reported inside individual playlist items are ignored, and `--chapters-file`
214
+ cannot be used with playlist URLs.
215
+
216
+ Set `YoutubeDownloadPath` in `kukicha.toml` before running this command. The
217
+ tool checks that `ffmpeg`, `ffprobe`, and Deno 2.0.0 or newer are available.
218
+ yt-dlp temporary and staged files are kept in the user's OS temp folder and are
219
+ cleaned up when the command exits.
220
+
221
+ ## Run With launchd
222
+
223
+ Save this as `~/Library/LaunchAgents/com.kukicha.player.plist` and adjust paths
224
+ as needed:
225
+
226
+ ```xml
227
+ <?xml version="1.0" encoding="UTF-8"?>
228
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
229
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
230
+ <plist version="1.0">
231
+ <dict>
232
+ <key>Label</key>
233
+ <string>com.kukicha.player</string>
234
+
235
+ <key>ProgramArguments</key>
236
+ <array>
237
+ <string>/Users/YOUR_USERNAME/.local/bin/kukicha</string>
238
+ <string>-c</string>
239
+ <string>/Users/YOUR_USERNAME/.config/kukicha/kukicha.toml</string>
240
+ </array>
241
+
242
+ <key>RunAtLoad</key>
243
+ <true/>
244
+
245
+ <key>KeepAlive</key>
246
+ <dict>
247
+ <key>SuccessfulExit</key>
248
+ <false/>
249
+ </dict>
250
+
251
+ <key>StandardOutPath</key>
252
+ <string>/Users/YOUR_USERNAME/Library/Logs/kukicha-player.log</string>
253
+
254
+ <key>StandardErrorPath</key>
255
+ <string>/Users/YOUR_USERNAME/Library/Logs/kukicha-player.err.log</string>
256
+ </dict>
257
+ </plist>
258
+ ```
259
+
260
+ Load and start it:
261
+
262
+ ```bash
263
+ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.kukicha.player.plist
264
+ ```
265
+
266
+ Show the status
267
+ ```bash
268
+ launchctl print gui/$(id -u)/com.kukicha.player
269
+ ```
270
+
271
+ Restart the running server:
272
+
273
+ ```bash
274
+ launchctl kickstart -k gui/$(id -u)/com.kukicha.player
275
+ ```
276
+
277
+ Shut it down and unload it:
278
+
279
+ ```bash
280
+ launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.kukicha.player.plist
281
+ ```
282
+
283
+ After changing the plist, unload it with `bootout`, then load it again with
284
+ `bootstrap`. The `bootout` and `kickstart -k` commands trigger normal process
285
+ shutdown, and Kukicha logs shutdown with the same timestamped stdout/stderr
286
+ logging as startup.
@@ -0,0 +1,272 @@
1
+ # kukicha
2
+
3
+ `kukicha` focuses on managing and streaming your audio library using a http server backed by single sqlite database file. It comes with a simple and fast builtin web UI.
4
+
5
+ Some noteworthy features:
6
+ - It supports both POSIX and Windows.
7
+ - Text/token based search & filters.
8
+ - Artist tag cloud page
9
+ - Albums grid page
10
+ - Easily sync library root paths
11
+ - Supports most audio formats
12
+ - Never transcodes audio streams
13
+ - Playlist are ordinary m3u, m3u8, pls files
14
+ - Genre/style taxonomy provides clean data
15
+ - Artist split patterns overrides (avoid artist names like `Brian Eno with Jon Hopkins & Leo Abrahams`)
16
+ - iTunes cover art lookup
17
+ - Musicbrainz release group & release IDs overrides
18
+ - Overwrite album-level audio tags for album artist, genre
19
+ - Overwrite track-level audio tags for artist, album title
20
+
21
+ Roadmap
22
+ - Mount remote library roots (S3, etc.)
23
+ - Support subset of Opensonic API to support different clients
24
+ - Live stream a playlist
25
+
26
+ ## Install With pipx
27
+
28
+ Kukicha is not published to PyPI yet. Install it from a checked-out project root with `pipx`:
29
+
30
+ ```bash
31
+ # from the project root
32
+ pipx ensurepath
33
+ pipx install .
34
+ ```
35
+
36
+ Verify the install:
37
+
38
+ ```bash
39
+ which kukicha
40
+ pipx list
41
+ kukicha --help
42
+ ```
43
+
44
+ Updates can be installed using force flag:
45
+
46
+ ```bash
47
+ # when we move to versions use `pipx upgrade kukicha`
48
+ pipx install --force .
49
+ ```
50
+
51
+ For contributor setup with an editable install and test commands, see
52
+ [DEVELOPMENT.md](DEVELOPMENT.md).
53
+
54
+ ## Configure The Player
55
+
56
+ By default the player reads its config from
57
+ `$XDG_CONFIG_HOME/kukicha/kukicha.toml` or `~/.config/kukicha/kukicha.toml`.
58
+ If that file is missing, Kukicha uses built-in defaults and stores the default
59
+ database at `kukicha.sqlite` in the same config directory.
60
+
61
+ Create the config directory and file:
62
+
63
+ ```bash
64
+ mkdir -p ~/.config/kukicha
65
+ $EDITOR ~/.config/kukicha/kukicha.toml
66
+ ```
67
+
68
+ Example config:
69
+
70
+ ```toml
71
+ LogLevel = "INFO"
72
+ Roots = ["/Users/YOUR_USERNAME/Music"]
73
+ YoutubeDownloadPath = "/Users/YOUR_USERNAME/Music/YouTube"
74
+ PreferMusicBrainzEnglishAliases = true
75
+ ```
76
+
77
+ Supported keys:
78
+
79
+ - `LogLevel`: Python logging level name, such as `DEBUG`, `INFO`, or `WARNING`.
80
+ - `DatabasePath`: SQLite database path. Relative paths are resolved from the
81
+ config file directory.
82
+ - `Roots`: music library folders to scan. Relative paths are resolved from the
83
+ config file directory. Roots can also be managed from the Roots page.
84
+ - `FFmpegPath`: optional path to an executable `ffmpeg`; leave empty to unset.
85
+ - `YoutubeDownloadPath`: folder where YouTube chapter audio downloads are
86
+ written. Relative paths are resolved from the config file directory.
87
+ - `PreferMusicBrainzEnglishAliases`: when writing MusicBrainz album tags, prefer
88
+ the first English artist alias from the MusicBrainz payload. Defaults to
89
+ `true`.
90
+ - `Host`: interface to bind, defaulting to `127.0.0.1`.
91
+ - `Port`: TCP port from `1` to `65535`, defaulting to `65042`.
92
+ - `OpenSubsonicUsername`: username for the OpenSubsonic API, defaulting to
93
+ `guest`.
94
+ - `OpenSubsonicPassword`: password for the OpenSubsonic API, defaulting to
95
+ `guest`.
96
+ - `OpenSubsonicHost`: interface for the OpenSubsonic API, defaulting to
97
+ `127.0.0.1`.
98
+ - `OpenSubsonicPort`: TCP port for the OpenSubsonic API, defaulting to `4533`.
99
+ - `AccentColor`: palette name or matching hex code. Run `kukicha --help` for the
100
+ full palette list.
101
+ - `Appearance`: `light`, `dark`, `dim`, or `system`. `system` follows the
102
+ browser's `prefers-color-scheme`, using `light` for light mode and `dim` for
103
+ dark mode. Defaults to `system`.
104
+ - `ToastTimeoutMs`: positive toast timeout in milliseconds.
105
+ - `AlbumArtistSplitPatterns`: strings used when splitting album artist names.
106
+
107
+ Run `kukicha --help` to print the active config path, current values, supported
108
+ keys, accent colors, and appearance names.
109
+
110
+ ## Run The Player
111
+
112
+ Launch the local browser player:
113
+
114
+ ```bash
115
+ kukicha
116
+ ```
117
+
118
+ Or point it at an explicit config file:
119
+
120
+ ```bash
121
+ kukicha -c /path/to/config/kukicha.toml
122
+ ```
123
+
124
+ The default player URL is:
125
+
126
+ ```text
127
+ http://127.0.0.1:65042
128
+ ```
129
+
130
+ The player runs as a foreground HTTP service so launchd, systemd, and similar
131
+ service managers can supervise it directly. Logs go to normal stdout/stderr (with
132
+ timestamps).
133
+
134
+ The player provides album browsing, playback, full-text search, and filters for
135
+ library roots, artists, genres, styles, and album properties. Search indexes
136
+ album titles, album artists, and track titles. Quoted terms match exact token
137
+ phrases, spaces mean AND, semicolons mean OR, and a leading `-` excludes a term.
138
+
139
+ ## Run The OpenSubsonic API
140
+
141
+ Launch the minimal OpenSubsonic-compatible API:
142
+
143
+ ```bash
144
+ kukicha opensubsonic
145
+ ```
146
+
147
+ The default OpenSubsonic URL is:
148
+
149
+ ```text
150
+ http://127.0.0.1:4533
151
+ ```
152
+
153
+ The API supports basic album and artist browsing, direct streaming, downloads,
154
+ cover art, password auth, salted token auth, JSON responses, and GET or form
155
+ POST parameters.
156
+
157
+ ## Bulk Tag Edit
158
+
159
+ Rewrite album-level tags for every supported music file under a folder:
160
+
161
+ ```bash
162
+ kukicha tools bulk-tag-edit \
163
+ --folder "/Users/YOUR_USERNAME/Library/Mobile Documents/com~apple~CloudDocs/music/downloaded2/Richard David James" \
164
+ --album-artist "Richard David James" \
165
+ --album "Soundcloud" \
166
+ --genre "Electronic"
167
+ ```
168
+
169
+ The command recurses with the same supported audio extensions used by the scanner
170
+ and only writes album artist, album title, and genre tags. It has been convenient for a bulk tag edit (album level) in some circumstances
171
+
172
+ ## YouTube Audio
173
+
174
+ Download audio-only YouTube media. Video URLs are split into chapter files:
175
+
176
+ ```bash
177
+ kukicha tools yt-download-audio "https://www.youtube.com/watch?v=VIDEO_ID"
178
+ ```
179
+
180
+ If yt-dlp does not report chapters, or you want to override them, provide a
181
+ manual chapter file:
182
+
183
+ ```bash
184
+ kukicha -c ~/kukicha.toml tools yt-download-audio \
185
+ --chapters-file chapters.txt \
186
+ "https://www.youtube.com/watch?v=VIDEO_ID"
187
+ ```
188
+
189
+ The chapter file uses one chapter per nonblank line. Lines starting with `#`
190
+ are ignored:
191
+
192
+ ```text
193
+ 0:00 Intro
194
+ 03:12 - Track Two
195
+ 1:02:03.5 Finale
196
+ ```
197
+
198
+ Playlist URLs are downloaded as one audio file per playlist item. Chapters
199
+ reported inside individual playlist items are ignored, and `--chapters-file`
200
+ cannot be used with playlist URLs.
201
+
202
+ Set `YoutubeDownloadPath` in `kukicha.toml` before running this command. The
203
+ tool checks that `ffmpeg`, `ffprobe`, and Deno 2.0.0 or newer are available.
204
+ yt-dlp temporary and staged files are kept in the user's OS temp folder and are
205
+ cleaned up when the command exits.
206
+
207
+ ## Run With launchd
208
+
209
+ Save this as `~/Library/LaunchAgents/com.kukicha.player.plist` and adjust paths
210
+ as needed:
211
+
212
+ ```xml
213
+ <?xml version="1.0" encoding="UTF-8"?>
214
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
215
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
216
+ <plist version="1.0">
217
+ <dict>
218
+ <key>Label</key>
219
+ <string>com.kukicha.player</string>
220
+
221
+ <key>ProgramArguments</key>
222
+ <array>
223
+ <string>/Users/YOUR_USERNAME/.local/bin/kukicha</string>
224
+ <string>-c</string>
225
+ <string>/Users/YOUR_USERNAME/.config/kukicha/kukicha.toml</string>
226
+ </array>
227
+
228
+ <key>RunAtLoad</key>
229
+ <true/>
230
+
231
+ <key>KeepAlive</key>
232
+ <dict>
233
+ <key>SuccessfulExit</key>
234
+ <false/>
235
+ </dict>
236
+
237
+ <key>StandardOutPath</key>
238
+ <string>/Users/YOUR_USERNAME/Library/Logs/kukicha-player.log</string>
239
+
240
+ <key>StandardErrorPath</key>
241
+ <string>/Users/YOUR_USERNAME/Library/Logs/kukicha-player.err.log</string>
242
+ </dict>
243
+ </plist>
244
+ ```
245
+
246
+ Load and start it:
247
+
248
+ ```bash
249
+ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.kukicha.player.plist
250
+ ```
251
+
252
+ Show the status
253
+ ```bash
254
+ launchctl print gui/$(id -u)/com.kukicha.player
255
+ ```
256
+
257
+ Restart the running server:
258
+
259
+ ```bash
260
+ launchctl kickstart -k gui/$(id -u)/com.kukicha.player
261
+ ```
262
+
263
+ Shut it down and unload it:
264
+
265
+ ```bash
266
+ launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.kukicha.player.plist
267
+ ```
268
+
269
+ After changing the plist, unload it with `bootout`, then load it again with
270
+ `bootstrap`. The `bootout` and `kickstart -k` commands trigger normal process
271
+ shutdown, and Kukicha logs shutdown with the same timestamped stdout/stderr
272
+ logging as startup.
@@ -0,0 +1,29 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "kukicha"
7
+ version = "0.1.0a1"
8
+ description = "Scan and query a SQLite-backed music metadata database."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ dependencies = [
12
+ "Flask>=3.1.0",
13
+ "Jinja2>=3.1.0",
14
+ "mutagen>=1.47.0",
15
+ "Pillow>=10.0.0",
16
+ "yt-dlp[default]==2026.3.17",
17
+ ]
18
+
19
+ [project.scripts]
20
+ kukicha = "kukicha.cli:main"
21
+
22
+ [tool.setuptools]
23
+ package-dir = {"" = "src"}
24
+
25
+ [tool.setuptools.packages.find]
26
+ where = ["src"]
27
+
28
+ [tool.setuptools.package-data]
29
+ kukicha = ["data/*.tsv", "templates/player/*.html", "static/*.css", "static/*.js", "static/*.svg"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ """kukicha package."""
@@ -0,0 +1,5 @@
1
+ from .cli import main
2
+
3
+
4
+ if __name__ == "__main__":
5
+ raise SystemExit(main())