Telestream Cloud HTML5 uploader

The Telestream Cloud uploader allows you to upload videos from your web application to Telestream Cloud. It’s an HTML5 uploader widget with Flash fallback that you can integrate with your web application to allow your users submit files for encoding.

It's library agnostic and resumable which means it will resume file upload if your connection goes down for any reason. This is key for anyone who is processing large files.

Uploader will use HTML5 upload if the browser supports it, and will fall back to Flash upload if necessary. Flash doesn’t have resumable capabilities and will upload your content as a MultiPart stream. This would be the case only for old browsers.

In order to start using the uploader, you need to paste the link to the CDN hosted minified version of the uploader library. You can keep up to date automatically with patch releases by linking to a minor version. The current stable version is 2.3. To do so, simply include the following declaration in your page:

<script src="//cdn.pandastream.com/u/2.3/panda-uploader.min.js"></script>

Initialization

By invoking panda.uploader.init(options) with a set of configuration options, you will initialize the Telestream Cloud uploader

Initialization configuration options

Property/MethodDescription
buttonIdDOM id of the styled browsing button. (required, this element should be a <div>)
authorizeUrlRoute of the authentication request, example: /panda/authorize_upload
autoStartUpload starts right after the user select a file, can be one of true or false, default is true
resumeIntervalInterval in milliseconds before the upload gets resumed, default: 5000
allowSelectMultipleFilesAllows you to add multiple files to the upload queue, can be one of true or false, default is false
progressBarIdDOM id of the progress bar element
fileDropIdDOM id of the file drop zone element
fileUrlInputIdDOM id of the text input where url will be placed
fileUrlButtonIdDOM id of submit button for fileUrlInputId
maxFileSizeMaximum allowed file size, example: 10 MB, valid values: [K|M|G]B, default: null which means there is no file size limit
confirmBeforeUnloadAlert the user that an upload is processing, can be one of true or false, default is true
typeForces the uploader type, can be one of html or flash, by default not set
onQueue (files)List of <files> added to the Queue
onStart (file)<file> starts uploading
onProgress (file, percent)<file> upload progress
onSuccess (file, json)The uploader has successfully uploaded <file> and returned a <json> object
onError (file, text)The uploader has failed uploading <file> and returned an error response
onComplete ()The upload queue has been completed
onCancel (file)<file> upload has been canceled.
onPause (file)<file> upload has been paused due to connectivity issues.

Uploader Object properties and methods

Property/MethodDescription
typeReturns the uploader type (html5 or flash)
setPayload (file, object)Add extra variables to the payload
setEnabled (bool)Enable/Disable the uploader
getQueuedFiles ()Returns the list of queued files
start ()Start uploading next queued file
cancel (file)Cancel <file> upload

File Object properties

PropertyDescription
nameReturns file name
sizeReturns file size in bytes

Upload authentication

The authentication of your new upload occurs via an HTTP Request to a configurable authentication url when the file is ready to be uploaded. In the JavaScript Uploader the HTTP Request is executed via AJAX POST request. The destination of the authentication request can be configured by setting the authorizeUrl param when calling panda.uploader.init.

The default is /panda/authorize_upload

A payload is then sent as a JSON encoded object in the body and can contain 2 sets of variables:

  • filesize, filename, content_type
  • fileurl

The api request to Telestream Cloud should include:

  • file_name and file_size for /videos/upload.json endpoint
  • source_url for /videos.json endpoint

Examples for Ruby, Python and PHP

# Using Rails and https://github.com/Telestream/telestream-cloud-ruby-sdk
# app/controllers/panda_controller.rb
class PandaController < ApplicationController
  def authorize_upload
    payload = JSON.parse(params['payload'])

    options = {
      profiles: "h264,webm",
      # payload: 'something',
      # path_format: ':video_id/:profile/play',
    }
    if payload['filename']
      url = '/videos/upload.json'
      options['file_name'] = payload['filename']
      options['file_size'] = payload['filesize']
    else
      url = "/videos.json"
      options['source_url'] = payload['fileurl']
    end

    upload = TelestreamCloud.post(url, options)

    render :json => {:upload_url => upload['location']}
  end
end
# Using Django and https://github.com/Telestream/telestream-cloud-python-sdk
# views.py
@csrf_exempt
def authorize_upload(request):
  params = json.loads(request.POST['payload'])

  options = {"profiles": "h264"}
  if params["filename"]:
    url = "/videos/upload.json"
    options["file_name"] = params["filename"]
    options["file_size"] = params["filesize"]
  else:
    url = "/videos.json"
    options["source_url"] = payload["fileurl"]

  upload = tc.post(url, options)

  auth = {"upload_url": json.loads(upload)["location"]}
  return HttpResponse(json.dumps(auth), mimetype='application/json')
<?php
// authorize_upload.php
$payload = json_decode($_POST['payload']);

$filename = $payload->{'filename'};
$filesize = $payload->{'filesize'};
$fileurl = $payload->{'fileurl'};

$options = array('profiles' => 'h264');
if ($filename) {
  $url = '/videos/upload.json';
  $options['file_name'] => $filename;
  $options['file_size'] => $filesize;
} else {
  $url = '/videos.json';
  $options['source_url'] => $fileurl;
}

