Wistia

to the tippy ↑

Wistia Uploader

The Wistia Uploader is the best way to enable video uploading directly from within your application to your Wistia account. Add a complete video uploading experience to your product quickly with a simple drop-in component, or customize the Uploader to suit your specific needs.

Demo: Try the Uploader

Upload a video below to see the Uploader in action. Don't have a video on hand? Download this one to play around with!

Note that the video you upload in this demo will only stick around until you refresh the page. To try the Uploader with your own Wistia account, head to Getting Started.

Tip

Before you start uploading, open the console in your browser to see some of the JavaScript events the Uploader triggers. 👀

Getting Started

Add the following code to your page to include the Uploader. You'll need to change the accessToken and projectId to sync with your Wistia account.

wistia_uploader_example.html
1
2
3
4
5
6
7
8
9
10
11
12
13
<script src="//fast.wistia.com/assets/external/api.js" async></script>
<link rel="stylesheet" href="//fast.wistia.com/assets/external/uploader.css" />
<div id="wistia_uploader" style="height:360px;width:640px;"></div>
<script>
window._wapiq = window._wapiq || [];
_wapiq.push(function(W) {
  window.wistiaUploader = new W.Uploader({
    accessToken: "ACCESS_TOKEN_GOES_HERE",
    dropIn: "wistia_uploader",
    projectId: "PROJECT_ID_GOES_HERE"
  });
});
</script>

The only options you need to change in the code above are accessToken and projectId. You can create a project through the Data API, or from the ▸ Actions menu in your Wistia account interface. The projectId is the same one that appears on the project page's URL in your account, like "bgdrq7qysq" in https://home.wistia.com/projects/bgdrq7qysq.

To create an access token, head to the API Access section of your Wistia Account Settings. Just be sure to check "Upload video" under "Permissions" when you create the access token.

There are plenty of other customizations available if you want to tailor your users' upload experience. Scroll down to the Options section for a list of available options.

Authentication

The Uploader always requires an accessToken with upload permissions to authenticate each upload. You can choose to use a permanent token or an expiring one. Expiring tokens provide added security.

Using expiring tokens

To generate a new expiring token, send a POST request to the expiring_tokens endpoint.

Note

The token you use in a request to generate an expiring token must be a permanent token. Expiring tokens cannot create more expiring tokens. That would not be very expiringly of them.

Parameters

Parameter Description
expires_at When the token should expire, in seconds-since-epoch.
required_params Params that are henceforth required in order for this token to make an API request. This is useful for restricting uploading to a specific project, for example.

Example request

expiring_token_request
1
curl -X POST "https://api.wistia.com/v2/expiring_token?api_password=PERMANENT_TOKEN_WITH_UPLOAD_SCOPE_HERE&required_params%5Bproject_id%5D=abcde12345"

Example response

expiring_token_response.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "data": {
    "id": "expiring_token_2b1998d6b18515b9f814bd90da2afe7e343ec312ebc1c1e9f23af91b2fffee32",
    "type": "access_token",
    "attributes": {
      "type": "access_token",
      "token": "expiring_token_2b1998d6b18515b9f814bd90da2afe7e343ec312ebc1c1e9f23af91b2fffee32",
      "scopes": ["media:upload"],
      "required_params": {
        "project_id": "abcde12345"
      },
      "expires_at": 1460825198
    }
  }
}

An expiring token always inherits the permissions (also known as "scopes") of the permanent token used to create it.

Handling the Uploaded Video

Once the video is embeddable, you can automatically embed it in a preview container. The preview option takes an element id, and is set to"wistia_upload_preview" by default. This is convenient for displaying the video immediately after it gets uploaded, but to display the video in your application in the future, you will need to store a reference to the video in your database.

When the uploadembeddable event fires, it provides the embedCode as an argument to the callback function you define. This embed code will use any options you define in embedCodeOptions.

Options

Need to customize your video upload experience? The Uploader offers several convenient options, which work the same way as the Wistia Player embed options:

accessToken (required)

The access token to authenticate the upload. Accepts a permanent or temporary access token. See Authentication for more info.

beforeUpload

Use this option to define a function that should run just before uploading begins. This is useful for changing the parameters of the next upload, like by asking the person uploading the video to provide a name or description after selecting the file.

wistiajs.js
1
2
3
4
beforeUpload: function() {
  wistiaUploader.setFileName('myfile');
  wistiaUploader.setFileDescription('the description');
}

If a Promise is returned, the Uploader waits until that promise resolves before starting the upload.

wistiajs.js
1
2
3
4
5
6
7
8
9
beforeUpload: function() {
  var promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
      wistiaUploader.setFileName('myfile');
      resolve();
    }, 1000);
  });
  return promise;
}

Or if a Promise is not available but async work is still required, a simple object with a then property will suffice:

wistiajs.js
1
2
3
4
5
6
7
8
9
10
beforeUpload: function() {
  return {
    then: function(resolve, reject) {
      setTimeout(function() {
        wistiaUploader.setFileName('myfile');
        resolve();
      }, 1000);
    }
  };
}

button

id attribute of the button container, or the DOM node itself. Preset to "wistia_upload_button". Required unless you use the dropIn option.

button.js
1
2
3
// either of these approaches are acceptible:
button: "wistia_upload_button"
button: $("[data-upload-button]")[0] // If you are using jQuery

customButton

If customButton is true, the Upload button will not automatically change color or display any messages to communicate the status of the upload. When using this option, you should bind to the events the uploader fires and construct your own ways to indicate upload progress, success, or... (gasp!)... failure.

dropIn

Set dropIn to the id of a container, and a complete Uploader will appear within it. When you use this option, you do not need to use button, dropZone, or preview. Set dropIn to false if you would like to customize the Uploader extensively.

dropZone

id of the drop zone container, or the DOM node itself. Preset to "wistia_upload_drop_zone". Required unless you use the dropIn option.

dropZoneClickable

Defaults to true. When false, clicking on the drop zone becomes a fruitless endeavor, and the person uploading a video must click the button directly instead.

embedCodeOptions

You can use this to define embed options for the video player that appears in the preview container. The same options are also applied the embed code provided as an argument to the uploadembeddable event's callback function.

In addition to player embed options, can also pass in oEmbed parameters to set things like the type of embed code. These parameters are only applied to the embed code passed to the uploadembeddable event's callback.

embedCodeOptions.js
1
2
3
4
embedCodeOptions: {
  playerColor: "56be8e",
  embedType: "async_popover"
}

extraVideoExtensions

Adds more extensions that will be accepted if allowNonVideoUploads is not set to true. Expects a space separated string of extensions.

wistiaja.js
1
extraVideoExtensions: 'mp4'

iframeUploader (for testing only)

Instead of resumable upload with XHR, an invisible iframe is placed over the upload button to handle the upload. This iframe will do a simple HTTP POST to upload the file.

No uploadprogress events are fired, and the iframe may interfere with hover events over the button.

This option returns true for IE8-10 and other browsers that do not support resumable upload, but is provided as an option on all browsers for testing purposes.

Tip

If you are using a custom upload button (see the customButton option), give it the style position: relative;. This will ensure that the absolutely positioned iframe starts in the right location.

noUploadSupport (for testing only)

On clicking Upload Video, there will be an alert that recommends upgrading to a modern browser.

This option returns true for IE7 and below, and other browsers that don't support the postMessage API, but is provided as an option for testing purposes.

onBeforeUnload

This is a function that will run if the person uploading tries to leave the page while the upload is active. It returns a string, which is the confirmation text the user will see. By default, this is set to:

"Are you sure you wish to leave the page? Any active uploads will be lost."

Set onBeforeUnload to a string, or a function that returns a string, to define a custom message. Set to false if you want to disable the warning entirely.

onBeforeUnload.js
1
2
3
4
5
6
7
8
9
window._wapiq = window._wapiq || [];
_wapiq.push(function(W) {
  window.wistiaUploader = new W.Uploader({
    accessToken: "...",
    projectId: "...",
    dropIn: "wistia_uploader",
    onBeforeUnload: false
  });
});

Note

There's currently a nasty little bug affecting people who use Chrome and OS X El Capitan, which prevents uploads from resuming after the user begins to navigate to a new page during the upload, but then thinks better of it and stays put. For now, with a heavy heart, we ask such people to begin their upload again.

preview

id (or the DOM node itself) of the container in which the video will be embedded when the uploadembeddable event fires.

Preset to "wistia_upload_preview". Required unless you use the dropIn option.

projectId (required)

The hashedId of the project to upload the video into.

theme

The Uploader comes with two available themes: light_background and dark_background. theme defaults to light_background. If your page has a dark background, the dark_background theme will probably look much nicer.

wistiajs.js
1
theme: 'dark_background'

videoExtensions

Limits the extensions that will be accepted if allowNonVideoUploads is not set to true. Expects a space separated string of extensions.

wistiajs.js
1
videoExtensions: 'mp4 avi wmv'

Methods

bind(eventType, callbackFn)

Runs a callback function when a specific event is triggered. Refer to the Events section to see how to respond to the different types events.

bind.js
1
2
3
wistiaUploader.bind('uploadsuccess', function(file, media) {
  console.log('The uploadsuccess event fires when the upload completes successfully, and provides the Media object:\n',  media);
});

cancel()

Cancels the current upload. When an upload in cancelled this way, the Uploader does not ask for confirmation.

cancel.js
1
2
3
$('#custom_cancel_button').click(function() {
  wistiaUploader.cancel();
});

getEmbedCode(id, embedType, callbackFn)

Returns an embed code for the given video with the given embed options, and runs a callback function. The callback is called like callback(embedCode, oembedResponse), where embedCode is a string and oembedResponse is a hash.

Best used in conjuction with the uploadembeddable event, as shown in this example:

getEmbedCode.js
1
2
3
4
5
wistiaUploader.bind('uploadembeddable', function(file, media, embedCode, oembedResponse) {
  wistiaUploader.getEmbedCode(media.id, { playerColor: "56be8e", embedType: "async" }, function(embedCode, resp) {
  console.log(embedCode);
  });
});

Tip

You can also use a media's id as the first parameter instead of the complete media object.

For details on the available video embed code types, see Construct An Embed Code.

getThumbnailUrl(id, options, callbackFn)

You can use getThumbnailUrl() to get a thumbnail image for a media as soon as you have its id. The uploadembeddable event provides the media object when it becomes available.

Valid options include:

  • width
  • height
  • params (see Working With Images for available params)
  • mode ('resize' or 'crop-resize'; 'crop-resize' by default)
getThumbnailUrl.js
1
2
3
wistiaUploader.getThumbnailUrl("id", { width: 300 }, function(thumbnailUrl) {
  console.log("Preserve natural aspect ratio and set width to 300", thumbnailUrl);
});

removePreview()

Resets the preview container. This is useful if you want to use the same Uploader to upload additional videos and your preview is covering the upload button.

setFileName(name)

Sets the name of the next file to be uploaded, which gets used as the media's name in Wistia. Intended to be used within the beforeUpload function. The name in Wistia will default to the file's native name if you do not use this option.

setFileDescription(description)

Sets the description of the next file to be uploaded. Intended to be used within the beforeUpload function.

setProjectId(projectId)

Sets the projectId of the next file to be uploaded. Intended to be used within the beforeUpload function.

unbind(eventType, callbackFn)

Unbind a callback that was setup with bind(eventType, callbackFn).

wistia_js.js
1
2
3
4
5
6
7
var onUploadSucceessFunction = function(file, video) {
  fireConfettiCannon();
}
wistiaUploader.bind("uploadsuccess", onUploadSuccessFunction;
$("#button_to_disable_confetti_cannon").click(function() {
  wistiaUploader.unbind("uploadsuccess", onUploadSuccessFunction);
});

Since binding until a condition is met is a common operation, the Uploader API also supports anonymous function unbinding.

wistia_js.js
1
2
3
4
wistiaUploader.bind("uploadsuccess", function() {
  console.log("Upload succeeded! This message will never appear again.");
  return wistiaUploader.unbind;
});

videoExtensions()

Returns a list of supported video file extensions. The Uploader only accepts files using these known extensions, unless allowNonVideoUploads is set to true.

For more details on the video formats Wistia supports, see Optimal Export Settings.

Events

uploadcancelled

When the person uploading decides to cancel the upload, this event will fire. It provides the file as an argument to a callback function.

uploadcancelled.js
1
2
3
wistiaUploader.bind('uploadcancelled', function(file) {
  console.log("We are no longer uploading " + file.name);
});

uploadembeddable

An embed code becomes available when Wistia can determine the width and height of the video, since this is required for the embed code's dimensions.

wistiajs.js
1
2
3
4
5
6
7
8
wistiaUploader.bind("uploadembeddable", function(file, media, embedCode, oembedResponse) {
  console.log("The video is now embeddable!");
  console.log("Here's the original file: ", file);
  console.log("Here's the media in Wistia: ", media);
  console.log("Here's an embed code: ", embedCode);
  console.log("And here's the full oEmbed response (see https://wistia.com/doc/oembed): ", oembedResponse);
  saveEmbedCode(embedCode); // save the embed code to your database to display the video in the future
});

This is also the moment at which the video will automatically get embedded into the preview container, unless you choose to not display a preview.

uploadfailed

If the upload fails for any reason besides an intentional cancellation, this event will fire, and Max Schnur will sense a great disturbance in the force.

wistiajs.js
1
2
3
wistiaUploader.bind("uploadfailed", function(file, errorResponse) {
  console.log("upload failed:", errorResponse.error);
});

uploadprogress

This event fires once every 500 ms during the uploading process, and provides the current progress of the upload as a decimal.

wistiajs.js
1
2
3
wistiaUploader.bind("uploadprogress", function(file, progress) {
  console.log(Math.round(progress * 100) + "% uploaded");
});

uploadstart

Fires as soon as the upload begins. 🚀

wistiajs.js
1
2
3
wistiaUploader.bind("uploadstart", function(file) {
  console.log("The upload started! This file is destined for greatness:\n", file);
});

uploadsuccess

The best event of all, uploadsuccess fires when the file is safely in Wistia and getting ready to play beautifully across devices all around the world.

uploadsuccess provides the file and media objects to your callback function.

uploadsuccess.js
1
2
3
wistiaUploader.bind('uploadsuccess', function(file, media) {
  console.log("The upload succeeded. Here's the media object!", media);
});

Advanced Customization

While the default Uploader embed code can be used as-is to provide a complete uploading interface, you can also customize it to fit seamlessly into your product.

If you intend to customize the Uploader interface, use the modular embed code as your starting point. In the modular embed code, the dropIn option is removed and replaced with options for three modular components: button, dropZone, and preview, along with corresponding div containers for each one.

By default, those components are arranged to provide a complete and self-contained uploading interface, all the way from accepting file input to displaying the uploaded video in the Wistia player. Feel free to mix and match them, and style them however you please.

Tip

The customButton option gives you complete control over the upload button's appearance and behavior.

Modular Uploader embed code

modular_wistia_uploader_example.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script src="//fast.wistia.com/assets/external/api.js" async></script>
<link rel="stylesheet" href="//fast.wistia.com/assets/external/uploader.css" />

<div id="wistia_upload_drop_zone" class="wistia_upload_drop_zone" style="height:360px;width:640px;">
  <div id="wistia_upload_preview" class="wistia_upload_preview"></div>
  <img src="//fast.wistia.com/images/upload-icon@2x.png" class="wistia_upload_graphic" alt="Upload Video" />
  <div class="wistia_upload_text" style="visibility:hidden;">Drag and drop a file or</div>
  <div class="wistia_upload_drop_zone_hover"></div>
  <div id="wistia_upload_button" alt="Upload Video"></div>
</div>

<script>
window._wapiq = window._wapiq || [];
_wapiq.push(function(W) {
  window.wistiaUploader = new W.Uploader({
    accessToken: "TOKEN_GOES_HERE",
    button: "wistia_upload_button",
    dropZone: "wistia_upload_drop_zone",
    preview: "wistia_upload_preview",
    projectId: "PROJECT_ID_GOES_HERE"
  });
});
</script>

Example Uploaders

Pure drop-in

With the dropIn option, you can easily create a complete drop-in Uploader in a given container:

dropin-uploader.html
1
2
3
4
5
6
7
8
9
10
11
12
13
<script src="//fast.wistia.com/assets/external/api.js" async></script>
<link rel="stylesheet" href="//fast.wistia.com/assets/external/uploader.css" />
<div id="wistia_uploader" style="height:360px;width:640px;"></div>
<script>
window._wapiq = window._wapiq || [];
_wapiq.push(function(W) {
  window.wistiaUploader = new W.Uploader({
    accessToken: "ACCESS_TOKEN_GOES_HERE",
    dropIn: "wistia_uploader",
    projectId: "PROJECT_ID_GOES_HERE"
  });
});
</script>

That will produce the default Uploader interface:

Button only

No drag-and-drop? No problem.

button_only.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script src="//fast.wistia.com/assets/external/api.js" async></script>
<link rel="stylesheet" href="//fast.wistia.com/assets/external/uploader.css" />

<div id="wistia_upload_button_button_only" alt="Upload Video"></div>

<script>
window._wapiq = window._wapiq || [];
_wapiq.push(function(W) {
  window.wistiaUploaderButtonOnly = new W.Uploader({
    accessToken: "ACCESS_TOKEN_GOES_HERE",
    button: "wistia_upload_button_button_only",
    projectId: "PROJECT_ID_GOES_HERE"
  });
});
</script>

No button

Here's an Uploader with no button. We haven't thought of any use cases for this yet. ¯\(ツ)

Upload Video

And here's the code behind it:

no-button.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script src="//fast.wistia.com/assets/external/api.js" async></script>
<link rel="stylesheet" href="//fast.wistia.com/assets/external/uploader.css" />

<div id="wistia_upload_drop_zone_no_button" class="wistia_upload_drop_zone" style="height:360px;width:640px;">
  <div id="wistia_upload_preview_no_button" class="wistia_upload_preview"></div>
  <img src="//fast.wistia.com/images/upload-icon@2x.png" class="wistia_upload_graphic" alt="Upload Video" />
  <div class="wistia_upload_text" style="visibility:hidden;">Drag and drop a file</div>
  <div class="wistia_upload_drop_zone_hover"></div>
</div>

<script>
window._wapiq = window._wapiq || [];
_wapiq.push(function(W) {
  window.wistiaUploader = new W.Uploader({
    accessToken: "ACCESS_TOKEN_GOES_HERE",
    projectId: "PROJECT_ID_GOES_HERE",
    dropZone: "wistia_upload_drop_zone_no_button",
    dropZoneClickable: true,
    preview: "wistia_upload_preview_no_button"
  });
});
</script>