eleven_rb 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +30 -1
- data/lib/eleven_rb/client.rb +16 -0
- data/lib/eleven_rb/resources/music.rb +153 -0
- data/lib/eleven_rb/version.rb +1 -1
- data/lib/eleven_rb.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f8b7a2ab5d7ebe900552e83ae3e8499545f788da927ffc60d54185464d3bbc3
|
|
4
|
+
data.tar.gz: ee1b62923b6fc88304f4c78a60f68164617fd0f46d68cca09ad1496f14dda10d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3079784a64fe6d3bff8e2c631d46763dcc6e352da16e9a7599d0ef0df7be45694c3b00279d3362f6459f7168c72f26b0e460eb80bd07239b675394979fd9cc59
|
|
7
|
+
data.tar.gz: 224530d093fdbd9b489adf6199cfd4cd19e22b2e9074bd42f59345fd0a5efcd06930c9ef9e9bfe9ab9034621c54eaf6c9443ba1b5aee91296c7365347fbcbe67
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-02-08
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Music generation via `client.music.generate` (`POST /v1/music`)
|
|
15
|
+
- Music streaming via `client.music.stream` (`POST /v1/music/stream`)
|
|
16
|
+
- Composition plan creation via `client.music.create_plan` (`POST /v1/music/plan`)
|
|
17
|
+
- `Client#generate_music` convenience method
|
|
18
|
+
|
|
10
19
|
## [0.2.0] - 2026-02-07
|
|
11
20
|
|
|
12
21
|
### Added
|
data/README.md
CHANGED
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
[](https://github.com/webventures/eleven_rb/actions/workflows/ci.yml)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
|
|
7
|
-
A Ruby client for the [ElevenLabs](https://try.elevenlabs.io/qyk2j8gumrjz) Text-to-Speech
|
|
7
|
+
A Ruby client for the [ElevenLabs](https://try.elevenlabs.io/qyk2j8gumrjz) Text-to-Speech, Sound Effects, and Music API.
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
11
|
- Text-to-Speech generation and streaming
|
|
12
12
|
- Sound effects generation from text descriptions
|
|
13
|
+
- Music generation from prompts or composition plans
|
|
13
14
|
- Voice management (list, get, create, update, delete)
|
|
14
15
|
- Voice Library access (search 10,000+ community voices)
|
|
15
16
|
- Voice Slot Manager for automatic slot management within account limits
|
|
@@ -109,6 +110,34 @@ audio = client.sound_effects.generate("gentle rain", loop: true)
|
|
|
109
110
|
audio = client.generate_sound_effect("explosion")
|
|
110
111
|
```
|
|
111
112
|
|
|
113
|
+
### Music
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
# Generate music from a text prompt
|
|
117
|
+
audio = client.music.generate("upbeat jazz piano solo")
|
|
118
|
+
audio.save_to_file("jazz.mp3")
|
|
119
|
+
|
|
120
|
+
# With options (duration, instrumental-only)
|
|
121
|
+
audio = client.music.generate(
|
|
122
|
+
"epic orchestral battle theme",
|
|
123
|
+
music_length_ms: 30_000,
|
|
124
|
+
force_instrumental: true
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# Using a composition plan (create_plan is free, no credits used)
|
|
128
|
+
plan = client.music.create_plan("lo-fi hip hop beats", music_length_ms: 60_000)
|
|
129
|
+
audio = client.music.generate(composition_plan: plan)
|
|
130
|
+
audio.save_to_file("lo-fi.mp3")
|
|
131
|
+
|
|
132
|
+
# Streaming
|
|
133
|
+
File.open("song.mp3", "wb") do |file|
|
|
134
|
+
client.music.stream("ambient electronic") { |chunk| file.write(chunk) }
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Convenience method
|
|
138
|
+
audio = client.generate_music("chill acoustic guitar")
|
|
139
|
+
```
|
|
140
|
+
|
|
112
141
|
### Voice Management
|
|
113
142
|
|
|
114
143
|
```ruby
|
data/lib/eleven_rb/client.rb
CHANGED
|
@@ -86,6 +86,13 @@ module ElevenRb
|
|
|
86
86
|
@sound_effects ||= Resources::SoundEffects.new(http_client)
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
+
# Music generation resource
|
|
90
|
+
#
|
|
91
|
+
# @return [Resources::Music]
|
|
92
|
+
def music
|
|
93
|
+
@music ||= Resources::Music.new(http_client)
|
|
94
|
+
end
|
|
95
|
+
|
|
89
96
|
# Voice slot manager
|
|
90
97
|
#
|
|
91
98
|
# @return [VoiceSlotManager]
|
|
@@ -112,6 +119,15 @@ module ElevenRb
|
|
|
112
119
|
sound_effects.generate(text, **options)
|
|
113
120
|
end
|
|
114
121
|
|
|
122
|
+
# Convenience method: generate music
|
|
123
|
+
#
|
|
124
|
+
# @param prompt [String] description of the music to generate
|
|
125
|
+
# @param options [Hash] additional options
|
|
126
|
+
# @return [Objects::Audio]
|
|
127
|
+
def generate_music(prompt, **options)
|
|
128
|
+
music.generate(prompt, **options)
|
|
129
|
+
end
|
|
130
|
+
|
|
115
131
|
# Convenience method: stream speech
|
|
116
132
|
#
|
|
117
133
|
# @param text [String] the text to convert
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ElevenRb
|
|
4
|
+
module Resources
|
|
5
|
+
# Music generation resource
|
|
6
|
+
#
|
|
7
|
+
# @example Generate music from a prompt
|
|
8
|
+
# audio = client.music.generate("upbeat jazz piano solo")
|
|
9
|
+
# audio.save_to_file("jazz.mp3")
|
|
10
|
+
#
|
|
11
|
+
# @example Generate music from a composition plan
|
|
12
|
+
# plan = client.music.create_plan("epic orchestral battle theme", music_length_ms: 30_000)
|
|
13
|
+
# audio = client.music.generate(composition_plan: plan)
|
|
14
|
+
# audio.save_to_file("battle.mp3")
|
|
15
|
+
#
|
|
16
|
+
# @example Stream music
|
|
17
|
+
# File.open("song.mp3", "wb") do |file|
|
|
18
|
+
# client.music.stream("lo-fi hip hop beats") { |chunk| file.write(chunk) }
|
|
19
|
+
# end
|
|
20
|
+
class Music < Base
|
|
21
|
+
DEFAULT_MODEL = 'music_v1'
|
|
22
|
+
|
|
23
|
+
# Generate music from a text prompt or composition plan
|
|
24
|
+
#
|
|
25
|
+
# @param prompt [String, nil] text description of the music to generate (mutually exclusive with composition_plan)
|
|
26
|
+
# @param composition_plan [Hash, nil] structured composition plan (mutually exclusive with prompt)
|
|
27
|
+
# @param music_length_ms [Integer, nil] duration in milliseconds (3000-600000, only with prompt)
|
|
28
|
+
# @param model_id [String] the model to use (default: music_v1)
|
|
29
|
+
# @param force_instrumental [Boolean, nil] whether to force instrumental output (only with prompt)
|
|
30
|
+
# @param respect_sections_durations [Boolean, nil] whether to respect section durations (only with compose)
|
|
31
|
+
# @param output_format [String] audio output format
|
|
32
|
+
# @return [Objects::Audio]
|
|
33
|
+
def generate(prompt = nil, composition_plan: nil, music_length_ms: nil,
|
|
34
|
+
model_id: DEFAULT_MODEL, force_instrumental: nil,
|
|
35
|
+
respect_sections_durations: nil, output_format: 'mp3_44100_128')
|
|
36
|
+
validate_prompt_or_plan!(prompt, composition_plan)
|
|
37
|
+
|
|
38
|
+
body = build_body(
|
|
39
|
+
prompt: prompt,
|
|
40
|
+
composition_plan: composition_plan,
|
|
41
|
+
music_length_ms: music_length_ms,
|
|
42
|
+
model_id: model_id,
|
|
43
|
+
force_instrumental: force_instrumental,
|
|
44
|
+
respect_sections_durations: respect_sections_durations
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
path = "/music?output_format=#{output_format}"
|
|
48
|
+
response = post_binary(path, body)
|
|
49
|
+
|
|
50
|
+
audio = Objects::Audio.new(
|
|
51
|
+
data: response,
|
|
52
|
+
format: output_format,
|
|
53
|
+
voice_id: nil,
|
|
54
|
+
text: prompt,
|
|
55
|
+
model_id: model_id
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
cost_info = Objects::CostInfo.new(text: prompt || '', voice_id: 'music', model_id: model_id)
|
|
59
|
+
http_client.config.trigger(
|
|
60
|
+
:on_audio_generated,
|
|
61
|
+
audio: audio,
|
|
62
|
+
voice_id: nil,
|
|
63
|
+
text: prompt,
|
|
64
|
+
cost_info: cost_info.to_h
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
audio
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Stream music from a text prompt or composition plan
|
|
71
|
+
#
|
|
72
|
+
# @param prompt [String, nil] text description of the music to generate
|
|
73
|
+
# @param composition_plan [Hash, nil] structured composition plan
|
|
74
|
+
# @param music_length_ms [Integer, nil] duration in milliseconds (3000-600000, only with prompt)
|
|
75
|
+
# @param model_id [String] the model to use
|
|
76
|
+
# @param force_instrumental [Boolean, nil] whether to force instrumental output (only with prompt)
|
|
77
|
+
# @param output_format [String] audio output format
|
|
78
|
+
# @yield [String] each chunk of audio data
|
|
79
|
+
# @return [void]
|
|
80
|
+
def stream(prompt = nil, composition_plan: nil, music_length_ms: nil,
|
|
81
|
+
model_id: DEFAULT_MODEL, force_instrumental: nil,
|
|
82
|
+
output_format: 'mp3_44100_128', &block)
|
|
83
|
+
validate_prompt_or_plan!(prompt, composition_plan)
|
|
84
|
+
raise ArgumentError, 'Block required for streaming' unless block_given?
|
|
85
|
+
|
|
86
|
+
body = build_body(
|
|
87
|
+
prompt: prompt,
|
|
88
|
+
composition_plan: composition_plan,
|
|
89
|
+
music_length_ms: music_length_ms,
|
|
90
|
+
model_id: model_id,
|
|
91
|
+
force_instrumental: force_instrumental
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
path = "/music/stream?output_format=#{output_format}"
|
|
95
|
+
post_stream(path, body, &block)
|
|
96
|
+
|
|
97
|
+
cost_info = Objects::CostInfo.new(text: prompt || '', voice_id: 'music', model_id: model_id)
|
|
98
|
+
http_client.config.trigger(
|
|
99
|
+
:on_audio_generated,
|
|
100
|
+
audio: nil,
|
|
101
|
+
voice_id: nil,
|
|
102
|
+
text: prompt,
|
|
103
|
+
cost_info: cost_info.to_h
|
|
104
|
+
)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Create a composition plan from a text prompt (free, no credits used)
|
|
108
|
+
#
|
|
109
|
+
# @param prompt [String] text description of the music
|
|
110
|
+
# @param music_length_ms [Integer, nil] desired duration in milliseconds
|
|
111
|
+
# @param model_id [String] the model to use
|
|
112
|
+
# @return [Hash] structured composition plan
|
|
113
|
+
def create_plan(prompt, music_length_ms: nil, model_id: DEFAULT_MODEL)
|
|
114
|
+
validate_presence!(prompt, 'prompt')
|
|
115
|
+
|
|
116
|
+
body = {
|
|
117
|
+
prompt: prompt,
|
|
118
|
+
model_id: model_id
|
|
119
|
+
}
|
|
120
|
+
body[:music_length_ms] = music_length_ms unless music_length_ms.nil?
|
|
121
|
+
|
|
122
|
+
post('/music/plan', body)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
private
|
|
126
|
+
|
|
127
|
+
def validate_prompt_or_plan!(prompt, composition_plan)
|
|
128
|
+
raise Errors::ValidationError, 'Either prompt or composition_plan must be provided' if prompt.nil? && composition_plan.nil?
|
|
129
|
+
|
|
130
|
+
return unless prompt && composition_plan
|
|
131
|
+
|
|
132
|
+
raise Errors::ValidationError, 'prompt and composition_plan are mutually exclusive'
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def build_body(prompt:, composition_plan:, music_length_ms:, model_id:,
|
|
136
|
+
force_instrumental: nil, respect_sections_durations: nil)
|
|
137
|
+
body = { model_id: model_id }
|
|
138
|
+
|
|
139
|
+
if prompt
|
|
140
|
+
body[:prompt] = prompt
|
|
141
|
+
body[:music_length_ms] = music_length_ms unless music_length_ms.nil?
|
|
142
|
+
body[:force_instrumental] = force_instrumental unless force_instrumental.nil?
|
|
143
|
+
else
|
|
144
|
+
body[:composition_plan] = composition_plan
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
body[:respect_sections_durations] = respect_sections_durations unless respect_sections_durations.nil?
|
|
148
|
+
|
|
149
|
+
body
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
data/lib/eleven_rb/version.rb
CHANGED
data/lib/eleven_rb.rb
CHANGED
|
@@ -107,6 +107,7 @@ require_relative 'eleven_rb/resources/voice_library'
|
|
|
107
107
|
require_relative 'eleven_rb/resources/models'
|
|
108
108
|
require_relative 'eleven_rb/resources/user'
|
|
109
109
|
require_relative 'eleven_rb/resources/sound_effects'
|
|
110
|
+
require_relative 'eleven_rb/resources/music'
|
|
110
111
|
|
|
111
112
|
# High-level components
|
|
112
113
|
require_relative 'eleven_rb/voice_slot_manager'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: eleven_rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Web Ventures Ltd
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|
|
@@ -156,6 +156,7 @@ files:
|
|
|
156
156
|
- lib/eleven_rb/objects/voice_settings.rb
|
|
157
157
|
- lib/eleven_rb/resources/base.rb
|
|
158
158
|
- lib/eleven_rb/resources/models.rb
|
|
159
|
+
- lib/eleven_rb/resources/music.rb
|
|
159
160
|
- lib/eleven_rb/resources/sound_effects.rb
|
|
160
161
|
- lib/eleven_rb/resources/text_to_speech.rb
|
|
161
162
|
- lib/eleven_rb/resources/user.rb
|