shrine-transloadit 0.5.1 → 1.0.0.beta
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 +469 -329
- data/lib/shrine/plugins/transloadit.rb +167 -326
- data/shrine-transloadit.gemspec +5 -7
- metadata +19 -43
- data/lib/shrine/plugins/transloadit2.rb +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 379b39a12a74f5b4e3e0c9336c1cc560eaa5ce78596fc55aa8990ea017d632bf
|
4
|
+
data.tar.gz: '04930268d5f2c682dac35cb635fd2e0be617fc6ce1c3bd55b0ee572f771b300f'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bc371cbec27b5cf8a642eedea74c372e5b1bbef48b82956635a28dd76b02eb1436870a5ba3b18671f26bc897199c77c995df16070704688fecb3d42d11b8f74
|
7
|
+
data.tar.gz: 3da98b2895dd0af05e9f6aac2cc835105b754ef91e0ae0cd528b6cd7ace93a9ac82e8b7dc1ae5dc22b928d24caff89ebb3203b9a97735ac69349e97249ec89b4
|
data/README.md
CHANGED
@@ -1,474 +1,608 @@
|
|
1
1
|
# Shrine::Plugins::Transloadit
|
2
2
|
|
3
|
-
Provides [Transloadit] integration for [Shrine].
|
3
|
+
Provides [Transloadit] integration for [Shrine], using its [Ruby SDK].
|
4
4
|
|
5
|
-
Transloadit is a service that helps you
|
5
|
+
Transloadit is a service that helps you handle file uploads, resize, crop and
|
6
6
|
watermark your images, make GIFs, transcode your videos, extract thumbnails,
|
7
|
-
generate audio waveforms
|
8
|
-
|
7
|
+
generate audio waveforms and more.
|
8
|
+
|
9
|
+
## Contents
|
10
|
+
|
11
|
+
* [Installation](#installation)
|
12
|
+
* [Setup](#setup)
|
13
|
+
- [Credentials](#credentials)
|
14
|
+
* [Usage](#usge)
|
15
|
+
- [Backgrounding](#backgrounding)
|
16
|
+
* [Notifications](#notifications)
|
17
|
+
* [Direct uploads](#direct-uploads)
|
18
|
+
* [Promotion](#promotion)
|
19
|
+
* [Skipping exports](#skipping-exports)
|
20
|
+
* [API](#api)
|
21
|
+
- [Processing & Saving](#processing-saving)
|
22
|
+
- [Generating steps](#generating-steps)
|
23
|
+
- [Parsing files](#parsing-files)
|
24
|
+
- [Verifying signature](#verifying-signature)
|
25
|
+
- [Transloadit instance](#transloadit-instance)
|
26
|
+
|
27
|
+
## Installation
|
28
|
+
|
29
|
+
Put the gem in your Gemfile:
|
30
|
+
|
31
|
+
```rb
|
32
|
+
# Gemfile
|
33
|
+
gem "shrine-transloadit", "~> 1.0"
|
34
|
+
```
|
9
35
|
|
10
36
|
## Setup
|
11
37
|
|
12
|
-
|
13
|
-
this plugin currently supports only Amazon S3 (just because there are no Shrine
|
14
|
-
integrations written for other services on that list yet). You can just add
|
15
|
-
shrine-transloadit to your current setup:
|
38
|
+
Load the `transloadit` plugin and configure your Transloadit key and secret:
|
16
39
|
|
17
40
|
```rb
|
18
|
-
|
19
|
-
|
20
|
-
|
41
|
+
Shrine.plugin :transloadit, auth: {
|
42
|
+
key: "YOUR_TRANSLOADIT_KEY",
|
43
|
+
secret: "YOUR_TRANSLOADIT_SECRET",
|
44
|
+
}
|
21
45
|
```
|
22
46
|
|
23
|
-
|
24
|
-
require "shrine"
|
25
|
-
require "shrine/storage/s3"
|
47
|
+
### Credentials
|
26
48
|
|
27
|
-
|
28
|
-
|
29
|
-
region: "my-region",
|
30
|
-
access_key_id: "abc",
|
31
|
-
secret_access_key: "xyz",
|
32
|
-
}
|
49
|
+
You'll need to create [credentials] for the storage services you want to import
|
50
|
+
from and export to. Then you need to map these credentials to Shrine storages:
|
33
51
|
|
52
|
+
```rb
|
34
53
|
Shrine.storages = {
|
35
|
-
cache: Shrine::Storage::S3.new(prefix: "cache", **
|
36
|
-
store: Shrine::Storage::S3.new(
|
54
|
+
cache: Shrine::Storage::S3.new(prefix: "cache", **options),
|
55
|
+
store: Shrine::Storage::S3.new(**options),
|
37
56
|
}
|
38
57
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
58
|
+
Shrine.plugin :transloadit, auth: { ... },
|
59
|
+
credentials: {
|
60
|
+
cache: :s3_store, # use "s3_store" credentials for :cache storage
|
61
|
+
store: :s3_store, # use "s3_store" credentials for :store storage
|
62
|
+
}
|
44
63
|
```
|
45
64
|
|
46
|
-
|
47
|
-
uploads to Transloadit], or just use any other `:cache` storage which provides
|
48
|
-
URLs for uploaded files.
|
49
|
-
|
50
|
-
## How it works
|
51
|
-
|
52
|
-
Transloadit works in a way that you create an "assembly", which contains all
|
53
|
-
information about how the file(s) should be processed, from import to export.
|
54
|
-
Processing itself happens asynchronously, and you can give Transloadit a URL
|
55
|
-
which it will POST results to when processing finishes.
|
65
|
+
### Derivatives
|
56
66
|
|
57
|
-
|
58
|
-
|
59
|
-
a URL to the route in your app where you'd like Transloadit to POST the results
|
60
|
-
of processing. Then you can call the plugin again in the route to save the
|
61
|
-
results to your attachment column.
|
67
|
+
The examples will assume you have the [`derivatives`][derivatives] plugin
|
68
|
+
loaded:
|
62
69
|
|
63
|
-
|
64
|
-
|
70
|
+
```rb
|
71
|
+
Shrine.plugin :derivatives
|
72
|
+
```
|
65
73
|
|
66
74
|
## Usage
|
67
75
|
|
68
|
-
|
69
|
-
|
70
|
-
|
76
|
+
The `transloadit` plugin provides helper methods for creating [import][import
|
77
|
+
robots] and [export][export robots] steps, as well as for parsing out exported
|
78
|
+
files from results.
|
71
79
|
|
72
|
-
|
73
|
-
|
74
|
-
|
80
|
+
Here is a basic example where we kick off transcoding and thumbnail extraction
|
81
|
+
from an attached video, wait for assembly to complete, then save processed
|
82
|
+
files as derivatives:
|
75
83
|
|
76
84
|
```rb
|
77
|
-
class
|
78
|
-
|
79
|
-
|
80
|
-
|
85
|
+
class VideoUploader < Shrine
|
86
|
+
Attacher.transloadit_processor :video do
|
87
|
+
import = file.transloadit_import_step
|
88
|
+
encode = transloadit_step "encode", "/video/encode", use: import
|
89
|
+
thumbs = transloadit_step "thumbs", "/video/thumbs", use: import
|
90
|
+
export = store.transloadit_export_step use: [encode, thumbs]
|
91
|
+
|
92
|
+
assembly = transloadit.assembly(steps: [import, encode, thumbs, export])
|
93
|
+
assembly.create!
|
94
|
+
end
|
81
95
|
|
82
|
-
|
96
|
+
Attacher.transloadit_saver :video do |response|
|
97
|
+
transcoded = store.transloadit_file(response["results"]["encode"])
|
98
|
+
thumbnails = store.transloadit_files(response["results"]["thumbs"])
|
99
|
+
|
100
|
+
merge_derivatives(transcoded: transcoded, thumbnails: thumbnails)
|
83
101
|
end
|
84
102
|
end
|
85
103
|
```
|
104
|
+
```rb
|
105
|
+
response = attacher.transloadit_process(:video)
|
106
|
+
response.reload_until_finished!
|
86
107
|
|
87
|
-
|
88
|
-
|
89
|
-
|
108
|
+
if response.error?
|
109
|
+
# handle error
|
110
|
+
end
|
90
111
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
112
|
+
attacher.transloadit_save(:video, response)
|
113
|
+
attacher.derivatives #=>
|
114
|
+
# {
|
115
|
+
# transcoded: #<Shrine::UploadedFile storage_key=:store ...>,
|
116
|
+
# thumbnails: [
|
117
|
+
# #<Shrine::UploadedFile storage_key=:store ...>,
|
118
|
+
# #<Shrine::UploadedFile storage_key=:store ...>,
|
119
|
+
# ...
|
120
|
+
# ]
|
121
|
+
# }
|
122
|
+
```
|
96
123
|
|
97
|
-
###
|
124
|
+
### Backgrounding
|
98
125
|
|
99
|
-
|
100
|
-
|
126
|
+
When using [backgrounding], it's probably best to create the assembly after
|
127
|
+
promotion:
|
101
128
|
|
102
129
|
```rb
|
103
|
-
class
|
104
|
-
|
130
|
+
class PromoteJob
|
131
|
+
def perform(record, name, file_data)
|
132
|
+
attacher = Shrine::Attacher.retrieve(model: record, name: name, file: file_data)
|
133
|
+
attacher.atomic_promote
|
134
|
+
attacher.transloadit_process(:video)
|
135
|
+
# ...
|
136
|
+
rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
|
137
|
+
end
|
138
|
+
end
|
139
|
+
```
|
105
140
|
|
106
|
-
|
107
|
-
original = transloadit_file(io)
|
108
|
-
medium = original.add_step("resize_500", "/image/resize", width: 500)
|
109
|
-
small = original.add_step("resize_300", "/image/resize", width: 300)
|
141
|
+
## Notifications
|
110
142
|
|
111
|
-
|
143
|
+
When using [assembly notifications], the attacher data can be sent to the
|
144
|
+
webhook via `:fields`:
|
112
145
|
|
113
|
-
|
114
|
-
|
146
|
+
```rb
|
147
|
+
Attacher.transloadit_processor :video do
|
148
|
+
# ...
|
149
|
+
assembly = transloadit.assembly(
|
150
|
+
steps: [ ... ],
|
151
|
+
notify_url: "https://example.com/webhooks/transloadit",
|
152
|
+
fields: {
|
153
|
+
attacher: {
|
154
|
+
record_class: record.class,
|
155
|
+
record_id: record.id,
|
156
|
+
name: name,
|
157
|
+
data: file_data,
|
158
|
+
}
|
159
|
+
}
|
160
|
+
)
|
161
|
+
assembly.create!
|
115
162
|
end
|
116
163
|
```
|
117
164
|
|
118
|
-
|
165
|
+
Then in the webhook handler we can load the attacher and [atomically
|
166
|
+
persist][atomic_helpers] assembly results. If during processing the attachment
|
167
|
+
has changed or record was deleted, we make sure we delete processed files.
|
119
168
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
format in which shrine-transloadit should save the processed files.
|
169
|
+
```rb
|
170
|
+
post "/transloadit/video" do
|
171
|
+
Shrine.transloadit_verify!(params) # verify transloadit signature
|
124
172
|
|
125
|
-
|
173
|
+
response = JSON.parse(params["transloadit"])
|
126
174
|
|
127
|
-
|
175
|
+
record_class, record_id, name, file_data = response["fields"]["attacher"].values
|
176
|
+
record_class = Object.const_get(record_class)
|
128
177
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
thumbs = transloadit_file(io)
|
133
|
-
.add_step("thumbs", "/document/thumbs", ...)
|
134
|
-
.multiple(:list) # marks that the result of this pipeline should be saved as a list
|
178
|
+
begin
|
179
|
+
record = record_class.find(record_id)
|
180
|
+
attacher = Shrine::Attacher.retrieve(model: record, name: name, file: file_data)
|
135
181
|
|
136
|
-
|
182
|
+
attacher.transloadit_save(:video, response)
|
183
|
+
|
184
|
+
attacher.atomic_persist
|
185
|
+
rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
|
186
|
+
unless attacher
|
187
|
+
attacher = record_class.send(:"#{name}_attacher")
|
188
|
+
attacher.transloadit_save(:video, response)
|
189
|
+
end
|
190
|
+
|
191
|
+
attacher.destroy(background: true) # delete orphaned files
|
137
192
|
end
|
193
|
+
|
194
|
+
# return successful response for Transloadit
|
195
|
+
status 200
|
138
196
|
end
|
139
197
|
```
|
140
198
|
|
141
|
-
|
199
|
+
Note that if you have CSRF protection, make sure that you skip verifying the
|
200
|
+
CSRF token for this route.
|
201
|
+
|
202
|
+
## Direct uploads
|
142
203
|
|
143
|
-
|
144
|
-
|
145
|
-
# [
|
146
|
-
# #<Shrine::UploadedFile ...>
|
147
|
-
# #<Shrine::UploadedFile ...>
|
148
|
-
# ...
|
149
|
-
# ]
|
204
|
+
Transloadit supports client side uploads via [Robodog], an [Uppy]-based
|
205
|
+
JavaScript library.
|
150
206
|
|
151
|
-
|
207
|
+
If you have an HTML form, you can use Robodog's [Form API][Robodog Form] to add
|
208
|
+
Transloadit's encoding capabilities to it:
|
209
|
+
|
210
|
+
```js
|
211
|
+
window.Robodog.form('form#myform', {
|
212
|
+
params: {
|
213
|
+
auth: { key: 'YOUR_TRANSLOADIT_KEY' },
|
214
|
+
template_id: 'YOUR_TEMPLATE_ID',
|
215
|
+
},
|
216
|
+
waitForEncoding: true,
|
217
|
+
// ...
|
218
|
+
})
|
152
219
|
```
|
153
220
|
|
154
|
-
|
221
|
+
With the above setup, Robodog will send the assembly results to your controller
|
222
|
+
in the `transloadit` param, which we can parse out and save to our record. See
|
223
|
+
the [demo app] for an example of doing this.
|
224
|
+
|
225
|
+
## Promotion
|
155
226
|
|
156
|
-
Transloadit
|
157
|
-
|
227
|
+
If you want Transloadit to also upload your cached original file to permanent
|
228
|
+
storage, you can skip promotion on the Shrine side:
|
158
229
|
|
159
230
|
```rb
|
160
|
-
class
|
161
|
-
|
162
|
-
|
163
|
-
|
231
|
+
class VideoUploader < Shrine
|
232
|
+
Attacher.transloadit_processor :video do
|
233
|
+
import = file.transloadit_import_step
|
234
|
+
encode = transloadit_step "encode", "/video/encode", use: import
|
235
|
+
thumbs = transloadit_step "thumbs", "/video/thumbs", use: import
|
236
|
+
export = store.transloadit_export_step use: [import, encode, thumbs] # include original
|
237
|
+
|
238
|
+
assembly = transloadit.assembly(use: [import, encode, thumbs, export])
|
239
|
+
assembly.create!
|
240
|
+
end
|
241
|
+
|
242
|
+
Attacher.transloadit_saver :video do |response|
|
243
|
+
stored = store.transloadit_file(response["results"]["import"])
|
244
|
+
transcoded = store.transloadit_file(response["results"]["encode"])
|
245
|
+
thumbnails = store.transloadit_files(response["results"]["thumbs"])
|
246
|
+
|
247
|
+
set(stored) # set promoted file
|
248
|
+
merge_derivatives(transcoded: transcoded, thumbnails: thumbnails)
|
164
249
|
end
|
165
250
|
end
|
166
251
|
```
|
252
|
+
```rb
|
253
|
+
class PromoteJob
|
254
|
+
def perform(record, name, file_data)
|
255
|
+
attacher = Shrine::Attacher.retrieve(model: record, name: name, file: file_data)
|
167
256
|
|
168
|
-
|
169
|
-
|
257
|
+
response = attacher.transloadit_process(:video)
|
258
|
+
response.reload_until_finished!
|
170
259
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
260
|
+
if response.error?
|
261
|
+
# handle error
|
262
|
+
end
|
263
|
+
|
264
|
+
original_file = attacher.file
|
265
|
+
attacher.transloadit_save(:video, response)
|
266
|
+
|
267
|
+
attacher.atomic_persist(original_file)
|
268
|
+
rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
|
269
|
+
# delete orphaned processed files (backgrounding plugin is recommended)
|
270
|
+
attacher.destroy(background: true) if attacher
|
271
|
+
end
|
175
272
|
end
|
176
273
|
```
|
177
274
|
|
178
|
-
|
179
|
-
CSRF token for this route.
|
180
|
-
|
181
|
-
### Direct uploads
|
275
|
+
## Skipping exports
|
182
276
|
|
183
|
-
Transloadit
|
184
|
-
|
185
|
-
client side uploads, take a look its [Transloadit plugin][uppy transloadit] for
|
186
|
-
more details.
|
277
|
+
If you want to use Transloadit only for processing, and prefer to store results
|
278
|
+
to yourself, you can do so with help of the [shrine-url] gem.
|
187
279
|
|
188
|
-
```
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
.use(Uppy.Tus, {})
|
196
|
-
.use(Uppy.Transloadit, {
|
197
|
-
waitForEncoding: true,
|
198
|
-
params: {
|
199
|
-
auth: { key: 'YOUR_TRANSLOADIT_KEY' },
|
200
|
-
steps: {
|
201
|
-
// ...
|
202
|
-
}
|
203
|
-
}
|
204
|
-
})
|
280
|
+
```rb
|
281
|
+
# Gemfile
|
282
|
+
gem "shrine-url"
|
283
|
+
```
|
284
|
+
```rb
|
285
|
+
# ...
|
286
|
+
require "shrine/storage/url"
|
205
287
|
|
206
|
-
|
288
|
+
Shrine.storages = {
|
289
|
+
# ...
|
290
|
+
url: Shrine::Storage::Url.new,
|
291
|
+
}
|
207
292
|
```
|
208
293
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
which case Transloadit will return temporary URL to the processed files, which
|
213
|
-
we can use as the uploaded file identifier:
|
294
|
+
If you don't specify an export step, Transloadit will return processed files
|
295
|
+
uploaded to Transloadit's temporary storage. You can load these results using
|
296
|
+
the `:url` storage, and then upload them to your permanent storage:
|
214
297
|
|
215
|
-
```
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
transloadit: result['meta'],
|
227
|
-
}
|
228
|
-
})
|
298
|
+
```rb
|
299
|
+
class VideoUploader < Shrine
|
300
|
+
Attacher.transloadit_processor :video do
|
301
|
+
import = file.transloadit_import_step
|
302
|
+
encode = transloadit_step "encode", "/video/encode", use: import
|
303
|
+
thumbs = transloadit_step "thumbs", "/video/thumbs", use: import
|
304
|
+
# no export step
|
305
|
+
|
306
|
+
assembly = transloadit.assembly(steps: [import, encode, thumbs])
|
307
|
+
assembly.create!
|
308
|
+
end
|
229
309
|
|
230
|
-
|
231
|
-
|
232
|
-
|
310
|
+
Attacher.transloadit_saver :video do |response|
|
311
|
+
url = shrine_class.new(:url)
|
312
|
+
transcoded = url.transloadit_file(response["results"]["encode"])
|
313
|
+
thumbnails = url.transloadit_files(response["results"]["thumbs"])
|
233
314
|
|
234
|
-
|
235
|
-
|
315
|
+
# results are uploaded to Transloadit's temporary storage
|
316
|
+
transcoded #=> #<Shrine::UploadedFile @storage_key=:url @id="https://tmp.transloadit.com/..." ...>
|
317
|
+
thumbnails #=> [#<Shrine::UploadedFile @storage_key=:url @id="https://tmp.transloadit.com/..." ...>, ...]
|
236
318
|
|
319
|
+
# upload results to permanent storage
|
320
|
+
add_derivatives(transcoded: transcoded, thumbnails: thumbnails)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
```
|
237
324
|
```rb
|
238
|
-
|
325
|
+
response = attacher.transloadit_process(:video)
|
326
|
+
response.reload_until_finished!
|
327
|
+
|
328
|
+
if response.error?
|
329
|
+
# handle error
|
330
|
+
end
|
331
|
+
|
332
|
+
attacher.transloadit_save(:video, response)
|
333
|
+
attacher.derivatives #=>
|
334
|
+
# {
|
335
|
+
# transcoded: #<Shrine::UploadedFile storage_key=:store ...>,
|
336
|
+
# thumbnails: [
|
337
|
+
# #<Shrine::UploadedFile storage_key=:store ...>,
|
338
|
+
# #<Shrine::UploadedFile storage_key=:store ...>,
|
339
|
+
# ...
|
340
|
+
# ]
|
341
|
+
# }
|
239
342
|
```
|
240
343
|
|
344
|
+
## API
|
345
|
+
|
346
|
+
### Processor
|
347
|
+
|
348
|
+
The processor is just a block registered under an identifier, which is expected
|
349
|
+
to create a Transloadit assembly:
|
350
|
+
|
241
351
|
```rb
|
242
|
-
|
243
|
-
|
352
|
+
class VideoUploader < Shrine
|
353
|
+
Attacher.transloadit_processor :video do
|
354
|
+
# ...
|
355
|
+
end
|
356
|
+
end
|
244
357
|
```
|
245
358
|
|
246
|
-
|
247
|
-
|
248
|
-
### Templates
|
359
|
+
It is executed when `Attacher#transloadit_process` is called:
|
249
360
|
|
250
|
-
|
251
|
-
|
361
|
+
```rb
|
362
|
+
attacher.transloadit_process(:video) # calls :video processor
|
363
|
+
```
|
252
364
|
|
253
|
-
|
254
|
-
and we just set the location of the imported file.
|
365
|
+
Any arguments passed to the processor will be given to the block:
|
255
366
|
|
256
367
|
```rb
|
257
|
-
|
258
|
-
{
|
259
|
-
steps: {
|
260
|
-
resize: {
|
261
|
-
robot: "/image/resize",
|
262
|
-
use: "import", # the "import" step will be passed in
|
263
|
-
width: 800
|
264
|
-
},
|
265
|
-
export: {
|
266
|
-
robot: "/s3/store",
|
267
|
-
use: "resize",
|
268
|
-
bucket: "YOUR_AWS_BUCKET",
|
269
|
-
key: "YOUR_AWS_KEY",
|
270
|
-
secret: "YOUR_AWS_SECRET",
|
271
|
-
bucket_region: "YOUR_AWS_REGION",
|
272
|
-
path: "videos/${unique_prefix}/${file.url_name}"
|
273
|
-
}
|
274
|
-
}
|
275
|
-
}
|
368
|
+
attacher.transloadit_process(:video, foo: "bar")
|
276
369
|
```
|
277
370
|
```rb
|
278
|
-
class
|
279
|
-
|
280
|
-
|
281
|
-
transloadit_assembly("my_template", steps: [import])
|
371
|
+
class VideoUploader < Shrine
|
372
|
+
Attacher.transloadit_processor :video do |options|
|
373
|
+
options #=> { :foo => "bar" }
|
282
374
|
end
|
283
375
|
end
|
284
376
|
```
|
285
377
|
|
286
|
-
|
287
|
-
|
288
|
-
Even though submitting a Transloadit assembly doesn't require any uploading, it
|
289
|
-
still does two HTTP requests, so you might want to put them into a background
|
290
|
-
job. You can configure that in the `TransloaditUploader` base uploader class:
|
378
|
+
The processor block is executed in context of a `Shrine::Attacher` instance:
|
291
379
|
|
292
380
|
```rb
|
293
|
-
class
|
294
|
-
|
295
|
-
|
296
|
-
auth_secret: "your transloadit secret"
|
381
|
+
class VideoUploader < Shrine
|
382
|
+
Attacher.transloadit_processor :video do
|
383
|
+
self #=> #<Shrine::Attacher>
|
297
384
|
|
298
|
-
|
385
|
+
record #=> #<Video>
|
386
|
+
name #=> :file
|
387
|
+
file #=> #<Shrine::UploadedFile>
|
388
|
+
end
|
299
389
|
end
|
300
390
|
```
|
301
|
-
```rb
|
302
|
-
class TransloaditJob
|
303
|
-
include Sidekiq::Worker
|
304
391
|
|
305
|
-
|
306
|
-
|
392
|
+
### Saver
|
393
|
+
|
394
|
+
The saver is just a block registered under an identifier, which is expected to
|
395
|
+
save given Transloadit results into the attacher:
|
396
|
+
|
397
|
+
```rb
|
398
|
+
class VideoUploader < Shrine
|
399
|
+
Attacher.transloadit_saver :video do |results|
|
400
|
+
# ...
|
307
401
|
end
|
308
402
|
end
|
309
403
|
```
|
310
404
|
|
311
|
-
|
405
|
+
It is executed when `Attacher#transloadit_save` is called:
|
406
|
+
|
407
|
+
```rb
|
408
|
+
attacher.transloadit_save(:video, results) # calls :video saver
|
409
|
+
```
|
312
410
|
|
313
|
-
|
314
|
-
about the status of that assembly, which the plugin saves to the cached
|
315
|
-
attachment's metadata.
|
411
|
+
Any arguments passed to the saver will be given to the block:
|
316
412
|
|
317
413
|
```rb
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
# "execution_duration" => 2.113,
|
327
|
-
# "params" => "{\"steps\":{...}}",
|
328
|
-
# ...
|
329
|
-
# }
|
414
|
+
attacher.transloadit_save(:video, results, foo: "bar")
|
415
|
+
```
|
416
|
+
```rb
|
417
|
+
class VideoUploader < Shrine
|
418
|
+
Attacher.transloadit_saver :video do |results, options|
|
419
|
+
options #=> { :foo => "bar" }
|
420
|
+
end
|
421
|
+
end
|
330
422
|
```
|
331
423
|
|
332
|
-
|
333
|
-
information:
|
424
|
+
The saver block is executed in context of a `Shrine::Attacher` instance:
|
334
425
|
|
335
426
|
```rb
|
336
|
-
|
337
|
-
|
338
|
-
|
427
|
+
class VideoUploader < Shrine
|
428
|
+
Attacher.transloadit_saver :video do |results|
|
429
|
+
self #=> #<Shrine::Attacher>
|
430
|
+
|
431
|
+
record #=> #<Video>
|
432
|
+
name #=> :file
|
433
|
+
file #=> #<Shrine::UploadedFile>
|
434
|
+
end
|
435
|
+
end
|
339
436
|
```
|
340
437
|
|
341
|
-
###
|
438
|
+
### Step
|
342
439
|
|
343
|
-
|
344
|
-
metadata. When the Transloadit processing is finished and the results are saved
|
345
|
-
as a Shrine attachment, this metadata will be automatically used to populate
|
346
|
-
the attachment's metadata.
|
440
|
+
You can generate `Transloadit::Step` objects with `Shrine.transloadit_step`:
|
347
441
|
|
348
|
-
|
349
|
-
|
442
|
+
```rb
|
443
|
+
Shrine.transloadit_step "my_name", "/my/robot", **options
|
444
|
+
#=> #<Transloadit::Step name="my_name", robot="/my/robot", options={...}>
|
445
|
+
```
|
446
|
+
|
447
|
+
This method adds the ability to pass another `Transloadit::Step` object as the
|
448
|
+
`:use` parameter:
|
350
449
|
|
351
450
|
```rb
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
# "date_recorded" => "2013/09/04 08:03:39",
|
356
|
-
# "date_file_created" => "2013/09/04 12:03:39 GMT",
|
357
|
-
# "date_file_modified" => "2016/07/11 02:27:11 GMT",
|
358
|
-
# "aspect_ratio" => "1.504",
|
359
|
-
# "city" => "Decatur",
|
360
|
-
# "state" => "Georgia",
|
361
|
-
# "country" => "United States",
|
362
|
-
# "latitude" => 33.77519301,
|
363
|
-
# "longitude" => -84.295608,
|
364
|
-
# "orientation" => "Horizontal (normal)",
|
365
|
-
# "colorspace" => "RGB",
|
366
|
-
# "average_color" => "#8b8688",
|
367
|
-
# ...
|
368
|
-
# }
|
451
|
+
step_one = Shrine.transloadit_step "one", "/robot/one"
|
452
|
+
step_two = Shrine.transloadit_step "two", "/robot/two", use: step_one
|
453
|
+
step_two.options[:use] #=> ["one"]
|
369
454
|
```
|
370
455
|
|
371
|
-
### Import
|
456
|
+
### Import step
|
372
457
|
|
373
|
-
|
374
|
-
|
458
|
+
The `Shrine::UploadedFile#transloadit_import_step` method generates an import
|
459
|
+
step for the uploaded file:
|
375
460
|
|
376
461
|
```rb
|
377
|
-
|
462
|
+
file = Shrine.upload(io, :store)
|
463
|
+
file.storage #=> #<Shrine::Storage::S3>
|
464
|
+
file.id #=> "foo"
|
378
465
|
|
379
|
-
|
466
|
+
step = file.transloadit_import_step
|
380
467
|
|
381
|
-
|
382
|
-
|
468
|
+
step #=> #<Transloadit::Step ...>
|
469
|
+
step.name #=> "import"
|
470
|
+
step.robot #=> "/s3/import"
|
471
|
+
|
472
|
+
step.options[:path] #=> "foo"
|
473
|
+
step.options[:credentials] #=> :s3_store (inferred from the plugin setting)
|
383
474
|
```
|
384
475
|
|
476
|
+
You can change the default step name:
|
477
|
+
|
385
478
|
```rb
|
386
|
-
|
479
|
+
step = file.transloadit_import_step("my_import")
|
480
|
+
step.name #=> "my_import"
|
481
|
+
```
|
387
482
|
|
388
|
-
|
483
|
+
You can also pass step options:
|
389
484
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
})
|
485
|
+
```rb
|
486
|
+
step = file.transloadit_import_step(ignore_errors: ["meta"])
|
487
|
+
step.options[:ignore_errors] #=> ["meta"]
|
394
488
|
```
|
395
489
|
|
396
|
-
|
397
|
-
expanded forms.
|
490
|
+
The following import robots are currently supported:
|
398
491
|
|
399
|
-
|
492
|
+
| Robot | Description |
|
493
|
+
| :----------- | :---------- |
|
494
|
+
| `/s3/import` | activated for `Shrine::Storage::S3` |
|
495
|
+
| `/http/import` | activated for any other storage which returns HTTP(S) URLs |
|
496
|
+
| `/ftp/import` | activated for any other storage which returns FTP URLs |
|
400
497
|
|
401
|
-
|
402
|
-
|
403
|
-
|
498
|
+
### Export step
|
499
|
+
|
500
|
+
The `Shrine#transloadit_export_step` method generates an export step for the underlying
|
501
|
+
storage:
|
404
502
|
|
405
503
|
```rb
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
504
|
+
uploader = Shrine.new(:store)
|
505
|
+
uploader.storage #=> #<Shrine::Storage::S3>
|
506
|
+
|
507
|
+
step = uploader.transloadit_export_step
|
508
|
+
|
509
|
+
step #=> #<Transloadit::Step ...>
|
510
|
+
step.name #=> "export"
|
511
|
+
step.robot #=> "/s3/store"
|
512
|
+
|
513
|
+
step.options[:credentials] #=> :s3_store (inferred from the plugin setting)
|
414
514
|
```
|
415
515
|
|
416
|
-
|
516
|
+
You can change the default step name:
|
417
517
|
|
418
|
-
|
419
|
-
|
420
|
-
|
518
|
+
```rb
|
519
|
+
step = uploader.transloadit_export_step("my_export")
|
520
|
+
step.name #=> "my_export"
|
521
|
+
```
|
522
|
+
|
523
|
+
You can also pass step options:
|
421
524
|
|
422
525
|
```rb
|
423
|
-
|
424
|
-
|
425
|
-
|
526
|
+
step = file.transloadit_export_step(acl: "public-read")
|
527
|
+
step.options[:acl] #=> "public-read"
|
528
|
+
```
|
426
529
|
|
427
|
-
|
428
|
-
notify_url = "https://myapp.com/webhooks/transloadit"
|
429
|
-
else
|
430
|
-
# In development we cannot receive webhooks, because Transloadit as an
|
431
|
-
# external service cannot reach our localhost.
|
432
|
-
end
|
530
|
+
The following export robots are currently supported:
|
433
531
|
|
434
|
-
|
435
|
-
|
436
|
-
|
532
|
+
| Robot | Description |
|
533
|
+
| :---- | :---------- |
|
534
|
+
| `/s3/store` | activated for `Shrine::Storage::S3` |
|
535
|
+
| `/google/store` | activated for [`Shrine::Storage::GoogleCloudStorage`][shrine-gcs] |
|
536
|
+
| `/youtube/store` | activated for [`Shrine::Storage::YouTube`][shrine-youtube] |
|
537
|
+
|
538
|
+
### File
|
539
|
+
|
540
|
+
The `Shrine#transloadit_file` method will convert a Transloadit result hash
|
541
|
+
into a `Shrine::UploadedFile` object:
|
542
|
+
|
543
|
+
```rb
|
544
|
+
uploader = Shrine.new(:store)
|
545
|
+
uploader.storage #=> #<Shrine::Storage::S3>
|
546
|
+
|
547
|
+
file = uploader.transloadit_file(
|
548
|
+
"url" => "https://my-bucket.s3.amazonaws.com/foo",
|
549
|
+
# ...
|
550
|
+
)
|
551
|
+
|
552
|
+
file.storage #=> #<Shrine::Storage::S3>
|
553
|
+
file.id #=> "foo"
|
437
554
|
```
|
438
555
|
|
556
|
+
It will include basic metadata:
|
557
|
+
|
439
558
|
```rb
|
440
|
-
|
441
|
-
|
559
|
+
file = uploader.transloadit_file(
|
560
|
+
# ...
|
561
|
+
"name" => "matrix.mp4",
|
562
|
+
"size" => 44198,
|
563
|
+
"mime" => "video/mp4",
|
564
|
+
)
|
565
|
+
|
566
|
+
file.original_filename #=> "matrix.mp4"
|
567
|
+
file.size #=> 44198
|
568
|
+
file.mime_type #=> "video/mp4"
|
569
|
+
```
|
442
570
|
|
443
|
-
|
444
|
-
attacher = TransloaditUploader::Attacher.transloadit_process(data)
|
571
|
+
It will also merge any custom metadata:
|
445
572
|
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
end
|
573
|
+
```rb
|
574
|
+
file = uploader.transloadit_file(
|
575
|
+
# ...
|
576
|
+
"meta" => { "duration" => 9000, ... },
|
577
|
+
)
|
578
|
+
|
579
|
+
file["duration"] #=> 9000
|
454
580
|
```
|
455
581
|
|
456
|
-
|
582
|
+
Currently only `Shrine::Stroage::S3` is supported. However, you can still
|
583
|
+
handle other remote files using [`Shrine::Storage::Url`][shrine-url]:
|
457
584
|
|
458
|
-
|
459
|
-
|
585
|
+
```rb
|
586
|
+
Shrine.storages => {
|
587
|
+
# ...
|
588
|
+
url: Shrine::Storage::Url.new,
|
589
|
+
}
|
590
|
+
```
|
591
|
+
```rb
|
592
|
+
uploader = Shrine.new(:url)
|
593
|
+
uploader #=> #<Shrine::Storage::Url>
|
460
594
|
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
S3_ACCESS_KEY_ID="..."
|
468
|
-
S3_SECRET_ACCESS_KEY="..."
|
595
|
+
file = uploader.transloadit_file(
|
596
|
+
"url" => "https://example.com/foo",
|
597
|
+
# ...
|
598
|
+
)
|
599
|
+
|
600
|
+
file.id #=> "https://example.com/foo"
|
469
601
|
```
|
470
602
|
|
471
|
-
|
603
|
+
## Contributing
|
604
|
+
|
605
|
+
Tests are run with:
|
472
606
|
|
473
607
|
```sh
|
474
608
|
$ bundle exec rake test
|
@@ -480,12 +614,18 @@ $ bundle exec rake test
|
|
480
614
|
|
481
615
|
[Shrine]: https://github.com/shrinerb/shrine
|
482
616
|
[Transloadit]: https://transloadit.com/
|
483
|
-
[
|
484
|
-
[
|
485
|
-
[
|
486
|
-
[
|
487
|
-
[
|
488
|
-
[
|
489
|
-
[
|
490
|
-
[
|
617
|
+
[Ruby SDK]: https://github.com/transloadit/ruby-sdk
|
618
|
+
[credentials]: https://transloadit.com/docs/#16-template-credentials
|
619
|
+
[import robots]: https://transloadit.com/docs/transcoding/#overview-service-file-importing
|
620
|
+
[export robots]: https://transloadit.com/docs/transcoding/#overview-service-file-exporting
|
621
|
+
[derivatives]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/derivatives.md#readme
|
622
|
+
[assembly notifications]: https://transloadit.com/docs/#24-assembly-notifications
|
623
|
+
[backgrounding]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/backgrounding.md#readme
|
624
|
+
[shrine-url]: https://github.com/shrinerb/shrine-url
|
625
|
+
[Robodog]: https://uppy.io/docs/robodog/
|
626
|
+
[Robodog Form]: https://uppy.io/docs/robodog/form/
|
627
|
+
[Uppy]: https://uppy.io/
|
628
|
+
[atomic_helpers]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/atomic_helpers.md#readme
|
629
|
+
[shrine-gcs]: https://github.com/renchap/shrine-google_cloud_storage
|
630
|
+
[shrine-youtube]: https://github.com/thedyrt/shrine-storage-you_tube
|
491
631
|
[shrine-url]: https://github.com/shrinerb/shrine-url
|