How to use our video API as a replacement for file input elements inside HTML forms

This article describes how to combine the Clipchamp HTML5 video API with HTML forms. We illustrate how to use the API as a drop-in replacement for HTML file input elements, letting you easily add webcam recording or video conversion and compression capabilities to existing forms on your websites.

This means that you’ll be able to have users enter written data such as their name and email address in form fields and have them record a video with their webcam on the same page so that all data gets submitted as part of the same upload workflow.

Our API offers webcam recording, video compression, and upload capabilities through a comprehensive JavaScript API. That is, our API normally handles the end-to-end process of picking a video file or making a webcam recording, converting and compressing that video file into a standard format (such as MP4 with H.264/AAC video and audio encoding), and finally uploading the resulting video to an upload destination you nominate.

However, sometimes you may want the Clipchamp API to act as a drop-in replacement for a file picker input element. That is, instead of using the behind-the-scenes upload to AWS S3, the Azure blob store, YouTube, Dropbox or Google Drive, you may rather want the compressed video file to be submitted alongside other form data to your backend. In other words, an

<input name="video" type="file">

shall be replaced by a video recording and uploading option, but leave the rest of the form untouched.

In this article, we show 2 alternative ways to use our API to achieve just that and act as a drop-in substitute for HTML file input elements, adding video file conversion/compression and/or webcam recording to your form. We assume that you’ve already registered for a free API trial or are already actively using the API past the trial phase.

 

Option 1: Hidden Input Fields

The approach that requires the least amount of coding is to replace the file input element with a hidden input element and use our blob output option to:

  1. First receive the output video blob locally within the onVideoCreated callback; and
  2. Then Base64-encode the output video and set the resulting string as the value of the hidden input element.

The corresponding changes first need to change the existing file input element into a hidden input element and add a button to launch the Clipchamp widget next to it:

<input name="file-input" type="hidden">
<button id="launch-clichamp">Record video</button>

Further, you will need to make sure that the form submission uses the multipart/form-data encoding. This does happen by default when your form contains a file input element, but otherwise needs to be explicitly specified by adding the enctype attribute to the form element:

<form enctype="multipart/form-data" method="POST" action="...your backend URL goes here...">
...
</form>

Please note that you cannot submit a form using a HTTP GET request using multipart/form-data encoding. But submitting forms as GET requests is a bad practice anyways, so you are probably not doing it in the first place.

All that remains to be done then is to implement our API’s onVideoCreated callback. To also blend in visually, we use the API’s custom button option, using the previously added button:

The onVideoCreated callback will use the FileReader API to read the output video blob into a data URL, which contains video data as a Base64-encoded string. We extract that portion of the data URL and and set the hidden input element’s “value” attribute to that string. Once the end user submits the form, the encoded video data will be transferred to your backend server alongside other form fields.

While it’s very straightforward to replace a regular file picker input element with the Clipchamp API in this way, there are some downsides to consider that are associated with this approach:

  • For one, using hidden input elements does not let us specify the video file’s MIME type (eg., video/mp4) or its encoding (here: Base64), which would normally be stated using a per-part “Content-Type” and “Content-Transfer-Encoding” header field, respectively. In the absence of this information, the form’s backend endpoint cannot automatically infer how to unpack the video file from the HTTP body. In effect, you may have to make some minor changes to your backend code where you work with conventions, instead. That is, your backend would have to assume that the video file is transferred as a Base64-encoded ASCII string. The MIME type (if important for your backend to know) could be transferred as another hidden input field (not shown in the sample code above).
  • Secondly, using hidden input fields you cannot transfer your video file in binary form, hence the need to use a binary-to-text encoding scheme like Base64. Since you may have to adapt your backend anyways, you can however opt for alternative codecs such as BasE91, which has less encoding overhead than Base64, but requires extra libraries – both for your client-side JavaScript code and most likely also for your backend code.

In summary, using hidden input fields is a simple, albeit somewhat “hackish” approach to replace HTML file input elements with the Clipchamp API. In case you do not require the response from your form submission to be an HTML document, we therefore recommend another variant, illustrated below.

 

Option 2 (recommended): Using the FormData and XMLHttpRequest APIs

Submitting forms that cause the browser to replace the current website with whatever HTML payload is returned with the response body is not feasible for single-page applications, where the browser runs off one and the same URL.

Also, the aforementioned Base64 encoding convention and corresponding adaptations to your backend code may be a reason to pick our second (and recommended) approach to replacing file input elements with the Clipchamp API.

Specifically, this second variant entails:

  1. Programmatically constructing a multipart/form-data payload using the JavaScript FormData API and adding the video file that is output by our video API in binary form.
  2. Submitting the FormData instance to your backend form submission endpoint using an AJAX request (with the XMLHttpRequest API).

Since we are programmatically submitting the form using the XMLHttpRequest API, we can remove the “clutter” (HTTP verb, endpoint URL end encoding) from the form element:

<form>
...
</form>

The FormData API lets us programmatically create a correct multipart/form-data payload. Using the FormData API makes sure that the payload is syntactically correct and is highly recommended over building the request body “by hand”.

Moreover, we can directly embed binary content into the HTTP body, which helps to lower HTTP request size and to avoid the overhead of encoding (decoding) a Base64-encoded file on the client (server).  We add the compressed output video in the onVideoCreated callback by simply calling the “append” function of the FormData instance:

formData.append('file', blob);

Note that we can synchronously return from onVideoCreated, i.e. without signalling through callbacks or a returned Promise when we are done handling the output video. This is due to the fact that the “append” function is as such synchronous. We later also add the value of the other (text) input element to the FormData instance and submit it as request payload.

The complete example is shown below:

Using the FormData API in combination with an AJAX request (i.e. using the XMLHttpRequest or Fetch API) is clearly the preferred way to submit a compressed video or webcam recording that was produced by the Clipchamp API.

Here are some things to be aware of, nevertheless:

  • If the form submission endpoint is on a different domain than your website, you will need to make sure that this endpoint serves the CORS headers in response to an OPTIONS request. Only then will you be able to programmatically evaluate any response details that are returned by that endpoint.
  • You cannot use AJAX requests when your backend sets response headers that your browser implicitly reacts upon, most importantly the Set-Cookie header, which is commonly used in response to login forms. If this is the case for you, you should consider using option 1 above.
  • Likewise, AJAX requests are not the method of choice when the backend responds with an HTML payload that the browser is supposed to render. Again, you will need to resort to option 1.