Integration Docs

Getting Started

Welcome to our docs! We’ve got six sections, the first two are useful to most people integrating with Transloadit:

  1. Integration — the current page. Start here, as we cover basic Transloadit concepts, getting started, and different integrations.
  2. Transcoding — all our features ranging from handling uploads, to importing, to processing, to exporting.
  3. Best Practices — how to get the most out of Transloadit in terms of speed and security.
  4. FAQ — good chance we already have an answer to your question.
  5. API — low-level nuts and bolts. Mostly useful to SDKs builders.
  6. Formats — comprehensive list of all the supported audio, video, image, formats and codecs.

What we Offer

Transloadit is versatile and our API makes light work of file automation tasks, like:

Input

Process

Output

All of our 52 wildly different features can be stringed together to create workflows unique to your use case. Those can then be integrated into your web/mobile app, back-end service, or command-line utility via 17 convenient SDKs like Uppy or the Go SDK, as well as directly via our JSON REST API.

Concepts

If we peel away layers of technology, at its core, Transloadit runs a tool on a file, for instance: convert avatar.png avatar.webp. We call this a Job and it would be performed by our /image/resize Robot. But it could be that you want us to convert five images. Or perhaps turn five images into one slideshow video. And then add an audio track to it. We call the execution of a number of Jobs that belong together an Assembly.

Below you'll see our Robots working on an Assembly line. In this case, Transloadit was integrated into a customer's website. Our Robots accept a video upload, convert it to an optimal format, burn a copyright logo into it, extract thumbnails, and export all of it to the customer's cloud storage. The media is now ready to be consumed optimally by all visitors of the website, regardless of their device and connection.


Transloadit Robots working together on an Assembly

Assemblies are the bread and butter at Transloadit and we process many millions of these logical units each day.

But how do we know which Robots to put to work on incoming files? What should your Assembly line look like?

Customers specify this in a declarative JSON recipe. That document contains the Assembly Instructions, and they describe each Step of the workflow. A Step defines at least which Robot should be put to work, and what other Step to use as its input. For example, the thumbnail Robot should take its input from the Bot that burned logos into the video.

Your app can bundle Assembly Instructions with the request to start an Assembly, or, you can save the Instructions in your account. That's what we call a Template. Many Assemblies can be spawned based on a single Template. When your app wants Transloadit to encode something, it passes along a template_id instead of the entire recipe each time. The advantages of that approach are that:

  1. Assembly Instructions could contain secrets, that you don't want to transmit, or for client-side integrations to even be aware of. Kept in a Template they are encrypted at rest.
  2. If an Assembly should ever error out, with Templates we can replay them (automatically if you opt into this).
  3. You don't want bad actors to tamper with Instructions residing on a client, or use Transloadit on your behalf. Using Templates in conjunction with Signature Authentication is the best way to avoid this.

"If Transloadit is unix, our Robots are tools that do one thing well. Pipe them together to create value greater than the sum of its parts. This is an Assembly."

When an Assembly is created, an endpoint that exposes the current Assembly Status JSON is returned that your app can subscribe to until all Jobs are completed (every SDK supports this out of the box). We call this Sync Mode. Alternatively, you can add a notify_url to your Instructions and set waitForEncoding to false. In that case, Transloadit posts the Assembly Status JSON to your back-end when all is done, and the app/end-user does not have to wait on any encoding. When all is done we ping your back-end, and then you ping your end-user. We call this Async Mode. Async requires more work to set up, but pays off in a better user experience when long processing times are involved, such as when you have us encode large video files. Async is also more reliable, because it allows you enable Assembly Replays in case there was a problem, since we already have a way to notify end-users/systems in an indirect way.

Many customers of ours use Transloadit for large batch imports with server-side languages orchestrating that. But even more integrate Transloadit into websites. We used to offer a jQuery SDK for this, but in 2018, we launched the open source file uploader :dog: Uppy. Now with over 21,000 stargazers on GitHub it is the #1 file uploader in the world. It allows recording from from Webcam, picking files from Dropbox & friends without hitting your local device (hence preserving battery life & data plans), and resuming uploads after a network hiccup or even a browser crash or accidental navigate-away. It works great with :robot: Transloadit (via its Robodog Plugin), and it works great without.

Now if anything is ever unclear, just hit the speech balloon in the lower right corner of the site to talk to a human, we're staring at it all day and enjoy it even if you just say hi or want to do a quick remote coffee with us. :coffee:

:pray::boom: That's it, you made it! You're now equally well versed in Transloadit vocabulary as we are. We can exchange secret handshakes and any further documentation is gonna be a piece of cake after this. Ready?

Let's build something!

My First App

As indicated in What We Offer, Transloadit is versatile and there are many ways to leverage our API. To pick one happy path for demo purposes, we'll default to a web browser integration with Uppy's Robodog Plugin.

We will create a simple web page where:

  1. You can upload a photo (handled by Transloadit via the /upload/handle Robot)
  2. Transloadit will then automatically detect a face and crop the photo alongside (via the /image/facedetect Robot) and
  3. Store the result on your S3 bucket (via the /s3/store Robot)

Let's look at the Assembly Instructions to accomplish this. We'll see three Steps that we named: :original, faces_detected, and exported:

{
  ":original": {
    "robot": "/upload/handle"
  },
  "faces_detected": {
    "use": ":original",
    "robot": "/image/facedetect",
    "crop": true,
    "faces": "max-confidence",
    "format": "preserve",
    "crop_padding": "10%"
  },
  "exported": {
    "use": [
      "faces_detected",
      ":original"
    ],
    "robot": "/s3/store",
    "credentials": "YOUR_AWS_CREDENTIALS",
    "url_prefix": "https://demos.transloadit.com/"
  }
}

:bulb: The credentials to S3 are stored separately for security. You can read more about this in the Template Credentials docs. You refer to them by name, replacing YOUR_S3_CREDENTIALS.

Now let's take a closer look at those three Steps:

  1. :original invokes the /upload/handle Robot and it will receive any file that Uppy throws at it, and then emit it, for other Robots to consume.
  2. faces_detected is happy to take those files off of :original's hands. It explicitly says "use": ":original" to indicate that. It also lists "robot": "/image/facedetect" to invoke face detection, along with some parameters that are specific to the /image/facedetect Robot, such as crop.
  3. exported then takes files emitted by both :original as well as faces_detected, and then invokes the /s3/store robot to export them to an S3 bucket. This way, we'll have saved both the original upload, and the cropped face to S3.

If you don't have an S3 bucket (or any other supported export target) you could create one or leave out the exported Step for now. Our prototype will still work, but result files are then hosted with us and removed after 24h.

We save these JSON Instructions in a Template in the Template Editor in your Account, so we can get a Template ID, which we can then refer to in our Uppy integration (currently indicated by YOUR_TEMPLATE_ID). We'll add this to any HTML page that is accessible in your browser, which could be just a local test.html for now:

<!-- This pulls Uppy from our CDN. Alternatively use `npm i @uppy/robodog --save` -->
<!-- if you want smaller self-hosted bundles and/or to use modern JavaScript -->
<link href="//transloadit.edgly.net/releases/uppy/robodog/v1.5.1/robodog.min.css" rel="stylesheet">
<script src="//transloadit.edgly.net/releases/uppy/robodog/v1.5.1/robodog.min.js"></script>
<button id="browse">Select Files</button>
<script>
  document.getElementById('browse').addEventListener('click', function () {
    var uppy = window.Robodog.pick({
      providers: [ 'instagram', 'url', 'webcam', 'dropbox', 'google-drive' ],
      waitForEncoding: true,
      params: {
        // To avoid tampering, use Signature Authentication
        auth: { key: 'YOUR_TRANSLOADIT_KEY' },
        template_id: 'YOUR_TEMPLATE_ID'
      }
    }).then(function (bundle) {
      // Due to `waitForEncoding: true` this is fired after encoding is done.
      // Alternatively, set `waitForEncoding` to `false` and provide a `notify_url`
      // for Async Mode where your back-end receives the encoding results
      // so that your user can be on their way as soon as the upload completes.
      console.log(bundle.transloadit) // Array of Assembly Statuses
      console.log(bundle.results)     // Array of all encoding results
    }).catch(console.error)
  })
</script>

You'll notice that along with YOUR_TEMPLATE_ID, we'll also need to replace YOUR_TRANSLOADIT_KEY, the value for which can be obtained from your API Settings in your Account.

That's it! :sparkles: If you were copy/pasting/replacing along you'll now have a working prototype. The results are dumped in your browser's console log. And you can also see Assemblies in your Account added in real time. If you didn't type along, you can still try it live in this face detect demo.

Ok but wait a minute, we have the results now your S3 bucket, and the references in the browser, dumped in the console log. But how do we get them to your back-end so that others can enjoy them too?

Saving Results

Let's take a look at the full Assembly Status JSON that you'd receive after we processed the face crop from My First App:

As you can see, Transloadit provides the final locations and metadata for all the uploaded files (all the way at the bottom in the uploads key), as well as all produced result files (in the results key).

Each file object contains metadata, as well as an ssl_url that points to the result. If you used one of our export Robots, these locations will reflect your specified storage, such as your S3 bucket. Otherwise, the location is a temporary URL that will be removed after 24 hours.

Depending on your integration, you can either:

There's an example for this in the Assembly Notifications docs.

Displaying Results

After saving the files to persistent storage, and saving any metadata that is useful to your app to your database, you can serve them to your users. In our case, we'll show the cropped image like this:

<img 
  alt="avatar" 
  src="https://s3.amazonaws.com/demos.transloadit.com/7b/22df50590d11e8be51b7c2c7cc7e22/joe-gardner-149699.jpg" 
/>

If you were dealing with video, you could look into players such as Plyr or indigo-player which also support MPEG-DASH.

Further Reading

If you're eager for more hands on examples, you can check out walkthroughs like Automatically burn logos into videos as they’re added to Google Drive and demos like Generate a video from an image sequence.

Another quick way to get started is to use the integration wizard inside your app. It asks about five questions and then generates all Instructions and integration code for you. Great to get going and very easy to then tweak to get it even closer to your use case.

Otherwise we recommend continuing these integration docs as we have many more powerful things in store for you :muscle::convenience_store:. For instance, you may want to make things faster and more reliable with Async Mode, or secure your communication with Transloadit. Those things are all covered as topics of their own, below.

Topics

Assembly Instructions

We briefly introduced Assembly Instructions while going over Transloadit's concepts and in My First App, now let's dig a little deeper :pick: and take a take a look at this example:

{
  "steps": {
    "imported": {
      "robot": "/http/import",
      "url": "https://transloadit.edgly.net/assets/images/face.jpg"
    },
    "resized": {
      "robot": "/image/resize",
      "use": "imported",
      "width": 100,
      "height": 100,
      "resize_strategy": "fillcrop"
    },
    "exported": {
      "robot": "/s3/store",
      "use": ["imported", "encoded"],
      "bucket": "YOUR_S3_BUCKET",
      "key": "YOUR_S3_KEY",
      "secret": "YOUR_S3_SECRET",
      "path": "/my_images/${file.id}/${file.url_name}"
    }
  }
}

As indicated Assembly Instructions consist of Steps. If one or more Steps fail, the whole Assembly will end and show an error in its Assembly Status JSON. The example shows three Steps: imported, resized and exported. You can name your Steps anything you like. Giving good names makes it easier to reference and understand what's going on. One exception is our /upload/handle Robot, it can only be used in a single Step, and that must be called :original.

Please also note that you must not name any Step :original that is not also using the /upload/handle Robot, as that can lead to weird job spawning behavior. Your Assembly will error out with a validation error if you do this.

For example, notice how the imported Step is used as an input to the resized Step. And both the imported and the resized Steps are used as the input for the exported Step. This way we'll import an image from a webserver, have it resized, and export both the imported image and the resized version to S3.

Not all Steps require inputs, our imported Step for instance, provides the first input by downloading it, so that's where we'll omit use. Other examples of Robots that don't require input files are our /html/convert Robot which can take a screenshot from a website and create the first file that way, or the /upload/handle Robot that takes its files from your app's visitors, instead of from another Step.

Step Parameters

