lara-sdk 1.5.1 → 1.6.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/lib/lara/audio.rb +70 -0
- data/lib/lara/auth_token.rb +1 -1
- data/lib/lara/client.rb +15 -13
- data/lib/lara/models/audio.rb +47 -0
- data/lib/lara/translator.rb +6 -3
- data/lib/lara/version.rb +1 -1
- 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: cc633e73a404baacc47d8235d9c1e6df124f738b2395444dd63f67a150d518f8
|
|
4
|
+
data.tar.gz: 8030176d5341129e0b9a4b827d29bf5f8380acfedd1cf967dc91d0b31558bcb5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b18a99373f8706f6cdc4177d85527f50d6c8696bf322fe4242151e48a119a533a8f0d573d709dcd384e1645e65c151b03e52f5119b210ead410ad9b760b79d44
|
|
7
|
+
data.tar.gz: 34fe09cf554d21b9d5b3a31d8e8707dbfb001879f8eed9a6c50e82d167c643b000e8ef0ed183ad85bc4503eb985223ecd583f33972aab22668f8361e4a93a1bf
|
data/lib/lara/audio.rb
CHANGED
|
@@ -93,6 +93,76 @@ module Lara
|
|
|
93
93
|
end
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
+
# Uploads an audio file to S3 and creates a transcript translation job.
|
|
97
|
+
# @return [Lara::Models::Audio]
|
|
98
|
+
def upload_for_transcription(file_path:, filename:, target:, source: nil, adapt_to: nil, glossaries: nil,
|
|
99
|
+
no_trace: false, style: nil)
|
|
100
|
+
response_data = @client.get("/v2/audio/upload-url", params: { filename: filename })
|
|
101
|
+
url = response_data["url"]
|
|
102
|
+
fields = response_data["fields"]
|
|
103
|
+
|
|
104
|
+
@s3.upload(url: url, fields: fields, io: file_path)
|
|
105
|
+
|
|
106
|
+
body = {
|
|
107
|
+
s3key: fields["key"],
|
|
108
|
+
target: target,
|
|
109
|
+
source: source,
|
|
110
|
+
adapt_to: adapt_to,
|
|
111
|
+
glossaries: glossaries,
|
|
112
|
+
style: style
|
|
113
|
+
}.compact
|
|
114
|
+
|
|
115
|
+
headers = {}
|
|
116
|
+
headers["X-No-Trace"] = "true" if no_trace
|
|
117
|
+
|
|
118
|
+
response = @client.post("/v2/audio/translate-transcript", body: body, headers: headers)
|
|
119
|
+
response_params = response.transform_keys(&:to_sym)
|
|
120
|
+
Lara::Models::Audio.new(**filter_audio_params(response_params))
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Retrieves the translated transcript JSON.
|
|
124
|
+
# @return [Lara::Models::AudioTextResult]
|
|
125
|
+
def get_translated_transcript(id)
|
|
126
|
+
response = @client.get("/v2/audio/#{id}/translated-transcript")
|
|
127
|
+
Lara::Models::AudioTextResult.new(
|
|
128
|
+
id: response["id"],
|
|
129
|
+
source: response["source"],
|
|
130
|
+
target: response["target"],
|
|
131
|
+
filename: response["filename"],
|
|
132
|
+
duration: response["duration"],
|
|
133
|
+
text: response["text"],
|
|
134
|
+
translation: response["translation"],
|
|
135
|
+
segments: response["segments"]
|
|
136
|
+
)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Translates an audio transcript end-to-end
|
|
140
|
+
# @return [Lara::Models::AudioTextResult]
|
|
141
|
+
def translate_transcript(file_path:, filename:, target:, source: nil, adapt_to: nil, glossaries: nil,
|
|
142
|
+
no_trace: false, style: nil)
|
|
143
|
+
audio = upload_for_transcription(file_path: file_path, filename: filename, target: target, source: source,
|
|
144
|
+
adapt_to: adapt_to, glossaries: glossaries, no_trace: no_trace, style: style)
|
|
145
|
+
|
|
146
|
+
max_wait_time = 60 * 15 # 15 minutes
|
|
147
|
+
start = Time.now
|
|
148
|
+
|
|
149
|
+
loop do |_|
|
|
150
|
+
current = status(audio.id)
|
|
151
|
+
|
|
152
|
+
case current.status
|
|
153
|
+
when Lara::Models::AudioStatus::TRANSLATED
|
|
154
|
+
return get_translated_transcript(current.id)
|
|
155
|
+
when Lara::Models::AudioStatus::ERROR
|
|
156
|
+
raise Lara::LaraApiError.new(500, "AudioError",
|
|
157
|
+
current.error_reason || "Unknown error")
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
raise Timeout::Error if Time.now - start > max_wait_time
|
|
161
|
+
|
|
162
|
+
sleep @polling_interval
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
96
166
|
private
|
|
97
167
|
|
|
98
168
|
def filter_audio_params(params)
|
data/lib/lara/auth_token.rb
CHANGED
data/lib/lara/client.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Lara
|
|
|
16
16
|
DEFAULT_BASE_URL = "https://api.laratranslate.com"
|
|
17
17
|
|
|
18
18
|
def initialize(auth_method, base_url: DEFAULT_BASE_URL, connection_timeout: nil,
|
|
19
|
-
read_timeout: nil)
|
|
19
|
+
read_timeout: nil, session_id: nil)
|
|
20
20
|
case auth_method
|
|
21
21
|
when Credentials
|
|
22
22
|
@credentials = auth_method
|
|
@@ -31,6 +31,7 @@ module Lara
|
|
|
31
31
|
@base_url = base_url.to_s.sub(%r{/+$}, "")
|
|
32
32
|
@connection_timeout = connection_timeout
|
|
33
33
|
@read_timeout = read_timeout
|
|
34
|
+
@session_id = session_id
|
|
34
35
|
@extra_headers = {}
|
|
35
36
|
@auth_mutex = Monitor.new
|
|
36
37
|
|
|
@@ -64,7 +65,8 @@ module Lara
|
|
|
64
65
|
# @yield [Hash] Each partial JSON result from the stream (if streaming)
|
|
65
66
|
# @return [Hash, Array, String, nil] The JSON 'content' from the API, CSV body, or raw bytes.
|
|
66
67
|
def post(path, body: nil, files: nil, headers: nil, raw_response: false, &callback)
|
|
67
|
-
request(:post, path, body: body, files: files, headers: headers, raw_response: raw_response,
|
|
68
|
+
request(:post, path, body: body, files: files, headers: headers, raw_response: raw_response,
|
|
69
|
+
&callback)
|
|
68
70
|
end
|
|
69
71
|
|
|
70
72
|
# Sends a PUT request to the Lara API.
|
|
@@ -88,17 +90,18 @@ module Lara
|
|
|
88
90
|
|
|
89
91
|
private
|
|
90
92
|
|
|
91
|
-
def request(method, path, body: nil, files: nil, headers: nil, params: nil,
|
|
93
|
+
def request(method, path, body: nil, files: nil, headers: nil, params: nil,
|
|
94
|
+
raw_response: false, &callback)
|
|
92
95
|
ensure_valid_token
|
|
93
96
|
|
|
94
97
|
make_request(method, path, body: body, files: files, headers: headers, params: params,
|
|
95
|
-
|
|
98
|
+
raw_response: raw_response, &callback)
|
|
96
99
|
rescue LaraApiError => e
|
|
97
100
|
raise unless e.status_code == 401
|
|
98
101
|
|
|
99
102
|
@auth_mutex.synchronize { refresh_or_reauthenticate }
|
|
100
103
|
make_request(method, path, body: body, files: files, headers: headers, params: params,
|
|
101
|
-
|
|
104
|
+
raw_response: raw_response, &callback)
|
|
102
105
|
end
|
|
103
106
|
|
|
104
107
|
def ensure_valid_token
|
|
@@ -110,7 +113,7 @@ module Lara
|
|
|
110
113
|
end
|
|
111
114
|
|
|
112
115
|
def refresh_or_reauthenticate
|
|
113
|
-
if @auth_token&.refresh_token
|
|
116
|
+
if @auth_token&.refresh_token
|
|
114
117
|
begin
|
|
115
118
|
do_refresh
|
|
116
119
|
return
|
|
@@ -146,6 +149,8 @@ module Lara
|
|
|
146
149
|
'application/json', timestamp)}"
|
|
147
150
|
}
|
|
148
151
|
|
|
152
|
+
headers["X-Lara-Auth-Session-Id"] = @session_id if @session_id && !@session_id.empty?
|
|
153
|
+
|
|
149
154
|
conn = Faraday.new(url: @base_url) do |c|
|
|
150
155
|
c.adapter Faraday.default_adapter
|
|
151
156
|
end
|
|
@@ -160,8 +165,6 @@ module Lara
|
|
|
160
165
|
data = JSON.parse(response.body)
|
|
161
166
|
refresh_token_value = response.headers["x-lara-refresh-token"]
|
|
162
167
|
|
|
163
|
-
raise LaraError, "Missing refresh token in authentication response" unless refresh_token_value
|
|
164
|
-
|
|
165
168
|
AuthToken.new(data["token"], refresh_token_value)
|
|
166
169
|
end
|
|
167
170
|
|
|
@@ -186,12 +189,11 @@ module Lara
|
|
|
186
189
|
data = JSON.parse(response.body)
|
|
187
190
|
refresh_token_value = response.headers["x-lara-refresh-token"]
|
|
188
191
|
|
|
189
|
-
raise LaraError, "Missing refresh token in refresh response" unless refresh_token_value
|
|
190
|
-
|
|
191
192
|
@auth_token = AuthToken.new(data["token"], refresh_token_value)
|
|
192
193
|
end
|
|
193
194
|
|
|
194
|
-
def make_request(method, path, body: nil, files: nil, headers: nil, params: nil,
|
|
195
|
+
def make_request(method, path, body: nil, files: nil, headers: nil, params: nil,
|
|
196
|
+
raw_response: false, &callback)
|
|
195
197
|
path = "/#{path}" unless path.start_with?("/")
|
|
196
198
|
request_headers = build_request_headers(body, files, headers)
|
|
197
199
|
|
|
@@ -248,7 +250,7 @@ module Lara
|
|
|
248
250
|
|
|
249
251
|
begin
|
|
250
252
|
result = JSON.parse(trimmed_line)
|
|
251
|
-
block
|
|
253
|
+
block&.call(result)
|
|
252
254
|
last_result = result
|
|
253
255
|
rescue JSON::ParserError
|
|
254
256
|
next
|
|
@@ -258,7 +260,7 @@ module Lara
|
|
|
258
260
|
if !buffer.empty? && buffer.strip != ""
|
|
259
261
|
begin
|
|
260
262
|
result = JSON.parse(buffer.strip)
|
|
261
|
-
block
|
|
263
|
+
block&.call(result)
|
|
262
264
|
last_result = result
|
|
263
265
|
rescue JSON::ParserError
|
|
264
266
|
end
|
data/lib/lara/models/audio.rb
CHANGED
|
@@ -52,5 +52,52 @@ module Lara
|
|
|
52
52
|
@error_reason = error_reason
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
|
+
|
|
56
|
+
# Audio text segment for transcript results
|
|
57
|
+
class AudioTextSegment < Base
|
|
58
|
+
attr_reader :id, :start, :text, :translation
|
|
59
|
+
|
|
60
|
+
# JSON field is "end"; expose as #end to match the wire contract / other SDKs.
|
|
61
|
+
attr_reader :end
|
|
62
|
+
|
|
63
|
+
def initialize(id: nil, start: nil, end_time: nil, text: nil, translation: nil, **kwargs)
|
|
64
|
+
super()
|
|
65
|
+
@id = id
|
|
66
|
+
@start = start
|
|
67
|
+
@end = end_time.nil? ? (kwargs[:end] || kwargs["end"]) : end_time
|
|
68
|
+
@text = text
|
|
69
|
+
@translation = translation
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Audio text result for transcript translation
|
|
74
|
+
class AudioTextResult < Base
|
|
75
|
+
attr_reader :id, :source, :target, :filename, :duration, :text, :translation, :segments
|
|
76
|
+
|
|
77
|
+
def initialize(id: nil, source: nil, target: nil, filename: nil, duration: nil, text: nil,
|
|
78
|
+
translation: nil, segments: nil, **_kwargs)
|
|
79
|
+
super()
|
|
80
|
+
@id = id
|
|
81
|
+
@source = source
|
|
82
|
+
@target = target
|
|
83
|
+
@filename = filename
|
|
84
|
+
@duration = duration
|
|
85
|
+
@text = text
|
|
86
|
+
@translation = translation
|
|
87
|
+
@segments = Array(segments).map do |seg|
|
|
88
|
+
if seg.is_a?(Hash)
|
|
89
|
+
AudioTextSegment.new(
|
|
90
|
+
id: seg["id"] || seg[:id],
|
|
91
|
+
start: seg["start"] || seg[:start],
|
|
92
|
+
end_time: seg["end"] || seg[:end],
|
|
93
|
+
text: seg["text"] || seg[:text],
|
|
94
|
+
translation: seg["translation"] || seg[:translation]
|
|
95
|
+
)
|
|
96
|
+
else
|
|
97
|
+
seg
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
55
102
|
end
|
|
56
103
|
end
|
data/lib/lara/translator.rb
CHANGED
|
@@ -11,8 +11,9 @@ module Lara
|
|
|
11
11
|
# @param base_url [String,nil]
|
|
12
12
|
# @param connection_timeout [Integer,nil]
|
|
13
13
|
# @param read_timeout [Integer,nil]
|
|
14
|
+
# @param session_id [String,nil]
|
|
14
15
|
def initialize(credentials: nil, auth_token: nil, access_key_id: nil, access_key_secret: nil,
|
|
15
|
-
base_url: nil, connection_timeout: nil, read_timeout: nil)
|
|
16
|
+
base_url: nil, connection_timeout: nil, read_timeout: nil, session_id: nil)
|
|
16
17
|
auth_method = if auth_token
|
|
17
18
|
auth_token
|
|
18
19
|
elsif credentials
|
|
@@ -25,7 +26,8 @@ module Lara
|
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
@client = Client.new(auth_method, base_url: base_url,
|
|
28
|
-
connection_timeout: connection_timeout, read_timeout: read_timeout
|
|
29
|
+
connection_timeout: connection_timeout, read_timeout: read_timeout,
|
|
30
|
+
session_id: session_id)
|
|
29
31
|
@memories = Memories.new(@client)
|
|
30
32
|
@glossaries = Glossaries.new(@client)
|
|
31
33
|
@styleguides = Styleguides.new(@client)
|
|
@@ -140,7 +142,8 @@ module Lara
|
|
|
140
142
|
# @return [Lara::Models::ProfanityDetectResult]
|
|
141
143
|
def detect_profanities(text, language:, content_type: "text/plain")
|
|
142
144
|
unless VALID_CONTENT_TYPES.include?(content_type)
|
|
143
|
-
raise ArgumentError,
|
|
145
|
+
raise ArgumentError,
|
|
146
|
+
"Invalid content_type '#{content_type}'. Must be one of: #{VALID_CONTENT_TYPES.join(', ')}"
|
|
144
147
|
end
|
|
145
148
|
|
|
146
149
|
body = { text: text, language: language, content_type: content_type }
|
data/lib/lara/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lara-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Translated
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-07-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|