veloura-audio 0.3.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.
Files changed (35) hide show
  1. veloura_audio-0.3.0/MANIFEST.in +4 -0
  2. veloura_audio-0.3.0/PKG-INFO +188 -0
  3. veloura_audio-0.3.0/README.md +159 -0
  4. veloura_audio-0.3.0/docs/release_checklist.md +53 -0
  5. veloura_audio-0.3.0/docs/veloura_scope.md +86 -0
  6. veloura_audio-0.3.0/examples/streamer_player.py +145 -0
  7. veloura_audio-0.3.0/pyproject.toml +57 -0
  8. veloura_audio-0.3.0/setup.cfg +4 -0
  9. veloura_audio-0.3.0/tests/test_beat_aware_experiment.py +93 -0
  10. veloura_audio-0.3.0/tests/test_veloura_audio.py +266 -0
  11. veloura_audio-0.3.0/tests/test_veloura_cache.py +119 -0
  12. veloura_audio-0.3.0/tests/test_veloura_pcm.py +48 -0
  13. veloura_audio-0.3.0/tests/test_veloura_public_api.py +87 -0
  14. veloura_audio-0.3.0/veloura/__init__.py +5 -0
  15. veloura_audio-0.3.0/veloura/__main__.py +6 -0
  16. veloura_audio-0.3.0/veloura/audio/__init__.py +99 -0
  17. veloura_audio-0.3.0/veloura/audio/beat.py +485 -0
  18. veloura_audio-0.3.0/veloura/audio/cache.py +130 -0
  19. veloura_audio-0.3.0/veloura/audio/constants.py +23 -0
  20. veloura_audio-0.3.0/veloura/audio/crossfade.py +287 -0
  21. veloura_audio-0.3.0/veloura/audio/ffmpeg_stream.py +123 -0
  22. veloura_audio-0.3.0/veloura/audio/models.py +83 -0
  23. veloura_audio-0.3.0/veloura/audio/pcm.py +83 -0
  24. veloura_audio-0.3.0/veloura/audio/presets.py +75 -0
  25. veloura_audio-0.3.0/veloura/audio/resolver.py +70 -0
  26. veloura_audio-0.3.0/veloura/audio/session.py +139 -0
  27. veloura_audio-0.3.0/veloura/audio/transition.py +376 -0
  28. veloura_audio-0.3.0/veloura/cli.py +192 -0
  29. veloura_audio-0.3.0/veloura/py.typed +1 -0
  30. veloura_audio-0.3.0/veloura_audio.egg-info/PKG-INFO +188 -0
  31. veloura_audio-0.3.0/veloura_audio.egg-info/SOURCES.txt +33 -0
  32. veloura_audio-0.3.0/veloura_audio.egg-info/dependency_links.txt +1 -0
  33. veloura_audio-0.3.0/veloura_audio.egg-info/entry_points.txt +2 -0
  34. veloura_audio-0.3.0/veloura_audio.egg-info/requires.txt +12 -0
  35. veloura_audio-0.3.0/veloura_audio.egg-info/top_level.txt +1 -0
@@ -0,0 +1,4 @@
1
+ include README.md
2
+ recursive-include docs *.md
3
+ recursive-include examples *.py
4
+ recursive-include tests *.py
@@ -0,0 +1,188 @@
1
+ Metadata-Version: 2.4
2
+ Name: veloura-audio
3
+ Version: 0.3.0
4
+ Summary: Reusable Python audio engine with crossfade and beat-aware transition planning.
5
+ Project-URL: Homepage, https://github.com/VelouraAudio/veloura-audio
6
+ Project-URL: Repository, https://github.com/VelouraAudio/veloura-audio
7
+ Project-URL: Issues, https://github.com/VelouraAudio/veloura-audio/issues
8
+ Keywords: audio,crossfade,ffmpeg,music,streaming
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Multimedia :: Sound/Audio
16
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Mixers
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Requires-Python: >=3.12
19
+ Description-Content-Type: text/markdown
20
+ Provides-Extra: stream
21
+ Requires-Dist: yt-dlp>=2026.3.17; extra == "stream"
22
+ Provides-Extra: discord
23
+ Requires-Dist: discord.py>=2.3.0; extra == "discord"
24
+ Requires-Dist: PyNaCl>=1.5.0; extra == "discord"
25
+ Provides-Extra: all
26
+ Requires-Dist: discord.py>=2.3.0; extra == "all"
27
+ Requires-Dist: PyNaCl>=1.5.0; extra == "all"
28
+ Requires-Dist: yt-dlp>=2026.3.17; extra == "all"
29
+
30
+ # Veloura
31
+
32
+ Veloura is a reusable Python audio transition engine for smooth queue playback.
33
+ It provides FFmpeg-backed PCM decoding, equal-power crossfades, transition
34
+ analysis, beat-aware planning, and a small CLI for local inspection.
35
+
36
+ Veloura is framework-agnostic. Use it in streamer tools, radio pipelines,
37
+ desktop music apps, Discord/Twitch bots, or backend automation without tying
38
+ your project to one bot implementation.
39
+
40
+ ## Features
41
+
42
+ - Equal-power crossfade mixing for signed 16-bit PCM audio
43
+ - Queue/session helpers for buffering, skip, and current-track snapshots
44
+ - Smart transition planning based on track duration, silence trim, and loudness
45
+ - Beat/BPM analysis with beat-aware transition plans
46
+ - Project-local or user-cache transition analysis storage
47
+ - Optional `yt-dlp` stream resolution for URLs and search queries
48
+ - Optional Discord audio source compatibility
49
+ - Pure-Python PCM fallback for Python builds without `audioop`
50
+
51
+ ## Requirements
52
+
53
+ - Python 3.12 or newer
54
+ - FFmpeg for decoding, playback, silence analysis, loudness analysis, and beat
55
+ analysis
56
+ - `yt-dlp` only when resolving online stream/search inputs
57
+ - `discord.py` and `PyNaCl` only when using the Discord audio source directly
58
+
59
+ ## Installation
60
+
61
+ Install the core package:
62
+
63
+ ```bash
64
+ pip install veloura-audio
65
+ ```
66
+
67
+ Install stream resolution support:
68
+
69
+ ```bash
70
+ pip install "veloura-audio[stream]"
71
+ ```
72
+
73
+ Install Discord voice support:
74
+
75
+ ```bash
76
+ pip install "veloura-audio[discord]"
77
+ ```
78
+
79
+ Install every optional integration:
80
+
81
+ ```bash
82
+ pip install "veloura-audio[all]"
83
+ ```
84
+
85
+ ## Quick Start
86
+
87
+ ```python
88
+ from veloura.audio import AudioTrack, CrossfadeSession, transition_preset
89
+
90
+ config = transition_preset("streamer")
91
+
92
+ track = AudioTrack.from_source(
93
+ "/music/current-song.flac",
94
+ title="Artist - Current Song",
95
+ duration=184,
96
+ )
97
+
98
+ session = CrossfadeSession(volume=0.65, crossfade_seconds=config.base_crossfade_seconds)
99
+ session.source.enqueue(track)
100
+ ```
101
+
102
+ For online sources, install `veloura-audio[stream]` and resolve a playable stream:
103
+
104
+ ```python
105
+ import asyncio
106
+
107
+ from veloura.audio import resolve_stream_track, transition_preset
108
+
109
+
110
+ async def main():
111
+ track = await resolve_stream_track(
112
+ "artist song official audio",
113
+ transition_config=transition_preset("streamer"),
114
+ )
115
+ print(track.title, track.stream_url)
116
+
117
+
118
+ asyncio.run(main())
119
+ ```
120
+
121
+ ## CLI
122
+
123
+ Veloura exposes the same core tools through `python -m veloura` or the
124
+ `veloura` console script:
125
+
126
+ ```bash
127
+ python -m veloura presets
128
+ python -m veloura prepare ./song.mp3 --preset streamer
129
+ python -m veloura analyze ./song.mp3
130
+ python -m veloura plan ./current.mp3 ./next.mp3 --preset broadcast
131
+ ```
132
+
133
+ For YouTube/search inputs, install `veloura-audio[stream]` and add `--resolve`:
134
+
135
+ ```bash
136
+ python -m veloura plan "current song" "next song" --preset streamer --resolve
137
+ ```
138
+
139
+ Transition analysis is cached under `~/.cache/veloura` by default, or under the
140
+ directory set in `VELOURA_CACHE_DIR`. Use `--cache-dir` for a project-local
141
+ cache, or `--no-cache` when comparing fresh analysis.
142
+
143
+ ## Presets
144
+
145
+ - `streamer`: balanced transitions for livestream/background music
146
+ - `broadcast`: longer, smoother radio-style blends
147
+ - `low-latency`: shorter analysis windows for weaker machines or fast queues
148
+
149
+ Aliases such as `streamer-safe`, `broadcast-smooth`, and `fast` are also
150
+ available.
151
+
152
+ ## Standalone Example
153
+
154
+ The example player resolves local files or stream queries, prepares transition
155
+ analysis, mixes the queue, and pipes PCM into `ffplay`:
156
+
157
+ ```bash
158
+ python examples/streamer_player.py ./song-a.mp3 ./song-b.mp3 --preset streamer
159
+ python examples/streamer_player.py ./song-a.mp3 ./song-b.mp3 --cache-dir ./veloura-cache
160
+ ```
161
+
162
+ ## Public API
163
+
164
+ Prefer these names for new projects:
165
+
166
+ - `AudioTrack`
167
+ - `CrossfadeSession`
168
+ - `FileAnalysisCache`
169
+ - `transition_preset`
170
+ - `prepare_smart_transition`
171
+ - `plan_beat_transition`
172
+ - `resolve_stream_track`
173
+
174
+ Compatibility names:
175
+
176
+ - `MixerTrack`
177
+ - `CrossfadeAudioSource`
178
+
179
+ ## Development Checks
180
+
181
+ ```bash
182
+ python3 -m unittest discover -s tests
183
+ python3 -m py_compile veloura/*.py veloura/audio/*.py examples/*.py
184
+ ```
185
+
186
+ Before publishing publicly, confirm the package name on PyPI, add project URLs,
187
+ choose the license/copyright owner, build the distribution, and publish to
188
+ TestPyPI first.
@@ -0,0 +1,159 @@
1
+ # Veloura
2
+
3
+ Veloura is a reusable Python audio transition engine for smooth queue playback.
4
+ It provides FFmpeg-backed PCM decoding, equal-power crossfades, transition
5
+ analysis, beat-aware planning, and a small CLI for local inspection.
6
+
7
+ Veloura is framework-agnostic. Use it in streamer tools, radio pipelines,
8
+ desktop music apps, Discord/Twitch bots, or backend automation without tying
9
+ your project to one bot implementation.
10
+
11
+ ## Features
12
+
13
+ - Equal-power crossfade mixing for signed 16-bit PCM audio
14
+ - Queue/session helpers for buffering, skip, and current-track snapshots
15
+ - Smart transition planning based on track duration, silence trim, and loudness
16
+ - Beat/BPM analysis with beat-aware transition plans
17
+ - Project-local or user-cache transition analysis storage
18
+ - Optional `yt-dlp` stream resolution for URLs and search queries
19
+ - Optional Discord audio source compatibility
20
+ - Pure-Python PCM fallback for Python builds without `audioop`
21
+
22
+ ## Requirements
23
+
24
+ - Python 3.12 or newer
25
+ - FFmpeg for decoding, playback, silence analysis, loudness analysis, and beat
26
+ analysis
27
+ - `yt-dlp` only when resolving online stream/search inputs
28
+ - `discord.py` and `PyNaCl` only when using the Discord audio source directly
29
+
30
+ ## Installation
31
+
32
+ Install the core package:
33
+
34
+ ```bash
35
+ pip install veloura-audio
36
+ ```
37
+
38
+ Install stream resolution support:
39
+
40
+ ```bash
41
+ pip install "veloura-audio[stream]"
42
+ ```
43
+
44
+ Install Discord voice support:
45
+
46
+ ```bash
47
+ pip install "veloura-audio[discord]"
48
+ ```
49
+
50
+ Install every optional integration:
51
+
52
+ ```bash
53
+ pip install "veloura-audio[all]"
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ```python
59
+ from veloura.audio import AudioTrack, CrossfadeSession, transition_preset
60
+
61
+ config = transition_preset("streamer")
62
+
63
+ track = AudioTrack.from_source(
64
+ "/music/current-song.flac",
65
+ title="Artist - Current Song",
66
+ duration=184,
67
+ )
68
+
69
+ session = CrossfadeSession(volume=0.65, crossfade_seconds=config.base_crossfade_seconds)
70
+ session.source.enqueue(track)
71
+ ```
72
+
73
+ For online sources, install `veloura-audio[stream]` and resolve a playable stream:
74
+
75
+ ```python
76
+ import asyncio
77
+
78
+ from veloura.audio import resolve_stream_track, transition_preset
79
+
80
+
81
+ async def main():
82
+ track = await resolve_stream_track(
83
+ "artist song official audio",
84
+ transition_config=transition_preset("streamer"),
85
+ )
86
+ print(track.title, track.stream_url)
87
+
88
+
89
+ asyncio.run(main())
90
+ ```
91
+
92
+ ## CLI
93
+
94
+ Veloura exposes the same core tools through `python -m veloura` or the
95
+ `veloura` console script:
96
+
97
+ ```bash
98
+ python -m veloura presets
99
+ python -m veloura prepare ./song.mp3 --preset streamer
100
+ python -m veloura analyze ./song.mp3
101
+ python -m veloura plan ./current.mp3 ./next.mp3 --preset broadcast
102
+ ```
103
+
104
+ For YouTube/search inputs, install `veloura-audio[stream]` and add `--resolve`:
105
+
106
+ ```bash
107
+ python -m veloura plan "current song" "next song" --preset streamer --resolve
108
+ ```
109
+
110
+ Transition analysis is cached under `~/.cache/veloura` by default, or under the
111
+ directory set in `VELOURA_CACHE_DIR`. Use `--cache-dir` for a project-local
112
+ cache, or `--no-cache` when comparing fresh analysis.
113
+
114
+ ## Presets
115
+
116
+ - `streamer`: balanced transitions for livestream/background music
117
+ - `broadcast`: longer, smoother radio-style blends
118
+ - `low-latency`: shorter analysis windows for weaker machines or fast queues
119
+
120
+ Aliases such as `streamer-safe`, `broadcast-smooth`, and `fast` are also
121
+ available.
122
+
123
+ ## Standalone Example
124
+
125
+ The example player resolves local files or stream queries, prepares transition
126
+ analysis, mixes the queue, and pipes PCM into `ffplay`:
127
+
128
+ ```bash
129
+ python examples/streamer_player.py ./song-a.mp3 ./song-b.mp3 --preset streamer
130
+ python examples/streamer_player.py ./song-a.mp3 ./song-b.mp3 --cache-dir ./veloura-cache
131
+ ```
132
+
133
+ ## Public API
134
+
135
+ Prefer these names for new projects:
136
+
137
+ - `AudioTrack`
138
+ - `CrossfadeSession`
139
+ - `FileAnalysisCache`
140
+ - `transition_preset`
141
+ - `prepare_smart_transition`
142
+ - `plan_beat_transition`
143
+ - `resolve_stream_track`
144
+
145
+ Compatibility names:
146
+
147
+ - `MixerTrack`
148
+ - `CrossfadeAudioSource`
149
+
150
+ ## Development Checks
151
+
152
+ ```bash
153
+ python3 -m unittest discover -s tests
154
+ python3 -m py_compile veloura/*.py veloura/audio/*.py examples/*.py
155
+ ```
156
+
157
+ Before publishing publicly, confirm the package name on PyPI, add project URLs,
158
+ choose the license/copyright owner, build the distribution, and publish to
159
+ TestPyPI first.
@@ -0,0 +1,53 @@
1
+ # Veloura Public Release Checklist
2
+
3
+ Use this checklist before publishing Veloura as a public/global Python package.
4
+
5
+ ## Identity
6
+
7
+ - Confirm the public package name on PyPI: `veloura-audio`
8
+ - Choose the legal license and add a `LICENSE` file
9
+ - Decide the copyright owner or contributor line
10
+ - Add official project URLs to `pyproject.toml`:
11
+ - Homepage
12
+ - Source repository
13
+ - Issue tracker
14
+ - Documentation
15
+
16
+ ## Package Metadata
17
+
18
+ - Keep `veloura.__version__` and `pyproject.toml` version in sync
19
+ - Confirm the Python version floor: currently `>=3.12`
20
+ - Confirm optional extras:
21
+ - `stream` for `yt-dlp`
22
+ - `discord` for Discord voice support
23
+ - `all` for every optional integration
24
+ - Recheck classifiers after choosing a license
25
+
26
+ ## Local Verification
27
+
28
+ ```bash
29
+ python3 -m unittest discover -s tests
30
+ python3 -m py_compile veloura/*.py veloura/audio/*.py examples/*.py
31
+ python3 -m build
32
+ python3 -m twine check dist/*
33
+ ```
34
+
35
+ ## Publishing Flow
36
+
37
+ 1. Build from a clean source tree.
38
+ 2. Upload to TestPyPI first.
39
+ 3. Install from TestPyPI in a fresh virtual environment.
40
+ 4. Run `python -m veloura presets`.
41
+ 5. Test `prepare`, `analyze`, and the streamer example with local files.
42
+ 6. Test stream resolution with `pip install "veloura-audio[stream]"`.
43
+ 7. Publish the same checked artifacts to PyPI.
44
+
45
+ ## Release Notes
46
+
47
+ For each public release, include:
48
+
49
+ - New features
50
+ - Compatibility notes
51
+ - Dependency or Python-version changes
52
+ - Known limitations
53
+ - Migration notes for renamed or deprecated public APIs
@@ -0,0 +1,86 @@
1
+ # Veloura Scope
2
+
3
+ Veloura is a reusable Python audio transition engine. The Discord bot is one
4
+ consumer of the package, not the package's identity.
5
+
6
+ ## Target Use Cases
7
+
8
+ - Streamer background music engines
9
+ - 24/7 radio or livestream music pipelines
10
+ - Discord, Twitch, or web music bots
11
+ - Desktop music tools that need smooth queue playback
12
+ - Audio automation scripts that need predictable fades and gain control
13
+
14
+ ## Core Package Owns
15
+
16
+ - Audio track models
17
+ - PCM helpers
18
+ - FFmpeg-backed PCM decoding
19
+ - Equal-power crossfade mixing
20
+ - Queue/session buffering
21
+ - Silence trim analysis
22
+ - Loudness normalization
23
+ - Beat/BPM analysis
24
+ - Beat-aware transition planning
25
+ - Stream URL resolution helpers
26
+ - Presets for streamer, broadcast, and low-latency modes
27
+ - File-based transition analysis cache
28
+ - CLI tools for local analysis and transition planning
29
+
30
+ ## Core Package Does Not Own
31
+
32
+ - Discord buttons, views, embeds, slash commands, or permissions
33
+ - Lavalink nodes
34
+ - Guild/server state
35
+ - User playlists and saved songs
36
+ - Spotify, Apple Music, Deezer, or Tidal scraping
37
+ - Bot banners and presence
38
+ - Database schemas for a specific app
39
+
40
+ ## Public API Direction
41
+
42
+ Prefer these public names for new projects:
43
+
44
+ - `AudioTrack`
45
+ - `CrossfadeSession`
46
+ - `FileAnalysisCache`
47
+ - `transition_preset`
48
+ - `prepare_smart_transition`
49
+ - `plan_beat_transition`
50
+ - `resolve_stream_track`
51
+
52
+ Keep these names for compatibility:
53
+
54
+ - `MixerTrack`
55
+ - `CrossfadeAudioSource`
56
+
57
+ ## Release Milestones
58
+
59
+ ### 0.3
60
+
61
+ - Generic `AudioTrack` public model
62
+ - Streamer/broadcast/low-latency presets
63
+ - `python -m veloura` CLI
64
+ - File-based transition analysis cache
65
+ - Generated audio tests for trim/loudness behavior
66
+ - Docs for non-Discord use
67
+
68
+ ### 0.4
69
+
70
+ - Example streamer player script
71
+ - Cleaner status/snapshot model for external UIs
72
+ - Optional playback adapters
73
+
74
+ ### 0.5
75
+
76
+ - Stronger beat-aware planning
77
+ - Better confidence scoring
78
+ - Safer automatic fallback decisions
79
+ - Transition preview/export helpers
80
+
81
+ ### 1.0
82
+
83
+ - Stable typed API
84
+ - Backward-compatible migration notes
85
+ - Separate docs site/package README
86
+ - Published package ready for public use
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env python3
2
+ """Minimal standalone streamer player powered by Veloura.
3
+
4
+ This example does not import the Discord bot. It resolves each argument into an
5
+ audio track, applies Veloura transition analysis, then pipes mixed PCM into
6
+ ``ffplay``.
7
+
8
+ Example:
9
+
10
+ python examples/streamer_player.py "./song-a.mp3" "./song-b.mp3"
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ import asyncio
17
+ import shutil
18
+ import subprocess
19
+ import sys
20
+ from pathlib import Path
21
+
22
+ from veloura.audio import (
23
+ CHANNELS,
24
+ FRAME_RATE,
25
+ AudioTrack,
26
+ CrossfadeSession,
27
+ FileAnalysisCache,
28
+ prepare_smart_transition,
29
+ resolve_stream_track,
30
+ transition_preset,
31
+ )
32
+
33
+
34
+ def probe_duration(source: str) -> float:
35
+ ffprobe = shutil.which("ffprobe")
36
+ if not ffprobe:
37
+ return 0.0
38
+ result = subprocess.run(
39
+ [
40
+ ffprobe,
41
+ "-v",
42
+ "error",
43
+ "-show_entries",
44
+ "format=duration",
45
+ "-of",
46
+ "default=noprint_wrappers=1:nokey=1",
47
+ source,
48
+ ],
49
+ stdout=subprocess.PIPE,
50
+ stderr=subprocess.DEVNULL,
51
+ text=True,
52
+ check=False,
53
+ )
54
+ try:
55
+ return float((result.stdout or "0").strip() or 0.0)
56
+ except ValueError:
57
+ return 0.0
58
+
59
+
60
+ async def build_track(source: str, *, preset: str, cache: FileAnalysisCache | None) -> AudioTrack:
61
+ config = transition_preset(preset)
62
+ if Path(source).exists():
63
+ track = AudioTrack.from_source(
64
+ source,
65
+ title=Path(source).stem,
66
+ duration=probe_duration(source),
67
+ )
68
+ if cache:
69
+ return await asyncio.to_thread(cache.prepare_transition, track, config)
70
+ return await asyncio.to_thread(prepare_smart_transition, track, config)
71
+ return await resolve_stream_track(source, transition_config=config, analysis_cache=cache)
72
+
73
+
74
+ async def build_tracks(
75
+ sources: list[str],
76
+ *,
77
+ preset: str,
78
+ cache: FileAnalysisCache | None,
79
+ ) -> list[AudioTrack]:
80
+ return [await build_track(source, preset=preset, cache=cache) for source in sources]
81
+
82
+
83
+ def open_ffplay() -> subprocess.Popen:
84
+ ffplay = shutil.which("ffplay")
85
+ if not ffplay:
86
+ raise RuntimeError("ffplay was not found. Install FFmpeg with ffplay to run this example.")
87
+ return subprocess.Popen(
88
+ [
89
+ ffplay,
90
+ "-nodisp",
91
+ "-autoexit",
92
+ "-loglevel",
93
+ "warning",
94
+ "-f",
95
+ "s16le",
96
+ "-ar",
97
+ str(FRAME_RATE),
98
+ "-ac",
99
+ str(CHANNELS),
100
+ "-i",
101
+ "pipe:0",
102
+ ],
103
+ stdin=subprocess.PIPE,
104
+ )
105
+
106
+
107
+ def play_tracks(tracks: list[AudioTrack], *, volume: float, crossfade: float):
108
+ session = CrossfadeSession(volume=volume, crossfade_seconds=crossfade)
109
+ for track in tracks:
110
+ session.source.enqueue(track)
111
+
112
+ player = open_ffplay()
113
+ try:
114
+ while True:
115
+ frame = session.source.read()
116
+ if not frame:
117
+ break
118
+ if not player.stdin:
119
+ break
120
+ player.stdin.write(frame)
121
+ finally:
122
+ session.stop()
123
+ if player.stdin:
124
+ player.stdin.close()
125
+ player.wait(timeout=5)
126
+
127
+
128
+ def main(argv: list[str] | None = None) -> int:
129
+ parser = argparse.ArgumentParser(description="Play a Veloura-powered streamer queue.")
130
+ parser.add_argument("sources", nargs="+", help="Local files, stream URLs, or yt-dlp search queries.")
131
+ parser.add_argument("--preset", default="streamer")
132
+ parser.add_argument("--volume", type=float, default=0.65)
133
+ parser.add_argument("--crossfade", type=float, default=8.0)
134
+ parser.add_argument("--cache-dir")
135
+ parser.add_argument("--no-cache", action="store_true")
136
+ args = parser.parse_args(argv)
137
+
138
+ cache = None if args.no_cache else FileAnalysisCache(args.cache_dir)
139
+ tracks = asyncio.run(build_tracks(args.sources, preset=args.preset, cache=cache))
140
+ play_tracks(tracks, volume=args.volume, crossfade=args.crossfade)
141
+ return 0
142
+
143
+
144
+ if __name__ == "__main__":
145
+ raise SystemExit(main(sys.argv[1:]))
@@ -0,0 +1,57 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "veloura-audio"
7
+ version = "0.3.0"
8
+ description = "Reusable Python audio engine with crossfade and beat-aware transition planning."
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ keywords = [
12
+ "audio",
13
+ "crossfade",
14
+ "ffmpeg",
15
+ "music",
16
+ "streaming",
17
+ ]
18
+ classifiers = [
19
+ "Development Status :: 3 - Alpha",
20
+ "Intended Audience :: Developers",
21
+ "Operating System :: OS Independent",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Topic :: Multimedia :: Sound/Audio",
26
+ "Topic :: Multimedia :: Sound/Audio :: Mixers",
27
+ "Topic :: Software Development :: Libraries :: Python Modules",
28
+ ]
29
+ dependencies = []
30
+
31
+ [project.scripts]
32
+ veloura = "veloura.cli:main"
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/VelouraAudio/veloura-audio"
36
+ Repository = "https://github.com/VelouraAudio/veloura-audio"
37
+ Issues = "https://github.com/VelouraAudio/veloura-audio/issues"
38
+
39
+ [project.optional-dependencies]
40
+ stream = [
41
+ "yt-dlp>=2026.3.17",
42
+ ]
43
+ discord = [
44
+ "discord.py>=2.3.0",
45
+ "PyNaCl>=1.5.0",
46
+ ]
47
+ all = [
48
+ "discord.py>=2.3.0",
49
+ "PyNaCl>=1.5.0",
50
+ "yt-dlp>=2026.3.17",
51
+ ]
52
+
53
+ [tool.setuptools.packages.find]
54
+ include = ["veloura*"]
55
+
56
+ [tool.setuptools.package-data]
57
+ veloura = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+