songbrain 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.
@@ -0,0 +1,33 @@
1
+ # OS / editors
2
+ .DS_Store
3
+ Thumbs.db
4
+ .vscode/
5
+ .idea/
6
+
7
+ # Secrets
8
+ .env
9
+ .env.*
10
+ !.env.example
11
+
12
+ # Python
13
+ __pycache__/
14
+ *.py[cod]
15
+ *.egg-info/
16
+ .venv/
17
+ venv/
18
+ build/
19
+ dist/
20
+ .pytest_cache/
21
+ .mypy_cache/
22
+ .ruff_cache/
23
+
24
+ # Node
25
+ node_modules/
26
+ js/dist/
27
+ *.tgz
28
+ npm-debug.log*
29
+
30
+ # MCP publisher
31
+ mcp-publisher
32
+ mcp-publisher.exe
33
+ .mcpregistry_*
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Songbrain
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,154 @@
1
+ Metadata-Version: 2.5
2
+ Name: songbrain
3
+ Version: 0.1.0
4
+ Summary: Official Python client for the Songbrain API: song in, video plan out. Song DNA, beat grid, best moments, timed lyrics, story and a beat-synced shot plan.
5
+ Project-URL: Homepage, https://www.songbrain.ai/api-access
6
+ Project-URL: Documentation, https://www.songbrain.ai/docs/api
7
+ Project-URL: Source, https://github.com/songbrain-ai/songbrain
8
+ Project-URL: Issues, https://github.com/songbrain-ai/songbrain/issues
9
+ Author-email: Songbrain <support@songbrain.ai>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: ai music video,beat detection,lyrics timestamps,mcp,music analysis api,shot plan,song structure,songbrain
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
25
+ Classifier: Topic :: Multimedia :: Video
26
+ Classifier: Typing :: Typed
27
+ Requires-Python: >=3.9
28
+ Requires-Dist: requests>=2.25
29
+ Provides-Extra: dev
30
+ Requires-Dist: build>=1; extra == 'dev'
31
+ Requires-Dist: pytest>=7; extra == 'dev'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # songbrain
35
+
36
+ **Song in, video plan out.** The official Python client for the [Songbrain API](https://www.songbrain.ai/docs/api), the music analysis API for AI video.
37
+
38
+ One call returns the song DNA (genre, tempo, key, mood, instruments, loudness), a beat grid, sections, the best moments with reasons, word-timed lyrics, the story, world and palette, and a beat-synced shot plan with a ready prompt for every scene.
39
+
40
+ ```bash
41
+ pip install songbrain
42
+ ```
43
+
44
+ Python 3.9+. One dependency: `requests`.
45
+
46
+ ## Quickstart
47
+
48
+ Get a key at [app.songbrain.ai/developers](https://app.songbrain.ai/developers). 5 songs a month are free.
49
+
50
+ ```python
51
+ from songbrain import Songbrain
52
+
53
+ sb = Songbrain() # reads SONGBRAIN_API_KEY
54
+
55
+ song = sb.analyze("song.mp3") # or analyze(audio_url="https://…/song.mp3")
56
+
57
+ print(song["song_dna"]["genre"], song["song_dna"]["tempo_bpm"], song["song_dna"]["key"])
58
+ for scene in song["shot_plan"]["clip"]["scenes"]:
59
+ print(f'{scene["start_sec"]:.2f}-{scene["end_sec"]:.2f} [{scene["act"]}] {scene["prompt"]}')
60
+ ```
61
+
62
+ `analyze()` uploads the song, waits until the analysis is done (typically 60–90 s) and returns the full document.
63
+
64
+ ## Try it without a key
65
+
66
+ The example endpoints return real analyses of Songbrain's own songs, in exactly the format your songs get.
67
+
68
+ ```python
69
+ from songbrain import Songbrain
70
+
71
+ sb = Songbrain()
72
+ print([e["id"] for e in sb.examples()["data"]])
73
+ plan = sb.example_shot_plan("old-truck-home")
74
+ print(plan["shot_plan"]["clip"]["scenes"][0]["prompt"])
75
+ ```
76
+
77
+ ## Methods
78
+
79
+ Every method returns the JSON body of the response as a `dict`. Types for editors live in `songbrain.types` (`Song`, `SongDNA`, `Timeline`, `BestMoment`, `Lyrics`, `Scores`, `Story`, `ShotPlan`, `Scene`, …).
80
+
81
+ | Method | API call | Key |
82
+ |---|---|---|
83
+ | `analyze(file=None, *, audio_url=None, title=None, artist=None, webhook_url=None, external_ref=None, filename=None, wait=True, poll_interval=5, timeout=300)` | `POST /songs`, then polls `GET /songs/{id}` | yes |
84
+ | `wait_for(song_id, *, poll_interval=5, timeout=300)` | polls `GET /songs/{id}` | yes |
85
+ | `get_song(id, view=None, include=None)` | `GET /songs/{id}` | yes |
86
+ | `shot_plan(id)` | `GET /songs/{id}/shot-plan` | yes |
87
+ | `list_songs(limit=20)` | `GET /songs` | yes |
88
+ | `delete_song(id)` | `DELETE /songs/{id}` | yes |
89
+ | `account()` | `GET /account` | yes |
90
+ | `pricing()` | `GET /pricing` | no |
91
+ | `examples()` | `GET /examples` | no |
92
+ | `example(id, view=None, include=None)` | `GET /examples/{id}` | no |
93
+ | `example_shot_plan(id)` | `GET /examples/{id}/shot-plan` | no |
94
+
95
+ - `file` can be a path, `bytes` or an open binary file. MP3, WAV, FLAC, M4A, AAC, OGG or AIFF, up to 100 MB, 30 s to 10 min. The file name's extension has to match the audio; for bytes without a name the client detects the format or you pass `filename="song.mp3"`.
96
+ - `wait=False` returns the 202 body right away: `{"id", "status": "processing", "eta_sec", "billing"}`. Use `wait_for(id)` or a webhook later.
97
+ - `view="summary"` drops word timings and beat arrays (about 3x smaller). `include=["song_dna", "shot_plan"]` returns only those sections.
98
+
99
+ ```python
100
+ sb = Songbrain(api_key="sb_live_…", timeout=60, max_retries=3)
101
+ ```
102
+
103
+ ## Errors
104
+
105
+ API errors raise `SongbrainError` with `.status`, `.code` and `.message`. Subclasses:
106
+
107
+ | Exception | When |
108
+ |---|---|
109
+ | `AuthenticationError` | 401 `missing_api_key`, `invalid_api_key` |
110
+ | `InsufficientCredits` | 402: free songs used up and fewer than 25 credits |
111
+ | `NotFound` | 404: unknown id, or not yours |
112
+ | `RateLimited` | 429, with `.retry_after` in seconds |
113
+ | `AnalysisFailed` | the song was accepted but failed (credits are refunded) |
114
+ | `WaitTimeout` | `analyze(wait=True)` gave up; the song keeps processing |
115
+
116
+ The client retries 429 and 5xx responses up to 3 times with backoff and honours `Retry-After` (up to 60 s). Uploads are only retried when nothing can have been created (429, 502, 503).
117
+
118
+ ```python
119
+ from songbrain import Songbrain, InsufficientCredits, RateLimited
120
+
121
+ try:
122
+ song = Songbrain().analyze(audio_url="https://example.com/song.mp3")
123
+ except InsufficientCredits:
124
+ print("Top up at https://app.songbrain.ai/developers/billing")
125
+ except RateLimited as e:
126
+ print("Try again in", e.retry_after, "s")
127
+ ```
128
+
129
+ ## Webhooks
130
+
131
+ Pass `webhook_url` and Songbrain POSTs `song.done` or `song.failed` (and `account.low_balance`). Verify the `Songbrain-Signature` header against the raw body:
132
+
133
+ ```python
134
+ from songbrain import webhooks
135
+
136
+ ok = webhooks.verify(raw_body, request.headers["Songbrain-Signature"], secret) # bool
137
+ event = webhooks.construct_event(raw_body, header, secret) # verified dict, or raises
138
+ ```
139
+
140
+ The default tolerance is 300 s. A full Flask receiver is in [examples/python/webhook_server.py](https://github.com/songbrain-ai/songbrain/blob/main/examples/python/webhook_server.py).
141
+
142
+ ## Pricing
143
+
144
+ 5 free songs per account per month. Then 25 credits per song (about $0.50). No subscription. Everything is included: analysis, story and shot plan. Results are yours, also in a paid or white-label product. See [Terms §17](https://www.songbrain.ai/terms#api).
145
+
146
+ ## Links
147
+
148
+ - API docs: https://www.songbrain.ai/docs/api
149
+ - OpenAPI: https://api.songbrain.ai/v1/openapi.json
150
+ - MCP server: https://api.songbrain.ai/mcp
151
+ - Get a key: https://app.songbrain.ai/developers
152
+ - Source: https://github.com/songbrain-ai/songbrain
153
+
154
+ MIT License.
@@ -0,0 +1,121 @@
1
+ # songbrain
2
+
3
+ **Song in, video plan out.** The official Python client for the [Songbrain API](https://www.songbrain.ai/docs/api), the music analysis API for AI video.
4
+
5
+ One call returns the song DNA (genre, tempo, key, mood, instruments, loudness), a beat grid, sections, the best moments with reasons, word-timed lyrics, the story, world and palette, and a beat-synced shot plan with a ready prompt for every scene.
6
+
7
+ ```bash
8
+ pip install songbrain
9
+ ```
10
+
11
+ Python 3.9+. One dependency: `requests`.
12
+
13
+ ## Quickstart
14
+
15
+ Get a key at [app.songbrain.ai/developers](https://app.songbrain.ai/developers). 5 songs a month are free.
16
+
17
+ ```python
18
+ from songbrain import Songbrain
19
+
20
+ sb = Songbrain() # reads SONGBRAIN_API_KEY
21
+
22
+ song = sb.analyze("song.mp3") # or analyze(audio_url="https://…/song.mp3")
23
+
24
+ print(song["song_dna"]["genre"], song["song_dna"]["tempo_bpm"], song["song_dna"]["key"])
25
+ for scene in song["shot_plan"]["clip"]["scenes"]:
26
+ print(f'{scene["start_sec"]:.2f}-{scene["end_sec"]:.2f} [{scene["act"]}] {scene["prompt"]}')
27
+ ```
28
+
29
+ `analyze()` uploads the song, waits until the analysis is done (typically 60–90 s) and returns the full document.
30
+
31
+ ## Try it without a key
32
+
33
+ The example endpoints return real analyses of Songbrain's own songs, in exactly the format your songs get.
34
+
35
+ ```python
36
+ from songbrain import Songbrain
37
+
38
+ sb = Songbrain()
39
+ print([e["id"] for e in sb.examples()["data"]])
40
+ plan = sb.example_shot_plan("old-truck-home")
41
+ print(plan["shot_plan"]["clip"]["scenes"][0]["prompt"])
42
+ ```
43
+
44
+ ## Methods
45
+
46
+ Every method returns the JSON body of the response as a `dict`. Types for editors live in `songbrain.types` (`Song`, `SongDNA`, `Timeline`, `BestMoment`, `Lyrics`, `Scores`, `Story`, `ShotPlan`, `Scene`, …).
47
+
48
+ | Method | API call | Key |
49
+ |---|---|---|
50
+ | `analyze(file=None, *, audio_url=None, title=None, artist=None, webhook_url=None, external_ref=None, filename=None, wait=True, poll_interval=5, timeout=300)` | `POST /songs`, then polls `GET /songs/{id}` | yes |
51
+ | `wait_for(song_id, *, poll_interval=5, timeout=300)` | polls `GET /songs/{id}` | yes |
52
+ | `get_song(id, view=None, include=None)` | `GET /songs/{id}` | yes |
53
+ | `shot_plan(id)` | `GET /songs/{id}/shot-plan` | yes |
54
+ | `list_songs(limit=20)` | `GET /songs` | yes |
55
+ | `delete_song(id)` | `DELETE /songs/{id}` | yes |
56
+ | `account()` | `GET /account` | yes |
57
+ | `pricing()` | `GET /pricing` | no |
58
+ | `examples()` | `GET /examples` | no |
59
+ | `example(id, view=None, include=None)` | `GET /examples/{id}` | no |
60
+ | `example_shot_plan(id)` | `GET /examples/{id}/shot-plan` | no |
61
+
62
+ - `file` can be a path, `bytes` or an open binary file. MP3, WAV, FLAC, M4A, AAC, OGG or AIFF, up to 100 MB, 30 s to 10 min. The file name's extension has to match the audio; for bytes without a name the client detects the format or you pass `filename="song.mp3"`.
63
+ - `wait=False` returns the 202 body right away: `{"id", "status": "processing", "eta_sec", "billing"}`. Use `wait_for(id)` or a webhook later.
64
+ - `view="summary"` drops word timings and beat arrays (about 3x smaller). `include=["song_dna", "shot_plan"]` returns only those sections.
65
+
66
+ ```python
67
+ sb = Songbrain(api_key="sb_live_…", timeout=60, max_retries=3)
68
+ ```
69
+
70
+ ## Errors
71
+
72
+ API errors raise `SongbrainError` with `.status`, `.code` and `.message`. Subclasses:
73
+
74
+ | Exception | When |
75
+ |---|---|
76
+ | `AuthenticationError` | 401 `missing_api_key`, `invalid_api_key` |
77
+ | `InsufficientCredits` | 402: free songs used up and fewer than 25 credits |
78
+ | `NotFound` | 404: unknown id, or not yours |
79
+ | `RateLimited` | 429, with `.retry_after` in seconds |
80
+ | `AnalysisFailed` | the song was accepted but failed (credits are refunded) |
81
+ | `WaitTimeout` | `analyze(wait=True)` gave up; the song keeps processing |
82
+
83
+ The client retries 429 and 5xx responses up to 3 times with backoff and honours `Retry-After` (up to 60 s). Uploads are only retried when nothing can have been created (429, 502, 503).
84
+
85
+ ```python
86
+ from songbrain import Songbrain, InsufficientCredits, RateLimited
87
+
88
+ try:
89
+ song = Songbrain().analyze(audio_url="https://example.com/song.mp3")
90
+ except InsufficientCredits:
91
+ print("Top up at https://app.songbrain.ai/developers/billing")
92
+ except RateLimited as e:
93
+ print("Try again in", e.retry_after, "s")
94
+ ```
95
+
96
+ ## Webhooks
97
+
98
+ Pass `webhook_url` and Songbrain POSTs `song.done` or `song.failed` (and `account.low_balance`). Verify the `Songbrain-Signature` header against the raw body:
99
+
100
+ ```python
101
+ from songbrain import webhooks
102
+
103
+ ok = webhooks.verify(raw_body, request.headers["Songbrain-Signature"], secret) # bool
104
+ event = webhooks.construct_event(raw_body, header, secret) # verified dict, or raises
105
+ ```
106
+
107
+ The default tolerance is 300 s. A full Flask receiver is in [examples/python/webhook_server.py](https://github.com/songbrain-ai/songbrain/blob/main/examples/python/webhook_server.py).
108
+
109
+ ## Pricing
110
+
111
+ 5 free songs per account per month. Then 25 credits per song (about $0.50). No subscription. Everything is included: analysis, story and shot plan. Results are yours, also in a paid or white-label product. See [Terms §17](https://www.songbrain.ai/terms#api).
112
+
113
+ ## Links
114
+
115
+ - API docs: https://www.songbrain.ai/docs/api
116
+ - OpenAPI: https://api.songbrain.ai/v1/openapi.json
117
+ - MCP server: https://api.songbrain.ai/mcp
118
+ - Get a key: https://app.songbrain.ai/developers
119
+ - Source: https://github.com/songbrain-ai/songbrain
120
+
121
+ MIT License.
@@ -0,0 +1,61 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "songbrain"
7
+ version = "0.1.0"
8
+ description = "Official Python client for the Songbrain API: song in, video plan out. Song DNA, beat grid, best moments, timed lyrics, story and a beat-synced shot plan."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.9"
13
+ authors = [{ name = "Songbrain", email = "support@songbrain.ai" }]
14
+ keywords = [
15
+ "music analysis api",
16
+ "ai music video",
17
+ "shot plan",
18
+ "beat detection",
19
+ "song structure",
20
+ "lyrics timestamps",
21
+ "songbrain",
22
+ "mcp",
23
+ ]
24
+ classifiers = [
25
+ "Development Status :: 4 - Beta",
26
+ "Intended Audience :: Developers",
27
+ "License :: OSI Approved :: MIT License",
28
+ "Operating System :: OS Independent",
29
+ "Programming Language :: Python :: 3",
30
+ "Programming Language :: Python :: 3 :: Only",
31
+ "Programming Language :: Python :: 3.9",
32
+ "Programming Language :: Python :: 3.10",
33
+ "Programming Language :: Python :: 3.11",
34
+ "Programming Language :: Python :: 3.12",
35
+ "Programming Language :: Python :: 3.13",
36
+ "Topic :: Multimedia :: Sound/Audio :: Analysis",
37
+ "Topic :: Multimedia :: Video",
38
+ "Typing :: Typed",
39
+ ]
40
+ dependencies = ["requests>=2.25"]
41
+
42
+ [project.optional-dependencies]
43
+ dev = ["pytest>=7", "build>=1"]
44
+
45
+ [project.urls]
46
+ Homepage = "https://www.songbrain.ai/api-access"
47
+ Documentation = "https://www.songbrain.ai/docs/api"
48
+ Source = "https://github.com/songbrain-ai/songbrain"
49
+ Issues = "https://github.com/songbrain-ai/songbrain/issues"
50
+
51
+ [tool.hatch.build.targets.wheel]
52
+ packages = ["src/songbrain"]
53
+
54
+ [tool.hatch.build.targets.sdist]
55
+ include = ["src/songbrain", "tests", "README.md", "LICENSE", "pyproject.toml"]
56
+
57
+ [tool.pytest.ini_options]
58
+ testpaths = ["tests"]
59
+ markers = [
60
+ "live: calls the real Songbrain API (no-key example endpoints). Skip with -m 'not live' or SONGBRAIN_OFFLINE=1.",
61
+ ]
@@ -0,0 +1,42 @@
1
+ """Songbrain: song in, video plan out.
2
+
3
+ The official Python client for the Songbrain API (https://www.songbrain.ai/docs/api).
4
+
5
+ from songbrain import Songbrain
6
+
7
+ sb = Songbrain() # reads SONGBRAIN_API_KEY
8
+ song = sb.analyze("song.mp3")
9
+ for scene in song["shot_plan"]["clip"]["scenes"]:
10
+ print(scene["start_sec"], scene["end_sec"], scene["prompt"])
11
+ """
12
+
13
+ from . import types, webhooks
14
+ from ._client import DEFAULT_BASE_URL, SECTIONS, FileInput, Include, Songbrain
15
+ from ._version import __version__
16
+ from .errors import (
17
+ AnalysisFailed,
18
+ AuthenticationError,
19
+ InsufficientCredits,
20
+ NotFound,
21
+ RateLimited,
22
+ SongbrainError,
23
+ WaitTimeout,
24
+ )
25
+
26
+ __all__ = [
27
+ "Songbrain",
28
+ "DEFAULT_BASE_URL",
29
+ "SECTIONS",
30
+ "FileInput",
31
+ "Include",
32
+ "SongbrainError",
33
+ "AuthenticationError",
34
+ "InsufficientCredits",
35
+ "NotFound",
36
+ "RateLimited",
37
+ "AnalysisFailed",
38
+ "WaitTimeout",
39
+ "types",
40
+ "webhooks",
41
+ "__version__",
42
+ ]