plexmix 0.1.0__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.
- plexmix-0.1.0/PKG-INFO +394 -0
- plexmix-0.1.0/README.md +362 -0
- plexmix-0.1.0/pyproject.toml +61 -0
- plexmix-0.1.0/src/plexmix/__init__.py +20 -0
- plexmix-0.1.0/src/plexmix/ai/__init__.py +51 -0
- plexmix-0.1.0/src/plexmix/ai/base.py +113 -0
- plexmix-0.1.0/src/plexmix/ai/claude_provider.py +50 -0
- plexmix-0.1.0/src/plexmix/ai/gemini_provider.py +64 -0
- plexmix-0.1.0/src/plexmix/ai/openai_provider.py +50 -0
- plexmix-0.1.0/src/plexmix/ai/tag_generator.py +274 -0
- plexmix-0.1.0/src/plexmix/cli/__init__.py +0 -0
- plexmix-0.1.0/src/plexmix/cli/main.py +678 -0
- plexmix-0.1.0/src/plexmix/config/__init__.py +0 -0
- plexmix-0.1.0/src/plexmix/config/credentials.py +73 -0
- plexmix-0.1.0/src/plexmix/config/settings.py +132 -0
- plexmix-0.1.0/src/plexmix/database/__init__.py +0 -0
- plexmix-0.1.0/src/plexmix/database/models.py +166 -0
- plexmix-0.1.0/src/plexmix/database/sqlite_manager.py +433 -0
- plexmix-0.1.0/src/plexmix/database/vector_index.py +169 -0
- plexmix-0.1.0/src/plexmix/playlist/__init__.py +0 -0
- plexmix-0.1.0/src/plexmix/playlist/generator.py +195 -0
- plexmix-0.1.0/src/plexmix/plex/__init__.py +0 -0
- plexmix-0.1.0/src/plexmix/plex/client.py +278 -0
- plexmix-0.1.0/src/plexmix/plex/sync.py +275 -0
- plexmix-0.1.0/src/plexmix/utils/__init__.py +0 -0
- plexmix-0.1.0/src/plexmix/utils/embeddings.py +286 -0
- plexmix-0.1.0/src/plexmix/utils/logging.py +64 -0
plexmix-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: plexmix
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AI-powered Plex playlist generator using mood-based queries
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: Anthony Izzo
|
|
7
|
+
Requires-Python: >=3.10,<4.0
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Requires-Dist: anthropic (>=0.8.0,<0.9.0)
|
|
16
|
+
Requires-Dist: click (==8.1.7)
|
|
17
|
+
Requires-Dist: faiss-cpu (>=1.7.4,<2.0.0)
|
|
18
|
+
Requires-Dist: google-generativeai (>=0.3.0,<0.4.0)
|
|
19
|
+
Requires-Dist: keyring (>=24.3.0,<25.0.0)
|
|
20
|
+
Requires-Dist: numpy (>=1.26.0,<2.0.0)
|
|
21
|
+
Requires-Dist: openai (>=1.6.0,<2.0.0)
|
|
22
|
+
Requires-Dist: plexapi (>=4.15.0,<5.0.0)
|
|
23
|
+
Requires-Dist: pydantic (>=2.5.0,<3.0.0)
|
|
24
|
+
Requires-Dist: pydantic-settings (>=2.1.0,<3.0.0)
|
|
25
|
+
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
|
26
|
+
Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
|
|
27
|
+
Requires-Dist: rich (>=13.7.0,<14.0.0)
|
|
28
|
+
Requires-Dist: sentence-transformers (>=2.2.0,<3.0.0)
|
|
29
|
+
Requires-Dist: typer (>=0.12.0,<0.13.0)
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# PlexMix
|
|
33
|
+
|
|
34
|
+
[](https://opensource.org/licenses/MIT)
|
|
35
|
+
|
|
36
|
+
**AI-powered Plex playlist generator using mood-based queries**
|
|
37
|
+
|
|
38
|
+
PlexMix syncs your Plex music library to a local SQLite database, generates semantic embeddings for tracks, and uses AI to create personalized playlists based on mood descriptions.
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
- ✨ **Simple Setup** - Only requires a Google API key to get started
|
|
43
|
+
- 🎵 **Smart Sync** - Syncs Plex music library with incremental updates
|
|
44
|
+
- 🤖 **AI-Powered** - Uses Google Gemini, OpenAI GPT, or Anthropic Claude
|
|
45
|
+
- 🏷️ **AI Tagging** - Automatically generates tags, environments, and instruments for tracks
|
|
46
|
+
- 🔍 **Semantic Search** - FAISS vector similarity search for intelligent track matching
|
|
47
|
+
- 🎨 **Mood-Based** - Generate playlists from natural language descriptions
|
|
48
|
+
- ⚡ **Fast** - Local database with optimized indexes and full-text search
|
|
49
|
+
- 🎯 **Flexible** - Filter by genre, year, rating, artist, environment, and instrument
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Install dependencies
|
|
55
|
+
poetry install
|
|
56
|
+
|
|
57
|
+
# Run setup wizard
|
|
58
|
+
poetry run plexmix config init
|
|
59
|
+
|
|
60
|
+
# Sync your Plex library (generates embeddings automatically)
|
|
61
|
+
poetry run plexmix sync full
|
|
62
|
+
|
|
63
|
+
# Generate AI tags for tracks (enhances search quality)
|
|
64
|
+
poetry run plexmix tags generate
|
|
65
|
+
|
|
66
|
+
# Create a playlist
|
|
67
|
+
poetry run plexmix create "upbeat morning energy"
|
|
68
|
+
|
|
69
|
+
# With filters
|
|
70
|
+
poetry run plexmix create "chill evening vibes" --genre jazz --year-min 2010 --limit 30
|
|
71
|
+
|
|
72
|
+
# Filter by environment and instrument
|
|
73
|
+
poetry run plexmix create "focus music" --environment study --instrument piano
|
|
74
|
+
|
|
75
|
+
# Use alternative AI provider
|
|
76
|
+
poetry run plexmix create "workout motivation" --provider openai
|
|
77
|
+
|
|
78
|
+
# If you encounter issues (e.g., "0 candidate tracks")
|
|
79
|
+
poetry run plexmix doctor
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Installation
|
|
83
|
+
|
|
84
|
+
### From Source (Recommended)
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
git clone https://github.com/izzoa/plexmix.git
|
|
88
|
+
cd plexmix
|
|
89
|
+
poetry install
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### From PyPI (Coming Soon)
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pip install plexmix
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Configuration
|
|
99
|
+
|
|
100
|
+
PlexMix uses **Google Gemini by default** for both AI playlist generation and embeddings, requiring only a **single API key**!
|
|
101
|
+
|
|
102
|
+
### Required
|
|
103
|
+
|
|
104
|
+
- **Plex Server**: URL and authentication token
|
|
105
|
+
- **Google API Key**: For Gemini AI and embeddings ([Get one here](https://makersuite.google.com/app/apikey))
|
|
106
|
+
|
|
107
|
+
### Optional Alternative Providers
|
|
108
|
+
|
|
109
|
+
- **OpenAI API Key**: For GPT models and text-embedding-3-small
|
|
110
|
+
- **Anthropic API Key**: For Claude models
|
|
111
|
+
- **Local Embeddings**: sentence-transformers (free, offline, no API key needed)
|
|
112
|
+
|
|
113
|
+
### Getting a Plex Token
|
|
114
|
+
|
|
115
|
+
1. Open Plex Web App
|
|
116
|
+
2. Play any media item
|
|
117
|
+
3. Click the three dots (...) → Get Info
|
|
118
|
+
4. View XML
|
|
119
|
+
5. Copy the `X-Plex-Token` from the URL
|
|
120
|
+
|
|
121
|
+
## Usage
|
|
122
|
+
|
|
123
|
+
### Configuration Commands
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Interactive setup wizard
|
|
127
|
+
plexmix config init
|
|
128
|
+
|
|
129
|
+
# Show current configuration
|
|
130
|
+
plexmix config show
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Sync Commands
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Full sync with embedding generation
|
|
137
|
+
plexmix sync full
|
|
138
|
+
|
|
139
|
+
# Sync without embeddings
|
|
140
|
+
plexmix sync full --no-embeddings
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Database Health Check
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Diagnose and fix database issues
|
|
147
|
+
plexmix doctor
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**What does doctor do?**
|
|
151
|
+
- Detects orphaned embeddings (embeddings that reference deleted tracks)
|
|
152
|
+
- Shows database health status (track count, embeddings, orphans)
|
|
153
|
+
- Interactively removes orphaned data
|
|
154
|
+
- Regenerates missing embeddings
|
|
155
|
+
- Rebuilds vector index
|
|
156
|
+
|
|
157
|
+
**When to use:**
|
|
158
|
+
- After "No tracks found matching criteria" errors
|
|
159
|
+
- When playlist generation finds 0 candidates
|
|
160
|
+
- After database corruption or manual track deletion
|
|
161
|
+
- Periodic maintenance to keep database healthy
|
|
162
|
+
|
|
163
|
+
### Tag Generation
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Generate AI tags for all untagged tracks
|
|
167
|
+
plexmix tags generate
|
|
168
|
+
|
|
169
|
+
# Use alternative AI provider
|
|
170
|
+
plexmix tags generate --provider openai
|
|
171
|
+
|
|
172
|
+
# Skip embedding regeneration (faster, but tags won't be in search)
|
|
173
|
+
plexmix tags generate --no-regenerate-embeddings
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**What are tags?**
|
|
177
|
+
AI-generated metadata (per track) that enhances semantic search:
|
|
178
|
+
- **Tags** (3-5): Mood descriptors like energetic, melancholic, upbeat, chill, intense
|
|
179
|
+
- **Environments** (1-3): Best-fit contexts like work, study, focus, relax, party, workout, sleep, driving, social
|
|
180
|
+
- **Instruments** (1-3): Most prominent instruments like piano, guitar, saxophone, drums, bass, synth, vocals, strings
|
|
181
|
+
|
|
182
|
+
All metadata is automatically included in embeddings for more accurate mood-based playlist generation.
|
|
183
|
+
|
|
184
|
+
### Playlist Generation
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Basic playlist (prompts for track count)
|
|
188
|
+
plexmix create "happy upbeat summer vibes"
|
|
189
|
+
|
|
190
|
+
# Specify track count
|
|
191
|
+
plexmix create "rainy day melancholy" --limit 25
|
|
192
|
+
|
|
193
|
+
# Filter by genre
|
|
194
|
+
plexmix create "energetic workout" --genre rock --limit 40
|
|
195
|
+
|
|
196
|
+
# Filter by year range
|
|
197
|
+
plexmix create "90s nostalgia" --year-min 1990 --year-max 1999
|
|
198
|
+
|
|
199
|
+
# Filter by environment (work, study, focus, relax, party, workout, sleep, driving, social)
|
|
200
|
+
plexmix create "workout energy" --environment workout
|
|
201
|
+
|
|
202
|
+
# Filter by instrument (piano, guitar, saxophone, drums, etc.)
|
|
203
|
+
plexmix create "piano jazz" --instrument piano
|
|
204
|
+
|
|
205
|
+
# Use specific AI provider
|
|
206
|
+
plexmix create "chill study session" --provider claude
|
|
207
|
+
|
|
208
|
+
# Custom playlist name
|
|
209
|
+
plexmix create "morning coffee" --name "Perfect Morning Mix"
|
|
210
|
+
|
|
211
|
+
# Don't create in Plex (save locally only)
|
|
212
|
+
plexmix create "test playlist" --no-create-in-plex
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Architecture
|
|
216
|
+
|
|
217
|
+
PlexMix uses a two-stage retrieval system with AI-enhanced tagging:
|
|
218
|
+
|
|
219
|
+
1. **AI Tagging** → Tracks receive:
|
|
220
|
+
- 3-5 descriptive tags (mood, energy, tempo, emotion)
|
|
221
|
+
- 1-3 environments (work, study, focus, relax, party, workout, sleep, driving, social)
|
|
222
|
+
- 1-3 instruments (piano, guitar, saxophone, drums, bass, synth, vocals, strings, etc.)
|
|
223
|
+
2. **SQL Filters** → Filter tracks by genre, year, rating, artist, environment, instrument
|
|
224
|
+
3. **FAISS Similarity Search** → Retrieve top-K candidates using semantic embeddings (includes all metadata)
|
|
225
|
+
4. **LLM Selection** → AI provider selects final tracks matching the mood
|
|
226
|
+
|
|
227
|
+
### Technology Stack
|
|
228
|
+
|
|
229
|
+
- **Language**: Python 3.10+
|
|
230
|
+
- **CLI**: Typer with Rich console output
|
|
231
|
+
- **Database**: SQLite with FTS5 full-text search
|
|
232
|
+
- **Vector Search**: FAISS (CPU) with cosine similarity
|
|
233
|
+
- **AI Providers**: Google Gemini (default), OpenAI GPT, Anthropic Claude
|
|
234
|
+
- **Embeddings**: Google Gemini (3072d), OpenAI (1536d), Local (384-768d)
|
|
235
|
+
- **Plex Integration**: PlexAPI
|
|
236
|
+
|
|
237
|
+
### Project Structure
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
plexmix/
|
|
241
|
+
├── src/plexmix/
|
|
242
|
+
│ ├── ai/ # AI provider implementations
|
|
243
|
+
│ │ ├── base.py # Abstract base class
|
|
244
|
+
│ │ ├── gemini_provider.py
|
|
245
|
+
│ │ ├── openai_provider.py
|
|
246
|
+
│ │ ├── claude_provider.py
|
|
247
|
+
│ │ └── tag_generator.py # AI-based tag generation
|
|
248
|
+
│ ├── cli/ # Command-line interface
|
|
249
|
+
│ │ └── main.py # Typer CLI app
|
|
250
|
+
│ ├── config/ # Configuration management
|
|
251
|
+
│ │ ├── settings.py # Pydantic settings
|
|
252
|
+
│ │ └── credentials.py # Keyring integration
|
|
253
|
+
│ ├── database/ # Database layer
|
|
254
|
+
│ │ ├── models.py # Pydantic models
|
|
255
|
+
│ │ ├── sqlite_manager.py # SQLite CRUD
|
|
256
|
+
│ │ └── vector_index.py # FAISS index
|
|
257
|
+
│ ├── plex/ # Plex integration
|
|
258
|
+
│ │ ├── client.py # PlexAPI wrapper
|
|
259
|
+
│ │ └── sync.py # Sync engine
|
|
260
|
+
│ ├── playlist/ # Playlist generation
|
|
261
|
+
│ │ └── generator.py # Core generation logic
|
|
262
|
+
│ └── utils/ # Utilities
|
|
263
|
+
│ ├── embeddings.py # Embedding providers
|
|
264
|
+
│ └── logging.py # Logging setup
|
|
265
|
+
└── tests/ # Test suite
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Database Schema
|
|
269
|
+
|
|
270
|
+
PlexMix stores all music metadata locally:
|
|
271
|
+
|
|
272
|
+
- **artists**: Artist information
|
|
273
|
+
- **albums**: Album details with artist relationships
|
|
274
|
+
- **tracks**: Track metadata with full-text search, AI-generated tags (3-5), environments (1-3), and instruments (1-3)
|
|
275
|
+
- **embeddings**: Vector embeddings for semantic search (includes all AI-generated metadata)
|
|
276
|
+
- **playlists**: Generated playlist metadata
|
|
277
|
+
- **sync_history**: Synchronization audit log
|
|
278
|
+
|
|
279
|
+
## Embedding Providers
|
|
280
|
+
|
|
281
|
+
| Provider | Model | Dimensions | API Key Required |
|
|
282
|
+
|----------|-------|------------|------------------|
|
|
283
|
+
| **Google Gemini** (default) | gemini-embedding-001 | 3072 | Yes |
|
|
284
|
+
| OpenAI | text-embedding-3-small | 1536 | Yes |
|
|
285
|
+
| Local | all-MiniLM-L6-v2 | 384 | No |
|
|
286
|
+
|
|
287
|
+
## AI Providers
|
|
288
|
+
|
|
289
|
+
| Provider | Model | Context | Notes |
|
|
290
|
+
|----------|-------|---------|-------|
|
|
291
|
+
| **Google Gemini** (default) | gemini-2.5-flash | ~1M tokens | Fast, accurate, cost-effective |
|
|
292
|
+
| OpenAI | gpt-5-mini | ~400K tokens | Latest model, high quality |
|
|
293
|
+
| OpenAI | gpt-5-nano | ~400K tokens | Fastest, most efficient |
|
|
294
|
+
| OpenAI | gpt-4o-mini | ~128K tokens | Previous generation |
|
|
295
|
+
| Anthropic | claude-sonnet-4-5 | ~200K tokens | Latest model, excellent reasoning |
|
|
296
|
+
| Anthropic | claude-3-5-haiku-20241022 | ~200K tokens | Fast, efficient |
|
|
297
|
+
|
|
298
|
+
## Development
|
|
299
|
+
|
|
300
|
+
### Setup Development Environment
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
# Clone repository
|
|
304
|
+
git clone https://github.com/izzoa/plexmix.git
|
|
305
|
+
cd plexmix
|
|
306
|
+
|
|
307
|
+
# Install with development dependencies
|
|
308
|
+
poetry install
|
|
309
|
+
|
|
310
|
+
# Run tests
|
|
311
|
+
poetry run pytest
|
|
312
|
+
|
|
313
|
+
# Format code
|
|
314
|
+
poetry run black src/
|
|
315
|
+
|
|
316
|
+
# Lint
|
|
317
|
+
poetry run ruff src/
|
|
318
|
+
|
|
319
|
+
# Type check
|
|
320
|
+
poetry run mypy src/
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Running Tests
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
poetry run pytest
|
|
327
|
+
poetry run pytest --cov=plexmix --cov-report=html
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Troubleshooting
|
|
331
|
+
|
|
332
|
+
### "No music libraries found"
|
|
333
|
+
- Ensure your Plex server has a music library
|
|
334
|
+
- Verify your Plex token is correct
|
|
335
|
+
- Check server URL is accessible
|
|
336
|
+
|
|
337
|
+
### "Failed to generate embeddings"
|
|
338
|
+
- Verify API keys are configured correctly
|
|
339
|
+
- Check internet connection
|
|
340
|
+
- Try local embeddings: `--embedding-provider local`
|
|
341
|
+
|
|
342
|
+
### "No tracks found matching criteria"
|
|
343
|
+
- **First, try:** `plexmix doctor` to check for database issues
|
|
344
|
+
- Ensure library is synced: `plexmix sync full`
|
|
345
|
+
- Check filters aren't too restrictive
|
|
346
|
+
- Verify embeddings were generated
|
|
347
|
+
|
|
348
|
+
### "0 candidate tracks" or "No orphaned embeddings"
|
|
349
|
+
- This usually means embeddings reference old track IDs
|
|
350
|
+
- **Solution:** Run `plexmix doctor` to detect and fix orphaned embeddings
|
|
351
|
+
- The doctor will clean up orphaned data and regenerate embeddings
|
|
352
|
+
|
|
353
|
+
### Performance Tips
|
|
354
|
+
|
|
355
|
+
- Use local embeddings for faster offline operation
|
|
356
|
+
- Run sync during off-peak hours for large libraries
|
|
357
|
+
- Adjust candidate pool size based on library size
|
|
358
|
+
- Use filters to narrow search space
|
|
359
|
+
|
|
360
|
+
## Roadmap
|
|
361
|
+
|
|
362
|
+
- [ ] Docker support
|
|
363
|
+
- [ ] Web UI dashboard
|
|
364
|
+
- [ ] Multi-library support
|
|
365
|
+
- [ ] Playlist templates
|
|
366
|
+
- [ ] Smart shuffle and ordering
|
|
367
|
+
- [ ] Export/import playlists (M3U, JSON)
|
|
368
|
+
- [ ] Audio feature analysis integration
|
|
369
|
+
|
|
370
|
+
## Contributing
|
|
371
|
+
|
|
372
|
+
Contributions welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
373
|
+
|
|
374
|
+
1. Fork the repository
|
|
375
|
+
2. Create a feature branch
|
|
376
|
+
3. Make your changes
|
|
377
|
+
4. Add tests
|
|
378
|
+
5. Submit a pull request
|
|
379
|
+
|
|
380
|
+
## License
|
|
381
|
+
|
|
382
|
+
MIT License - see [LICENSE](LICENSE) for details
|
|
383
|
+
|
|
384
|
+
## Acknowledgments
|
|
385
|
+
|
|
386
|
+
- Built with [Typer](https://typer.tiangolo.com/) and [Rich](https://rich.readthedocs.io/)
|
|
387
|
+
- Plex integration via [python-plexapi](https://github.com/pkkid/python-plexapi)
|
|
388
|
+
- Vector search powered by [FAISS](https://github.com/facebookresearch/faiss)
|
|
389
|
+
- AI providers: Google, OpenAI, Anthropic
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
**Made with ❤️ for music lovers**
|
|
394
|
+
|