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 +4 -4
- data/lib/typecast/client.rb +47 -6
- data/lib/typecast/models.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '07508aef051788fd8993b3c844fd431689193ea006541bc4f2cfc0224de8ed79'
|
|
4
|
+
data.tar.gz: 0dd2fc6ee5a0c435e5742f89dc8d14cb25feb9a3bc0dad9c6179ba0150617565
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a234192530e80f46f39d8bb4943d796dfad95f4dbe8521e92a52b74ee4b8c393ccd73741dc4f802469ea57e157d096f5a49a5e5ca8f93bfbde87605768a5543c
|
|
7
|
+
data.tar.gz: ec1f70d384151b04825b6018f9c478fe9c1a301859ddb529ee973128cbf8a44e097765bd9d735612ee9ed110576e1e782f08229cdeaae5d450a8600b540f3926
|
data/lib/typecast/client.rb
CHANGED
|
@@ -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 =
|
|
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 =
|
|
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
|
data/lib/typecast/models.rb
CHANGED
|
@@ -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.
|
|
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-
|
|
11
|
+
date: 2026-06-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|