@nikanjuri/buzzjam-cli 3.0.0

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nikhil Anjuri
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.
package/README.md ADDED
@@ -0,0 +1,403 @@
1
+ # Buzzjam — Lyrics Typewriter Player v3.0
2
+
3
+ A **complete**, **professional** Python application that downloads tracks, plays them, and displays synchronized lyrics with typewriter effects, karaoke mode, web interface, and more!
4
+
5
+ > **NEW in v3.0**: Karaoke Mode, Auto-Sync Tool, Playlists, Video Export, Web Interface, Spotify/SoundCloud Support, Automated Tests! [**See all v3.0 features →**](FEATURES_V3.md)
6
+
7
+ > ** NEWEST: Quick Play** - Just paste a YouTube URL and everything happens automatically! [**Quick Play Guide →**](QUICK_PLAY_GUIDE.md)
8
+
9
+ ![Version](https://img.shields.io/badge/version-3.0-blue)
10
+ ![Python](https://img.shields.io/badge/python-3.11+-green)
11
+ ![License](https://img.shields.io/badge/license-MIT-orange)
12
+
13
+ ---
14
+
15
+ ## **Quick Play - The Easiest Way!**
16
+
17
+ **Just paste a YouTube URL** and Buzzjam will:
18
+ 1. **Automatically fetch synced lyrics** from online sources
19
+ 2. **Download the audio** from YouTube
20
+ 3. **Play with synchronized display** instantly!
21
+
22
+ ### One Command - That's It!
23
+
24
+ ```bash
25
+ python quick_play.py "https://youtube.com/watch?v=YOUR_VIDEO_ID"
26
+ ```
27
+
28
+ **No manual configuration needed!** The system automatically:
29
+ - Extracts song metadata (artist, title)
30
+ - Searches multiple lyrics databases
31
+ - Downloads high-quality audio
32
+ - Plays with perfectly synced typewriter lyrics
33
+
34
+ [**See Quick Play Guide for details →**](QUICK_PLAY_GUIDE.md)
35
+
36
+ ---
37
+
38
+
39
+ ## Features
40
+
41
+ ### Audio & Playback
42
+ - Downloads audio via `yt-dlp` with automatic MP3 conversion
43
+ - Precise playback control (play, pause, resume, stop)
44
+ - Seek forward/backward with keyboard shortcuts
45
+ - Volume adjustment on-the-fly
46
+ - Support for local audio files (MP3, WAV, OGG, FLAC, M4A)
47
+
48
+ ### Lyrics & Display
49
+ - Typewriter effect with real-time sync to audio
50
+ - **LRC file format support** for standard lyrics files
51
+ - Preview upcoming lyrics
52
+ - **Colored terminal output** for enhanced visuals
53
+ - Real-time progress and timing display
54
+ - Live lyric offset adjustment (±0.25s increments)
55
+
56
+ ### Configuration
57
+ - **YAML configuration files** for easy customization
58
+ - **Command-line arguments** for quick operations
59
+ - Export configurations for reuse
60
+ - Multiple songs and playlists support
61
+
62
+ ### Developer Features
63
+ - **Modular architecture** for easy extension
64
+ - Type hints throughout codebase
65
+ - Test-ready structure
66
+ - Backward compatible with v1.0
67
+
68
+ ## Requirements
69
+
70
+ - **Python 3.11+**
71
+ - Virtual environment (recommended)
72
+
73
+ ## Quick Start
74
+
75
+ The easiest way to install Buzzjam is via npm. It will automatically handle downloading and isolating all Python dependencies for you!
76
+
77
+ ```bash
78
+ npm install -g @nikanjuri/buzzjam-cli
79
+ ```
80
+
81
+ *Don't have Node.js? Use our bash script instead:*
82
+ ```bash
83
+ curl -fsSL https://raw.githubusercontent.com/nikanjuri/buzzjam/main/install.sh | bash
84
+ ```
85
+
86
+ *(Homebrew support coming soon!)*
87
+
88
+ Channel release details: [DISTRIBUTION.md](DISTRIBUTION.md)
89
+
90
+ ### Available CLI Commands
91
+
92
+ After install, these commands are available:
93
+
94
+ ```bash
95
+ buzzjam --help
96
+ buzzjam play --file my_song.mp3 --lyrics song.lrc
97
+ buzzjam fetch-lyrics "https://youtube.com/watch?v=..." --json
98
+ buzzjam web --host 127.0.0.1 --port 5000
99
+ buzzjam web --no-open # headless/server mode
100
+ buzzjam-sync my_song.mp3 --output synced_lyrics.lrc
101
+ ```
102
+
103
+ If the selected web port is already in use, Buzzjam automatically picks a free port and prints the final URL.
104
+
105
+ For machine integrations, `play` can stream structured events:
106
+
107
+ ```bash
108
+ buzzjam play --file my_song.mp3 --lyrics song.lrc --events-jsonl --non-interactive
109
+ buzzjam play --file my_song.mp3 --events-file ./logs/buzzjam.jsonl --non-interactive
110
+ buzzjam play --file my_song.mp3 --events-jsonl --event-types playback.started,lyrics.line_started
111
+ ```
112
+
113
+ Event contract reference: [EVENTS.md](EVENTS.md)
114
+
115
+ Python applications can also run playback directly:
116
+
117
+ ```python
118
+ from buzzjam import Config, PlaybackSession
119
+ from buzzjam.playback_session import jsonl_event_printer
120
+
121
+ cfg = Config()
122
+ cfg.song.local_file = "my_song.mp3"
123
+ cfg.lyrics_file = "song.lrc"
124
+
125
+ session = PlaybackSession(cfg, event_handler=jsonl_event_printer, interactive=False)
126
+ ok = session.run()
127
+ ```
128
+
129
+ ### Run with Defaults
130
+
131
+ ```bash
132
+ # Using the new modular version
133
+ .venv/bin/buzzjam play
134
+
135
+ # Or activate venv first
136
+ source .venv/bin/activate
137
+ buzzjam play
138
+ ```
139
+
140
+ ### Run with Custom Options
141
+
142
+ ```bash
143
+ # Use a config file
144
+ buzzjam play --config my_song.yaml
145
+
146
+ # Specify YouTube URL and lyrics
147
+ buzzjam play --url "https://youtube.com/..." --lyrics song.lrc
148
+
149
+ # Use local file with custom start time
150
+ buzzjam play --file my_song.mp3 --lyrics song.lrc --start 30
151
+
152
+ # Quick play with title
153
+ buzzjam play --url "..." --title "My Favorite Song" --lyrics song.lrc
154
+ ```
155
+
156
+ ### Backward Compatibility
157
+
158
+ The original script still works:
159
+
160
+ ```bash
161
+ .venv/bin/python buzzjam.py
162
+ ```
163
+
164
+ ## Controls
165
+
166
+ Once the player is running, use these keyboard commands:
167
+
168
+ | Key | Action | Description |
169
+ |-----|--------|-------------|
170
+ | `p` | Pause | Pause playback |
171
+ | `r` | Resume | Resume playback |
172
+ | `[` | Earlier | Make lyrics appear 0.25s earlier |
173
+ | `]` | Later | Make lyrics appear 0.25s later |
174
+ | `,` | Skip Back | Skip backward 5 seconds |
175
+ | `.` | Skip Forward | Skip forward 5 seconds |
176
+ | `-` | Volume Down | Decrease volume by 10% |
177
+ | `+` or `=` | Volume Up | Increase volume by 10% |
178
+ | `o` | Show Offset | Display current lyric offset |
179
+ | `h` or `?` | Help | Show available commands |
180
+ | `s` or `q` | Stop | Stop playback and quit |
181
+
182
+ ## Configuration Files
183
+
184
+ ### YAML Config Example
185
+
186
+ Create a `config.yaml` file:
187
+
188
+ ```yaml
189
+ song:
190
+ youtube_url: "https://www.youtube.com/watch?v=..."
191
+ local_file: "" # Or path to local file
192
+ start_time: 0
193
+ title: "My Awesome Song"
194
+
195
+ playback:
196
+ char_delay: 0.12 # Typewriter speed
197
+ sample_rate: 44100 # Audio quality
198
+ volume: 1.0 # 0.0 to 1.0
199
+
200
+ display:
201
+ show_time: true # Show playback time
202
+ show_progress: true # Show progress percentage
203
+ show_preview: true # Show upcoming lyrics
204
+ preview_lines: 2 # Number of preview lines
205
+ colored_output: true # Use colors
206
+
207
+ lyrics_file: "lyrics.lrc"
208
+ output_dir: "."
209
+ ```
210
+
211
+ Then run:
212
+
213
+ ```bash
214
+ buzzjam play --config config.yaml
215
+ ```
216
+
217
+ ### LRC Lyrics Format
218
+
219
+ Create lyrics in standard LRC format (`song.lrc`):
220
+
221
+ ```lrc
222
+ [00:12.00]First line of lyrics
223
+ [00:15.50]Second line with decimal seconds
224
+ [01:23.00]Minute and seconds format
225
+ ```
226
+
227
+ **LRC Format Guide:**
228
+ - Timestamps: `[MM:SS.ss]`
229
+ - Minutes: 2 digits
230
+ - Seconds: 2 digits
231
+ - Centiseconds: Optional, 2 digits
232
+ - Text after timestamp
233
+
234
+ ## Project Structure
235
+
236
+ ```
237
+ buzzjam/
238
+ ├── buzzjam/ # Main package
239
+ │ ├── __init__.py # Package exports
240
+ │ ├── config.py # Configuration management
241
+ │ ├── downloader.py # YouTube/audio download
242
+ │ ├── player.py # Audio playback engine
243
+ │ ├── lyrics.py # Lyrics parsing & sync
244
+ │ └── controls.py # Input & display management
245
+ ├── buzzjam.py # Legacy script (v1.0)
246
+ ├── config.example.yaml # Example configuration
247
+ ├── lyrics.lrc # Example lyrics file
248
+ ├── .gitignore # Git exclusions
249
+ └── README.md # This file
250
+ ```
251
+
252
+ ## Features in Detail
253
+
254
+ ### Typewriter Effect
255
+
256
+ The typewriter effect synchronizes character-by-character with the music:
257
+
258
+ - **Smart timing**: Calculates how many characters should be visible based on elapsed time
259
+ - **Pause-aware**: Automatically pauses when music pauses
260
+ - **Offset adjustment**: Fine-tune timing on-the-fly with `[` and `]` keys
261
+
262
+ ### Preview Mode
263
+
264
+ See what's coming next:
265
+
266
+ ```
267
+ Currently typing: This is the current line...
268
+
269
+ Upcoming:
270
+ ↓ Next line preview
271
+ ↓ Line after that
272
+ ```
273
+
274
+ ### Status Display
275
+
276
+ Real-time information during playback:
277
+
278
+ ```
279
+ [02:15] Progress: 45% | Offset: -0.50s
280
+ ```
281
+
282
+ ## Advanced Usage
283
+
284
+ ### Export Your Configuration
285
+
286
+ Save your settings for reuse:
287
+
288
+ ```bash
289
+ buzzjam play --url "..." --lyrics song.lrc --export-config my_config.yaml
290
+ ```
291
+
292
+ ### Disable Colors
293
+
294
+ For terminals without color support:
295
+
296
+ ```bash
297
+ buzzjam play --no-color
298
+ ```
299
+
300
+ ### Create Custom Lyrics
301
+
302
+ You can create `.lrc` files manually or use online LRC editors:
303
+ - [LRC Editor Online](https://lrc-maker.github.io/)
304
+ - Or use the typewriter effect to time them yourself!
305
+
306
+ ## Troubleshooting
307
+
308
+ ### YouTube Rate Limits / Bot Blocks (Silent Hangs)
309
+ YouTube aggressively blocks automated scripts (`yt-dlp` and `spotdl`). If your downloads are silently hanging forever or instantly failing with HTTP 429, **you have been rate-limited**.
310
+
311
+ To bypass this, Buzzjam automatically detects your primary installed web browser (Safari, Chrome, Firefox, Edge, or Brave) and securely borrows its local cookies so YouTube trusts the download request. No manual setup is required!
312
+
313
+ *(Disclaimer: This extracts YouTube cookies locally to authenticate your request. If you have privacy concerns and wish to disable this behavior, you can run `export BUZZJAM_BROWSER="off"`).*
314
+
315
+ ### "No module named 'pygame'"
316
+
317
+ Make sure you're using the virtual environment Python:
318
+
319
+ ```bash
320
+ .venv/bin/buzzjam play
321
+ # Ensure your environment is active
322
+ ```
323
+
324
+ ### Download fails
325
+
326
+ If YouTube download fails:
327
+ 1. Update yt-dlp: `pip install -U yt-dlp`
328
+ 2. Check your internet connection
329
+ 3. Verify the URL is correct
330
+ 4. Try using a local file instead
331
+
332
+ ### Lyrics out of sync
333
+
334
+ Use the live adjustment controls:
335
+ - Press `[` to make lyrics appear earlier
336
+ - Press `]` to make lyrics appear later
337
+ - Each press adjusts by 0.25 seconds
338
+ - Press `o` to see current offset
339
+
340
+ ### No audio output
341
+
342
+ 1. Check your system audio settings
343
+ 2. Verify the audio file is valid
344
+ 3. Try adjusting volume with `+` or `-`
345
+ 4. Check if file exists: `ls -la song.mp3`
346
+
347
+ ## Development
348
+
349
+ ### Running Tests
350
+
351
+ ```bash
352
+ # TODO: Add tests
353
+ python -m pytest tests/
354
+ ```
355
+
356
+ ### Code Structure
357
+
358
+ The codebase follows these principles:
359
+ - **Separation of Concerns**: Each module has a single responsibility
360
+ - **Type Safety**: Type hints throughout
361
+ - **Error Handling**: Graceful degradation
362
+ - **Extensibility**: Easy to add new features
363
+
364
+ ### Adding New Features
365
+
366
+ To add a new control command:
367
+
368
+ ```python
369
+ # In buzzjam/playback_session.py, BuzzjamPlayer._setup_controls()
370
+ self.controls.register_command('x', self.my_function, "Description")
371
+ ```
372
+
373
+ ## Contributing
374
+
375
+ Contributions welcome! Areas for improvement:
376
+ - Add tests
377
+ - Support more audio sources (Spotify, SoundCloud)
378
+ - Karaoke mode with word-level highlighting
379
+ - Web interface
380
+ - Lyrics editing tool
381
+
382
+ ## License
383
+
384
+ Copyright © 2026. Licensed under the [MIT License](LICENSE). Feel free to use and modify!
385
+
386
+ ## Credits
387
+
388
+ Built with:
389
+ - [yt-dlp](https://github.com/yt-dlp/yt-dlp) - YouTube downloader
390
+ - [pygame](https://www.pygame.org/) - Audio playback
391
+ - [imageio-ffmpeg](https://github.com/imageio/imageio-ffmpeg) - FFmpeg binaries
392
+ - [colorama](https://github.com/tartley/colorama) - Colored terminal output
393
+ - [PyYAML](https://pyyaml.org/) - YAML parsing
394
+
395
+ ## Enjoy!
396
+
397
+ Now sit back, relax, and enjoy your music with synchronized lyrics!
398
+
399
+ For questions or issues, please open an issue on GitHub.
400
+
401
+ ---
402
+
403
+ **Pro Tip**: Create a collection of `.lrc` files for your favorite songs and keep them organized in a `lyrics/` folder!
package/bin/buzzjam.js ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawnSync } = require("node:child_process");
4
+ const path = require("node:path");
5
+ const os = require("node:os");
6
+ const fs = require("node:fs");
7
+
8
+ const repoSpec = process.env.BUZZJAM_INSTALL_SPEC || "git+https://github.com/nikanjuri/buzzjam.git";
9
+ const pythonBin = process.env.PYTHON_BIN || "python3";
10
+ const args = process.argv.slice(2);
11
+
12
+ const venvDir = path.join(os.homedir(), ".buzzjam-venv");
13
+ const venvPython = process.platform === "win32"
14
+ ? path.join(venvDir, "Scripts", "python.exe")
15
+ : path.join(venvDir, "bin", "python");
16
+
17
+ function run(command, commandArgs, options = {}) {
18
+ return spawnSync(command, commandArgs, {
19
+ stdio: "inherit",
20
+ ...options,
21
+ });
22
+ }
23
+
24
+ function runCapture(command, commandArgs) {
25
+ return spawnSync(command, commandArgs, {
26
+ stdio: ["ignore", "pipe", "pipe"],
27
+ encoding: "utf8",
28
+ });
29
+ }
30
+
31
+ function ensurePython() {
32
+ const check = runCapture(pythonBin, ["--version"]);
33
+ if (check.status !== 0) {
34
+ console.error(`Buzzjam requires ${pythonBin}. Please install Python 3 on your system first.`);
35
+ process.exit(check.status || 1);
36
+ }
37
+ }
38
+
39
+ function ensureVenvAndPackage() {
40
+ if (!fs.existsSync(venvDir)) {
41
+ console.log("\n📦 Setting up Buzzjam isolated Python environment (this may take a minute)...");
42
+ const venv = run(pythonBin, ["-m", "venv", venvDir]);
43
+ if (venv.status !== 0) {
44
+ console.error("❌ Failed to create virtual environment.");
45
+ process.exit(venv.status || 1);
46
+ }
47
+ }
48
+
49
+ const probe = runCapture(venvPython, ["-m", "pip", "show", "buzzjam"]);
50
+ if (probe.status === 0) return;
51
+
52
+ console.log("⬇️ Installing Buzzjam Python dependencies...\n");
53
+ const install = run(venvPython, ["-m", "pip", "install", "--upgrade", repoSpec]);
54
+ if (install.status !== 0) {
55
+ console.error("\n❌ Failed to install Buzzjam Python package.");
56
+ process.exit(install.status || 1);
57
+ }
58
+ console.log("\n✅ Buzzjam installed successfully!\n");
59
+ }
60
+
61
+ function runBuzzjam() {
62
+ const result = run(venvPython, ["-m", "buzzjam", ...args]);
63
+ process.exit(result.status || 0);
64
+ }
65
+
66
+ ensurePython();
67
+ ensureVenvAndPackage();
68
+ runBuzzjam();
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@nikanjuri/buzzjam-cli",
3
+ "version": "3.0.0",
4
+ "description": "Global npm wrapper for the Buzzjam Python CLI",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "buzzjam": "bin/buzzjam.js"
8
+ },
9
+ "files": [
10
+ "bin"
11
+ ],
12
+ "keywords": [
13
+ "buzzjam",
14
+ "lyrics",
15
+ "karaoke",
16
+ "cli"
17
+ ],
18
+ "engines": {
19
+ "node": ">=18"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/nikanjuri/buzzjam.git"
24
+ },
25
+ "homepage": "https://github.com/nikanjuri/buzzjam",
26
+ "bugs": {
27
+ "url": "https://github.com/nikanjuri/buzzjam/issues"
28
+ }
29
+ }