As you can see, each Step is defined as an object with a handful of properties, or parameters. Most of them are in fact Robot Parameters as they instruct for instance the width of an image after a resize. Those are all covered in the respective Robot docs. But there are 4 parameters that instruct the Assembly engine itself, defining which Robots are invoked and how they are interconnected:

Name Type Default Description
use (required) String / Array of Strings / Object

General

Specifies which Step(s) to use as our input.

Special Step names

A special Step name is ":original", which provides user uploads handled by Transloadit. Outside of this restriction you can pick your own names.

Providing several Steps as input

You can add arrays to use several Steps:
"use": [
  ":original",
  "encoded",
  "resized"
]
:bulb: That's likely all you need to know about use, but you can view advanced use cases:
› Advanced use cases

Step bundling

Some Robots can gather several Step results for a single invocation. For example, the /file/compress Robot would normally create one archive for each file passed to it. If you'd set bundle_steps to true, however, it will create one archive containing all the result files from all Steps you give it. To enable bundling, provide an object like the one below to the use parameter:
"use": {
  "steps": [
    ":original",
    "encoded",
    "resized"
  ],
  "bundle_steps": true
}
This is also a crucial parameter for the /video/adaptive Robot, otherwise you'll generate 1 playlist for each viewing quality.
Keep in mind that all input Steps must be present in your Template. If one of them is missing (for instance it is rejected by a filter), no result is generated because the Robot waits indefinitely for all input Steps to be finished. Here's a demo that showcases Step bundling.

Group by original

Sticking with the /file/compress Robot example, you can set group_by_original to true, in order to create a separate archive for each of your uploaded or imported files, instead of creating one archive containing all originals (or one per resulting file). This is important for for the /media/playlist Robot where you'd typically set:
"use": {
  "steps": [
    "segmented"
  ],
  "bundle_steps": true,
  "group_by_original": true
}

Fields

You can be more discriminatory by only using files that match a field name by setting the fields property. When this array is specified, the corresponding Step will only be executed for files submitted through one of the given field names, which correspond with the strings in the name attribute of the HTML file input field tag for instance. When using a back-end SDK, it corresponds with myFieldName1 in e.g.: $transloadit->addFile('myFieldName1', './chameleon.jpg'). This parameter is set to true by default, meaning all fields are accepted. Example:
"use": {
  "steps": [ ":original" ],
  "fields": [ "myFieldName1" ]
}

Use As

Sometimes Robots take several inputs. For instance, the /video/merge Robot can create a slideshow from audio and images. You can map different Steps to the appropriate inputs. Example:
"use": {
  "steps": [
    { "name": "audio_encoded", "as": "audio" },
    { "name": "images_resized", "as": "image" }
  ]
}
Sometimes the ordering is important, for instance, with our concat Robots. In these cases, you can add an index that starts at 1. You can also optionally filter by the multipart field name. Like in this example, where all files are coming from the same source (end-user uploads), but with different <input> names: Example:
"use": {
  "steps": [
    { "name": ":original", "fields": "myFirstVideo", "as": "video_1" },
    { "name": ":original", "fields": "mySecondVideo", "as": "video_2" },
    { "name": ":original", "fields": "myThirdVideo", "as": "video_3" }
  ]
}
For times when it is not apparent where we should put the file, you can use Assembly Variables to be specific. For instance, you may want to pass a text file to the /image/resize Robot to burn the text in an image, but you are burning multiple texts, so where do we put the text file? We use specify it via ${use.text_1}, to indicate the first text file that was passed. Example:
"watermarked": {
  "robot": "/image/resize",
  "use"  : {
    "steps": [
      { "name": "resized", as: "base" },
      { "name": "transcribed", as: "text" },
    ],
  },
  "text": [
    {
      "text"  : "Hi there",
      "valign": "top",
      "align" : "left",
    },
    {
      "text"    : "From the 'transcribed' Step: ${use.text_1}",
      "valign"  : "bottom",
      "align"   : "right",
      "x_offset": 16,
      "y_offset": -10,
    }
  ]
}
robot (required) String Specifies which Robot should process files passed to this Step.
There are 52 Robots, each with their own parameters, such as width to control how an image is resized. The full list of parameters per Robot can be taken from the Robot docs.
result Boolean Automatic Controls whether the results of this Step should be present in the Assembly Status JSON.
If set to true, the result of this Step be present. If files from that Step weren't exported to your storage, their location will be set to a temporary URL.
By default we set this to true for leaf Steps and false for any intermediate Step. Explicitly setting it to false can be a useful tool in keeping the Assembly Status JSON small.
force_accept Boolean false Force a Robot to accept a file type it would have ignored.
By default Robots ignore files they are not familiar with. The /video/encode Robot, for example, will happily ignore and refuse to emit images.

With the force_accept parameter set to true you can force Robots to accept all files thrown at them. This will typically lead to errors and should only be used for debugging or combatting edge cases.

Order of Execution

In order to speed up Assemblies, Steps will be executed as soon as their input Steps emit files, so that means many things are processed in parallel. For example, let's say you want to encode an uploaded video and would also like to extract thumbnails from it:

{
  "steps": {
    ":original": {
      "robot": "/upload/handle"
    },
    "encoded": {
      "use": ":original",
      "robot": "/video/encode",
      "preset": "ipad-high"
    },
    "thumbed": {
      "use": ":original",
      "robot": "/video/thumbs",
      "count": 4
    },
    "exported": {
      "use": [ "encoded", "thumbed" ],
      "robot": "/s3/store",
      "credentials": "YOUR_S3_CREDENTIALS"
    }
  }
}

Both the encoded and the thumbed Steps will be executed in parallel as soon as the first file upload is complete. The exported Step is fired for each of the files coming from encoded and thumbed, and so most likely, thumbnails hit your S3 bucket before the video that was optimized for iPad, even though thumbnails were defined later. So the order of Steps does not really matter. The use parameter defines the input for each Step and this ultimately dictates how our Steps are chained.

Filtering to make Steps Conditional

Using our /file/filter Robot you can execute Steps based on a file's properties. This allows you to create Assembly Instructions that cater to both video, and audio uploads, reject files that are too small, only apply an effect on images that have transparent areas, etc. These and more things are covered in the Robot's docs, but it's worth a mention here.

Assembly Variables

Transloadit supports variables so you can create more powerful workflows. You can for instance filter files based on width, influence storage location based on type, etc. Here is a full list of placeholder variables available to Assembly Instructions. They can be used in any parameter value in any Robot:

Variable Description
${assembly.id} The ID of the Assembly representing the current upload.
${unique_prefix} A unique 33-character prefix used to avoid file name collisions, such as "f2/d3eeeb67479f11f8b091b04f6181ad". Please notice the / in the prefix. If you use ${unique_prefix} in the path parameter of the /s3/store Robot for example, then it will create sub-directories in your S3 bucket. This may or may not be desired. Please use ${file.id} if you require a unique prefix without slashes.
${unique_original_prefix} This is similar to ${unique_prefix}, with the exception that two different encoding results of the same uploaded file (the original file) will have the same prefix value here.
${previous_step.name} The name of the previous Step that produced the current file.
${file.id} The ID of the file being processed, which is a 32-character long, unique UUID. It does not contain any periods, slashes or other non-alphanumeric characters.
${file.original_id} The ID of the original file that a certain file derives from. For example, if you use an import robot to import files and then encode them somehow, the encoding result files will have a ${file.original_id} that matches the ${file.id} of the imported file.
${file.original_name} The name of the original file (including file extension) that a certain file derives from. For example, if you use an import robot to import files and then encode them somehow, the encoding result files will have a ${file.original_name} that matches the ${file.name} of the imported file.
${file.original_basename} The basename of the original file that a certain file derives from. For example, if you use an import robot to import files and then encode them somehow, the encoding result files will have a ${file.original_basename} that matches the ${file.basename} of the imported file.
${file.original_path} The import path of the original file that a certain file derives from. All of our import robots set ${file.original_path} accordingly. For example, if you use the /s3/import Robot to import files from Amazon S3, the imported files, as well a all files that are derived from them, will have a file.original_path that equals the path to the file on S3, but without the filename. So if the S3 path was "path/to/file.txt", then file.original_path will be "/path/to/". If the path was "/a.txt", ${file.original_path} will be "/". file.original_path will always have sufficient slashes in order for you to safely use it in the path parameter of your export step, like this: "path": "${file.original_path}${file.name}". This is handy if you want to import files from, for example, S3, convert them somehow and store them again on S3 in the same (or similar) file structure.
${file.name} The name of the file being processed, including the file extension.
${file.url_name} The slugged name of the file. Any characters other than A-Z a-z 0-9 -_. are replaced with underscores, and spaces are replaced with dashes. This includes the file extension as well. Note that if you have two files ッッ.jpg and チチ.jpg they will both be called __.jpg. So you'll want to take extra care to only use ${file.url_name} in conjunction with ${unique_prefix} or ${file.md5hash}.
${file.basename} The name of the file being processed, without the file extension.
${file.url_basename} The slugged basename of the file (the file name without the file extension). Any characters other than A-Z a-z 0-9 -_. are replaced with underscores, and spaces are replaced with dashes. Note that if you have two files ッッ.jpg and チチ.jpg they will both be called __.jpg. So you'll want to take extra care to only use ${file.url_basename} in conjunction with ${unique_prefix} or ${file.md5hash}.
${file.ext} The file extension.
${file.size} The file size.
${file.mime} The file's mime type.
${file.md5hash} The file's MD5 hash. This is a hash over the file's contents, not only over the file's name.
${file.*} Any file property available in the final results array, such as ${file.meta.width}. Not all meta keys are available for all file types.
${fields.*} The fields submitted together with the upload.
For example, in the case of a Form submission where Uppy was set to allow fields: ['myvar'], and the form had a tag like <input type="hidden" name="myvar" value="1" />, ${fields.myvar} would contain a value of 1.
Alternatively, fields could also be populated programmatically like so: json { "steps": { "store": { "use": "encoded", "robot": "/s3/store", "credentials": "YOUR_S3_CREDENTIALS_NAME", "path": "${assembly.id}/${fields.subdir}/356" } }, "fields": { "subdir": "bar" } } In the case of a conflict, variables derived from form fields take precedence over those derived from the fields key.
Assembly Variables Example

Let's say you don't like the location where files are stored. By default, Transloadit is careful not to overwrite anything so all export Robots have a path parameter with a default of "${unique_prefix}/${file.url_name}", resulting in locations such as: "f2/d3eeeb67479f11f8b091b04f6181ad/my-file-name.png".

We could, for example, change the parameter's value to "${previous_step.name}/${file.id}.${file.ext}", which would make the paths end up looking like "video-step-name/a8d3eeeb67479f11f8b091b04f6181ad.png".

Not all Assembly Variables are created equal and some are more unique (and hence suitable to solely base storage location on). Some examples, ordered from less, to more unique:

  • ${file.ext} is the same for many files
  • ${file.url_name} especially across users and time, a high likelihood of collisions, for instance: avatar.jpg
  • ${previous_step.name} is the same for all files that are results of the same Step
  • ${assembly.id} is the same for all files within a single Assembly
  • ${file.id} as well as ${unique_prefix} are unique for each file

Templates

As explained in Transloadit's concepts, you can send us Assembly Instructions directly with each request, or you can save them in a Template and refer to its template_id in your requests.

Sending Instructions directly allows for quick prototyping, but saving them in a Template comes with some advantages:

  1. You can refrain from transmitting sensitive data, and implementation details with each request to encode. Especially interesting when you integrate with browsers.
  2. Paired with "allow_steps_override": false, Instructions cannot be tampered with.
  3. Paired with Assembly Notifications you can enable Assembly Replays.
  4. If you integrated Transloadit into an app, you can change the encoding settings without deploying or waiting for an App Store to release a new version.

How to Create a Template

  1. "Create a Template in your Account".
  2. Give your Template a name for future (human) reference.
  3. Provide the Assembly Instructions JSON for your Template. You can select examples from a list, let our Wizard generate Instructions, duplicate an existing Template or start from scratch.
  4. Hit Save.

Once the Template is saved, a page is displayed showing the Template you created. At the top of the page, the Template's ID is shown, such as 4b62ee4dbb38455d96fe13d972ec3211. You can then copy/pasted its ID into your integration code's template_id, or look further down the Template Editor where we already show examples including this ID.

:bulb: The Template Editor also has a testing area where you can test your Templates along with an upload form right in the browser without updating your integration (you don't even have to hit Save).

Overruling Templates at Runtime

You would think they are mutually exclusive, but it is possible to supply both template_id and steps inside params, as this let's you change Template behavior at runtime. In fact, any other property inside params, with the exception of allow_steps_override, will be recursively merged over the Template that's loaded via template_id.

For example, let's take a look at the following Template which handles an upload, encodes a video to play well on iPads, and saves the result on S3:

{
  "steps": {
    ":original": {
      "robot": "/upload/handle"
    },
    "encoded": {
      "use": ":original",
      "robot": "/video/encode",
      "preset": "ipad-high"
    },
    "exported": {
      "use": "encoded",
      "robot": "/s3/store",
      "credentials": "YOUR_S3_CREDENTIALS",
      "bucket": "main-bucket"
    }
  }
}

When you create an Assembly, we can tweak the Template's behavior at runtime by e.g. adding a steps property:

{
  "template_id": "4b62ee4dbb38455d96fe13d972ec3211",
  "steps": {
    "exported": {
      "bucket": "another-bucket"
    }
  }
}

This is then merged by Transloadit to create the following Assembly Instructions:

{
  "steps": {
    "encoded": {
      "use": ":original",
      "robot": "/video/encode",
      "preset": "ipad-high"
    },
    "exported": {
      "use": "encoded",
      "robot": "/s3/store",
      "credentials": "YOUR_S3_CREDENTIALS",
      "bucket": "another-bucket"
    }
  }
}

As you can see, the bucket value changed from "main-bucket" to "another-bucket". This can be convenient and powerful in trusted environments.

In other environments you may want to disallow overriding of Steps, so that a browser could not modify the behavior. For this you would set allow_steps_override to false inside the saved Template like so:

{
  "allow_steps_override": false,
  "steps": {
    ...
  }
}

Now, only ever main-bucket will be used, whether additional steps were supplied, or not.

Template Options

Besides steps, and allow_steps_override, there are more options to control an Assembly's behavior.

Since most of them can also be set when not using Templates, they are documented in the API docs for Creating a New Assembly. However, if you integrate Transloadit into untrusted environments such as browsers, an abuser could easily change them, so to allow dynamically changing a Template's parameters in untrusted environments, consider using Signature Authentication.

Template Credentials

As discussed in our concepts, Transloadit can export files to your cloud bucket or server. To authenticate we'll need credentials (write-only if possible). You can set these directly in your import- and export Robot parameters (often via key and secret), but as of 2018 we recommend that you use Template Credentials instead. With Template Credentials you store the credentials separately, and then refer to them by name via the credentials Robot Parameter . You can check the individual Robot docs.

We have created Template Credentials so you can:

  • Enjoy stronger encryption and protection (e.g. showing them requires re-entering password).
  • Easily reuse your credentials across several Templates.
  • Easily share Templates with our Support or colleagues without having to redact credentials each time.
  • Be more liberal sending Assembly Instructions directly (without using a Template). Even though Templates are recommended, this allows prototyping without transmitting secrets each time.
  • Revoke leaked credentials and replace them without modifying all your Templates or code.
  • Add tokens. Some cloud providers require an interactive "oAuth dance" in order to give Transloadit access. The web interface for Template Credentials allows for this.

Here are Assembly Instructions using Template Credentials that were previously saved in your account as my_s3_credentials and my_youtube_credentials. It imports videos from an S3 bucket and uploads them to YouTube:

{
  "steps": {
    "imported": {
      "robot": "/s3/import",
      "credentials": "my_s3_credentials",
      "path": "/some/path"
    },
    "exported": {
      "robot": "/youtube/store",
      "use": "imported",
      "credentials": "my_youtube_credentials"
    }
  }
}

How to Create Template Credentials

  1. Go to your App's "Credentials" page.
  2. Choose your cloud provider from the dropdown menu at the top of the page and fill out all the fields for bucket names, keys and secrets.
  3. Give your Template Credentials a name for future reference in your Templates and hit save.

You can now set the name as the credentials property in your export Robot.

Assembly Notifications

As briefly touched on in our concepts, Transloadit supports two basic modes of operation:

  • Sync Mode: where the client waits for encoding to complete and then optionally notifies your back-end.
  • Async Mode: where the client resumes as soon as uploading is done, and Transloadit notifies your back-end when encoding completes.

Async Mode is slightly more work to set up, but recommended as it results in:

  1. A smoother user experience. The user does not have to wait on encoding.
  2. Reliability. We can retry encoding as well as sending Notifications.

To get the results to your back-end, Transloadit sends an Assembly Notification to your back-end. This is a multipart POST with a field called transloadit, which contains the full Assembly Status JSON. You can find an example of this in our API Response docs.

You specify where we should send this payload in a notify_url like so:

{
  "steps": { ... },
  "notify_url": "https://example.com/transloadit_pingback"
}

Your back-end needs to respond with a 200 header, otherwise Transloadit assumes the Notification has failed and retries 5 times over a period of 20 minutes.

When you add a notify_url, Transloadit is going to inform your back-end, no matter your client integration. If you don't want your users/program to wait for encoding, this often also involves setting a flag. In the case of Uppy, set the waitForEncoding parameter to false. In many back-end SDKs, waiting for encoding involves explicitly polling the Assembly Status so just refraining from that will do the trick.

Example

Let's assume you had indeed specified "notify_url": "https://example.com/transloadit_pingback" and that the back-end server that would accept incoming POSTs there was written in Node.js, that could look like so:

You could run this script like so:

$ env AUTH_SECRET=******** node notification-backend-node.js 3020
Server started, listening on http://0.0.0.0:3020

While you're testing locally behind a NAT, you could use a tool like ngrok so Transloadit can still reach your local script. Ngrok is a paid service, but limited use is free forever, and sufficient for our testing purposes. In a new Tab:

$ brew cask install ngrok || snap install ngrok # || https://ngrok.com/download
ngrok 2.3.35 from Khiem Doan (khiemdoan) installed

$ ngrok http 3020
Forwarding                    http://2cf99440.ngrok.io -> http://localhost:3020   

You can now create a Template and paste the following Instructions. Don't forget to replace the ngrok code of 2cf99440 to whatever ngrok reported in your case:

{
  "notify_url": "http://2cf99440.ngrok.io/transloadit_pingback",
  "steps": {
    ":original": {
      "robot": "/upload/handle"
    },
    "faces_detected": {
      "use": ":original",
      "robot": "/image/facedetect",
      "crop": true,
      "faces": "max-confidence",
      "crop_padding": "10%",
      "format": "preserve"
    }
  }
}

Now you're ready to test right inside the browser. The Instructions we used detect a face, so for optimal results, upload a photo of someone using the Template Editor's testing area. You can use Uppy's Webcam feature if you don't have one nearby.

Your Node.js script should report it has successfully received the Assembly Notification when the Assembly completes:

--> ASSEMBLY_COMPLETED https://api2.transloadit.com/assemblies/b2b580bdc969427091a48f1f0d3d9d40
    ^- uploaded 'avatar.jpg' ready at https://s3.amazonaws.com/tmp.transloadit.com/ff89be82...
    ^- faces_detected 'avatar.jpg' ready at https://s3.amazonaws.com/tmp.transloadit.com/fd2f61b9...

In addition, you'll see a record of the Notification at /assembly-notifications/, as well in the Assembly page that the Notification was for, where you can also manually retry them for further testing.

Retry as many times as you like!

Signature Authentication for Notifications

While the Assembly Status JSON resides in the transloadit field of the multipart POST, you'll find there is another field transmitted too, called signature. You can use that to ensure that only Transloadit can send you data to your notify_url.

We generated this for the request. You can use your Auth Secret to calculate the signature of the request on your end, too. If it matches, you can be sure the response came from Transloadit and was not tampered with, assuming that we are the only two parties that know this secret.

To verify, you'll need to calculate the signature yourself for the entire body of the transloadit field of the Assembly Notification. When the signature in the signature field matches the one you calculate, the request is valid. If not, then the request was tinkered with and should be ignored! And we should call the police too! :police_car:

The Example code higher up shows how to do this in Node.js, but there are examples for many other languages in the Signature Authentication docs.

Signature Authentication

As briefly mentioned in Transloadit's concepts, Signature Authentication is a security measure that can prevent outsiders from tampering with your Assembly Instructions. It adds trust in untrusted environments.

Given that there are only two parties in the world that have your account's Auth Secret (Transloadit and you), we can leverage that to generate a cryptographic signature on both our ends for the data that we exchange. We compare signatures after receiving a message, and know this exact message could have only come from someone that has the secret.

Since the signature is calculated via one-way encryption, the signature itself is not a secret, and someone seeing it could not derive the Auth Secret used to generate it. That's great because signatures are generated by servers that can keep a secret safe, and then injected into web browsers that don't share that quality.

For creating Assemblies with Transloadit, your back-end could calculate the Signature, only for parameters, authenticated users, and a timeframe that it deems legitimate usage. For instance, it would refuse to generate a signature for users that are not logged in. You could use any business logic on the server-side here to decide if you hand out a signature, or not, and Transloadit can be configured to reject any request for your Account that does not come with a correct signature for the payload.

If you want to make Signature Authentication mandatory for all requests of your account:

  1. Go to the API Credentials in your Account
  2. Enable the "Deny requests that do not include a signature or a wrong one" checkbox.
  3. Click the Update button.

:bulb: Most back-end SDKs automatically use Signature Authentication when you supply your Auth Secret. So perhaps, just this introduction is all you need to know. If you are integrating Transloadit into untrusted environments however, such as browsers (Uppy!), you'll want to continue reading to see how your back-end can supply signatures to it.

How to Generate Signatures

So how does this all look?

The typical params field when creating an Assembly without Signature Authentication is as follows:

{
  "auth": {
    "key": "23c96d084c744219a2ce156772ec3211"
  },
  "steps": { ... }
}

The auth.key in this example is the Auth Key from API Credentials in your Account.

To sign this request, the additional auth.expires field needs to be added. This adds it to our payload which is protected by our signature, so if someone would change it, Transloadit would reject the request as the signature no longer matches. You signed a different payload than the one we received. If the signature does match, then we'll naturally compare and reject by date as instructed, so requests become very hard to indefinitely repeat by a third party that got a hold of this payload. Because although our A+ grade HTTPS should already go a long way in preventing that, browser cache could be easier to snoop on.

The expires property must contain a timestamp in the (near) future. Use YYYY/MM/DD HH:mm:SS+00:00 as the date format, making sure that UTC is used for the timezone. For example:

{
  "auth": {
    "key": "23c96d084c744219a2ce156772ec3211",
    "expires": "2020/01/31 16:53:14+00:00"
  },
  "steps": { ... }
}

To calculate the signature for this request:

  1. Stringify the above JavaScript object into JSON.
  2. Calculate an RFC 2104-compliant HMAC hex signature on the string, with your Auth Secret as the key, and SHA1 as the hash algorithm.
  3. Add a signature multipart POST field to your request (e.g. a hidden field in a form), with the signature created in step 2.

:bulb: If your implementation uses a template_id instead of steps, there's no need to generate a signature for the Instructions that your Template contains. We should only sign communication payloads.

Signature Authentication is offered on requests that you send to Transloadit, but also the other way around. For instance, in Async Mode you'll want to ensure that Assembly Notifications that Transloadit sends to your back-end are actually coming from us. The example Node.js code in the Assembly Notifications docs illustrates this flow, and we have example code for generating signatures in different languages right below.

Example code for different languages

When you deal with JSON, please keep in mind that your language of choice might escape slashes. That is to say, it might turn occurrences of / into \/. We calculate the signatures on our end with unescaped slashes! Please make sure to remove backslashes from your JSON before calculating its signature.

If you use PHP for example, please check the JSON_UNESCAPED_SLASHES option of the json_encode function.

const crypto = require('crypto')

const utcDateString = (ms) => {
  return new Date(ms)
    .toISOString()
    .replace(/-/g, '/')
    .replace(/T/, ' ')
    .replace(/\.\d+\Z$/, '+00:00')
}

// expire 1 hour from now (this must be milliseconds)
const expires    = utcDateString((+new Date()) + 1 * 60 * 60 * 1000)
const authKey    = 'YOUR_TRANSLOADIT_KEY'
const authSecret = 'YOUR_TRANSLOADIT_SECRET'

const params = JSON.stringify({
  auth: {
    key    : authKey,
    expires: expires,
  },
  template_id: 'YOUR_TRANSLOADIT_TEMPLATE_ID',
  // your other params like template_id, notify_url, etc.
})
const signature = crypto
  .createHmac('sha1', authSecret)
  .update(Buffer.from(params, 'utf-8'))
  .digest('hex')

console.log(`${expires} ${signature}`)
<?php
// expire 1 hours from now
$expires    = gmdate('Y/m/d H:i:s+00:00', strtotime('+1 hour'));
$authKey    = 'YOUR_TRANSLOADIT_KEY';
$authSecret = 'YOUR_TRANSLOADIT_SECRET';

$params = json_encode([
  'auth' => [
    'key'     => $authKey,
    'expires' => $expires,
  ],
  'template_id' => 'YOUR_TRANSLOADIT_TEMPLATE_ID',
], JSON_UNESCAPED_SLASHES);
$signature = hash_hmac('sha1', $params, $authSecret);

echo $expires . " " . $signature . PHP_EOL;
require 'rubygems'
require 'openssl'
require 'json'

# expire one hour from now
expires     = (Time.now.utc + 1 * 60 * 60).strftime('%Y/%m/%d %H:%M:%S+00:00')
auth_key    = 'YOUR_TRANSLOADIT_KEY'
auth_secret = 'YOUR_TRANSLOADIT_SECRET'

params = JSON.generate({
  :auth => {
    :key     => auth_key,
    :expires => expires,
  },
  :template_id => 'YOUR_TRANSLOADIT_TEMPLATE_ID',
})
signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), auth_secret, params)

