elevenlabs_client 0.2.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2eb4466ffb626d55734bcd3569141c50293bbee7219fcffc252bd161f3bacac5
4
- data.tar.gz: 2b045b85c15865d17f000a924c2f5088558d81f85b50e1273a11b6950e4eda9f
3
+ metadata.gz: 2b65be08b17b9ae232158f2c004511a7840688e76853c014f9be37984a9639d1
4
+ data.tar.gz: 2de88d74e59af044cfe943e32f0d2f2d8b45f71200469a69b3f95fc7605436d2
5
5
  SHA512:
6
- metadata.gz: 30cfe941d5a311175436c55e5952d743efaa42410fc38e3e2c6df5c1b8db374720d960f86cc57c8985127028b6bc9312a360d4744e7536913576a1ce4c3bbb9e
7
- data.tar.gz: ec656950468c78eede815ae879c1e7475e6c8d64d725a850c4d6ebf95f7ce9c058174b734a4cec19c4c65133ede31aac0b57f08b271e17ce6a87904c2609e3e3
6
+ metadata.gz: f919ebdf7090d2f4cdd812589eccd1425e8be5e86615c04f3bf2882c7e8e8e07058db4f37cdf420e6b1948c668c3acbb177fe796b48c7f23563fa41a7204f4ce
7
+ data.tar.gz: 23b7dc77bb3ca90e2019d4098887b8555d103d66c1fdf259f883f7952b4c26f57671f9bd2e250e27491acc42c2518e85b37bcb48cdb678fd163f9b3be9b1d7e4
data/CHANGELOG.md CHANGED
@@ -5,7 +5,174 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [Unreleased]
8
+ ## [0.4.0] - 2025-09-12
9
+
10
+ ### Added
11
+
12
+ - **🎵 Dubbing Generation API**
13
+ - `delete(dubbing_id)` - Delete dubbing projects
14
+ - `get_resource(dubbing_id)` - Get detailed resource information
15
+ - `create_segment(options)` - Create new segments
16
+ - `delete_segment(options)` - Delete segments
17
+ - `update_segment(options)` - Update segment text/timing
18
+ - `transcribe_segment(options)` - Regenerate transcriptions
19
+ - `translate_segment(options)` - Regenerate translations
20
+ - `dub_segment(options)` - Regenerate dubs
21
+ - `render_project(options)` - Render output media
22
+ - `update_speaker(options)` - Update speaker voices
23
+ - `get_similar_voices(options)` - Get voice recommendations
24
+ - **🔧 HTTP Client Improvements** - Added HTTP method
25
+ - Added `patch` method for PATCH requests
26
+
27
+ ## [0.3.0] - 2025-09-12
28
+
29
+ ### Added
30
+ - **🎵 Music Generation API** - AI-powered music composition and streaming
31
+ - `client.music.compose(options)` - Generate music from text prompts
32
+ - `client.music.compose_stream(options, &block)` - Real-time music streaming
33
+ - `client.music.compose_detailed(options)` - Generate music with metadata
34
+ - `client.music.create_plan(options)` - Create structured composition plans
35
+ - **🎭 Voice Management API** - Complete CRUD operations for individual voices
36
+ - `client.voices.get(voice_id)` - Get detailed voice information
37
+ - `client.voices.list()` - List all voices in account
38
+ - `client.voices.create(name, samples, **options)` - Create custom voices from audio samples
39
+ - `client.voices.edit(voice_id, samples, **options)` - Edit existing voices
40
+ - `client.voices.delete(voice_id)` - Delete voices from account
41
+ - `client.voices.banned?(voice_id)` - Check voice safety status
42
+ - `client.voices.active?(voice_id)` - Check voice availability
43
+ - **📋 Enhanced Rakefile** - Comprehensive gem management and development tasks
44
+ - Build, install, push, and clean gem operations
45
+ - Development tools (linting, testing, security audit)
46
+ - Documentation generation and serving
47
+ - Release preparation and management
48
+ - Maintenance and cleanup tasks
49
+
50
+ ### Enhanced
51
+ - **🚨 Consolidated Error Handling** - Unified error handling across all endpoints
52
+ - Merged `handle_response`, `handle_binary_response`, and `handle_streaming_response` into single method
53
+ - Enhanced error message extraction from JSON, nested objects, arrays, and plain text
54
+ - More specific error types: `BadRequestError`, `NotFoundError`, `UnprocessableEntityError`
55
+ - Better error messages extracted from actual API responses instead of generic fallbacks
56
+ - **🔧 HTTP Client Improvements** - Added missing HTTP methods and consolidated functionality
57
+ - Added `delete` method for DELETE requests
58
+ - Enhanced `post_with_custom_headers` for flexible header management
59
+ - Consistent error handling across all HTTP methods (GET, POST, DELETE, multipart, binary, streaming)
60
+ - **📚 Documentation Organization** - Comprehensive documentation for all new features
61
+ - [MUSIC.md](docs/MUSIC.md) - Complete music generation guide (570 lines)
62
+ - [VOICES.md](docs/VOICES.md) - Voice management documentation (519 lines)
63
+ - Enhanced README with music capabilities and updated feature list
64
+ - Professional Rails integration examples
65
+
66
+ ### New Error Classes
67
+ - `ElevenlabsClient::BadRequestError` (400) - Invalid parameters or malformed requests
68
+ - `ElevenlabsClient::NotFoundError` (404) - Resource not found
69
+ - `ElevenlabsClient::UnprocessableEntityError` (422) - Valid request but invalid data
70
+
71
+ ### Music Generation Features
72
+ - **🎼 Composition Styles** - Support for all major music genres
73
+ - Electronic: EDM, House, Techno, Ambient, Synthwave
74
+ - Orchestral: Classical, Film Score, Epic Orchestral
75
+ - Popular: Pop, Rock, Hip-Hop, Country, Folk
76
+ - Jazz & Blues: Traditional Jazz, Smooth Jazz, Blues
77
+ - World Music: Celtic, Medieval, New Age, Ethnic
78
+ - **🎛️ Advanced Controls** - Detailed composition parameters
79
+ - Custom composition plans with sections, tempo, key, instruments
80
+ - Multiple output formats (MP3, WAV) with quality settings
81
+ - Music length control (5 seconds to 5 minutes)
82
+ - Model selection for different generation approaches
83
+ - **📡 Streaming Support** - Real-time music generation and playback
84
+ - Chunk-based streaming for immediate playback
85
+ - Memory-efficient processing for long compositions
86
+ - WebSocket integration for live applications
87
+
88
+ ### Voice Management Features
89
+ - **🎤 Voice Creation** - Create custom voices from audio samples
90
+ - Multiple sample upload support for better quality
91
+ - Voice metadata and labeling system
92
+ - Quality validation and optimization
93
+ - **🔧 Voice Editing** - Modify existing voices
94
+ - Add new samples to improve voice quality
95
+ - Update voice metadata and descriptions
96
+ - Batch voice operations
97
+ - **🔍 Voice Discovery** - Advanced voice management
98
+ - Search and filter voices by category, labels, quality
99
+ - Voice status checking (active, banned, available)
100
+ - Voice analytics and usage tracking
101
+
102
+ ### Rails Integration Examples
103
+ - **[MusicController](examples/music_controller.rb)** - Complete music generation implementation
104
+ - Basic and advanced music generation endpoints
105
+ - Streaming music with real-time playback
106
+ - Composition planning and structured music creation
107
+ - Batch generation and music library management
108
+ - Interactive music generation with user preferences
109
+ - **[VoicesController](examples/voices_controller.rb)** - Voice management implementation
110
+ - Full CRUD operations for voice management
111
+ - File upload handling for voice samples
112
+ - Voice search and filtering capabilities
113
+ - Batch voice operations and management workflows
114
+
115
+ ### Technical Improvements
116
+ - **🧪 Comprehensive Testing** - Expanded test coverage
117
+ - **57 new music tests** (24 unit + 33 integration)
118
+ - **Enhanced error handling tests** across all endpoints
119
+ - **Total test coverage**: 300+ tests with consistent passing
120
+ - **🏗️ Architecture Consolidation** - Cleaner codebase
121
+ - Removed duplicate error handling methods
122
+ - Consolidated HTTP response processing
123
+ - Enhanced error message extraction with fallback handling
124
+ - Improved code organization and maintainability
125
+ - **📦 Release Management** - Professional release workflow
126
+ - Automated release preparation tasks
127
+ - Version management and changelog automation
128
+ - Security auditing and dependency management
129
+ - Documentation generation and validation
130
+
131
+ ### Breaking Changes
132
+ - **Error Handling** - More specific error types may require catch block updates
133
+ ```ruby
134
+ # Before (v0.2.0)
135
+ rescue ElevenlabsClient::ValidationError => e
136
+ # Handle all 4xx errors
137
+ end
138
+
139
+ # After (v0.3.0) - More specific handling
140
+ rescue ElevenlabsClient::BadRequestError => e
141
+ # Handle 400 Bad Request
142
+ rescue ElevenlabsClient::NotFoundError => e
143
+ # Handle 404 Not Found
144
+ rescue ElevenlabsClient::UnprocessableEntityError => e
145
+ # Handle 422 Unprocessable Entity
146
+ rescue ElevenlabsClient::ValidationError => e
147
+ # Handle other 4xx errors
148
+ end
149
+ ```
150
+
151
+ ### Migration Guide
152
+ ```ruby
153
+ # New Music API Usage
154
+ client = ElevenlabsClient.new
155
+
156
+ # Generate music
157
+ music_data = client.music.compose(
158
+ prompt: "Upbeat electronic dance track",
159
+ music_length_ms: 30000
160
+ )
161
+
162
+ # Stream music generation
163
+ client.music.compose_stream(prompt: "Relaxing ambient") do |chunk|
164
+ # Process audio chunk in real-time
165
+ end
166
+
167
+ # Voice management
168
+ voices = client.voices.list
169
+ voice = client.voices.get("voice_id")
170
+
171
+ # Create custom voice
172
+ File.open("sample.mp3", "rb") do |sample|
173
+ voice = client.voices.create("My Voice", [sample])
174
+ end
175
+ ```
9
176
 
10
177
  ## [0.2.0] - 2025-09-12
11
178
 
@@ -104,4 +271,4 @@ client.dubs.create(file_io: file, filename: "video.mp4", target_languages: ["es"
104
271
  - **File Support**: Multiple video and audio formats (MP4, MOV, MP3, WAV, etc.)
105
272
  - **Language Support**: Multiple target languages for dubbing
106
273
  - **Configuration**: Flexible API key and endpoint configuration
107
- - **Testing**: Comprehensive test suite with integration tests
274
+ - **Testing**: Comprehensive test suite with integration tests
data/README.md CHANGED
@@ -1,9 +1,8 @@
1
1
  # ElevenlabsClient
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/elevenlabs_client.svg)](https://badge.fury.io/rb/elevenlabs_client)
4
- [![Build Status](https://github.com/yourusername/elevenlabs_client/workflows/CI/badge.svg)](https://github.com/yourusername/elevenlabs_client/actions)
5
4
 
6
- A comprehensive Ruby client library for the ElevenLabs API, supporting voice synthesis, dubbing, dialogue generation, and sound effects.
5
+ A comprehensive Ruby client library for the ElevenLabs API, supporting voice synthesis, dubbing, dialogue generation, sound effects, and AI music composition.
7
6
 
8
7
  ## Features
9
8
 
@@ -11,6 +10,10 @@ A comprehensive Ruby client library for the ElevenLabs API, supporting voice syn
11
10
  🎬 **Dubbing** - Create dubbed versions of audio/video content
12
11
  💬 **Dialogue Generation** - Multi-speaker conversations
13
12
  🔊 **Sound Generation** - AI-generated sound effects and ambient audio
13
+ 🎵 **Music Generation** - AI-powered music composition and streaming
14
+ 🎨 **Voice Design** - Create custom voices from text descriptions
15
+ 🎭 **Voice Management** - Create, edit, and manage individual voices
16
+ 🤖 **Models** - List available models and their capabilities
14
17
  📡 **Streaming** - Real-time audio streaming
15
18
  ⚙️ **Configurable** - Flexible configuration options
16
19
  🧪 **Well-tested** - Comprehensive test coverage
@@ -106,6 +109,38 @@ audio_data = client.text_to_dialogue.convert(dialogue)
106
109
  # Sound Generation
107
110
  audio_data = client.sound_generation.generate("Ocean waves crashing on rocks")
108
111
 
112
+ # Voice Design
113
+ design_result = client.text_to_voice.design("Warm, professional female voice")
114
+ generated_voice_id = design_result["previews"].first["generated_voice_id"]
115
+
116
+ voice_result = client.text_to_voice.create(
117
+ "Professional Voice",
118
+ "Warm, professional female voice",
119
+ generated_voice_id
120
+ )
121
+
122
+ # List Available Models
123
+ models = client.models.list
124
+ fastest_model = models["models"].min_by { |m| m["token_cost_factor"] }
125
+ puts "Fastest model: #{fastest_model['name']}"
126
+
127
+ # Voice Management
128
+ voices = client.voices.list
129
+ puts "Total voices: #{voices['voices'].length}"
130
+
131
+ # Create custom voice from audio samples
132
+ File.open("sample1.mp3", "rb") do |sample|
133
+ voice = client.voices.create("My Voice", [sample], description: "Custom narrator voice")
134
+ puts "Created voice: #{voice['voice_id']}"
135
+ end
136
+
137
+ # Music Generation
138
+ music_data = client.music.compose(
139
+ prompt: "Upbeat electronic dance track with synthesizers",
140
+ music_length_ms: 30000
141
+ )
142
+ File.open("generated_music.mp3", "wb") { |f| f.write(music_data) }
143
+
109
144
  # Streaming Text-to-Speech
110
145
  client.text_to_speech_stream.stream("voice_id", "Streaming text") do |chunk|
111
146
  # Process audio chunk in real-time
@@ -122,6 +157,10 @@ end
122
157
  - **[Text-to-Speech Streaming API](docs/TEXT_TO_SPEECH_STREAMING.md)** - Real-time audio streaming
123
158
  - **[Text-to-Dialogue API](docs/TEXT_TO_DIALOGUE.md)** - Multi-speaker conversations
124
159
  - **[Sound Generation API](docs/SOUND_GENERATION.md)** - AI-generated sound effects
160
+ - **[Music Generation API](docs/MUSIC.md)** - AI-powered music composition and streaming
161
+ - **[Text-to-Voice API](docs/TEXT_TO_VOICE.md)** - Design and create custom voices
162
+ - **[Voice Management API](docs/VOICES.md)** - Manage individual voices (CRUD operations)
163
+ - **[Models API](docs/MODELS.md)** - List available models and capabilities
125
164
 
126
165
  ### Available Endpoints
127
166
 
@@ -132,6 +171,10 @@ end
132
171
  | `client.text_to_speech_stream.*` | Streaming TTS | [TEXT_TO_SPEECH_STREAMING.md](docs/TEXT_TO_SPEECH_STREAMING.md) |
133
172
  | `client.text_to_dialogue.*` | Dialogue generation | [TEXT_TO_DIALOGUE.md](docs/TEXT_TO_DIALOGUE.md) |
134
173
  | `client.sound_generation.*` | Sound effect generation | [SOUND_GENERATION.md](docs/SOUND_GENERATION.md) |
174
+ | `client.music.*` | AI music composition and streaming | [MUSIC.md](docs/MUSIC.md) |
175
+ | `client.text_to_voice.*` | Voice design and creation | [TEXT_TO_VOICE.md](docs/TEXT_TO_VOICE.md) |
176
+ | `client.voices.*` | Voice management (CRUD) | [VOICES.md](docs/VOICES.md) |
177
+ | `client.models.*` | Model information and capabilities | [MODELS.md](docs/MODELS.md) |
135
178
 
136
179
  ## Configuration Options
137
180
 
@@ -189,13 +232,16 @@ The gem is designed to work seamlessly with Rails applications. See the [example
189
232
  - [StreamingAudioController](examples/streaming_audio_controller.rb) - Real-time streaming
190
233
  - [TextToDialogueController](examples/text_to_dialogue_controller.rb) - Dialogue generation
191
234
  - [SoundGenerationController](examples/sound_generation_controller.rb) - Sound effects
235
+ - [MusicController](examples/music_controller.rb) - AI music composition and streaming
236
+ - [TextToVoiceController](examples/text_to_voice_controller.rb) - Voice design and creation
237
+ - [VoicesController](examples/voices_controller.rb) - Voice management (CRUD operations)
192
238
 
193
239
  ## Development
194
240
 
195
241
  After checking out the repo, run:
196
242
 
197
243
  ```bash
198
- bin/setup # Install dependencies
244
+ bin/setup # Install dependencies
199
245
  bundle exec rspec # Run tests
200
246
  ```
201
247
 
@@ -221,6 +267,7 @@ bundle exec rspec
221
267
 
222
268
  # Run specific test files
223
269
  bundle exec rspec spec/elevenlabs_client/endpoints/
270
+ bundle exec rspec spec/elevenlabs_client/client
224
271
  bundle exec rspec spec/integration/
225
272
 
226
273
  # Run with documentation format
@@ -7,7 +7,7 @@ module ElevenlabsClient
7
7
  class Client
8
8
  DEFAULT_BASE_URL = "https://api.elevenlabs.io"
9
9
 
10
- attr_reader :base_url, :api_key, :dubs, :text_to_speech, :text_to_speech_stream, :text_to_dialogue, :sound_generation
10
+ attr_reader :base_url, :api_key, :dubs, :text_to_speech, :text_to_speech_stream, :text_to_dialogue, :sound_generation, :text_to_voice, :models, :voices, :music
11
11
 
12
12
  def initialize(api_key: nil, base_url: nil, api_key_env: "ELEVENLABS_API_KEY", base_url_env: "ELEVENLABS_BASE_URL")
13
13
  @api_key = api_key || fetch_api_key(api_key_env)
@@ -18,6 +18,10 @@ module ElevenlabsClient
18
18
  @text_to_speech_stream = TextToSpeechStream.new(self)
19
19
  @text_to_dialogue = TextToDialogue.new(self)
20
20
  @sound_generation = SoundGeneration.new(self)
21
+ @text_to_voice = TextToVoice.new(self)
22
+ @models = Models.new(self)
23
+ @voices = Voices.new(self)
24
+ @music = Endpoints::Music.new(self)
21
25
  end
22
26
 
23
27
  # Makes an authenticated GET request
@@ -39,7 +43,33 @@ module ElevenlabsClient
39
43
  def post(path, body = nil)
40
44
  response = @conn.post(path) do |req|
41
45
  req.headers["xi-api-key"] = api_key
42
- req.body = body if body
46
+ req.headers["Content-Type"] = "application/json"
47
+ req.body = body.to_json if body
48
+ end
49
+
50
+ handle_response(response)
51
+ end
52
+
53
+ # Makes an authenticated DELETE request
54
+ # @param path [String] API endpoint path
55
+ # @return [Hash] Response body
56
+ def delete(path)
57
+ response = @conn.delete(path) do |req|
58
+ req.headers["xi-api-key"] = api_key
59
+ end
60
+
61
+ handle_response(response)
62
+ end
63
+
64
+ # Makes an authenticated PATCH request
65
+ # @param path [String] API endpoint path
66
+ # @param body [Hash, nil] Request body
67
+ # @return [Hash] Response body
68
+ def patch(path, body = nil)
69
+ response = @conn.patch(path) do |req|
70
+ req.headers["xi-api-key"] = api_key
71
+ req.headers["Content-Type"] = "application/json"
72
+ req.body = body.to_json if body
43
73
  end
44
74
 
45
75
  handle_response(response)
@@ -69,7 +99,7 @@ module ElevenlabsClient
69
99
  req.body = body.to_json if body
70
100
  end
71
101
 
72
- handle_binary_response(response)
102
+ handle_response(response)
73
103
  end
74
104
 
75
105
  # Makes an authenticated POST request with custom headers
@@ -87,7 +117,7 @@ module ElevenlabsClient
87
117
 
88
118
  # For streaming/binary responses, return raw body
89
119
  if custom_headers["Accept"]&.include?("audio") || custom_headers["Transfer-Encoding"] == "chunked"
90
- handle_binary_response(response)
120
+ handle_response(response)
91
121
  else
92
122
  handle_response(response)
93
123
  end
@@ -111,7 +141,7 @@ module ElevenlabsClient
111
141
  end
112
142
  end
113
143
 
114
- handle_streaming_response(response)
144
+ handle_response(response)
115
145
  end
116
146
 
117
147
  # Helper method to create Faraday::Multipart::FilePart
@@ -157,44 +187,58 @@ module ElevenlabsClient
157
187
  case response.status
158
188
  when 200..299
159
189
  response.body
190
+ when 400
191
+ error_message = extract_error_message(response.body)
192
+ raise BadRequestError, error_message.empty? ? "Bad request - invalid parameters" : error_message
160
193
  when 401
161
- raise AuthenticationError, "Invalid API key or authentication failed"
194
+ error_message = extract_error_message(response.body)
195
+ raise AuthenticationError, error_message.empty? ? "Invalid API key or authentication failed" : error_message
196
+ when 404
197
+ error_message = extract_error_message(response.body)
198
+ raise NotFoundError, error_message.empty? ? "Resource not found" : error_message
199
+ when 422
200
+ error_message = extract_error_message(response.body)
201
+ raise UnprocessableEntityError, error_message.empty? ? "Unprocessable entity - invalid data" : error_message
162
202
  when 429
163
- raise RateLimitError, "Rate limit exceeded"
203
+ error_message = extract_error_message(response.body)
204
+ raise RateLimitError, error_message.empty? ? "Rate limit exceeded" : error_message
164
205
  when 400..499
165
- raise ValidationError, response.body.inspect
206
+ error_message = extract_error_message(response.body)
207
+ raise ValidationError, error_message.empty? ? "Client error occurred with status #{response.status}" : error_message
166
208
  else
167
- raise APIError, "API request failed with status #{response.status}: #{response.body.inspect}"
209
+ error_message = extract_error_message(response.body)
210
+ raise APIError, error_message.empty? ? "API request failed with status #{response.status}" : error_message
168
211
  end
169
212
  end
170
213
 
171
- def handle_binary_response(response)
172
- case response.status
173
- when 200..299
174
- response.body
175
- when 401
176
- raise AuthenticationError, "Invalid API key or authentication failed"
177
- when 429
178
- raise RateLimitError, "Rate limit exceeded"
179
- when 400..499
180
- raise ValidationError, "API request failed with status #{response.status}"
181
- else
182
- raise APIError, "API request failed with status #{response.status}"
183
- end
184
- end
214
+ private
185
215
 
186
- def handle_streaming_response(response)
187
- case response.status
188
- when 200..299
189
- response
190
- when 401
191
- raise AuthenticationError, "Invalid API key or authentication failed"
192
- when 429
193
- raise RateLimitError, "Rate limit exceeded"
194
- when 400..499
195
- raise ValidationError, "API request failed with status #{response.status}"
196
- else
197
- raise APIError, "API request failed with status #{response.status}"
216
+ def extract_error_message(response_body)
217
+ return "" if response_body.nil? || response_body.empty?
218
+
219
+ # Handle non-string response bodies
220
+ body_str = response_body.is_a?(String) ? response_body : response_body.to_s
221
+
222
+ begin
223
+ error_info = JSON.parse(body_str)
224
+
225
+ # Try different common error message fields
226
+ message = error_info["detail"] ||
227
+ error_info["message"] ||
228
+ error_info["error"] ||
229
+ error_info["errors"]
230
+
231
+ # Handle nested detail objects
232
+ if message.is_a?(Hash)
233
+ message = message["message"] || message.to_s
234
+ elsif message.is_a?(Array)
235
+ message = message.first.to_s
236
+ end
237
+
238
+ message.to_s
239
+ rescue JSON::ParserError, TypeError
240
+ # If not JSON or can't be parsed, return the raw body (truncated if too long)
241
+ body_str.length > 200 ? "#{body_str[0..200]}..." : body_str
198
242
  end
199
243
  end
200
244
 
@@ -53,6 +53,162 @@ module ElevenlabsClient
53
53
  @client.get("/v1/dubbing/#{dubbing_id}/resources")
54
54
  end
55
55
 
56
+ # DELETE /v1/dubbing/{id}
57
+ # Deletes a dubbing project
58
+ #
59
+ # @param dubbing_id [String] The dubbing job ID
60
+ # @return [Hash] Response with status
61
+ def delete(dubbing_id)
62
+ @client.delete("/v1/dubbing/#{dubbing_id}")
63
+ end
64
+
65
+ # GET /v1/dubbing/resource/{dubbing_id}
66
+ # Gets dubbing resource with detailed information including segments, speakers, etc.
67
+ #
68
+ # @param dubbing_id [String] The dubbing job ID
69
+ # @return [Hash] Detailed dubbing resource information
70
+ def get_resource(dubbing_id)
71
+ @client.get("/v1/dubbing/resource/#{dubbing_id}")
72
+ end
73
+
74
+ # POST /v1/dubbing/resource/{dubbing_id}/speaker/{speaker_id}/segment
75
+ # Creates a new segment in dubbing resource
76
+ #
77
+ # @param dubbing_id [String] The dubbing job ID
78
+ # @param speaker_id [String] The speaker ID
79
+ # @param start_time [Float] Start time of the segment
80
+ # @param end_time [Float] End time of the segment
81
+ # @param text [String, nil] Optional text for the segment
82
+ # @param translations [Hash, nil] Optional translations map
83
+ # @return [Hash] Response with version and new segment ID
84
+ def create_segment(dubbing_id:, speaker_id:, start_time:, end_time:, text: nil, translations: nil)
85
+ payload = {
86
+ start_time: start_time,
87
+ end_time: end_time,
88
+ text: text,
89
+ translations: translations
90
+ }.compact
91
+
92
+ @client.post("/v1/dubbing/resource/#{dubbing_id}/speaker/#{speaker_id}/segment", payload)
93
+ end
94
+
95
+ # DELETE /v1/dubbing/resource/{dubbing_id}/segment/{segment_id}
96
+ # Deletes a single segment from the dubbing
97
+ #
98
+ # @param dubbing_id [String] The dubbing job ID
99
+ # @param segment_id [String] The segment ID
100
+ # @return [Hash] Response with version
101
+ def delete_segment(dubbing_id, segment_id)
102
+ @client.delete("/v1/dubbing/resource/#{dubbing_id}/segment/#{segment_id}")
103
+ end
104
+
105
+ # PATCH /v1/dubbing/resource/{dubbing_id}/segment/{segment_id}/{language}
106
+ # Updates a single segment with new text and/or start/end times
107
+ #
108
+ # @param dubbing_id [String] The dubbing job ID
109
+ # @param segment_id [String] The segment ID
110
+ # @param language [String] The language ID
111
+ # @param start_time [Float, nil] Optional new start time
112
+ # @param end_time [Float, nil] Optional new end time
113
+ # @param text [String, nil] Optional new text
114
+ # @return [Hash] Response with version
115
+ def update_segment(dubbing_id:, segment_id:, language:, start_time: nil, end_time: nil, text: nil)
116
+ payload = {
117
+ start_time: start_time,
118
+ end_time: end_time,
119
+ text: text
120
+ }.compact
121
+
122
+ @client.patch("/v1/dubbing/resource/#{dubbing_id}/segment/#{segment_id}/#{language}", payload)
123
+ end
124
+
125
+ # POST /v1/dubbing/resource/{dubbing_id}/transcribe
126
+ # Regenerates transcriptions for specified segments
127
+ #
128
+ # @param dubbing_id [String] The dubbing job ID
129
+ # @param segments [Array<String>] List of segment IDs to transcribe
130
+ # @return [Hash] Response with version
131
+ def transcribe_segment(dubbing_id, segments)
132
+ payload = { segments: segments }
133
+ @client.post("/v1/dubbing/resource/#{dubbing_id}/transcribe", payload)
134
+ end
135
+
136
+ # POST /v1/dubbing/resource/{dubbing_id}/translate
137
+ # Regenerates translations for specified segments/languages
138
+ #
139
+ # @param dubbing_id [String] The dubbing job ID
140
+ # @param segments [Array<String>] List of segment IDs to translate
141
+ # @param languages [Array<String>, nil] Optional list of languages to translate
142
+ # @return [Hash] Response with version
143
+ def translate_segment(dubbing_id, segments, languages = nil)
144
+ payload = {
145
+ segments: segments,
146
+ languages: languages
147
+ }.compact
148
+
149
+ @client.post("/v1/dubbing/resource/#{dubbing_id}/translate", payload)
150
+ end
151
+
152
+ # POST /v1/dubbing/resource/{dubbing_id}/dub
153
+ # Regenerates dubs for specified segments/languages
154
+ #
155
+ # @param dubbing_id [String] The dubbing job ID
156
+ # @param segments [Array<String>] List of segment IDs to dub
157
+ # @param languages [Array<String>, nil] Optional list of languages to dub
158
+ # @return [Hash] Response with version
159
+ def dub_segment(dubbing_id, segments, languages = nil)
160
+ payload = {
161
+ segments: segments,
162
+ languages: languages
163
+ }.compact
164
+
165
+ @client.post("/v1/dubbing/resource/#{dubbing_id}/dub", payload)
166
+ end
167
+
168
+ # POST /v1/dubbing/resource/{dubbing_id}/render/{language}
169
+ # Renders the output media for a language
170
+ #
171
+ # @param dubbing_id [String] The dubbing job ID
172
+ # @param language [String] The language to render
173
+ # @param render_type [String] The type of render (mp4, aac, mp3, wav, aaf, tracks_zip, clips_zip)
174
+ # @param normalize_volume [Boolean, nil] Whether to normalize volume (defaults to false)
175
+ # @return [Hash] Response with version and render_id
176
+ def render_project(dubbing_id:, language:, render_type:, normalize_volume: nil)
177
+ payload = {
178
+ render_type: render_type,
179
+ normalize_volume: normalize_volume
180
+ }.compact
181
+
182
+ @client.post("/v1/dubbing/resource/#{dubbing_id}/render/#{language}", payload)
183
+ end
184
+
185
+ # PATCH /v1/dubbing/resource/{dubbing_id}/speaker/{speaker_id}
186
+ # Updates speaker metadata such as voice
187
+ #
188
+ # @param dubbing_id [String] The dubbing job ID
189
+ # @param speaker_id [String] The speaker ID
190
+ # @param voice_id [String, nil] Voice ID from library or 'track-clone'/'clip-clone'
191
+ # @param languages [Array<String>, nil] Languages to apply changes to
192
+ # @return [Hash] Response with version
193
+ def update_speaker(dubbing_id:, speaker_id:, voice_id: nil, languages: nil)
194
+ payload = {
195
+ voice_id: voice_id,
196
+ languages: languages
197
+ }.compact
198
+
199
+ @client.patch("/v1/dubbing/resource/#{dubbing_id}/speaker/#{speaker_id}", payload)
200
+ end
201
+
202
+ # GET /v1/dubbing/resource/{dubbing_id}/speaker/{speaker_id}/similar-voices
203
+ # Gets similar voices for a speaker
204
+ #
205
+ # @param dubbing_id [String] The dubbing job ID
206
+ # @param speaker_id [String] The speaker ID
207
+ # @return [Hash] Response with list of similar voices
208
+ def get_similar_voices(dubbing_id, speaker_id)
209
+ @client.get("/v1/dubbing/resource/#{dubbing_id}/speaker/#{speaker_id}/similar-voices")
210
+ end
211
+
56
212
  private
57
213
 
58
214
  attr_reader :client
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ElevenlabsClient
4
+ class Models
5
+ def initialize(client)
6
+ @client = client
7
+ end
8
+
9
+ # GET /v1/models
10
+ # Gets a list of available models
11
+ # Documentation: https://elevenlabs.io/docs/api-reference/models/list
12
+ #
13
+ # @return [Hash] The JSON response containing an array of models
14
+ def list
15
+ endpoint = "/v1/models"
16
+ @client.get(endpoint)
17
+ end
18
+
19
+ # Alias for backward compatibility and convenience
20
+ alias_method :list_models, :list
21
+
22
+ private
23
+
24
+ attr_reader :client
25
+ end
26
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ElevenlabsClient
4
+ module Endpoints
5
+ class Music
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ # POST /v1/music
11
+ # Compose music and return binary audio data
12
+ # Documentation: https://elevenlabs.io/docs/api-reference/music/compose
13
+ #
14
+ # @param options [Hash] Music composition parameters
15
+ # @option options [String] :prompt Text description of the music to generate
16
+ # @option options [Hash] :composition_plan Detailed composition structure (optional)
17
+ # @option options [Integer] :music_length_ms Length of music in milliseconds (optional)
18
+ # @option options [String] :model_id Model to use for generation (default: "music_v1")
19
+ # @option options [String] :output_format Audio format (e.g., "mp3_44100_128")
20
+ # @return [String] Binary audio data
21
+ def compose(options = {})
22
+ endpoint = "/v1/music"
23
+ request_body = build_music_request_body(options)
24
+
25
+ query_params = {}
26
+ query_params[:output_format] = options[:output_format] if options[:output_format]
27
+
28
+ endpoint_with_query = query_params.empty? ? endpoint : "#{endpoint}?#{URI.encode_www_form(query_params)}"
29
+
30
+ @client.post_binary(endpoint_with_query, request_body)
31
+ end
32
+
33
+ # POST /v1/music/stream
34
+ # Compose music with streaming audio response
35
+ # Documentation: https://elevenlabs.io/docs/api-reference/music/compose-stream
36
+ #
37
+ # @param options [Hash] Music composition parameters
38
+ # @option options [String] :prompt Text description of the music to generate
39
+ # @option options [Hash] :composition_plan Detailed composition structure (optional)
40
+ # @option options [Integer] :music_length_ms Length of music in milliseconds (optional)
41
+ # @option options [String] :model_id Model to use for generation (default: "music_v1")
42
+ # @option options [String] :output_format Audio format (e.g., "mp3_44100_128")
43
+ # @param block [Proc] Block to handle streaming audio chunks
44
+ # @return [nil] Audio is streamed via the block
45
+ def compose_stream(options = {}, &block)
46
+ endpoint = "/v1/music/stream"
47
+ request_body = build_music_request_body(options)
48
+
49
+ query_params = {}
50
+ query_params[:output_format] = options[:output_format] if options[:output_format]
51
+
52
+ endpoint_with_query = query_params.empty? ? endpoint : "#{endpoint}?#{URI.encode_www_form(query_params)}"
53
+
54
+ @client.post_streaming(endpoint_with_query, request_body, &block)
55
+ end
56
+
57
+ # POST /v1/music/detailed
58
+ # Compose music and return detailed response with metadata and audio
59
+ # Documentation: https://elevenlabs.io/docs/api-reference/music/compose-detailed
60
+ #
61
+ # @param options [Hash] Music composition parameters
62
+ # @option options [String] :prompt Text description of the music to generate
63
+ # @option options [Hash] :composition_plan Detailed composition structure (optional)
64
+ # @option options [Integer] :music_length_ms Length of music in milliseconds (optional)
65
+ # @option options [String] :model_id Model to use for generation (default: "music_v1")
66
+ # @option options [String] :output_format Audio format (e.g., "mp3_44100_128")
67
+ # @return [String] Multipart response with JSON metadata and binary audio
68
+ def compose_detailed(options = {})
69
+ endpoint = "/v1/music/detailed"
70
+ request_body = build_music_request_body(options)
71
+
72
+ query_params = {}
73
+ query_params[:output_format] = options[:output_format] if options[:output_format]
74
+
75
+ endpoint_with_query = query_params.empty? ? endpoint : "#{endpoint}?#{URI.encode_www_form(query_params)}"
76
+
77
+ # Use post_with_custom_headers to handle multipart response
78
+ @client.post_with_custom_headers(
79
+ endpoint_with_query,
80
+ request_body,
81
+ { "Accept" => "multipart/mixed" }
82
+ )
83
+ end
84
+
85
+ # POST /v1/music/plan
86
+ # Create a composition plan for music generation
87
+ # Documentation: https://elevenlabs.io/docs/api-reference/music/create-plan
88
+ #
89
+ # @param options [Hash] Plan creation parameters
90
+ # @option options [String] :prompt Text description of the music style/structure
91
+ # @option options [Integer] :music_length_ms Desired length of music in milliseconds
92
+ # @option options [Hash] :source_composition_plan Base plan to modify (optional)
93
+ # @option options [String] :model_id Model to use for plan generation (default: "music_v1")
94
+ # @return [Hash] JSON response containing the composition plan
95
+ def create_plan(options = {})
96
+ endpoint = "/v1/music/plan"
97
+ request_body = {
98
+ prompt: options[:prompt],
99
+ music_length_ms: options[:music_length_ms],
100
+ source_composition_plan: options[:source_composition_plan],
101
+ model_id: options[:model_id] || "music_v1"
102
+ }.compact
103
+
104
+ @client.post(endpoint, request_body)
105
+ end
106
+
107
+ # Alias methods for convenience
108
+ alias_method :compose_music, :compose
109
+ alias_method :compose_music_stream, :compose_stream
110
+ alias_method :compose_music_detailed, :compose_detailed
111
+ alias_method :create_music_plan, :create_plan
112
+
113
+ private
114
+
115
+ attr_reader :client
116
+
117
+ def build_music_request_body(options)
118
+ {
119
+ prompt: options[:prompt],
120
+ composition_plan: options[:composition_plan],
121
+ music_length_ms: options[:music_length_ms],
122
+ model_id: options[:model_id] || "music_v1"
123
+ }.compact
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ElevenlabsClient
4
+ class TextToVoice
5
+ def initialize(client)
6
+ @client = client
7
+ end
8
+
9
+ # POST /v1/text-to-voice/design
10
+ # Designs a voice based on a description
11
+ # Documentation: https://elevenlabs.io/docs/api-reference/text-to-voice/design
12
+ #
13
+ # @param voice_description [String] Description of the voice (20-1000 characters)
14
+ # @param options [Hash] Optional parameters
15
+ # @option options [String] :output_format Output format (e.g., "mp3_44100_192")
16
+ # @option options [String] :model_id Model to use (e.g., "eleven_multilingual_ttv_v2", "eleven_ttv_v3")
17
+ # @option options [String] :text Text to generate (100-1000 characters, optional)
18
+ # @option options [Boolean] :auto_generate_text Auto-generate text (default: false)
19
+ # @option options [Float] :loudness Loudness level (-1 to 1, default: 0.5)
20
+ # @option options [Integer] :seed Random seed (0 to 2147483647, optional)
21
+ # @option options [Float] :guidance_scale Guidance scale (0 to 100, default: 5)
22
+ # @option options [Boolean] :stream_previews Stream previews (default: false)
23
+ # @option options [String] :remixing_session_id Remixing session ID (optional)
24
+ # @option options [String] :remixing_session_iteration_id Remixing session iteration ID (optional)
25
+ # @option options [Float] :quality Quality level (-1 to 1, optional)
26
+ # @option options [String] :reference_audio_base64 Base64 encoded reference audio (optional, requires eleven_ttv_v3)
27
+ # @option options [Float] :prompt_strength Prompt strength (0 to 1, optional, requires eleven_ttv_v3)
28
+ # @return [Hash] JSON response containing previews and text
29
+ def design(voice_description, **options)
30
+ endpoint = "/v1/text-to-voice/design"
31
+ request_body = { voice_description: voice_description }
32
+
33
+ # Add optional parameters if provided
34
+ request_body[:output_format] = options[:output_format] if options[:output_format]
35
+ request_body[:model_id] = options[:model_id] if options[:model_id]
36
+ request_body[:text] = options[:text] if options[:text]
37
+ request_body[:auto_generate_text] = options[:auto_generate_text] unless options[:auto_generate_text].nil?
38
+ request_body[:loudness] = options[:loudness] if options[:loudness]
39
+ request_body[:seed] = options[:seed] if options[:seed]
40
+ request_body[:guidance_scale] = options[:guidance_scale] if options[:guidance_scale]
41
+ request_body[:stream_previews] = options[:stream_previews] unless options[:stream_previews].nil?
42
+ request_body[:remixing_session_id] = options[:remixing_session_id] if options[:remixing_session_id]
43
+ request_body[:remixing_session_iteration_id] = options[:remixing_session_iteration_id] if options[:remixing_session_iteration_id]
44
+ request_body[:quality] = options[:quality] if options[:quality]
45
+ request_body[:reference_audio_base64] = options[:reference_audio_base64] if options[:reference_audio_base64]
46
+ request_body[:prompt_strength] = options[:prompt_strength] if options[:prompt_strength]
47
+
48
+ @client.post(endpoint, request_body)
49
+ end
50
+
51
+ # POST /v1/text-to-voice
52
+ # Creates a voice from the designed voice generated_voice_id
53
+ # Documentation: https://elevenlabs.io/docs/api-reference/text-to-voice
54
+ #
55
+ # @param voice_name [String] Name of the voice
56
+ # @param voice_description [String] Description of the voice (20-1000 characters)
57
+ # @param generated_voice_id [String] The generated voice ID from design_voice
58
+ # @param options [Hash] Optional parameters
59
+ # @option options [Hash] :labels Optional metadata for the voice
60
+ # @option options [Array<String>] :played_not_selected_voice_ids Optional list of voice IDs played but not selected
61
+ # @return [Hash] JSON response containing voice_id and other voice details
62
+ def create(voice_name, voice_description, generated_voice_id, **options)
63
+ endpoint = "/v1/text-to-voice"
64
+ request_body = {
65
+ voice_name: voice_name,
66
+ voice_description: voice_description,
67
+ generated_voice_id: generated_voice_id
68
+ }
69
+
70
+ # Add optional parameters if provided
71
+ request_body[:labels] = options[:labels] if options[:labels]
72
+ request_body[:played_not_selected_voice_ids] = options[:played_not_selected_voice_ids] if options[:played_not_selected_voice_ids]
73
+
74
+ @client.post(endpoint, request_body)
75
+ end
76
+
77
+ # GET /v1/voices
78
+ # Retrieves all voices associated with your Elevenlabs account
79
+ # Documentation: https://elevenlabs.io/docs/api-reference/voices
80
+ #
81
+ # @return [Hash] The JSON response containing an array of voices
82
+ def list_voices
83
+ endpoint = "/v1/voices"
84
+ @client.get(endpoint)
85
+ end
86
+
87
+ # Alias methods for backward compatibility and convenience
88
+ alias_method :design_voice, :design
89
+ alias_method :create_from_generated_voice, :create
90
+
91
+ private
92
+
93
+ attr_reader :client
94
+ end
95
+ end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ElevenlabsClient
4
+ class Voices
5
+ def initialize(client)
6
+ @client = client
7
+ end
8
+
9
+ # GET /v1/voices/{voice_id}
10
+ # Retrieves details about a single voice
11
+ # Documentation: https://elevenlabs.io/docs/api-reference/voices/get-voice
12
+ #
13
+ # @param voice_id [String] The ID of the voice to retrieve
14
+ # @return [Hash] Details of the voice
15
+ def get(voice_id)
16
+ endpoint = "/v1/voices/#{voice_id}"
17
+ @client.get(endpoint)
18
+ end
19
+
20
+ # GET /v1/voices
21
+ # Retrieves all voices associated with your Elevenlabs account
22
+ # Documentation: https://elevenlabs.io/docs/api-reference/voices
23
+ #
24
+ # @return [Hash] The JSON response containing an array of voices
25
+ def list
26
+ endpoint = "/v1/voices"
27
+ @client.get(endpoint)
28
+ end
29
+
30
+ # POST /v1/voices/add
31
+ # Creates a new voice by cloning from audio samples
32
+ # Documentation: https://elevenlabs.io/docs/api-reference/voices/add-voice
33
+ #
34
+ # @param name [String] Name of the voice
35
+ # @param samples [Array<File, IO>] Array of audio files to train the voice
36
+ # @param options [Hash] Additional parameters
37
+ # @option options [String] :description Description of the voice
38
+ # @option options [Hash] :labels Metadata labels for the voice
39
+ # @return [Hash] Response containing the new voice details
40
+ def create(name, samples = [], **options)
41
+ endpoint = "/v1/voices/add"
42
+
43
+ # Build multipart payload
44
+ payload = {
45
+ "name" => name,
46
+ "description" => options[:description] || ""
47
+ }
48
+
49
+ # Add labels if provided
50
+ if options[:labels]
51
+ options[:labels].each do |key, value|
52
+ payload["labels[#{key}]"] = value.to_s
53
+ end
54
+ end
55
+
56
+ # Add sample files
57
+ samples.each_with_index do |sample, index|
58
+ payload["files"] = @client.file_part(sample, "audio/mpeg")
59
+ end
60
+
61
+ @client.post_multipart(endpoint, payload)
62
+ end
63
+
64
+ # POST /v1/voices/{voice_id}/edit
65
+ # Updates an existing voice
66
+ # Documentation: https://elevenlabs.io/docs/api-reference/voices/edit-voice
67
+ #
68
+ # @param voice_id [String] The ID of the voice to edit
69
+ # @param samples [Array<File, IO>] Array of audio files (optional)
70
+ # @param options [Hash] Voice parameters to update
71
+ # @option options [String] :name New name for the voice
72
+ # @option options [String] :description New description for the voice
73
+ # @option options [Hash] :labels New labels for the voice
74
+ # @return [Hash] Response containing the updated voice details
75
+ def edit(voice_id, samples = [], **options)
76
+ endpoint = "/v1/voices/#{voice_id}/edit"
77
+
78
+ # Build multipart payload
79
+ payload = {}
80
+
81
+ # Add text fields if provided
82
+ payload["name"] = options[:name] if options[:name]
83
+ payload["description"] = options[:description] if options[:description]
84
+
85
+ # Add labels if provided
86
+ if options[:labels]
87
+ options[:labels].each do |key, value|
88
+ payload["labels[#{key}]"] = value.to_s
89
+ end
90
+ end
91
+
92
+ # Add sample files if provided
93
+ if samples && !samples.empty?
94
+ samples.each_with_index do |sample, index|
95
+ payload["files"] = @client.file_part(sample, "audio/mpeg")
96
+ end
97
+ end
98
+
99
+ @client.post_multipart(endpoint, payload)
100
+ end
101
+
102
+ # DELETE /v1/voices/{voice_id}
103
+ # Deletes a voice from your account
104
+ # Documentation: https://elevenlabs.io/docs/api-reference/voices/delete-voice
105
+ #
106
+ # @param voice_id [String] The ID of the voice to delete
107
+ # @return [Hash] Response confirming deletion
108
+ def delete(voice_id)
109
+ endpoint = "/v1/voices/#{voice_id}"
110
+ @client.delete(endpoint)
111
+ end
112
+
113
+ # Check if a voice is banned (safety control)
114
+ # @param voice_id [String] The ID of the voice to check
115
+ # @return [Boolean] True if the voice is banned
116
+ def banned?(voice_id)
117
+ voice = get(voice_id)
118
+ voice["safety_control"] == "BAN"
119
+ rescue ElevenlabsClient::ValidationError, ElevenlabsClient::APIError, ElevenlabsClient::NotFoundError
120
+ # If we can't get the voice, assume it's not banned
121
+ false
122
+ end
123
+
124
+ # Check if a voice is active (exists in the voice list)
125
+ # @param voice_id [String] The ID of the voice to check
126
+ # @return [Boolean] True if the voice is active
127
+ def active?(voice_id)
128
+ voices = list
129
+ active_voice_ids = voices["voices"].map { |voice| voice["voice_id"] }
130
+ active_voice_ids.include?(voice_id)
131
+ rescue ElevenlabsClient::ValidationError, ElevenlabsClient::APIError, ElevenlabsClient::NotFoundError
132
+ # If we can't get the voice list, assume it's not active
133
+ false
134
+ end
135
+
136
+ # Alias methods for backward compatibility and convenience
137
+ alias_method :get_voice, :get
138
+ alias_method :list_voices, :list
139
+ alias_method :create_voice, :create
140
+ alias_method :edit_voice, :edit
141
+ alias_method :delete_voice, :delete
142
+
143
+ private
144
+
145
+ attr_reader :client
146
+ end
147
+ end
@@ -6,4 +6,7 @@ module ElevenlabsClient
6
6
  class AuthenticationError < Error; end
7
7
  class RateLimitError < Error; end
8
8
  class ValidationError < Error; end
9
+ class NotFoundError < Error; end
10
+ class BadRequestError < Error; end
11
+ class UnprocessableEntityError < Error; end
9
12
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ElevenlabsClient
4
- VERSION = "0.2.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -8,6 +8,10 @@ require_relative "elevenlabs_client/endpoints/text_to_speech"
8
8
  require_relative "elevenlabs_client/endpoints/text_to_speech_stream"
9
9
  require_relative "elevenlabs_client/endpoints/text_to_dialogue"
10
10
  require_relative "elevenlabs_client/endpoints/sound_generation"
11
+ require_relative "elevenlabs_client/endpoints/text_to_voice"
12
+ require_relative "elevenlabs_client/endpoints/models"
13
+ require_relative "elevenlabs_client/endpoints/voices"
14
+ require_relative "elevenlabs_client/endpoints/music"
11
15
  require_relative "elevenlabs_client/client"
12
16
 
13
17
  module ElevenlabsClient
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elevenlabs_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vitor Oliveira
@@ -122,10 +122,14 @@ files:
122
122
  - lib/elevenlabs_client.rb
123
123
  - lib/elevenlabs_client/client.rb
124
124
  - lib/elevenlabs_client/endpoints/dubs.rb
125
+ - lib/elevenlabs_client/endpoints/models.rb
126
+ - lib/elevenlabs_client/endpoints/music.rb
125
127
  - lib/elevenlabs_client/endpoints/sound_generation.rb
126
128
  - lib/elevenlabs_client/endpoints/text_to_dialogue.rb
127
129
  - lib/elevenlabs_client/endpoints/text_to_speech.rb
128
130
  - lib/elevenlabs_client/endpoints/text_to_speech_stream.rb
131
+ - lib/elevenlabs_client/endpoints/text_to_voice.rb
132
+ - lib/elevenlabs_client/endpoints/voices.rb
129
133
  - lib/elevenlabs_client/errors.rb
130
134
  - lib/elevenlabs_client/settings.rb
131
135
  - lib/elevenlabs_client/version.rb