$upload = json_decode(@$panda->post($url, $options);

$response = array('upload_url' => $upload->location);

header('Content-Type: application/json');
echo json_encode($response);
?>

Optionally, you can also set:

-use_all_profiles - to use all profiles in the Factory, can be one of true or false, default is false
-profiles - comma-separated list of profile names, by default no encodings are created yet
-payload - arbitrary string stored along the Video object.
-path_format - allows you to set the location inside your S3 Bucket, it should not include the file extension

The generated JSON should include:
-upload_url - Location where to upload the file
-postprocess_url - optional, when the upload is complete, a request is made to this url to let your server know that the uploader has finished uploading the file

Example

The following is the simplest working form that will let you upload a video:

  1. Click on “Choose file”. You will be shown a file selection dialog.
  2. Select a file to upload.
  3. Wait for the upload to complete.
  4. After the upload completes, Telestream Cloud returns a unique ID that identifies your video. The form will finally be submitted so that your application can read this value and use it to reference the video later on.

onQueue adds some extra data to be sent alongside the payload.

HTML Form

<form action="/path/to/action" id="new_video" method="POST">
  <input type="hidden" name="panda_video_id"/>
  <div id="browse-files">Choose file</div>
</form>

Javascript uploader setup

var upl = panda.uploader.init({
  'buttonId': 'browse-files',
  'onProgress': function(file, percent) {
    console.log("progress", percent, "%"),
  'onQueue': function(files) {
    $.each(files, function(i, file) {
      upl.setPayload(file, {'authenticity_token': AUTH_TOKEN});
   });
  },
  },
  'onSuccess': function(file, data) {
    $("#new_video")
      .find("[name=panda_video_id]")
        .val(data.id)
      .end()
      .submit();
  },
  'onError': function(file, message) {
    console.log("error", message);
  },
});

Extra features

Progress bar and file drop

The uploader comes with some handy handlers like Progress Bars and File Drop, there is no styling though.

<form action="/path/to/action" id="new_video" method="POST">
  <input type="hidden" name="panda_video_id"/>
  <div class='progress'><span id="progress-bar" class='bar'></span></div>
  <div id="file-drop">Drop files here</div>
  <div id="browse-files">Choose file</div>
</form>
var upl = panda.uploader.init({
  ...
  'progressBarId': "progress-bar",
  'fileDropId': "file-drop",
});

Resume an upload

If you have been disconnected from the Internet while you were uploading a file you will be notified by the onPause callback. It’s important to note that the Flash uploader doesn’t support this feature so the upload will fail.

By default, the uploader will setup a resume interval of 5 seconds. You can also add a resume button.

To resume your uploading queue, just call the start method and your current upload will continue where it left off.

var upl = panda.uploader.init({
  ...
  'autoResume': false,
  'onPause': function(){
    $("#notice").text("You went offline.");
  }
})

$("#resume-btn").click(function() {
  upl.start();
})

Abort an upload

If you want to abort an upload that is currently taking place, use the cancel() function from the uploader instance. An aborted upload is no longer resumable.

$("#cancel-btn").click(function() {
  upl.cancel(file);
})

Upload file from another server

You can also allow to upload any publicly available video file just by submitting the URL of it. First, the form example:

<form action="/path/to/action" id="new_video" method="POST">

  <input type="hidden" name="panda_video_id"/>

  <input id="file-url" type="text" placeholder="Type URL to file">
  <button id="file-url-send" type="button">Upload from URL</button>

  <div id="browse-files">Choose file</div>

</form>

And Javascript:

var upl = panda.uploader.init({
  ...
  'fileUrlInputId': "file-url"
  'fileUrlButtonId': "file-url-send"
});

You can also omit the HTML form part, and just call uploader method uploadFromUrl to achieve the same effect.

var upl = panda.uploader.init({
  ...
});

upl.uploadFromUrl("http://mysite/video.mp4", function (error) {
  // If something went wrong the error parameter will be passed to this callback function.
  // If error is undefined it means action ended with success.
});

Post-upload processing

You might want to let your server know that the uploader finished uploading a file. This is quite useful when handling multiple uploads on a single web page.

To achieve this, you simply need to return the postprocess_url during the authentication handshake.

# app/controllers/panda_controller.rb
class PandaController < ApplicationController
  def authorize_upload
    ...
    render :json => {
      :upload_url => upload['location'],
      :postprocess_url => '/some/postprocess'
    }
  end
end
# views.py
def authorize_upload(request):
  ...
  auth = {
    "upload_url": json.loads(upload)["location"],
    "postprocess_url": '/some/postprocess',
  }

  return HttpResponse(json.dumps(auth), mimetype='application/json')
<?php
// authorize_upload.php
$response = array(
  'upload_url' => $upload->location},
  'postprocess_url' => 'postprocess.php'
  );

header('Content-Type: application/json');
echo json_encode($response);
?>

Once the video is successfully uploaded to Telestream Cloud, your server will receive a POST request like this:

# app/controllers/some_controller.rb
class SomeController < ApplicationController
  def postprocess
    response = JSON.parse(params["upload_response"])
    render :json => { :id => "some-id" }
  end
end
# views.py
@csrf_exempt
def postprocess(request):
  response = json.loads(request.POST['upload_response'])
  return HttpResponse(json.dumps({"id": "some-id"}), mimetype='application/json')
<?php
// postprocess.php

$response = json_decode($_POST['upload_response']);
header('Content-Type: application/json');
echo json_encode(array('id' => 'some-id'));
?>

The onSuccess callback will expose the data received from the post-process request.

var upl = panda.uploader.init({
  ...
  'onSuccess': function(file, data) {
    console.log(data['id']); // 'some-id'
  }
})