puts(expires + " " + signature)
import hmac
import hashlib
import json
from datetime import datetime, timedelta

expires = (timedelta(seconds=60 * 60) + datetime.utcnow()).strftime("%Y/%m/%d %H:%M:%S+00:00")
auth_key = 'YOUR_TRANSLOADIT_KEY'
auth_secret = 'YOUR_TRANSLOADIT_SECRET'
params = {
    'auth': {
        'key': auth_key,
        'expires': expires,
    },
    'template_id': 'YOUR_TRANSLOADIT_TEMPLATE_ID'
    # your other params like template_id, notify_url, etc.
}

message = json.dumps(params, separators=(',', ':'))
signature = hmac.new(auth_secret.encode('utf-8'),
                    message.encode('utf-8'),
                    hashlib.sha1).hexdigest()

print(expires, signature)
package com.transloadit.sdk;

import org.apache.commons.codec.binary.Hex;
import org.joda.time.Instant;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;


public class JavaSignature {
    public static void main(String[] args) {
        String authKey = "YOUR_TRANSLOADIT_KEY";
        String authSecret = "YOUR_TRANSLOADIT_SECRET";
        String templateId = "YOUR_TRANSLOADIT_TEMPLATE_ID";
        DateTimeFormatter formatter = DateTimeFormat
                .forPattern("Y/MM/dd HH:mm:ss+00:00")
                .withZoneUTC();
        String expiry = formatter.print(Instant.now().plus(60 * 60 * 1000));

        String messageFormat = "{\"auth\":{\"key\":\"%s\",\"expires\":\"%s\"},\"template_id\":\"%s\"}";
        String message = String.format(messageFormat, authKey, expiry, templateId);

        byte[] kSecret = authSecret.getBytes(Charset.forName("UTF-8"));
        byte[] rawHmac = HmacSHA1(kSecret, message);
        byte[] hexBytes = new Hex().encode(rawHmac);

        System.out.println(expiry + " " + new String(hexBytes, Charset.forName("UTF-8")));
    }

    private static byte[] HmacSHA1(byte[] key, String data) {
        final String ALGORITHM = "HmacSHA1";
        Mac mac;

        try {
            mac = Mac.getInstance(ALGORITHM);
            mac.init(new SecretKeySpec(key, ALGORITHM));
            return mac.doFinal(data.getBytes(Charset.forName("UTF-8")));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        }
    }
}

Software Development Kits

Here you'll find our officially maintained SDKs. SDKs make it easy to interact with our API, implement our Best Practices, and save you from writing boilerplate. We'll list them alphabetically by platform. Further down you can find community built integrations, not maintained by Transloadit, but often still a valuable source of inspiration.

Name Platform Build status Links
Android SDK Android Build Status Inline docs · GitHub repo
Transloadify CLI Build Status Inline docs · GitHub repo
Go SDK Go Build Status Inline docs · GitHub repo
Heroku Addon Heroku Not Applicable Inline docs
Multipart Form HTML2 Not Applicable Inline docs
Uppy File Uploader HTML5 Build Status Inline docs · GitHub repo
TransloaditKit iOS & macOS Build Status Inline docs · GitHub repo
Java SDK Java Build Status Inline docs · GitHub repo
jQuery SDK jQuery Build Status Inline docs · GitHub repo
Node SDK Node.js Build Status Inline docs · GitHub repo
PHP SDK PHP Build Status Inline docs · GitHub repo
Python SDK Python Build Status Inline docs · GitHub repo
Rails SDK Rails Build Status Inline docs · GitHub repo
Ruby SDK Ruby Build Status Inline docs · GitHub repo
Zapier Integration Zapier Not Applicable Inline docs

Android


The recommended way to integrate Transloadit's file uploading and encoding capabilities with Android is by using our Android SDK.

Install

The JARs can be downloaded manually from our Bintray project, or can be installed from the Maven and Jcenter repositories.

Gradle:

compile 'com.transloadit.android.sdk:transloadit-android:0.0.2'

Maven:

<dependency>
  <groupId>com.transloadit.android.sdk</groupId>
  <artifactId>transloadit-android</artifactId>
  <version>0.0.2</version>
</dependency>

Usage

All interactions with the SDK begin with the com.transloadit.android.sdk.Transloadit class.

Create an Assembly

To create an assembly, you use the newAssembly method.

To use this functionality in it's full glory, you need implement the AssemblyProgressListener interface.


public class MyAssemblyProgressListener  implements AssemblyProgressListener {
    @Override
    public void onUploadFinished() {
        System.out.println("upload finished!!! waiting for execution ...");
    }

    @Override
    public void onUploadPogress(long uploadedBytes, long totalBytes) {
        System.out.println("uploaded: " + uploadedBytes + " of: " + totalBytes);
    }

    @Override
    public void onAssemblyFinished(AssemblyResponse response) {
        System.out.println("Assembly finished with status: " + response.json().getString("ok"));
    }

    @Override
    public void onUploadFailed(Exception exception) {
        System.out.println("upload failed :(");
        exception.printStackTrace();
    }

    @Override
    public void onAssemblyStatusUpdateFailed(Exception exception) {
        System.out.println("unable to fetch status update :(");
        exception.printStackTrace();
    }
}
    

And in your activity you can have something like this

public class MainActivity extends AppCompatActivity {
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        
        AssemblyProgressListener listener = new MyAssemblyProgressListener();

        AndroidTransloadit transloadit = new AndroidTransloadit("key", "secret");
        AndroidAsyncAssembly assembly = transloadit.newAssembly(listener);
        assembly.addFile(new File("path/to/file.jpg"), "file");
        
        Map<String, Object> stepOptions = new HashMap<>();
        stepOptions.put("width", 75);
        stepOptions.put("height", 75);
        stepOptions.put("resize_strategy", "pad");
        assembly.addStep("resize", "/image/resize", stepOptions);

        assembly.save();
    }
}

Example

For fully working examples take a look at examples/.

Documentation

See Javadoc for full API documentation.

Blog posts

We wrote the following posts about our Android integration on our blog:

CLI


The recommended way to integrate Transloadit's file uploading and encoding capabilities with CLI is by using our Transloadify.

Install

$ npm install -g transloadify

Usage

Transloadify needs Transloadit API authentication information. It looks for it in the environment variables TRANSLOADIT_KEY and TRANSLOADIT_SECRET. Check the API credentials page for these values.

See transloadify --help for complete usage instructions.

Processing media

Transloadify uses the Transloadit API. Transloadit allows you to process media in the cloud by creating Assemblies. An Assembly in an execution of processing instructions on an uploaded file. The simplest way to create Assemblies using Transloadify is to put the processing instructions (called Assembly Instructions) in a JSON file and give it to Transloadify using the --steps option. Transloadify will then upload whatever is passed to it via standard in, and output the result file to standard out.

$ transloadify --steps steps.json < input.jpg > output.jpg

Transloadit supports Templates which are Assembly Instructions stored in the cloud. Templates can be created and managed through Transloadify using the templates commands. If you have a Template that you would like to use to process media, you can specify it with the --template option instead of specifying a --steps.

$ transloadify --template TEMPLATE_ID < input.jpg > output.jpg

If your Template expects certain custom fields to be set, those can be specified using the --field option.

$ transloadify --template TEMPLATE_ID --field size=100 < input.jpg > output.jpg

Rather than use STDIN and STDOUT, you can also pass files to Transloadify using the --input and --output flags. These flags are also more flexible than standard IO because they can take directories, to process media in batch, optionally traversing subdirectories with the --recursive option.

$ transloadify --template TEMPLATE_ID --field size=100 \
    --input images --recursive --output thumbs

Transloadify also has the option to watch inputs for changes, using the --watch option, and reprocessing them whenever a change is detected.

$ transloadify --template TEMPLATE_ID --field size=100 \
    --input images --recursive --output thumbs --watch

All of these flags support shortened versions, to avoid invocations getting too long. See transloadify assemblies create --help for details. The above can be shortened to:

$ transloadify -tTEMPLATE_ID -fsize=100 -i images -o thumbs -wr
Assemblies

The transloadify assemblies subcommand lets you manage assemblies. Using transloadify you can create, cancel, replay, list and fetch Assembly Statuses. See transloadify assemblies --help for a list of available actions, and transloadify assemblies ACTION --help for specific action documentation.

Creation

The usage described in "Processing media" implicitly uses the transloadify assemblies create command, which has the same behavior as the bare transloadify command.

Listing

You can use Transloadify to list assemblies associated with the account, optionally filtered by date and keywords. For instance:

$ transloadify assemblies list --after 2016-11-08

See transloadify assemblies list --help for a list of accepted options.

One use-case is to recover failed assemblies once the issue has been resolved. If a Template definition contained an error that caused Assemblies to fail, you can salvage them by fixing the Template and using an invocation like this, using the jq JSON utility.

$ transloadify assemblies list --json --after "$AFFECTED_DATE" \
  | jq -r 'select(.error) | .id' \
  | xargs transloadify assemblies get --json \
  | jq -r 'select(.template_id == "'$AFFECTED_TEMPLATE'") | .assembly_id' \
  | xargs transloadify assemblies replay --reparse-template
Templates

transloadify templates is used to create and manage templates. transloadify templates --help gives a list of supported actions.

Modification

transloadify templates modify will read new Template contents from standard in if no file is specified. If you just want to rename a Template using the --name option, the command will ignore empty input:

$ transloadify templates rename $TEMPLATE_ID --name my_template < /dev/null
Assembly Notifications

Support for listing and replaying Assembly Notifications is provided by transloadify assembly-notifications list and transloadify assembly-notifications replay respectively.

Listing

transloadify assembly-notifications list can list, optionally filtered by whether they succeeded or failed, either all Notifications associated with an account, or for a given Assembly. If you would like to see Notifications for a list of Assemblies, it must be called for each one individually.

$ transloadify assemblies list --after 2016-11-08 \
  | xargs -n1 transloadify assembly-notifications list
Bills

Monthly billing information can be fetched with transloadify bills get YYYY-MM.... By default only the total charge is output, but more detailed information can be displayed in JSON format with the --json flag.

$ transloadify bills get 2016-11 --json
Tips
  • Command names have aliases, the following are interchangeable
    • assemblies, assembly, a
    • templates, template, t
    • assembly-notifications, assembly-notification, notifications, notification, n
    • bills, bill, b
    • create, new, c
    • delete, cancel, d
    • modify, edit, alter, m
    • replay, r
    • list, l
    • get, info, view, display, g
  • All output, from any command, can also be provided in JSON format using the --json flag

