This article explains the purpose and use of the Blob output option that is available in the Business and Enterprise plans of the Clipchamp API. We illustrate when to favour the Blob output option over our “pre-canned” video upload options, such as the inbuilt capability to have us upload your users’ videos to your AWS S3 or Microsoft Azure accounts.
What is a Blob and what does the Blob output option do?
You can think of an instance of Blob as a file handle that may represent some in-memory data, binary data received from
XMLHttpRequest , data that is persistently stored on the client’s file system using the IndexedDB or FileWriter APIs. Blobs may even be views onto other Blob instances. For instance, you can create a “wrapper Blob” from other Blob instances like so:
Your application needs to perform some custom client side post-processing steps after output video data has become available. For instance, you may want to embed the output video in an HTML5 video player and play it to the user before uploading it to your backend server.
You cannot use any of our (steadily growing list of) inbuilt upload targets for regulatory (legal) reasons, technical obstacles, or cost considerations and store the uploaded videos on your own servers instead.
Generally, we recommend to consider using the inbuilt upload targets before opting for the Blob output. This does not only save you time and effort to code the upload to your own servers yourself. It will also make you benefit from all the robustness that we have built into the upload protocol, including retry mechanisms in sketchy network conditions and robust security protocols to safeguard your videos from malicious third parties while uploading.
How to use the Blob output option?
In order to use the Blob output option, you need to subscribe to the Business or Enterprise plan of the Clipchamp API. Please contact email@example.com to discuss your specific requirements. Using the Blob output option essentially requires you to adjust the way you invoke our API in two ways:
'blob'as the value of the
Provide a callback function in the
Using the Blob output option would thus follow this pattern:
In the example above, we assume you use jQuery in conjunction with the Clipchamp API and choose to use the Clipchamp-styled button, which we inject into the DOM (inside the wrapper element that is selected with the jQuery selector). Naturally, using the Blob output option is not confined to this use of the Clipchamp API.
That is, you can use the Blob output option without jQuery or when using the “custom button” flavour of our API (see CUSTOM BUTTON API on that page). The Clipchamp API will call the
onVideoCreated callback with the output video, which is an instance of
Blob . In the following, we will describe 3 ways how to process that blob inside the
Synchronous processing (discouraged!)
The simple-most, albeit discouraged way to implement the
onVideoCreated callback function is to process
outputVideoBlob only synchronously. Doing so requires you to finish up all use of the output video synchronously, such that when your implementation of
onVideoCreated returns control to the Clipchamp API, we can immediately destroy the
outputVideoBlob object and delete its underlying persistent storage.
A synchronous implementation of
Blob object into another Blob object synchronously. What you may be able to do is performing a synchronous
XMLHttpRequest where you send the outputVideoBlob to your backend server:
onVideoCreated as a synchronous function, but use one of the following two asynchronous implementations instead.
The most straightforward way to make
onVideoCreated asynchronous is to add a number of callback parameters that you need to asynchronously invoke to signal the successful (or unsuccessful) completion of handling the
outputVideoBlob in your code. For instance, the asynchronous counterpart of a simple video upload functionality could be implemented like so:
Notice how we added two parameters to the signature on
failCallback . Once you add them to the function signature, the Clipchamp API will be smart enough to pass a function to each. Your code then needs to either invoke the
failCallback , depending on whether or not your post-processing of outputVideoBlob was successful (or unsuccessful).
When your post-processing merely comprises of asynchronously uploading the video to a some HTTP(S) endpoint of yours, you should tie the success of that uploading operation to invoking
failCallback. While doing so, you are free to delay invoking
doneCallback until the complete post-processing operation is finally complete. Similarly, you only need to call
failCallback if it has ultimately failed.
For instance, you could implement a simple chunking upload protocol based on HTTP
Content-Range request headers, where you split outputVideoBlob into smaller chunks and send each one in a separate HTTP request (provided that your server can handle chunked uploads):
Let’s unpack this slightly more complex implementation of the onVideoCreated function. For the sake of better modularity, it defines two nested functions:
uploadSingleChunk(asynchronously) sends a POST request with a 1 MB chunk to a HTTPS endoint. To signal the fragment of
outputVideoBlobthat is being sent with this request, we set the
Content-Rangeheader to the corresponding byte interval. Notice that the upper value in the
bytes=...range is inclusive.
uploadNextChunkrecursively traverses over
outputVideoBlob, slicing out 1 MB chunks that it passes to
uploadSingleChunksucceeds, it recursively invokes
uploadNextChunkwith the next chunk offset. Otherwise, it retries sending the current chunk after one second. If it fails another time, we invoke the (global)
failCallback. Once the offset has exceeded the size of
outputVideoBlob, we invoke the (global)
In reality, a retry policy of chunked uploads would be even more robust with an exponential timely backoff strategy.
Promises often constitute a superior programming model, replacing callbacks with a (stateful) concept where an asynchronous function returns a promise object. That promise object allows to register callbacks that get invoked when the promise is “resolved” or “rejected”, i.e., the asynchronous function has succeeded or failed.
The Clipchamp API allows you to use promises instead of callbacks, supporting both the upcoming Promise A+ standard and jQuery’s “deferred” objects. In either case, your implementation of
onVideoCreated needs to return a promise object and can then (asynchronously) resolve or reject that promise. The following example uses Promise A+, which is part of the ECMAScript 6 standard.
The beauty of promises does not stop there, but includes the notion of being “chainable”. In fact, much of jQuery’s utility functions use their “deferred” implementation. That includes jQuery’s AJAX functions, which provide a convenience wrapper around
Notice how we package
outputVideoBlob into a
FormData instance, which makes sure jQuery uses a
Besides signalling the success or failure of your asynchronous post-processing of the
outputVideoBlob , you can optionally signal the progress of your processing step to the Clipchamp API as a percentage value. We will use that value to display a progress bar and calculate a timely estimate for the remaining duration before completion. To do so, you can either add a third
notifyCallback to the signature of
onVideoCreated _or _use the progress reporting capability of your promise object – note that not all promise implementations support progress reporting, jQuery promises do though:
failCallback , the
notifyCallback can be invoked multiple times. You should make sure to pass increasing percentage values such as to make sure that the progress bar only ever moves forward. The same is true for invoking the notify function of the jQuery promise. In order to signal the progress of a file upload using the
XMLHttpRequest API, you can do the following: