typecast-ruby 0.1.0 → 0.1.2

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: 783ee042ba45a4a26659e61c50b2e28fb058f03ba0ad11e1573bf43a5abca44a
4
- data.tar.gz: a15b17e6e707b5dc8bf4c524c6a3b50ceee8b0dcada0d34820359905f38042c9
3
+ metadata.gz: '07508aef051788fd8993b3c844fd431689193ea006541bc4f2cfc0224de8ed79'
4
+ data.tar.gz: 0dd2fc6ee5a0c435e5742f89dc8d14cb25feb9a3bc0dad9c6179ba0150617565
5
5
  SHA512:
6
- metadata.gz: 66ace71a958a4f2f05e321d9be6ff162f66e8fbf4c327bb300ff29f716a4b4e64d426cc9034fb830452a97689a2e28ad6143135d501c1e8f024d7d3ab6926c2a
7
- data.tar.gz: 1145c85137b9fb6253b3db418c8f50ecd53afe244c98a8c6df3b867ed9dc94b24f49f34ee98707fd76f6dc8cbfa1c39ae84698ec31895dff619492731e2ae5f3
6
+ metadata.gz: a234192530e80f46f39d8bb4943d796dfad95f4dbe8521e92a52b74ee4b8c393ccd73741dc4f802469ea57e157d096f5a49a5e5ca8f93bfbde87605768a5543c
7
+ data.tar.gz: ec1f70d384151b04825b6018f9c478fe9c1a301859ddb529ee973128cbf8a44e097765bd9d735612ee9ed110576e1e782f08229cdeaae5d450a8600b540f3926
@@ -14,8 +14,9 @@ module Typecast
14
14
  attr_reader :api_key, :base_url
15
15
 
16
16
  def initialize(api_key: ENV["TYPECAST_API_KEY"], base_url: ENV["TYPECAST_API_HOST"] || DEFAULT_BASE_URL, open_timeout: 10, read_timeout: 30)
17
- @api_key = api_key.to_s
17
+ @api_key = api_key.to_s.strip
18
18
  @base_url = normalize_base_url(base_url)
19
+ validate_api_key!
19
20
  @open_timeout = open_timeout
20
21
  @read_timeout = read_timeout
21
22
  end
@@ -29,6 +30,22 @@ module Typecast
29
30
  )
30
31
  end
31
32
 
33
+ # Browse available API voices at https://typecast.ai/developers/api/voices.
34
+ def generate_to_file(path, text:, voice_id:, model: Models::TTS_MODEL_V30, language: nil, prompt: nil, output: nil, seed: nil)
35
+ request = Models::TTSRequest.new(
36
+ voice_id: voice_id,
37
+ text: text,
38
+ model: model,
39
+ language: language,
40
+ prompt: prompt,
41
+ output: output || inferred_output(path),
42
+ seed: seed
43
+ )
44
+ response = text_to_speech(request)
45
+ File.binwrite(path, response.audio_data)
46
+ response
47
+ end
48
+
32
49
  def text_to_speech_stream(request)
33
50
  response = request_json(:post, "/v1/text-to-speech/stream", request.to_h)
34
51
  return enum_for(:text_to_speech_stream, request) unless block_given?
@@ -80,12 +97,19 @@ module Typecast
80
97
 
81
98
  private
82
99
 
100
+ def inferred_output(path)
101
+ case File.extname(path.to_s).downcase
102
+ when ".mp3" then Models::Output.new(audio_format: Models::AUDIO_MP3)
103
+ when ".wav" then Models::Output.new(audio_format: Models::AUDIO_WAV)
104
+ end
105
+ end
106
+
83
107
  def request_json(method, path, body = nil, query = nil)
84
- headers = { "X-API-KEY" => api_key, "Content-Type" => "application/json" }
108
+ headers = auth_headers.merge("Content-Type" => "application/json")
85
109
  request_raw(method, path, body.nil? ? nil : JSON.generate(body), headers, query)
86
110
  end
87
111
 
88
- def request_raw(method, path, body = nil, headers = { "X-API-KEY" => api_key }, query = nil)
112
+ def request_raw(method, path, body = nil, headers = auth_headers, query = nil)
89
113
  uri = build_uri(path, query)
90
114
  request = request_for(method, uri)
91
115
  headers.each { |key, value| request[key] = value }
@@ -121,13 +145,26 @@ module Typecast
121
145
  :post,
122
146
  path,
123
147
  body,
124
- {
125
- "X-API-KEY" => api_key,
148
+ auth_headers.merge(
126
149
  "Content-Type" => "multipart/form-data; boundary=#{boundary}"
127
- }
150
+ )
128
151
  )
129
152
  end
130
153
 
154
+ def auth_headers
155
+ api_key.empty? ? {} : { "X-API-KEY" => api_key }
156
+ end
157
+
158
+ def validate_api_key!
159
+ return unless api_key.empty? && default_base_url?
160
+
161
+ raise ArgumentError, "api_key is required for the default Typecast API host"
162
+ end
163
+
164
+ def default_base_url?
165
+ normalized_base_url(base_url).casecmp?(normalized_base_url(DEFAULT_BASE_URL))
166
+ end
167
+
131
168
  def validate_clone_inputs(audio, name)
132
169
  raise ArgumentError, "audio must be 25MB or smaller" if audio.bytesize > Models::CLONING_MAX_FILE_SIZE
133
170
  raise ArgumentError, "name must be 1-#{Models::CLONING_NAME_MAX_LENGTH} chars" if name.empty? || name.length > Models::CLONING_NAME_MAX_LENGTH
@@ -145,6 +182,10 @@ module Typecast
145
182
  raise ArgumentError, "base_url must be a valid URL"
146
183
  end
147
184
 
185
+ def normalized_base_url(value)
186
+ value.to_s.strip.sub(%r{/+\z}, "")
187
+ end
188
+
148
189
  def local_uri?(uri)
149
190
  uri.scheme == "http" && ["localhost", "127.0.0.1", "::1"].include?(uri.hostname)
150
191
  end
@@ -90,6 +90,7 @@ module Typecast
90
90
  class TTSRequest
91
91
  attr_reader :voice_id, :text, :model, :language, :prompt, :output, :seed
92
92
 
93
+ # Browse available API voices at https://typecast.ai/developers/api/voices.
93
94
  def initialize(voice_id:, text:, model:, language: nil, prompt: nil, output: nil, seed: nil)
94
95
  @voice_id = voice_id
95
96
  @text = text
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typecast-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neosapience
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-05 00:00:00.000000000 Z
11
+ date: 2026-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest