bannerbear 0.2.0 → 0.3.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/README.md +141 -5
- data/lib/bannerbear/v5/client.rb +109 -1
- data/lib/bannerbear/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: daa1514b2c5a5dddbef5836f7d64e3863932f4204e95a9625e7577b49dc70cad
|
|
4
|
+
data.tar.gz: 7a33d8e33c07d6b39561e6fbf6b64defafbb7d593a777bd1524f7623528e861c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 20c731f7f32fab1d5afc6fc6f85134febaacd2a386b3e86c526a0c2134a099272f8d98560ca469129f3300286db7439ff8f374e8bd62d1217c985a23a770d06f
|
|
7
|
+
data.tar.gz: df3b49048aa06fb412a3715228ae2af463701267636d00cdf8a7ede033c0a77e6d1c3bd7229cfb84fe1aef3ed1d79123741e23240cedeaa4895b096ed2bd34e2
|
data/README.md
CHANGED
|
@@ -31,6 +31,9 @@ For the **legacy V2 API**, see [Usage](#usage) below — that section is unchang
|
|
|
31
31
|
- [Account (V5)](#account-v5)
|
|
32
32
|
- [Image Templates (V5)](#image-templates-v5)
|
|
33
33
|
- [Images (V5)](#images-v5)
|
|
34
|
+
- [Tools (V5)](#tools-v5)
|
|
35
|
+
- [Assets (V5)](#assets-v5)
|
|
36
|
+
- [Publications (V5)](#publications-v5)
|
|
34
37
|
- [Batches (V5)](#batches-v5)
|
|
35
38
|
- [Webhooks (V5)](#webhooks-v5)
|
|
36
39
|
- [Instant URLs (V5)](#instant-urls-v5)
|
|
@@ -55,14 +58,38 @@ bb.account
|
|
|
55
58
|
|
|
56
59
|
### Image Templates (V5)
|
|
57
60
|
|
|
58
|
-
V5 renames V2's `templates` resource to `image_templates`.
|
|
61
|
+
V5 renames V2's `templates` resource to `image_templates`. Templates can be created, updated, and deleted through the API — `config` holds the full canvas.
|
|
59
62
|
|
|
60
63
|
```ruby
|
|
61
64
|
bb.list_image_templates(page: 1)
|
|
62
65
|
bb.get_image_template("template uid")
|
|
66
|
+
|
|
67
|
+
bb.create_image_template(
|
|
68
|
+
name: "My Template",
|
|
69
|
+
description: "Created from the API",
|
|
70
|
+
tags: ["portrait"],
|
|
71
|
+
width: 1080,
|
|
72
|
+
height: 1080,
|
|
73
|
+
config: { objects: [
|
|
74
|
+
{ id: "bg", type: "rectangle", left: 0, top: 0, width: 1080, height: 1080, "background-color" => "#0f172a" },
|
|
75
|
+
{ id: "headline", type: "text", left: 80, top: 400, width: 920, text: "Hello World!", "font-size" => 72, color: "#ffffff" }
|
|
76
|
+
] }
|
|
77
|
+
)
|
|
78
|
+
|
|
63
79
|
bb.update_image_template("template uid", name: "New Name", description: "...", tags: ["portrait"])
|
|
80
|
+
bb.delete_image_template("template uid")
|
|
64
81
|
```
|
|
65
82
|
|
|
83
|
+
##### Options for `create_image_template` / `update_image_template`
|
|
84
|
+
|
|
85
|
+
- `name` *required for create* (`string`)
|
|
86
|
+
- `description` (`string`)
|
|
87
|
+
- `tags` (`array`)
|
|
88
|
+
- `width` / `height`: canvas size in pixels (`integer`)
|
|
89
|
+
- `config`: full canvas configuration, `{ objects: [...] }`. Passing it **replaces** the existing config in place (`hash`)
|
|
90
|
+
|
|
91
|
+
Deleting is a soft delete: images already rendered from the template stay intact, but the template no longer appears in list/get calls and cannot be used for new renders.
|
|
92
|
+
|
|
66
93
|
### Images (V5)
|
|
67
94
|
|
|
68
95
|
V5's `modifications` is an **object** with two sub-keys:
|
|
@@ -95,7 +122,7 @@ bb.create_image("template uid", sync: true, modifications: { objects: [...] })
|
|
|
95
122
|
- `scale`: scale multiplier, 1–4 (`integer`)
|
|
96
123
|
- `dpi`: DPI metadata (`integer`)
|
|
97
124
|
- `quality`: quality control (`integer`)
|
|
98
|
-
- `proxy`: proxy
|
|
125
|
+
- `proxy`: proxy and resize external images before rendering (`boolean`)
|
|
99
126
|
- `metadata`: include any metadata to reference at a later point (`string`)
|
|
100
127
|
- `version`: pin template version (`integer`)
|
|
101
128
|
- `sync`: route to the sync host (`boolean`; Ruby-only, not sent to the API)
|
|
@@ -105,13 +132,112 @@ bb.get_image("image uid")
|
|
|
105
132
|
bb.list_images(page: 1)
|
|
106
133
|
```
|
|
107
134
|
|
|
135
|
+
### Tools (V5)
|
|
136
|
+
|
|
137
|
+
Tools are standalone media operations that do not use a template. Every tool is **asynchronous**: the call returns a pending *tool job*. Poll `get_tool_job` until the status is `"completed"` or `"failed"`, or subscribe to a webhook with the resource `"tool_job"`.
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
job = bb.trim_video(video_url: "https://example.com/clip.mp4", start: 2.5, end: 10.0)
|
|
141
|
+
|
|
142
|
+
job = bb.get_tool_job(job["uid"])
|
|
143
|
+
job["status"] # => "pending" | "running" | "completed" | "failed"
|
|
144
|
+
job["outputs"]["video_url"] if job["status"] == "completed"
|
|
145
|
+
|
|
146
|
+
bb.list_tool_jobs(page: 1)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Every tool also accepts an optional `metadata` string.
|
|
150
|
+
|
|
151
|
+
| Method | Required | Optional | Output key |
|
|
152
|
+
| --- | --- | --- | --- |
|
|
153
|
+
| `remove_bg` | `image_url` | — | `image_url` |
|
|
154
|
+
| `create_pdf` | `urls` | — | `pdf_url` |
|
|
155
|
+
| `trim_video` | `video_url`, `start`, `end` | — | `video_url` |
|
|
156
|
+
| `concat_videos` | `video_urls` | `width`, `height` | `video_url` |
|
|
157
|
+
| `resize_video` | `video_url`, `width`, `height` | `fit` | `video_url` |
|
|
158
|
+
| `crop_video` | `video_url`, `x`, `y`, `width`, `height` | — | `video_url` |
|
|
159
|
+
| `overlay_video` | `base_video_url`, `overlay_video_url`, `x`, `y` | `scale`, `start` | `video_url` |
|
|
160
|
+
| `overlay_image` | `video_url`, `image_url`, `x`, `y` | `opacity` | `video_url` |
|
|
161
|
+
| `subtitle_video` | `video_url` | `language`, `font`, `font_size`, `color`, `bold`, `italic`, `outline_color`, `outline_width`, `shadow_size`, `shadow_color`, `background_style`, `background_color`, `alignment` | `video_url` |
|
|
162
|
+
| `generate_voiceover` | `text`, `voice` | — | `audio_url` |
|
|
163
|
+
| `add_audio` | `video_url`, `audio_url`, `mode` | `volume`, `loop`, `ducking` | `video_url` |
|
|
164
|
+
| `add_cover_art` | `video_url`, `image_url` | — | `video_url` |
|
|
165
|
+
| `create_video_slideshow` | `image_urls` | `slide_duration`, `transition`, `transition_duration`, `width`, `height` | `video_url` |
|
|
166
|
+
| `apply_color_filter` | `video_url`, `filter` | — | `video_url` |
|
|
167
|
+
| `soften_video` | `video_url`, `strength` | — | `video_url` |
|
|
168
|
+
|
|
169
|
+
A few examples:
|
|
170
|
+
|
|
171
|
+
```ruby
|
|
172
|
+
bb.remove_bg(image_url: "https://example.com/product.png")
|
|
173
|
+
|
|
174
|
+
bb.subtitle_video(
|
|
175
|
+
video_url: "https://example.com/talk.mp4",
|
|
176
|
+
font: "montserrat",
|
|
177
|
+
font_size: 32,
|
|
178
|
+
color: "#ffffff",
|
|
179
|
+
background_style: "outline",
|
|
180
|
+
alignment: "2"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
bb.generate_voiceover(text: "Welcome to Bannerbear.", voice: "rachel")
|
|
184
|
+
|
|
185
|
+
bb.create_video_slideshow(
|
|
186
|
+
image_urls: ["https://example.com/1.jpg", "https://example.com/2.jpg"],
|
|
187
|
+
slide_duration: 3,
|
|
188
|
+
transition: "fade",
|
|
189
|
+
width: 1280,
|
|
190
|
+
height: 720
|
|
191
|
+
)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
`create_tool_job` calls any tool by name — the escape hatch for tools added after this release:
|
|
195
|
+
|
|
196
|
+
```ruby
|
|
197
|
+
bb.create_tool_job("remove_bg", image_url: "https://example.com/product.png")
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Assets (V5)
|
|
201
|
+
|
|
202
|
+
Upload a file (max 5MB) and get back a durable CDN URL you can feed to image modifications or tools. Uploads are deduplicated per workspace by SHA-256, so re-uploading the same bytes returns the existing record instead of creating a duplicate.
|
|
203
|
+
|
|
204
|
+
```ruby
|
|
205
|
+
asset = bb.upload_asset(File.binread("logo.png"), "image/png")
|
|
206
|
+
asset["url"]
|
|
207
|
+
|
|
208
|
+
bb.get_asset("asset uid")
|
|
209
|
+
bb.list_assets(page: 1)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Accepted mime types: `image/jpeg`, `image/png`, `image/webp`, `image/gif`, `video/mp4`, `video/webm`, `video/quicktime`, `audio/mpeg`, `audio/wav`, `audio/mp4`, `audio/webm`, `audio/ogg`, `application/pdf`.
|
|
213
|
+
|
|
214
|
+
`check_assets` maps each SHA-256 content hash to its existing asset (or `nil`), so a syncing client can skip the upload round-trip for content it already pushed. Max 100 hashes per call.
|
|
215
|
+
|
|
216
|
+
```ruby
|
|
217
|
+
digest = OpenSSL::Digest::SHA256.hexdigest(File.binread("logo.png"))
|
|
218
|
+
found = bb.check_assets([digest])
|
|
219
|
+
bb.upload_asset(File.binread("logo.png"), "image/png") if found[digest].nil?
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Publications (V5)
|
|
223
|
+
|
|
224
|
+
Publications are templates published to the public library. Installing one clones it into your workspace as a new image template.
|
|
225
|
+
|
|
226
|
+
```ruby
|
|
227
|
+
bb.list_publications(page: 1)
|
|
228
|
+
bb.get_publication("publication uid")
|
|
229
|
+
|
|
230
|
+
template = bb.install_publication("publication uid")
|
|
231
|
+
template["uid"]
|
|
232
|
+
```
|
|
233
|
+
|
|
108
234
|
### Batches (V5)
|
|
109
235
|
|
|
110
236
|
Generate multiple images in one request (up to 100).
|
|
111
237
|
|
|
112
238
|
```ruby
|
|
113
239
|
bb.create_batch(
|
|
114
|
-
type: "
|
|
240
|
+
type: "images",
|
|
115
241
|
items: [
|
|
116
242
|
{ template: "template uid 1", modifications: { objects: [...] } },
|
|
117
243
|
{ template: "template uid 2", modifications: { objects: [...] } }
|
|
@@ -132,7 +258,7 @@ hook = bb.create_webhook(
|
|
|
132
258
|
resource: "image",
|
|
133
259
|
event: "completed",
|
|
134
260
|
status: "active",
|
|
135
|
-
scope: "
|
|
261
|
+
scope: "all_templates",
|
|
136
262
|
templates: []
|
|
137
263
|
)
|
|
138
264
|
|
|
@@ -141,6 +267,16 @@ hook = bb.create_webhook(
|
|
|
141
267
|
puts hook["signing_key"]
|
|
142
268
|
```
|
|
143
269
|
|
|
270
|
+
##### Options for `create_webhook` / `update_webhook`
|
|
271
|
+
|
|
272
|
+
- `name` *required* (`string`)
|
|
273
|
+
- `url` *required* — the URL that receives the events (`string`)
|
|
274
|
+
- `resource`: `"image"`, `"batch"`, or `"tool_job"` (`string`)
|
|
275
|
+
- `event`: `"all_events"`, `"completed"`, or `"failed"` (`string`)
|
|
276
|
+
- `status`: `"active"` or `"disabled"` (`string`)
|
|
277
|
+
- `scope`: `"all_templates"` or `"specific_templates"` (`string`)
|
|
278
|
+
- `templates`: template UIDs, used when `scope` is `"specific_templates"` (`array`)
|
|
279
|
+
|
|
144
280
|
CRUD:
|
|
145
281
|
|
|
146
282
|
```ruby
|
|
@@ -151,7 +287,7 @@ bb.update_webhook("webhook uid",
|
|
|
151
287
|
resource: "image",
|
|
152
288
|
event: "completed",
|
|
153
289
|
status: "active",
|
|
154
|
-
scope: "
|
|
290
|
+
scope: "all_templates"
|
|
155
291
|
)
|
|
156
292
|
bb.delete_webhook("webhook uid")
|
|
157
293
|
bb.list_webhooks(page: 1)
|
data/lib/bannerbear/v5/client.rb
CHANGED
|
@@ -21,8 +21,16 @@ module Bannerbear
|
|
|
21
21
|
get_response "/image_templates/#{uid}"
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
def create_image_template(payload = {})
|
|
25
|
+
post_response "/image_templates", payload.slice(:name, :description, :tags, :width, :height, :config)
|
|
26
|
+
end
|
|
27
|
+
|
|
24
28
|
def update_image_template(uid, payload = {})
|
|
25
|
-
patch_response "/image_templates/#{uid}", payload.slice(:name, :description, :tags)
|
|
29
|
+
patch_response "/image_templates/#{uid}", payload.slice(:name, :description, :tags, :width, :height, :config)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def delete_image_template(uid)
|
|
33
|
+
delete_response "/image_templates/#{uid}"
|
|
26
34
|
end
|
|
27
35
|
|
|
28
36
|
# Images
|
|
@@ -39,6 +47,92 @@ module Bannerbear
|
|
|
39
47
|
post_response "/images", payload.slice(:modifications, :formats, :scale, :dpi, :quality, :proxy, :metadata, :version).merge({:template => uid}), payload[:sync]
|
|
40
48
|
end
|
|
41
49
|
|
|
50
|
+
# Tools
|
|
51
|
+
#
|
|
52
|
+
# Every tool is asynchronous: the POST returns a pending tool job. Poll
|
|
53
|
+
# get_tool_job until the status is "completed" or "failed", or subscribe
|
|
54
|
+
# to a webhook with the resource "tool_job".
|
|
55
|
+
|
|
56
|
+
TOOL_PARAMS = {
|
|
57
|
+
"remove_bg" => [:image_url],
|
|
58
|
+
"create_pdf" => [:urls],
|
|
59
|
+
"trim_video" => [:video_url, :start, :end],
|
|
60
|
+
"concat_videos" => [:video_urls, :width, :height],
|
|
61
|
+
"resize_video" => [:video_url, :width, :height, :fit],
|
|
62
|
+
"crop_video" => [:video_url, :x, :y, :width, :height],
|
|
63
|
+
"overlay_video" => [:base_video_url, :overlay_video_url, :x, :y, :scale, :start],
|
|
64
|
+
"overlay_image" => [:video_url, :image_url, :x, :y, :opacity],
|
|
65
|
+
"subtitle_video" => [:video_url, :language, :font, :font_size, :color, :bold, :italic,
|
|
66
|
+
:outline_color, :outline_width, :shadow_size, :shadow_color,
|
|
67
|
+
:background_style, :background_color, :alignment],
|
|
68
|
+
"generate_voiceover" => [:text, :voice],
|
|
69
|
+
"add_audio" => [:video_url, :audio_url, :mode, :volume, :loop, :ducking],
|
|
70
|
+
"add_cover_art" => [:video_url, :image_url],
|
|
71
|
+
"create_video_slideshow" => [:image_urls, :slide_duration, :transition, :transition_duration, :width, :height],
|
|
72
|
+
"apply_color_filter" => [:video_url, :filter],
|
|
73
|
+
"soften_video" => [:video_url, :strength]
|
|
74
|
+
}.freeze
|
|
75
|
+
|
|
76
|
+
def create_tool_job(tool, payload = {})
|
|
77
|
+
allowed = TOOL_PARAMS[tool.to_s]
|
|
78
|
+
raise ArgumentError, "unknown tool: #{tool.inspect}" if allowed.nil?
|
|
79
|
+
post_response "/tools/#{tool}", payload.slice(*allowed, :metadata)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Defines one method per tool, e.g. remove_bg(payload) or trim_video(payload).
|
|
83
|
+
TOOL_PARAMS.each_key do |tool|
|
|
84
|
+
define_method(tool) { |payload = {}| create_tool_job(tool, payload) }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Tool Jobs
|
|
88
|
+
|
|
89
|
+
def list_tool_jobs(params = {})
|
|
90
|
+
get_response "/tool_jobs?#{URI.encode_www_form(params.slice(:page))}"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def get_tool_job(uid)
|
|
94
|
+
get_response "/tool_jobs/#{uid}"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Assets
|
|
98
|
+
|
|
99
|
+
def list_assets(params = {})
|
|
100
|
+
get_response "/assets?#{URI.encode_www_form(params.slice(:page))}"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def get_asset(uid)
|
|
104
|
+
get_response "/assets/#{uid}"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Uploads raw file bytes (max 5MB). content_type must be the mime type of
|
|
108
|
+
# the data, e.g. "image/png" or "video/mp4". Uploads are deduplicated per
|
|
109
|
+
# workspace by SHA-256, so re-uploading the same bytes returns the
|
|
110
|
+
# existing asset instead of creating a duplicate.
|
|
111
|
+
def upload_asset(data, content_type)
|
|
112
|
+
upload_response "/assets", data, content_type
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Returns a map of SHA-256 content hash => asset (or nil when the hash is
|
|
116
|
+
# not stored in this workspace). Max 100 hashes per call.
|
|
117
|
+
def check_assets(content_hashes)
|
|
118
|
+
post_response "/assets/check", { :content_hashes => content_hashes }
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Publications
|
|
122
|
+
|
|
123
|
+
def list_publications(params = {})
|
|
124
|
+
get_response "/publications?#{URI.encode_www_form(params.slice(:page))}"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def get_publication(uid)
|
|
128
|
+
get_response "/publications/#{uid}"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Clones a publication into the workspace as a new image template.
|
|
132
|
+
def install_publication(uid)
|
|
133
|
+
post_response "/publications/#{uid}/install", {}
|
|
134
|
+
end
|
|
135
|
+
|
|
42
136
|
# Batches
|
|
43
137
|
|
|
44
138
|
def list_batches(params = {})
|
|
@@ -183,6 +277,20 @@ module Bannerbear
|
|
|
183
277
|
return body
|
|
184
278
|
end
|
|
185
279
|
|
|
280
|
+
def upload_response(url, data, content_type)
|
|
281
|
+
response = HTTParty.post("#{BB_API_ENDPOINT}#{url}",
|
|
282
|
+
body: data,
|
|
283
|
+
timeout: 30,
|
|
284
|
+
headers: {
|
|
285
|
+
'Authorization' => "Bearer #{@api_key}",
|
|
286
|
+
'Content-Type' => content_type
|
|
287
|
+
}
|
|
288
|
+
)
|
|
289
|
+
body = JSON.parse(response.body)
|
|
290
|
+
return {"error" => body['message'], "code" => response.code} if response.code >= 400
|
|
291
|
+
return body
|
|
292
|
+
end
|
|
293
|
+
|
|
186
294
|
def delete_response(url)
|
|
187
295
|
response = HTTParty.delete("#{BB_API_ENDPOINT}#{url}",
|
|
188
296
|
timeout: 5,
|
data/lib/bannerbear/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bannerbear
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jon Yongfook
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-08-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: httparty
|