Example

An example script written to add watermark to videos can be found here examples/.

Documentation

See GitHub for the full documentation.

Blog posts

We wrote the following posts about our CLI integration on our blog:

Go


The recommended way to integrate Transloadit's file uploading and encoding capabilities with Go is by using our Go SDK.

Install

go get gopkg.in/transloadit/go-sdk.v1

The Go SDK requires Go 1.7 or higher.

Usage

package main

import (
	"context"
	"fmt"

	"gopkg.in/transloadit/go-sdk.v1"
)

func main() {
	// Create client
	options := transloadit.DefaultConfig
	options.AuthKey = "YOUR_TRANSLOADIT_KEY"
	options.AuthSecret = "YOUR_TRANSLOADIT_SECRET"
	client := transloadit.NewClient(options)

	// Initialize new assembly
	assembly := transloadit.NewAssembly()

	// Add a file to upload
	assembly.AddFile("image", "/PATH/TO/FILE.jpg")

	// Add Instructions, e.g. resize image to 75x75px
	assembly.AddStep("resize", map[string]interface{}{
		"robot":           "/image/resize",
		"width":           75,
		"height":          75,
		"resize_strategy": "pad",
		"background":      "#000000",
	})

	// Start the upload
	info, err := client.StartAssembly(context.Background(), assembly)
	if err != nil {
		panic(err)
	}

	// All files have now been uploaded and the assembly has started but no
	// results are available yet since the conversion has not finished.
	// WaitForAssembly provides functionality for polling until the assembly
	// has ended.
	info, err = client.WaitForAssembly(context.Background(), info)
	if err != nil {
		panic(err)
	}

	fmt.Printf("You can view the result at: %s\n", info.Results["resize"][0].SSLURL)
}

Example

For fully working examples on how to use templates, non-blocking processing and more, take a look at examples/.

Documentation

See Godoc for full API documentation.

Blog posts

We wrote the following posts about our Go integration on our blog:

Heroku


The recommended way to integrate Transloadit's file uploading and encoding capabilities with Heroku is by using our Heroku Addon.

Install

Warning Heroku does not support overage in their billing and so we had to disable that on our end to be compatible with the platform without going bankrupt. This could result in stopping the service for you if you don't upgrade in time! If you'd rather enable overage, consider signing up for Transloadit directly.

Transloadit can be attached to a Heroku application via the CLI:

$ heroku addons:add transloadit
-----> Adding transloadit to sharp-mountain-4005... done, v18 (free)
A list of all plans available can be found here.

Once Transloadit has been added the TRANSLOADIT_AUTH_KEY and TRANSLOADIT_SECRET_KEY settings will be available in the app configuration and will contain the credentials needed to authenticate to the Transloadit API. This can be confirmed using the heroku config:get command.

$ heroku config:get TRANSLOADIT_AUTH_KEY
4bba21cf6d744fd1aeef0f0b72ec3212

Usage

With your TRANSLOADIT_AUTH_KEY and TRANSLOADIT_SECRET_KEY in place you can now integrate it with any of our SDKs corresponding to your project. Here's a list of our SDKs:

Using with Ruby (Uses our Ruby SDK)

Verify that the TRANSLOADIT_AUTH_KEY and TRANSLOADIT_SECRET_KEY variables are set.

Ruby applications need to add the following entry into their Gemfile specifying the Transloadit client library.

gem 'transloadit'

Then update application dependencies with bundler.

$ bundle install

Finally re-deploy your application.

$ git add .
$ git commit -a -m "add transloadit instrumentation"
$ git push heroku master
First encoding job

After installing the transloadit Gem and deploying your app you can start talking to the Transloadit API:

require 'transloadit'

puts "Resizing lolcat.jpg on #{ENV['TRANSLOADIT_URL']}"

transloadit = Transloadit.new(
  :service => ENV['TRANSLOADIT_URL'],
  :key     => ENV['TRANSLOADIT_AUTH_KEY'],
  :secret  => ENV['TRANSLOADIT_SECRET_KEY']
)

resize = transloadit.step 'resize', '/image/resize',
  :width  => 320,
  :height => 240

assembly = transloadit.assembly(
  :steps => [ resize ]
)

response = assembly.submit! open('lolcat.jpg')

# loop until processing is finished
until response.finished?
  sleep 1; response.reload! # you'll want to implement a timeout in your production app
end

if response.error?
 # handle error
else
 # handle other cases
end
Using with Ruby on Rails (Uses our Rails SDK)

Here we'll show how to use Transloadit in a freshly setup Rails project and Heroku app.

If you haven't already done so, go ahead and install Rails.

$ gem install rdoc rails

With Rails installed, let's create a new app called 'transloku'.

$ rails new transloku
$ cd transloku

In order to use Transloadit in this app, we need to add the Gem to our Gemfile and bundle things up.

Remove sqlite3 from your Gemfile

$ echo "ruby '2.0.0'" >> Gemfile
$ echo "gem 'transloadit-rails'" >> Gemfile
$ echo "gem 'pg'" >> Gemfile
$ bundle install

With that in place, it's time to generate our Transloadit configuration, as well as a basic UploadsController and a dummy Upload model.

$ rails g transloadit:install
$ rails g controller uploads new create
$ rails g model upload
$ rake  db:migrate

The controller generator we just executed has probably put two GET routes into your config/routes.rb. We don't want those, so let's go ahead and overwrite them with this.

Transloku::Application.routes.draw do
  resources :uploads
end

Next we need to configure our config/transloadit.yml file. For this tutorial, just put in your credentials, and define an image resize step as indicated below:

auth:
  key     : <%= ENV['TRANSLOADIT_AUTH_KEY'] %>
  secret  : <%= ENV['TRANSLOADIT_SECRET_KEY'] %>

templates:
  image_resize:
    steps:
      resize:
        robot : '/image/resize'
        format: 'jpg'
        width : 320
        height: 200

Note that we encourage you to enable authentication in your Transloadit Account and put your secret into the config/transloadit.yml to have your requests signed.

Make your config/database.yml look like this:

development:
  adapter: postgresql
  encoding: unicode
  database: transloku_development
  pool: 5
  password:

test:
  adapter: postgresql
  encoding: unicode
  database: transloku_test
  pool: 5
  password:

production:
  adapter: postgresql
  encoding: unicode
  database: transloku_production
  pool: 5
  password:

Alright, time to create our upload form. In order to do that, please open app/views/uploads/new.html.erb, and put the following code in:

<%= javascript_include_tag '//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js' %>

<h1>Upload an image</h1>
<%= form_for Upload.new, :html => { :id => 'upload' } do |form| %>
  <%= transloadit :image_resize %>
  <%= form.label      :file, 'File to upload' %>
  <%= form.file_field :file %>
  <%= form.submit %>
<% end %>

<%= transloadit_jquerify :upload, :wait => true %>

With this in place, we can modify the app/views/uploads/create.html.erb view to render the uploaded and resized image:

<h1>Resized upload image</h1>
<%= image_tag params[:transloadit][:results][:resize].first[:url] %>

In order to use the transloadit params in your controller and views you have to include the ParamsDecoder into your controller. Let's do that for our UploadsController.

Open up app/controllers/uploads_controller.rb and adapt it like that:

class UploadsController < ApplicationController
  include Transloadit::Rails::ParamsDecoder

  def new
  end

  def create
  end
end

That's it. If you've followed the steps closely, you should now be able to try your first upload. Don't forget to start your rails server first:

$ rails server

Then go to http://localhost:3000/uploads/new, and upload an image. If you did everything right, you should see the uploaded and resized file as soon as the upload finishes.

All looking sharp? Let's publish this to Heroku

$ git init
$ git add .
$ git commit -m "init"
$ heroku login
$ heroku create
$ heroku addons:add transloadit
$ heroku config:get TRANSLOADIT_AUTH_KEY
$ git push heroku master
$ heroku run rake db:migrate
$ heroku open && heroku logs --tail

Point your browser to /uploads/new

Using with any Language

Instead of talking server-to-server, your website visitors can directly upload to Transloadit's specialized upload servers, so in theory there's no need for server-side languages.

The easiest way to accomplish this would be to to include our jQuery SDK in your HTML.

It includes a Twitter Bootstrap compatible progress bar, and it saves you development time having to handle the file uploads yourself, and then pushing it to our API.

<script type="text/javascript" src="//assets.transloadit.com/js/jquery.transloadit2-v3-latest.js"></script>
<script type="text/javascript">
   // We call .transloadit() after the DOM is initialized:
   $(function() {
     $('#MyForm').transloadit();
   });
</script>

Alternatively, check our Uppy, our next-gen file uploader for the web.

Documentation

See GitHub for the full documentation.

Blog posts

We wrote the following posts about our Heroku integration on our blog:

HTML2

We originally built this approach to avoid the need to have JavaScript enabled in the browser. Times have changed and one can now assume that JavaScript is turned on in the browser, so we recommend using [Uppy](/docs/#uppy) as the browser integration of choice.

Even though we recommend Uppy, to showcase basic concepts, do a quick prototype, or in case you really do want to offer a fallback for browsers where JavaScript is disabled or crashed, you can integrate Transloadit using nothing more but a multipart <form>.

Install

There is nothing to install :ok_hand:

Usage

Set the form's action attribute to "https://api2.transloadit.com/assemblies". Files are then uploaded directly to our API, along with any Instructions inside a hidden params field.

To avoid any parsing issues in the browser, we should let a computer JSON encode the instructions and then escape HTML entities such as: < and " to &lt; and &quot;. The result is a little hard for a human to parse, so maybe don't even try :smile:

You can set a redirect_url inside the Instructions to tell our API to redirect the browser to a success page of your choosing when all is done. We'll append: ?assembly_id=xyz&assembly_ssl_url=https://api2.transloadit.com/assemblies/xyz to that URL.

When serving out the success page, your back-end could parse these query parameters so you can do further handling like downloading the Assembly Status JSON and the encoding results it refers to.

The success page is served to the browser as soon as the upload completes, so the Assembly may actually still be executing (encoding a large video for instance). You could either poll the assembly_ssl_url with your back-end, or you could set up Assembly Notifications and provide a notify_url with your Instructions. In that case we will POST the Assembly Status JSON to it so you can handle the results with your back-end that way.

Example

<!--
We'll be inlining the following Assembly Instructions into a hidden `params` field,
escaping HTML entities such as `<`, a task best left to machines : )

{ 
  "auth": { "key": "YOUR_TRANSLOADIT_KEY" }, 
  "redirect_url": "https://example.com/success", 
  "template_id": "YOUR_TEMPLATE_ID"
}
-->

<form method="POST" enctype="multipart/form-data" action="https://api2.transloadit.com/assemblies">
  <input type="hidden" name="params" value='{ &quot;auth&quot;: { &quot;key&quot;: &quot;YOUR_TRANSLOADIT_KEY&quot; }, &quot;redirect_url&quot;: &quot;https://example.com/success&quot;, &quot;template_id&quot;: &quot;YOUR_TEMPLATE_ID&quot;}' />
  <input type="file" name="myfile_1" multiple="multiple" />
  <input type="submit" value="Upload" />
</form>

HTML5


The recommended way to integrate Transloadit's file uploading and encoding capabilities with HTML5 is by using our Uppy File Uploader.

Robodog is an Uppy-based library that helps you talk to the Transloadit API. It includes a modal UI file picker with support for imports from third-party services like Instagram, integration with HTML forms, and more. Because it’s based on Uppy, you can add any existing Uppy plugin to add more functionality.

Transloadit hosts the required server components (Companion and Tusd) for you, as well as of course our encoding API. Robodog configures all the Plugins to leverage this.

If you wonder about the name, Transloadit's encoding features are grouped in Robots :robot: and we advertise Uppy is as cute as a puppy :dog: so we felt Robodog :robot::dog: to be the only appropriate name for a marriage of them.

Install

Option 1: Bundle yourself
npm install @uppy/robodog --save --save-exact

# OR:
yarn add @uppy/robodog

You could then require it via Browserify, Webpack or similar to bundle Uppy yourself like so:

const robodog = require('@uppy/robodog')
require('@uppy/robodog/dist/robodog.css')

