TUS uploads with vanilla Js.
I had a task of implementing video uploads with the the progress bar.
My stack was React on frontend, Django on server.
Here I lay out the choices I encountered, why I chose a combination of Transloadit SAAS with tus-js-client after all, and a step-by-step implementation guide.
Our server options
- Use direct AWS S3 resumable uploads from frontend. I didn’t choose this option, because I didn’t like their documentation, and I wouldn’t be able to encode or otherwise manipulate videos I’m uploading from the browser. Besides, most popular protocol for resumable uploads is TUS, and I wanted to use something that won’t make me depend on S3 specific libraries in the future.
- Implement own TUS server on my own server (I used Django). Then I would upload a file to my own server, encode it in the delayed job, and upload it to AWS S3 on my own. This is a very flexible approach, but, looking through the relevant python libraries, nothing seemed robust enough. And consider the points of failures I would encounter implementing it on my own: [TUS server made from a 30-star library; delayed jobs; ffmpeg; AWS upload]. All of these are not bad ideas, but they are, traditionally, very error-prone procedures.
- Use Vimeo. This is a great option, and I have actually implemented TUS uploads with Vimeo at first. Videos were stored directly on Vimeo. One drawback to this approach is that Vimeo only supports videos (and I’d enjoy to have resumable uploads for files and pics too), and my users couldn’t access Vimeo videos from their work accounts sometimes.
- Use Transloadit. This is what I chose in the end, and I don’t regret it. It’s similar to the Vimeo option in that I don’t need to have delayed jobs, ffmpeg, and what not, on my own server, I can delegate all of it to Transloadit servers. But it’s different in that I have a lot more flexibility with Transloadit. I can upload videos to any end storage (I chose AWS S3), I can upload any file (and not only videos) with Tus, and I can choose what formats I want to encode my files into.
Transloadit is on server - what are our frontend options?
Once we decided to use Transloadit, we need to think of what to use on the client.
- Uppy frontend library. This is a library (created by Transloadit, just like the TUS protocol itself) with the rich UI, that would make integration with Transloadit an ease. If you want to use their UI, and if you are fine with customizing the library — it’s probably the best option for you. With a few settings in place you will have loading bars, dropzone, and multiple-file uploads in place. There are React components present. In my use case I wouldn’t benefit from their UI much, and needing to adjust library internals to my use case would cause me some pain. That’s why I decided to go for a more close-to-metal solution.
- JQuery Transloadit SDK is another library by the Transloadit, meant to help you in interacting with their api. This looked more like something I wanted, but I didn’t want to be writing JQuery code in my React, and I sure as hell didn’t want to include default html markup and override css. And in general apis are easier to work with directly, without a layer of JQuery on top of them.
- Tus-js-client and simple ES6 fetch. Tus-js-client is, predictably, another library by Transloadit, but it isn’t directly connected to the Transloadit in any way, it’s a general library for any TUS client. In fact I used it when I was using Vimeo as a TUS server. This is the option I most liked, and the one I implemented.
Transloadit with Tus-js-client
- Sign up with Transloadit.
- Go to https://transloadit.com/account/api-settings, copypaste your auth key
TRANSLOADIT_AUTH_KEY = 'lalala';
- Give Transloadit access to your storage option, for me it’s AWS S3 (you can use whatever storage you like — e.g. dropbox, youtube): https://transloadit.com/template-credentials. Name it, for example,
MemcodeS3Credentials
. You will use this name later, without needing to disclose your AWS credentials to the world. - And, finally, write some code on your frontend!
In general we will use the following logic:
- Generate random AWS S3 url
=>awsS3Url
that we randomly generated for the third step, the url where our final video will be stored. - Create Transloadit assembly (by POSTing to https://api2.transloadit.com/assemblies).
What they call ‘assembly’ could be named a ‘job’ instead. This is basically telling Transloadit WHAT FILE to start processing, and in WHAT WAY to start processing it.
We feed assembly steps, describing what exactly should be done to the video we are yet to upload (upload itself will happen later).
We will use 3 steps:
1: ‘/upload/handle’ (this step is us uploading file from our computer to Transloadit via TUS),
2: ‘/video/encode’ (this step will turn any format we uploaded into standard mp4), and, finally,
3: ‘/s3/store’ (this step will upload encoded video to our AWS S3 account). We will give our random AWS S3 urlawsS3Url
to our assembly as an argument. Then we’ll store it somewhere, and we will be able to access our video at that url once the assembly is successful.
=> Two very important things returned to us after this fetch are:
1.response.tus_url
, the url for TUS upload (using this url we can start uploading our file!), and
2.response.assembly_url
, the url we will use to GET status of our assembly. - Upload our file via TUS (by using tus-js-client). We will upload it to the url Transloadit returned to us after we created the assembly —
response.tus_url
. - Start GETting status of our assembly! Once it’s ready — we can access the video we in our
awsS3Url
.
Q&A
Can I name my steps anything?
Yes, with one exception — when using the ‘/upload/handle’ robot, name should be ‘:original’, otherwise assembly creation will raise an error.
Why do we have to set
resume: false
in TusJsClient?
Because otherwise uploads of the files you have once uploaded will not work. This may seem counterintuitive considering the fact that one of the main appeals of the TUS protocol is file upload resumes, but it’s intentional decision from the Transloadit team.