From 4f5bc06ed519c82dec7d564b476d92582d7de7ec Mon Sep 17 00:00:00 2001 From: vijay pemmaraju Date: Mon, 16 Feb 2026 14:32:36 -0500 Subject: [PATCH 1/2] [music] support new params and surfacing song id --- src/elevenlabs/music_custom.py | 47 ++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/src/elevenlabs/music_custom.py b/src/elevenlabs/music_custom.py index 265b059c..8c73d0f6 100644 --- a/src/elevenlabs/music_custom.py +++ b/src/elevenlabs/music_custom.py @@ -30,6 +30,7 @@ class MultipartResponse: json: typing.Dict[str, typing.Any] # Contains compositionPlan and songMetadata audio: bytes filename: str + song_id: typing.Optional[str] = None class MusicClient(AutogeneratedMusicClient): @@ -46,26 +47,35 @@ def compose_detailed( # type: ignore[override] composition_plan: typing.Optional[MusicPrompt] = OMIT, music_length_ms: typing.Optional[int] = OMIT, model_id: typing.Optional[typing.Literal["music_v1"]] = OMIT, + force_instrumental: typing.Optional[bool] = OMIT, + store_for_inpainting: typing.Optional[bool] = OMIT, + with_timestamps: typing.Optional[bool] = OMIT, + sign_with_c_2_pa: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> MultipartResponse: """ Compose a song from a prompt or a composition plan with detailed response parsing. This method calls the original compose_detailed and then parses the stream response. - Returns a MultipartResponse containing parsed JSON metadata, audio bytes, and filename. + Returns a MultipartResponse containing parsed JSON metadata, audio bytes, filename, + and song_id (if store_for_inpainting was True). """ - # Call the parent method to get the stream - stream = super().compose_detailed( + # Use the raw client directly to access response headers (for song_id) + with self._raw_client.compose_detailed( output_format=output_format, prompt=prompt, composition_plan=composition_plan, music_length_ms=music_length_ms, model_id=model_id, + force_instrumental=force_instrumental, + store_for_inpainting=store_for_inpainting, + with_timestamps=with_timestamps, + sign_with_c_2_pa=sign_with_c_2_pa, request_options=request_options, - ) - - # Parse the stream using the parsing method - return self._parse_multipart(stream) + ) as r: + result = self._parse_multipart(r.data) + result.song_id = r.headers.get("song-id") + return result def _parse_multipart(self, stream: typing.Iterator[bytes]) -> MultipartResponse: """ @@ -172,26 +182,35 @@ async def compose_detailed( # type: ignore[override] composition_plan: typing.Optional[MusicPrompt] = OMIT, music_length_ms: typing.Optional[int] = OMIT, model_id: typing.Optional[typing.Literal["music_v1"]] = OMIT, + force_instrumental: typing.Optional[bool] = OMIT, + store_for_inpainting: typing.Optional[bool] = OMIT, + with_timestamps: typing.Optional[bool] = OMIT, + sign_with_c_2_pa: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> MultipartResponse: """ Compose a song from a prompt or a composition plan with detailed response parsing. This method calls the original compose_detailed and then parses the stream response. - Returns a MultipartResponse containing parsed JSON metadata, audio bytes, and filename. + Returns a MultipartResponse containing parsed JSON metadata, audio bytes, filename, + and song_id (if store_for_inpainting was True). """ - # Call the parent method to get the stream - stream = super().compose_detailed( + # Use the raw client directly to access response headers (for song_id) + async with self._raw_client.compose_detailed( output_format=output_format, prompt=prompt, composition_plan=composition_plan, music_length_ms=music_length_ms, model_id=model_id, + force_instrumental=force_instrumental, + store_for_inpainting=store_for_inpainting, + with_timestamps=with_timestamps, + sign_with_c_2_pa=sign_with_c_2_pa, request_options=request_options, - ) - - # Parse the stream using the parsing method - return await self._parse_multipart_async(stream) + ) as r: + result = await self._parse_multipart_async(r.data) + result.song_id = r.headers.get("song-id") + return result async def _parse_multipart_async(self, stream: typing.AsyncIterator[bytes]) -> MultipartResponse: """ From 9d766223b1b9fd1bbdf6368cd30edc86961f6e05 Mon Sep 17 00:00:00 2001 From: vijay pemmaraju Date: Thu, 19 Feb 2026 22:27:17 -0500 Subject: [PATCH 2/2] Fix param name for consistency --- src/elevenlabs/music_custom.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/elevenlabs/music_custom.py b/src/elevenlabs/music_custom.py index 2271ca4e..4897aeb5 100644 --- a/src/elevenlabs/music_custom.py +++ b/src/elevenlabs/music_custom.py @@ -50,7 +50,7 @@ def compose_detailed( # type: ignore[override] force_instrumental: typing.Optional[bool] = OMIT, store_for_inpainting: typing.Optional[bool] = OMIT, with_timestamps: typing.Optional[bool] = OMIT, - sign_with_c_2_pa: typing.Optional[bool] = OMIT, + sign_with_c2pa: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, **kwargs: typing.Any, ) -> MultipartResponse: @@ -71,7 +71,7 @@ def compose_detailed( # type: ignore[override] force_instrumental=force_instrumental, store_for_inpainting=store_for_inpainting, with_timestamps=with_timestamps, - sign_with_c_2_pa=sign_with_c_2_pa, + sign_with_c_2_pa=sign_with_c2pa, request_options=request_options, ) as r: result = self._parse_multipart(r.data) @@ -186,7 +186,7 @@ async def compose_detailed( # type: ignore[override] force_instrumental: typing.Optional[bool] = OMIT, store_for_inpainting: typing.Optional[bool] = OMIT, with_timestamps: typing.Optional[bool] = OMIT, - sign_with_c_2_pa: typing.Optional[bool] = OMIT, + sign_with_c2pa: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, **kwargs: typing.Any, ) -> MultipartResponse: @@ -207,7 +207,7 @@ async def compose_detailed( # type: ignore[override] force_instrumental=force_instrumental, store_for_inpainting=store_for_inpainting, with_timestamps=with_timestamps, - sign_with_c_2_pa=sign_with_c_2_pa, + sign_with_c_2_pa=sign_with_c2pa, request_options=request_options, ) as r: result = await self._parse_multipart_async(r.data)