This allows you to customize Uppy and create smaller, more focussed bundles leaving out any Plugin you don't need.

Option 2: Use a prebuilt bundle from our CDN

If you don't want to install anything or use bundlers, you can use the prebuilt bundle, by sourcing it directly from our CDN like so:

<link rel="stylesheet" href="//transloadit.edgly.net/releases/uppy/robodog/v1.5.1/robodog.min.css">
<script src="//transloadit.edgly.net/releases/uppy/robodog/v1.5.1/robodog.min.js"></script>
<!-- you can now use e.g.: window.Robodog.pick() -->

The downside of this is that you cannot just pick a few plugins that you need, and that if our CDN goes down, your file uploader stops working. That said, our CDN is based on AWS CloudFront so this should be unlikely, and if Transloadit itself goes down, file uploading will be broken anyway.

Usage

If you are migrating from the jQuery SDK, we recommend checking out Robodog's migration guide for jQuery SDK. This shows counterparts for all of the old SDKs options, and shows how to create a similar flow, where Uppy would use an existing form to operate on.

But as said, Robodog can also disguise as a button with a modal picker, or draw drag and drop area inline. Uppy is modular and customizable in that regard, and we recommend checking out the full documentation for Uppy's Robodog Plugin to discover the integration best for your use case.

Example

For demo purposes, we'll just show one happy path, of using Transloadit's face detection in combination with a picker, and we'll be using our CDN bundle for easy copy-pastability. Make sure to replace YOUR_TRANSLOADIT_KEY with your Transloadit API Key.

<!-- This pulls Uppy from our CDN. Alternatively use `npm i @uppy/robodog --save` -->
<!-- if you want smaller self-hosted bundles and/or to use modern JavaScript -->
<link href="//transloadit.edgly.net/releases/uppy/robodog/v1.5.1/robodog.min.css" rel="stylesheet">
<script src="//transloadit.edgly.net/releases/uppy/robodog/v1.5.1/robodog.min.js"></script>
<button id="browse">Select Files</button>
<script>
  document.getElementById('browse').addEventListener('click', function () {
    var uppy = window.Robodog.pick({
      providers: [ 'instagram', 'url', 'webcam', 'dropbox', 'google-drive' ],
      waitForEncoding: true,
      params: {
        // To avoid tampering, use Signature Authentication
        auth: { key: 'YOUR_TRANSLOADIT_KEY' },
        // To hide your `steps`, use a `template_id` instead
        steps: {
          ':original': {
            robot: '/upload/handle'
          },
          faces_detected: {
            use: ':original',
            robot: '/image/facedetect',
            crop: true,
            crop_padding: '10%',
            faces: 'max-confidence',
            format: 'preserve'
          },
          exported: {
            use: ['faces_detected', ':original'],
            robot: '/s3/store',
            credentials: 'YOUR_AWS_CREDENTIALS',
            url_prefix: 'https://demos.transloadit.com/'
          }
        }
      }
    }).then(function (bundle) {
      // Due to `waitForEncoding: true` this is fired after encoding is done.
      // Alternatively, set `waitForEncoding` to `false` and provide a `notify_url`
      // for Async Mode where your back-end receives the encoding results
      // so that your user can be on their way as soon as the upload completes.
      console.log(bundle.transloadit) // Array of Assembly Statuses
      console.log(bundle.results)     // Array of all encoding results
    }).catch(console.error)
  })
</script>

For more examples, take a look at examples/, or try them live. Uppy and Transloadit are very versatile so you may have a different need, and likely, we already support it.

Documentation

See the full documentation for Uppy's Robodog Plugin, which is the recommended way to integrate Transloadit and Uppy.

Blog posts

We wrote the following posts about our HTML5 integration on our blog:

iOS & macOS


The recommended way to integrate Transloadit's file uploading and encoding capabilities with iOS & macOS is by using our TransloaditKit.

Install

CocoaPods

Inside your podfile add,

pod 'Transloadit'
Carthage

Inside your Cartfile add,

github "transloadit/TransloaditKit"
Manual
  1. Download and unpack the ZIP file
  2. Drag the Transloadit directory into your project

Usage

Import TransloaditKit

Objective-C

#import <TransloaditKit/Transloadit.h>

Swift

import Transloadit
Initializing TransloaditKit

Objective-C

@interface TransloaditViewController () <TransloaditDelegate>
@end
...
Transloadit *transloadit;
....
- (void)viewDidLoad {
  [super viewDidLoad];
  transloadit = [[Transloadit alloc] init];
  [transloadit setDelegate:self];
  ...
}

Swift

class TransloaditViewControllerSwifty: UIViewController, TransloaditDelegate {
  ...
  let transloadit: Transloadit = Transloadit()
  override func viewDidLoad() {
    super.viewDidLoad()
    self.transloadit.delegate = self;
    ...
  }
}

Example

Download the GitHub repo and open the example project examples/.

Documentation

See GitHub for the full documentation.

Java


The recommended way to integrate Transloadit's file uploading and encoding capabilities with Java is by using our Java SDK.

Install

The JARs can be downloaded manually from our Bintray project, or can be installed from the Maven and Jcenter repositories.

Gradle:

compile 'com.transloadit.sdk:transloadit:0.1.5'

Maven:

<dependency>
  <groupId>com.transloadit.sdk</groupId>
  <artifactId>transloadit</artifactId>
  <version>0.1.5</version>
</dependency>

Usage

All interactions with the SDK begin with the com.transloadit.sdk.Transloadit class.

Create an Assembly

To create an assembly, you use the newAssembly method.

import com.transloadit.sdk.Transloadit;
import com.transloadit.sdk.exceptions.LocalOperationException;
import com.transloadit.sdk.exceptions.RequestException;
import com.transloadit.sdk.response.AssemblyResponse;

import java.io.File;
import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        Transloadit transloadit = new Transloadit("YOUR_TRANSLOADIT_KEY", "YOUR_TRANSLOADIT_SECRET");

        Assembly assembly = transloadit.newAssembly();

        Map<String, Object> stepOptions = new HashMap<>();
        stepOptions.put("width", 75);
        stepOptions.put("height", 75);
        assembly.addStep("resize", "/image/resize", stepOptions);

        assembly.addFile(new File("PATH/TO/FILE.jpg"));
        // you can skip this part if you don't want to wait till the
        // assembly is complete
        assembly.setShouldWaitForCompletion(true);
        try {
            AssemblyResponse response = assembly.save();

            System.out.println(response.getId());
            System.out.println(response.getUrl());
            System.out.println(response.json());

        } catch (RequestException | LocalOperationException e) {
            // handle exception here
        }
    }
}
Get an Assembly

The method, getAssembly, retrieves the JSON status of an assembly identified by the given assembly_Id.

import com.transloadit.sdk.Transloadit;
import com.transloadit.sdk.exceptions.LocalOperationException;
import com.transloadit.sdk.exceptions.RequestException;
import com.transloadit.sdk.response.AssemblyResponse;

public class Main {
    public static void main(String[] args) {
        Transloadit transloadit = new Transloadit("YOUR_TRANSLOADIT_KEY", "YOUR_TRANSLOADIT_SECRET");

        try {
            AssemblyResponse response = transloadit.getAssembly("ASSEMBLY_ID");

            System.out.println(response.getUrl());
            System.out.println(response.json());

        } catch (RequestException | LocalOperationException e) {
            // handle exception here
        }
    }
}

You may also get an assembly by url with the getAssemblyByUrl method.

    AssemblyResponse response = transloadit.getAssemblyByUrl("ASSEMBLY_URL");
Cancel an Assembly

To cancel an executing assembly, you use the cancelAssembly method, passing the Assembly ID as a parameter.

import com.transloadit.sdk.Transloadit;
import com.transloadit.sdk.exceptions.LocalOperationException;
import com.transloadit.sdk.exceptions.RequestException;
import com.transloadit.sdk.response.AssemblyResponse;

public class Main {
    public static void main(String[] args) {
        Transloadit transloadit = new Transloadit("YOUR_TRANSLOADIT_KEY", "YOUR_TRANSLOADIT_SECRET");

        try {
            AssemblyResponse response = transloadit.cancelAssembly("ASSEMBLY_ID");

            System.out.println(response.isCancelled()); // prints true
        } catch (RequestException | LocalOperationException e) {
            // handle exception here
        }
    }
}
List Assemblies

The method, listAssemblies, retrieves an array of assemblies according to the given options. Valid options can be page, pagesize, type, fromdate and todate. Please consult the Transloadit API docs for details.

import com.transloadit.sdk.Transloadit;
import com.transloadit.sdk.exceptions.LocalOperationException;
import com.transloadit.sdk.exceptions.RequestException;
import com.transloadit.sdk.response.ListResponse;

import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        Transloadit transloadit = new Transloadit("YOUR_TRANSLOADIT_KEY", "YOUR_TRANSLOADIT_SECRET");

        try {
            Map<String, Object> options = new HashMap<>();
            options.put("pagesize", 10);
            ListResponse response = transloadit.listAssemblies(options);

            System.out.println(response.size());  // number of assemblies on the list.
            System.out.println(response.getItems());  // returns an iterable json array

        } catch (RequestException | LocalOperationException e) {
            // handle exception here
        }
    }
}
Create a Template

To create a new template, you use the newTemplate method, passing the template name as a parameter.

import com.transloadit.sdk.Transloadit;
import com.transloadit.sdk.exceptions.LocalOperationException;
import com.transloadit.sdk.exceptions.RequestException;
import com.transloadit.sdk.response.Response;

import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        Transloadit transloadit = new Transloadit("YOUR_TRANSLOADIT_KEY", "YOUR_TRANSLOADIT_SECRET");

        Template template = transloadit.newTemplate("MY_TEMPLATE_NAME");

        Map<String, Object> resizeOptions = new HashMap<>();
        resizeOptions.put("width", 75);
        resizeOptions.put("height", 75);

        Map<String, Object> optimizeOptions = new HashMap<>();
        optimizeOptions.put("use", ":original");

        template.addStep("resize", "/image/resize", resizeOptions);
        template.addStep("resize", "/image/optimize", optimizeOptions);

        try {
            Response response = template.save();

            System.out.println(response.json());
            System.out.println(response.json().getString("id")); // gets the Template ID.
        } catch (RequestException | LocalOperationException e) {
            // handle exception here
        }
    }
}
Update a Template

To update a template, you use the updateTemplate method, passing the Template ID and options to update as a parameters.

import com.transloadit.sdk.Transloadit;
import com.transloadit.sdk.Steps;
import com.transloadit.sdk.exceptions.LocalOperationException;
import com.transloadit.sdk.exceptions.RequestException;
import com.transloadit.sdk.response.Response;

import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        Transloadit transloadit = new Transloadit("YOUR_TRANSLOADIT_KEY", "YOUR_TRANSLOADIT_SECRET");

        Steps steps = new Steps();

        Map<String, Object> stepOptions = new HashMap<>();
        stepOptions.put("width", 150);
        stepOptions.put("height", 150);
        steps.addStep("resize", "/image/resize", stepOptions);

        Map<String, Object> templateOptions = new HashMap<>();
        templateOptions.put("steps", steps.toMap());
        templateOptions.put("name", "MY_NEW_TEMPLATE_NAME");

        try {
            Response response = transloadit.updateTemplate("TEMPLATE_ID", templateOptions);

        } catch (RequestException | LocalOperationException e) {
            // handle exception here
        }
    }
}
Delete a Template

To delete a template, you use the deleteTemplate method, passing the Template ID as a parameter.

import com.transloadit.sdk.Transloadit;
import com.transloadit.sdk.exceptions.LocalOperationException;
import com.transloadit.sdk.exceptions.RequestException;
import com.transloadit.sdk.response.Response;

import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        Transloadit transloadit = new Transloadit("YOUR_TRANSLOADIT_KEY", "YOUR_TRANSLOADIT_SECRET");

        try {
            Response response = transloadit.deleteTemplate("TEMPLATE_ID");

        } catch (RequestException | LocalOperationException e) {
            // handle exception here
        }
    }
}
List Templates

To get a list of all templates under your account, you use the listTemplates method.

import com.transloadit.sdk.Transloadit;
import com.transloadit.sdk.exceptions.LocalOperationException;
import com.transloadit.sdk.exceptions.RequestException;
import com.transloadit.sdk.response.ListResponse;

