tryiton 1.0.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 +7 -0
- data/README.md +99 -0
- data/lib/tryiton/client.rb +150 -0
- data/lib/tryiton/version.rb +5 -0
- data/lib/tryiton.rb +9 -0
- metadata +47 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: dc7c9b0e58bea7120e432b59b8db60364d95f66f2962fdc54e04a64602d8d757
|
|
4
|
+
data.tar.gz: e1f08ab852de54a201dc962e9799d35853b7b7a8c1da8c6947e3d1d135a85814
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: b577a2d18b96023088aa636b0a287ec4a96581c264017fbc0aefb981af926b8bc49d1437964738e52e43da421628b7725028b7ac94dc54ca490c981769e4b445
|
|
7
|
+
data.tar.gz: 327f7c89b5a2b35f6dad23b60faaaaf6ee21e4ff7d39a42ea87ad29651eadd11c95679c000cc5c655893f386ecfd92104c05c38122009329a9969705dbb4d859
|
data/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# TryItOn Ruby SDK — AI Virtual Try-On API
|
|
2
|
+
|
|
3
|
+
Official Ruby client for the [TryItOn](https://tryiton.now) virtual try-on API. Add photoreal AI virtual try-on for clothing, accessories, hairstyles, and tattoos to your Ruby or Rails application with a few lines of code.
|
|
4
|
+
|
|
5
|
+
- Virtual clothing try-on and accessory try-on (eyewear, footwear, headwear, jewelry)
|
|
6
|
+
- Hairstyle and tattoo try-on
|
|
7
|
+
- Standard library only (no dependencies), with a built-in job polling helper
|
|
8
|
+
|
|
9
|
+
Full API reference: [docs.tryiton.now](https://docs.tryiton.now) · Get an API key: [tryiton.now/app/developer](https://tryiton.now/app/developer)
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
gem install tryiton
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or add it to your Gemfile:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
gem "tryiton"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Requires Ruby 2.6 or later.
|
|
24
|
+
|
|
25
|
+
## Quickstart: run a virtual try-on
|
|
26
|
+
|
|
27
|
+
Submit a garment and a model photo, then wait for the generated result image.
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
require "tryiton"
|
|
31
|
+
|
|
32
|
+
client = Tryiton::Client.new(api_key: ENV["TRYITON_API_KEY"])
|
|
33
|
+
|
|
34
|
+
# Submit a clothing try-on
|
|
35
|
+
job_id = client.try_on_clothes(
|
|
36
|
+
model_image: "https://example.com/model.jpg",
|
|
37
|
+
garment_image: "https://example.com/tshirt.jpg",
|
|
38
|
+
category: "clothing",
|
|
39
|
+
subcategory: "tops"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Poll until the job completes and return the output image URL(s)
|
|
43
|
+
urls = client.wait_for_result(job_id)
|
|
44
|
+
puts urls.first # CDN URL, available for 72 hours
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Image inputs accept a public URL or a base64 data URL (`data:image/png;base64,...`).
|
|
48
|
+
|
|
49
|
+
## Core parameters
|
|
50
|
+
|
|
51
|
+
`try_on_clothes` covers clothing and accessory try-on. The most important parameters:
|
|
52
|
+
|
|
53
|
+
| Parameter | Type | Required | Description |
|
|
54
|
+
| --------- | ---- | -------- | ----------- |
|
|
55
|
+
| `model_image` | String | Yes | URL or base64 data URL of the person. |
|
|
56
|
+
| `garment_image` | String | Yes | URL or base64 data URL of the garment or accessory. |
|
|
57
|
+
| `category` | String | No | Item type: `auto`, `clothing`, `eyewear`, `footwear`, `headwear`, `jewelry`, `accessories`, or `others`. `auto` detects it for you. |
|
|
58
|
+
| `subcategory` | String | No | Required for `clothing` (`tops`, `bottoms`, `dresses`), `jewelry`, and `accessories`. |
|
|
59
|
+
|
|
60
|
+
Additional options (`mode` and `moderation_level` for clothing; `num_samples` 1–4 and `output_format` `png`/`jpeg` for every try-on, including hairstyle and tattoo) are documented in the [API reference](https://docs.tryiton.now).
|
|
61
|
+
|
|
62
|
+
## Other endpoints
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
# Hairstyle try-on (see Tryiton::HAIRCUTS for all supported values)
|
|
66
|
+
client.try_on_hairstyle(face_image: face_url, haircut: "BuzzCut", hair_color: "ash blonde")
|
|
67
|
+
|
|
68
|
+
# Tattoo try-on
|
|
69
|
+
client.try_on_tattoo(body_image: body_url, design_image: design_url, placement: "on the right forearm, small")
|
|
70
|
+
|
|
71
|
+
# Poll a job manually, or check your credit balance
|
|
72
|
+
status = client.get_status(job_id) # { "status" => ..., "output" => [...], "error" => ... }
|
|
73
|
+
credits = client.get_credits # { "on_demand" => ..., "subscription" => ..., "purchased" => ..., "reserved" => ... }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Error handling
|
|
77
|
+
|
|
78
|
+
All failures raise `Tryiton::Error`, which carries the HTTP status code and the API error name.
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
begin
|
|
82
|
+
client.try_on_clothes(...)
|
|
83
|
+
rescue Tryiton::Error => e
|
|
84
|
+
puts "#{e.status} #{e.error_name} #{e.message}" # e.g. 429 OutOfCredits
|
|
85
|
+
end
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Notes
|
|
89
|
+
|
|
90
|
+
- Output image URLs expire 72 hours after completion. Download any results you want to keep.
|
|
91
|
+
- Failed jobs are never charged.
|
|
92
|
+
|
|
93
|
+
## Documentation
|
|
94
|
+
|
|
95
|
+
Full documentation, parameter reference, and guides: [docs.tryiton.now](https://docs.tryiton.now)
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
MIT
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "net/http"
|
|
5
|
+
require "uri"
|
|
6
|
+
|
|
7
|
+
module Tryiton
|
|
8
|
+
# Raised for API-level errors and runtime (job) failures.
|
|
9
|
+
#
|
|
10
|
+
# status - HTTP status code, or nil for a runtime job failure.
|
|
11
|
+
# error_name - the API error name, e.g. "OutOfCredits" / "ProcessingError".
|
|
12
|
+
class Error < StandardError
|
|
13
|
+
attr_reader :status, :error_name
|
|
14
|
+
|
|
15
|
+
def initialize(message, status: nil, error_name: nil)
|
|
16
|
+
super(message)
|
|
17
|
+
@status = status
|
|
18
|
+
@error_name = error_name
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Supported `haircut` values for hairstyle try-on.
|
|
23
|
+
HAIRCUTS = %w[
|
|
24
|
+
Afro BobCut BowlCut BoxBraids BuzzCut Chignon CombOver CornrowBraids CurlyBob
|
|
25
|
+
CurlyShag DoubleBun Dreadlocks FauxHawk FishtailBraid LongCurly LongHairTiedUp
|
|
26
|
+
LongHimeCut LongStraight LongTwintails LongWavy LongWavyCurtainBangs ManBun
|
|
27
|
+
MessyTousled PixieCut Pompadour Ponytail ShortCurlyPixie ShortTwintails
|
|
28
|
+
ShoulderLengthHair Spiky TexturedFringe TwinBraids Updo WavyShag
|
|
29
|
+
].freeze
|
|
30
|
+
|
|
31
|
+
# Client for the TryItOn virtual try-on API.
|
|
32
|
+
#
|
|
33
|
+
# client = Tryiton::Client.new(api_key: ENV["TRYITON_API_KEY"])
|
|
34
|
+
# job_id = client.try_on_clothes(
|
|
35
|
+
# model_image: "https://example.com/model.jpg",
|
|
36
|
+
# garment_image: "https://example.com/tshirt.jpg",
|
|
37
|
+
# category: "clothing", subcategory: "tops"
|
|
38
|
+
# )
|
|
39
|
+
# urls = client.wait_for_result(job_id)
|
|
40
|
+
#
|
|
41
|
+
# See https://docs.tryiton.now
|
|
42
|
+
class Client
|
|
43
|
+
DEFAULT_BASE_URL = "https://tryiton.now/api/v1"
|
|
44
|
+
|
|
45
|
+
def initialize(api_key:, base_url: DEFAULT_BASE_URL, timeout: 60)
|
|
46
|
+
raise Error.new("An api_key is required.", error_name: "ConfigError") if api_key.nil? || api_key.empty?
|
|
47
|
+
|
|
48
|
+
@api_key = api_key
|
|
49
|
+
@base_url = base_url.sub(%r{/+\z}, "")
|
|
50
|
+
@timeout = timeout
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Put a garment or accessory on a person. Returns the job id.
|
|
54
|
+
# Keys: model_image (required), garment_image (required), category,
|
|
55
|
+
# subcategory, mode, num_samples (1-4), output_format ("png"/"jpeg"),
|
|
56
|
+
# moderation_level ("conservative"/"permissive"/"none").
|
|
57
|
+
def try_on_clothes(**params)
|
|
58
|
+
request(:post, "/tryon/clothes", params)["jobId"]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Restyle a person's hair. Returns the job id.
|
|
62
|
+
# Keys: face_image (required), haircut (required), hair_color,
|
|
63
|
+
# num_samples (1-4), output_format ("png"/"jpeg").
|
|
64
|
+
def try_on_hairstyle(**params)
|
|
65
|
+
request(:post, "/tryon/hairstyle", params)["jobId"]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Ink a design onto skin. Returns the job id.
|
|
69
|
+
# Keys: body_image (required), design_image (required), placement,
|
|
70
|
+
# num_samples (1-4), output_format ("png"/"jpeg").
|
|
71
|
+
def try_on_tattoo(**params)
|
|
72
|
+
request(:post, "/tryon/tattoo", params)["jobId"]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Fetch the current status of a job.
|
|
76
|
+
# Returns { "status" => ..., "output" => [...], "error" => ... }.
|
|
77
|
+
def get_status(job_id)
|
|
78
|
+
data = request(:get, "/status/#{URI.encode_www_form_component(job_id)}")
|
|
79
|
+
{ "status" => data["status"] || "processing", "output" => data["output"] || [], "error" => data["error"] }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Fetch your current credit balance.
|
|
83
|
+
def get_credits
|
|
84
|
+
request(:get, "/credits")["credits"]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Poll a job until it completes, then return the output image URLs.
|
|
88
|
+
# Raises Tryiton::Error if the job fails or the timeout is reached.
|
|
89
|
+
def wait_for_result(job_id, poll_interval: 2.0, timeout: 120.0)
|
|
90
|
+
deadline = monotonic + timeout
|
|
91
|
+
loop do
|
|
92
|
+
status = get_status(job_id)
|
|
93
|
+
return status["output"] if status["status"] == "completed"
|
|
94
|
+
|
|
95
|
+
if status["status"] == "failed"
|
|
96
|
+
err = status["error"] || {}
|
|
97
|
+
raise Error.new(err["message"] || "Try-on failed.", error_name: err["name"] || "ProcessingError")
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
raise Error.new("Timed out waiting for job #{job_id}.", error_name: "Timeout") if monotonic > deadline
|
|
101
|
+
|
|
102
|
+
sleep(poll_interval)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def monotonic
|
|
109
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def request(method, path, body = nil)
|
|
113
|
+
uri = URI.parse("#{@base_url}#{path}")
|
|
114
|
+
req =
|
|
115
|
+
case method
|
|
116
|
+
when :post then Net::HTTP::Post.new(uri)
|
|
117
|
+
else Net::HTTP::Get.new(uri)
|
|
118
|
+
end
|
|
119
|
+
req["Authorization"] = "Bearer #{@api_key}"
|
|
120
|
+
|
|
121
|
+
unless body.nil?
|
|
122
|
+
compact = body.reject { |_, v| v.nil? }
|
|
123
|
+
req["Content-Type"] = "application/json"
|
|
124
|
+
req.body = JSON.generate(compact)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
begin
|
|
128
|
+
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https", read_timeout: @timeout) do |http|
|
|
129
|
+
http.request(req)
|
|
130
|
+
end
|
|
131
|
+
rescue StandardError => e
|
|
132
|
+
raise Error.new("Network error: #{e.message}", error_name: "NetworkError")
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
data =
|
|
136
|
+
begin
|
|
137
|
+
res.body && !res.body.empty? ? JSON.parse(res.body) : {}
|
|
138
|
+
rescue JSON::ParserError
|
|
139
|
+
{}
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
code = res.code.to_i
|
|
143
|
+
unless (200..299).cover?(code)
|
|
144
|
+
raise Error.new(data["message"] || "HTTP #{code}", status: code, error_name: data["error"])
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
data
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
data/lib/tryiton.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: tryiton
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- TryItOn
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: Add photoreal clothing, accessory, hairstyle, and tattoo virtual try-on
|
|
13
|
+
to your app.
|
|
14
|
+
executables: []
|
|
15
|
+
extensions: []
|
|
16
|
+
extra_rdoc_files: []
|
|
17
|
+
files:
|
|
18
|
+
- README.md
|
|
19
|
+
- lib/tryiton.rb
|
|
20
|
+
- lib/tryiton/client.rb
|
|
21
|
+
- lib/tryiton/version.rb
|
|
22
|
+
homepage: https://docs.tryiton.now
|
|
23
|
+
licenses:
|
|
24
|
+
- MIT
|
|
25
|
+
metadata:
|
|
26
|
+
homepage_uri: https://tryiton.now
|
|
27
|
+
documentation_uri: https://docs.tryiton.now
|
|
28
|
+
source_code_uri: https://github.com/tryiton-now/tryiton-ruby
|
|
29
|
+
bug_tracker_uri: https://github.com/tryiton-now/tryiton-ruby/issues
|
|
30
|
+
rdoc_options: []
|
|
31
|
+
require_paths:
|
|
32
|
+
- lib
|
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
34
|
+
requirements:
|
|
35
|
+
- - ">="
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '2.6'
|
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
39
|
+
requirements:
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: '0'
|
|
43
|
+
requirements: []
|
|
44
|
+
rubygems_version: 3.6.9
|
|
45
|
+
specification_version: 4
|
|
46
|
+
summary: Official Ruby SDK for the TryItOn virtual try-on API.
|
|
47
|
+
test_files: []
|