public class Main {
    public static void main(String[] args) {
        Transloadit transloadit = new Transloadit("YOUR_TRANSLOADIT_KEY", "YOUR_TRANSLOADIT_SECRET");

        try {
            ListResponse response = transloadit.listTemplates();

            System.out.println(response.size());  // number of assemblies on the list.
            System.out.println(response.getItems());  // returns an iterable json array

        } catch (RequestException | LocalOperationException e) {
            // handle exception here
        }
    }
}
Get a template

To get a particular template, you use the getTemplate method, passing the Template ID as a parameter.

import com.transloadit.sdk.Transloadit;
import com.transloadit.sdk.exceptions.LocalOperationException;
import com.transloadit.sdk.exceptions.RequestException;
import com.transloadit.sdk.response.Response;

public class Main {
    public static void main(String[] args) {
        Transloadit transloadit = new Transloadit("YOUR_TRANSLOADIT_KEY", "YOUR_TRANSLOADIT_SECRET");

        try {
            AssemblyResponse response = transloadit.getTemplate("TEMPLATE_ID");
            System.out.println(response.json());
        } catch (RequestException | LocalOperationException e) {
            // handle exception here
        }
    }
}
Get bill

To get your account billing details for a particular month, you use the getBill method, passing the month and year as parameters.

import com.transloadit.sdk.Transloadit;
import com.transloadit.sdk.exceptions.LocalOperationException;
import com.transloadit.sdk.exceptions.RequestException;
import com.transloadit.sdk.response.Response;

public class Main {
    public static void main(String[] args) {
        Transloadit transloadit = new Transloadit("YOUR_TRANSLOADIT_KEY", "YOUR_TRANSLOADIT_SECRET");

        try {
            ListResponse response = transloadit.getBill(3, 2017);

            System.out.println(response.json());
        } catch (RequestException | LocalOperationException e) {
            // handle exception here
        }
    }
}

Example

For fully working examples take a look at examples/.

Documentation

See Javadoc for full API documentation.

Blog posts

We wrote the following posts about our Java integration on our blog:

jQuery


The recommended way to integrate Transloadit's file uploading and encoding capabilities with jQuery is by using our jQuery SDK.

Install

Note You may also be interested in checking out Uppy, Transloadit's next-gen file uploader for the web.

Simply include the JavaScript asset in your HTML page like so. jQuery >= 1.9 is also required.

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="//assets.transloadit.com/js/jquery.transloadit2-v3-latest.js"></script>

Usage

The Transloadit jQuery plugin allows you to

  • show file upload progress,
  • get uploaded results directly without further API queries, and
  • wait for upload processing to complete before redirecting to the result page or calling a callback function.

Assuming a form with the ID "upload-form" (from the minimal integration), the jQuery plugin can be used like this:

<script src="//assets.transloadit.com/js/jquery.transloadit2-v3-latest.js"></script>
<script type="text/javascript">
// We call .transloadit() after the DOM is initialized:
$(function() {
  $('#upload-form').transloadit({
    wait  : true,
    fields: true,

    triggerUploadOnFileSelection: true,

    params : {
      auth  : { key : 'YOUR_TRANSLOADIT_KEY' },
      steps : {
        resize_to_75: {
          robot  : '/image/resize',
          use    : ':original',
          width  : 75,
          height : 75
        },
        // more Steps here
      }
    }
  });
});
</script>

By default, this will display an overlay with a progress bar.

Important Your file input fields must each have a proper name attribute for our jQuery SDK to work properly.

Example

An example use of this plugin can be found in the examples directory.

To run it, simply replace YOUR_TRANSLOADIT_KEY (on the HTML file) with your actual Transloadit key and load the html file on your browser.

Documentation

See GitHub for the full documentation.

Blog posts

We wrote the following posts about our jQuery integration on our blog:

Node.js


The recommended way to integrate Transloadit's file uploading and encoding capabilities with Node.js is by using our Node SDK.

Install

Inside your project, type

npm install transloadit --save

If there are no errors, you can start using the module.

Usage

const TransloaditClient = require('transloadit')
const transloadit       = new TransloaditClient({
  authKey   : 'YOUR_TRANSLOADIT_KEY',
  authSecret: 'YOUR_TRANSLOADIT_SECRET'
})

const options = {
  waitForCompletion: true,
  params           : {
    template_id: 'YOUR_TEMPLATE_ID',
  },
}

const doneCb = (err, status) => {
  let assemblyId = ''

  if (status) {
    if (status.assembly_id) {
      assemblyId = status.assembly_id
    }
    // Low level errors (e.g. connection errors) are in err, Assembly errors are in status.error.
    // For this example, we don't discriminate and only care about erroring out:
    if (!err && status.error) {
      err = `${status.error}. ${status.message}. `
    }
  }

  if (err) {
    console.error({ status })
    throw new Error(`❌ Unable to process Assembly ${assemblyId}. ${err}`)
  }

  console.log({ status })
  console.log(`✅ Success`)
}

const progressCb = (ret) => {
  let msg = ''
  if (ret.uploadProgress) {
    msg += `♻️ Upload progress polled: ` + ret.uploadProgress.uploadedBytes + ` of ` + ret.uploadProgress.totalBytes + ` bytes uploaded.`
  }
  if (ret.assemblyProgress) {
    msg += `♻️ Assembly progress polled: ${ ret.assemblyProgress.error ? ret.assemblyProgress.error : ret.assemblyProgress.ok } ret.assemblyProgress.assembly_id ... `
  }

  console.log(msg)
}

transloadit.addFile('file1', '/PATH/TO/FILE.jpg')
transloadit.createAssembly(options, doneCb, progressCb)

Example

For fully working examples take a look at examples/.

Documentation

See GitHub for the full documentation.

Blog posts

We wrote the following posts about our Node.js integration on our blog:

PHP


The recommended way to integrate Transloadit's file uploading and encoding capabilities with PHP is by using our PHP SDK.

Install

Add the Transloadit PHP SDK as a dependency to your composer.json file:

{
  "require": {
    "transloadit/php-sdk": "dev-master"
  }
}

Consider replacing dev-master with the latest version in order to pin your dependencies.

Install the Composer dependency:

php composer.phar install

Keep your Transloadit account's key & secret key nearby. You can check the API credentials page for these values.

Usage

1. Upload and resize an image from your server

This example demonstrates how you can use the SDK to create an Assembly on your server.

It takes a sample image file, uploads it to Transloadit, and starts a resizing job on it.

<?php
require 'vendor/autoload.php';

use transloadit\Transloadit;

$transloadit = new Transloadit(array(
  'key'    => 'YOUR_TRANSLOADIT_KEY',
  'secret' => 'YOUR_TRANSLOADIT_SECRET',
));

$response = $transloadit->createAssembly(array(
  'files' => array('/PATH/TO/FILE.jpg'),
  'params' => array(
    'steps' => array(
      'resize' => array(
        'robot' => '/image/resize',
        'width' => 200,
        'height' => 100,
      ),
    ),
  ),
));

// Show the results of the assembly we spawned
echo '<pre>';
print_r($response);
echo '</pre>';

2. Create a simple end-user upload form

This example shows you how to create a simple Transloadit upload form that redirects back to your site after the upload is done.

Once the script receives the redirect request, the current status for this Assembly is shown using Transloadit::response().

Note: There is no guarantee that the Assembly has already finished executing by the time the $response is fetched. You should use the notify_url parameter for this.

<?php
require 'vendor/autoload.php';

use transloadit\Transloadit;

$transloadit = new Transloadit(array(
  'key'    => 'YOUR_TRANSLOADIT_KEY',
  'secret' => 'YOUR_TRANSLOADIT_SECRET',
));

// Check if this request is a Transloadit redirect_url notification.
// If so fetch the response and output the current assembly status:
$response = Transloadit::response();
if ($response) {
  echo '<h1>Assembly status:</h1>';
  echo '<pre>';
  print_r($response);
  echo '</pre>';
  exit;
}

// This should work on most environments, but you might have to modify
// this for your particular setup.
$redirectUrl = sprintf(
  'http://%s%s',
  $_SERVER['HTTP_HOST'],
  $_SERVER['REQUEST_URI']
);

// Setup a simple file upload form that resizes an image to 200x100px
echo $transloadit->createAssemblyForm(array(
  'params' => array(
    'steps' => array(
      'resize' => array(
        'robot' => '/image/resize',
        'width' => 200,
        'height' => 100,
      )
    ),
    'redirect_url' => $redirectUrl,
  ),
));
?>
<h1>Pick an image to resize</h1>
<input name="example_upload" type="file">
<input type="submit" value="Upload">
</form>

3. Integrate the jQuery plugin into the previous example

Integrating the jQuery plugin simply means adding a few lines of JavaScript to the previous example. Check the HTML comments below to see what changed.

<?php
require 'vendor/autoload.php';

use transloadit\Transloadit;

$transloadit = new Transloadit(array(
  'key'    => 'YOUR_TRANSLOADIT_KEY',
  'secret' => 'YOUR_TRANSLOADIT_SECRET',
));

$response = Transloadit::response();
if ($response) {
  echo '<h1>Assembly status:</h1>';
  echo '<pre>';
  print_r($response);
  echo '</pre>';
  exit;
}

$redirectUrl = sprintf(
  'http://%s%s',
  $_SERVER['HTTP_HOST'],
  $_SERVER['REQUEST_URI']
);

echo $transloadit->createAssemblyForm(array(
  'params' => array(
    'steps' => array(
      'resize' => array(
        'robot' => '/image/resize',
        'width' => 200,
        'height' => 100,
      )
    ),
    'redirect_url' => $redirectUrl
  )
));
?>
<!--
  Including the jQuery plugin is as simple as adding jQuery and including the
  JS snippet for the plugin. See https://transloadit.com/docs/#jquery-sdk
-->
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
  var tlProtocol = (('https:' === document.location.protocol) ? 'https://' : 'http://');
  document.write(unescape("%3Cscript src='" + tlProtocol + "assets.transloadit.com/js/jquery.transloadit2.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
  $(document).ready(function() {
    // Tell the transloadit plugin to bind itself to our form
    $('form').transloadit();
  });
</script>
<!-- Nothing changed below here -->
<h1>Pick an image to resize</h1>
<form>
  <input name="example_upload" type="file">
  <input type="submit" value="Upload">
</form>

Alternatively, check our Uppy, our next-gen file uploader for the web.

4. Fetch the Assembly Status JSON

You can just use the TransloaditRequest class to get the job done easily.

<?php
require 'vendor/autoload.php';

$assemblyId = 'YOUR_ASSEMBLY_ID';
$transloadit = new Transloadit(array(
  'key'    => 'YOUR_TRANSLOADIT_KEY',
  'secret' => 'YOUR_TRANSLOADIT_SECRET',
));
$response = $transloadit->getAssembly($assemblyId);

echo '<pre>';
print_r($response);
echo '</pre>';
5. Create an assembly with a template.

This example demonstrates how you can use the SDK to create an Assembly with Templates.

You are expected to create a Template on your Transloadit account dashboard and add the Template ID here.

<?php
require 'vendor/autoload.php';

use transloadit\Transloadit;

$transloadit = new Transloadit(array(
  'key'    => 'YOUR_TRANSLOADIT_KEY',
  'secret' => 'YOUR_TRANSLOADIT_SECRET',
));

$response = $transloadit->createAssembly(array(
  'files' => array('/PATH/TO/FILE.jpg'),
  'params' => array(
    'template_id' => 'YOUR_TEMPLATE_ID'
  ),
));

// Show the results of the assembly we spawned
echo '<pre>';
print_r($response);
echo '</pre>';

Signature Auth

Signature Authentication is done by the PHP SDK by default internally so you do not need to worry about this :)

Example

For fully working examples take a look at examples/.

Documentation

See GitHub for the full documentation.

Blog posts

We wrote the following posts about our PHP integration on our blog:

Python


The recommended way to integrate Transloadit's file uploading and encoding capabilities with Python is by using our Python SDK.

Install

pip install pytransloadit

Usage

from transloadit import client

tl = client.Transloadit('TRANSLOADIT_KEY', 'TRANSLOADIT_SECRET')
assembly = tl.new_assembly()
assembly.add_file(open('PATH/TO/FILE.jpg', 'rb'))
assembly.add_step('resize', '/image/resize', {'width': 70, 'height': 70})
assembly_response = assembly.create(retries=5, wait=True)

print assembly_response.data.get('assembly_id')

# or
print assembly_response.data['assembly_id']

Example

For fully working examples, take a look at examples/.

Documentation

See readthedocs for full API documentation.

Blog posts

We wrote the following posts about our Python integration on our blog:

Rails


The recommended way to integrate Transloadit's file uploading and encoding capabilities with Rails is by using our Rails SDK.

Install

$ gem install transloadit-rails

or add the transloadit-rails Gem to your Rails project's Gemfile and update your bundle.

$ echo "gem 'transloadit-rails'" >> Gemfile
$ bundle install

After installation you need to run the transloadit:install generator to complete the setup.

$ rails g transloadit:install

Usage

Refer to the Templates (which you have set in the config) with the transloadit helper.

<%= form_for :upload, :html => { :id => 'upload' } do |form| %>
  <%= transloadit :s3_store %>
  <%= form.label      :file, 'File to upload' %>
  <%= form.file_field :file %>
  <%= form.submit %>
<% end %>

<%= javascript_include_tag '//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js' %>
<%= transloadit_jquerify :upload %>

This requires jQuery, and loads the Transloadit jQuery plugin. Be sure to exclude the <%= javascript_include_tag '//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js' %> tag if you already have jQuery loaded.

JavaScript also ensures your form is encoded as multipart/form-data.

If you want to use the automatic transloadit parameter decoding, you have to include the Transloadit::Rails::ParamsDecoder module into your controller

class YourController
  include Transloadit::Rails::ParamsDecoder
end

that way the param[:transloadit] is automatically decoded for you, if it exists

Note Since it's still very young, the Transloadit Rails SDK does not include batteries for it yet, but if you're looking for a jQuery-less integration, check out Uppy, our next-gen file uploader for the web.

Example

An example rails application following the tutorial above can be found in the examples directory.

Documentation

See GitHub for the full documentation.

Blog posts

We wrote the following posts about our Rails integration on our blog:

Ruby


The recommended way to integrate Transloadit's file uploading and encoding capabilities with Ruby is by using our Ruby SDK.

Install

gem install transloadit

Usage

To get started, you need to require the 'transloadit' gem:

$ irb -rubygems
>> require 'transloadit'
=> true

Then create a Transloadit instance, which will maintain your authentication credentials and allow us to make requests to the API.

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)
1. Resize and store an image

This example demonstrates how you can create an Assembly to resize an image and store the result on Amazon S3.

require 'transloadit'

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)

# First, we create two steps: one to resize the image to 320x240, and another to
# store the image in our S3 bucket.
resize = transloadit.step 'resize', '/image/resize',
  :width  => 320,
  :height => 240

store  = transloadit.step 'store', '/s3/store',
  :key    => 'YOUR_AWS_KEY',
  :secret => 'YOUR_AWS_SECRET',
  :bucket => 'YOUR_S3_BUCKET'

# Now that we have the steps, we create an assembly (which is just a request to
# process a file or set of files) and let Transloadit do the rest.
assembly = transloadit.assembly(
  :steps => [ resize, store ]
)

response = assembly.create! open('/PATH/TO/FILE.jpg')

# reloads the response once per second until all processing is finished
response.reload_until_finished!

if response.error?
  # handle error
else
  # handle other cases
  puts response
end

Note: the Assembly method submit! has been deprecated and replaced with create!. The submit! method remains as an alias of create! for backward Compatibility)

When the create! method returns, the file has been uploaded but may not yet be done processing. We can use the returned object to check if processing has completed, or examine other attributes of the request.

# returns the unique API ID of the assembly
response[:assembly_id] # => '9bd733a...'

# returns the API URL endpoint for the assembly
response[:assembly_url] # => 'http://api2.vivian.transloadit.com/assemblies/9bd733a...'

# checks how many bytes were expected / received by transloadit
response[:bytes_expected] # => 92933
response[:bytes_received] # => 92933

# checks if all processing has been finished
response.finished? # => false

# cancels further processing on the assembly
response.cancel! # => true

# checks if processing was successfully completed
response.completed? # => true

# checks if the processing returned with an error
response.error? # => false

It's important to note that none of these queries are "live" (with the exception of the cancel! method). They all check the response given by the API at the time the Assembly was created. You have to explicitly ask the Assembly to reload its results from the API.

# reloads the response's contents from the REST API
response.reload!

# reloads once per second until all processing is finished, up to number of 
# times specified in :tries option, otherwise will raise ReloadLimitReached
response.reload_until_finished! tries: 300 # default is 600

In general, you use hash accessor syntax to query any direct attribute from the response. Methods suffixed by a question mark provide a more readable way of querying state (e.g., assembly.completed? vs. checking the result of assembly[:ok]). Methods suffixed by a bang make a live query against the Transloadit HTTP API.

2. Uploading multiple files

Multiple files can be given to the create! method in order to upload more than one file in the same request. You can also pass a single Step for the steps parameter, without having to wrap it in an Array.

require 'transloadit'

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)

assembly = transloadit.assembly(steps: store)

response = assembly.create!(
  open('puppies.jpg'),
  open('kittens.jpg'),
  open('ferrets.jpg')
)

You can also pass an array of files to the create! method. Just unpack the array using the splat * operator.

files = [open('puppies.jpg'), open('kittens.jpg'), open('ferrets.jpg')]
response = assembly.create! *files
3. Parallel Assembly

Transloadit allows you to perform several processing steps in parallel. You simply need to use other Steps. Following their example:

require 'transloadit'

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)

encode = transloadit.step 'encode', '/video/encode', { ... }
thumbs = transloadit.step 'thumbs', '/video/thumbs', { ... }
export = transloadit.step 'store',  '/s3/store',     { ... }

export.use [ encode, thumbs ]

transloadit.assembly(
  :steps => [ encode, thumbs, export ]
).create! open('/PATH/TO/FILE.mpg')

You can also tell a step to use the original uploaded file by passing the Symbol :original instead of another step.

Check the YARD documentation for more information on using use.

4. Creating an Assembly with Templates

Transloadit allows you to use custom templates for recurring encoding tasks. In order to use these do the following:

require 'transloadit'

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)

transloadit.assembly(
  :template_id => 'YOUR_TEMPLATE_ID'
).create! open('/PATH/TO/FILE.mpg')

You can use your steps together with this template and even use variables. The Transloadit documentation has some nice examples for that.

5. Using fields

Transloadit allows you to submit form field values that you'll get back in the notification. This is quite handy if you want to add additional custom metadata to the upload itself. You can use fields like the following:

require 'transloadit'

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)

transloadit.assembly(
  :fields => {
    :tag => 'some_tag_name',
    :field_name => 'field_value'
  }
).create! open('/PATH/TO/FILE.mpg')
6. Notify URL

If you want to be notified when the processing is finished you can provide a Notify URL for the Assembly.

require 'transloadit'

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)

transloadit.assembly(
  :notify_url => 'http://example.com/processing_finished'
).create! open('/PATH/TO/FILE.mpg')

Read up more on the Notifications on Transloadit's documentation page

7. Other Assembly methods

Transloadit also provides methods to retrieve/replay Assemblies and their Notifications.

require 'transloadit'

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)

assembly = transloadit.assembly

# returns a list of all assemblies
assembly.list

# returns a specific assembly
assembly.get 'YOUR_ASSEMBLY_ID'

# replays a specific assembly
response = assembly.replay 'YOUR_ASSEMBLY_ID'
# should return true if assembly is replaying and false otherwise.
response.replaying?

# returns all assembly notifications
assembly.get_notifications

# replays an assembly notification
assembly.replay_notification 'YOUR_ASSEMBLY_ID'
8. Templates

Transloadit provides a templates api for recurring encoding tasks. Here's how you would create a Template:

require 'transloadit'

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)

template = transloadit.template

# creates a new template
template.create(
  :name => 'TEMPLATE_NAME',
  :template => {
    "steps": {
      "encode": {
        "use": ":original",
        "robot": "/video/encode",
        "result": true
      }
    }
  }
)

There are also some other methods to retrieve, update and delete a Template.

require 'transloadit'

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)

template = transloadit.template

# returns a list of all templates.
template.list

# returns a specific template.
template.get 'YOUR_TEMPLATE_ID'

# updates the template whose id is specified.
template.update(
  'YOUR_TEMPLATE_ID',
  :name => 'CHANGED_TEMPLATE_NAME',
  :template => {
    :steps => {
      :encode => {
        :use => ':original',
        :robot => '/video/merge'
      }
    }
  }
)

# deletes a specific template
template.delete 'YOUR_TEMPLATE_ID'
9. Getting Bill reports

If you want to retrieve your Transloadit account billing report for a particular month and year you can use the bill method passing the required month and year like the following:

require 'transloadit'

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)

# returns bill report for February, 2016.
transloadit.bill(2, 2016)

Not specifying the month or year would default to the current month or year.

10. Rate limits

Transloadit enforces rate limits to guarantee that no customers are adversely affected by the usage of any given customer. See Rate Limiting.

While creating an Assembly, if a rate limit error is received, by default, 2 more attempts would be made for a successful response. If after these attempts the rate limit error persists, a RateLimitReached exception will be raised.

To change the number of attempts that will be made when creating an Assembly, you may pass the tries option to your Assembly like so.

require 'transloadit'

transloadit = Transloadit.new(
  :key    => 'YOUR_TRANSLOADIT_KEY',
  :secret => 'YOUR_TRANSLOADIT_SECRET'
)

# would make one extra attempt after a failed attempt.
transloadit.assembly(:tries => 2).create! open('/PATH/TO/FILE.mpg')

# Would make no attempt at all. Your request would not be sent.
transloadit.assembly(:tries => 0).create! open('/PATH/TO/FILE.mpg')

Example

A small sample tutorial of using the Transloadit ruby-sdk to optimize an image, encode MP3 audio, add ID3 tags, and more can be found here.

Documentation

Up-to-date YARD documentation is automatically generated. You can view the docs for the released gem or for the latest git master.

Zapier


The recommended way to integrate Transloadit's file uploading and encoding capabilities with Zapier is by using our Zapier Integration.

Usage

We have a list of ready to use Zaps that you can quickly get started with.

Creating your own Zaps

We put together two short step-by-step video walkthroughs on adding encoding capabilities to other services on Zapier.

1. Sending videos from Dropbox to Transloadit for iPad Optimization:

2. Sending videos back from Transloadit to Dropbox after iPad Optimization:

Under the hood, Assemblies are tagged with the originating Zap name. This makes it possible to create new Zaps with triggers on actions, such as: 'when the iPad conversion is ready -> message Slack'.

Troubleshooting
  • Avoid Zap loops: in order to avoid Zap loops, be sure not to trigger Assembly actions in the same folder where your completed Templates files are received. In the case of Dropbox, use one folder for input, and a different one for output. For more information on this, see this Zapier help page.
  • If you have issues with Dropbox and large files, check out: Missing Dropbox File field, in large files.
  • Transloadit's encoding is non-blocking. If you want to pass a file from Dropbox to Transloadit, you can't use the results in consequential steps. Instead, you should create a second Zap as illustrated below.

Documentation

See Zapier for the full documentation.

Blog posts

We wrote the following posts about our Zapier integration on our blog:

Community Projects

The following is a list of projects created by community members, for community members.

Devtools

Libraries

Apps

Examples

  • Image Cropping Tool

    Features jQuery frontend and PHP backend. In this example application you upload an image and then select a cropping area using drag and drop. Submitting the form will crop the uploaded image via Transloadit and give the result image back to you.
  • Transloadit Paperclip integration

    A gist with integration for the popular Ruby Paperclip gem.
  • Transloadit-Uploader

    A jQuery integration of Transloadit with custom progressbar and support for the jQuery.validate plugin.
  • Video Preview Image Chooser

    Features jQuery frontend and PHP backend. In this example application you upload a video and then have to option to select a cover image for the video from 10 thumbnails that are extracted from the video. Your choice will be resized into several formats. The uploaded video will also be encoded into several different web formats.

Did you see something cool that could be useful to others in the community? Please get in touch and we will list your project here.