Single page video uploader

Sometimes not all info-beamer features are required. For example it happens that you want to provide some users a very simple way to just update a single video and have that loop on the screen(s). They might create their own account and you can then allow them access to your account using the permission system, but that might be overkill. Here’s an alternative approach that will use a simple HTML page that only allows updating a single video file with a single button:

image

Prepare a setup

Import the single video looper package into your account by clicking this button, then create a setup based on the newly imported package:

Import

Upload the video.mp4 file to your account and assign that to a setup. Assign that setup to your display(s). You now have an installation that infinitely loops a single video file. Now you need to allow your users to update that file in the simplest way possible.

Preparing the permission

You need to create a new access to your own account with restricted permission to only being able to upload and update a single video asset. Go to the policy page, click Create Policy…, give your policy a name (“video.mp4 upload only”) and apply the following policy:

{
  "Statements": [
    {
      "Action": "asset:upload",
      "Condition": {
        "StringEquals": {
          "asset:filename": "video.mp4",
          "asset:filetype": "video"
        }
      },
      "Effect": "allow"
    }
  ],
  "Version": 1
}

Save your policy and go to ACLs. Click on Create ACL…, give your ACL an name (“Video uploader”) and click on Create. Now click on your new ACL and click on the + button next to your “video.mp4 upload only” policy created earlier to add that to your ACL. Click on Save ACL.

Finally go to account access and click on Create new access…. Set the description to “Video uploader” and select the “Video uploader” ACL in the ACL dropdown. Then click on Create access. The new access list listed in the “Access to your own account” list. Click on the Access actions button and select “View API key…”. Copy the API key as you need it in the next step.

Preparing the uploader

Create the following HTML page:

<html>
  <body style='margin: 30px; font-size: 150%'>
    <label style='border:1px solid #ccc;border-radius:3px;padding:10px;cursor:pointer;'>
      <input id='upload' type='file' accept='video/mp4' style='display: none'>
      Upload new video
    </label>
    <script>
      const FILENAME = 'video.mp4'
      const API_KEY = '<YOUR API KEY HERE>'

      document.getElementById('upload').addEventListener('change', async e => {
        let headers = new Headers()
        headers.append('Authorization', `Basic ${btoa(':'+API_KEY)}`)
        let body = new FormData()
        body.append('file', e.target.files[0], FILENAME)
        try {
          let r = await fetch('https://info-beamer.com/api/v1/asset/upload', {
            method: 'POST',
            headers, body,
          })
          if (r.status == 200) {
            alert('Success. Video has been updated')
          } else if (r.status == 403) {
            alert('Error: Uploading permission denied')
          } else {
            let data = await r.json()
            alert(`Error: ${data.error}`)
          }
        } catch (e) {
          alert(`Error: ${e}`)
        }
      })
    </script>
  </body>
</html>

Replace <YOUR API KEY HERE> with the API key from the previous step. That’s all. If you now open this page in a browser it will allow you to only upload the video file video.mp4 to your info-beamer account. If you later need to revoke access, go to your access page and either revoke the access or renew the API key.

1 Like

Hi Florian,

I’m getting a TypeError: Failed to fetch when selecting the mp4.

fetch

Just making sure: You did change the <YOUR API KEY HERE> value in the HTML (or JS to be precise)?

Yeah that’s been changed.

This is likely a CORS issue. The problem is that info-beamer doesn’t allow cross domain requests from non-HTTPS pages, unless it happens to be from localhost. If you placed your HTML on an internal non-HTTPS webserver, the request gets denied.

Do you have an HTTPS enabled location you can use?

1 Like

Just tested it on a HTTPS location and it worked perfectly.

Thanks for the support, Florain!

Is there some way of showing the upload progress to the end user?
If you upload rather large video files (which can take about a minute to upload) the end user does not get any feedback about the upload process at all.

Any Ideas? Thanks

There is indeed. Here’s a quick implementation using XMLHttpRequest that shows a rudimentary progress bar during upload. Be sure to replace the API key placeholder with a restricted API key:

<html>
  <body style='margin: 30px; font-size: 150%'>
    <label style='border:1px solid #ccc;border-radius:3px;padding:10px;cursor:pointer;display:block;'>
      <input id='upload' type='file' accept='video/mp4' style='display: none'>
      Upload new video
    </label>
    <progress id="progress" value='0' style='margin:3px 0;display:block;width:100%;'/>
    <script>
      const FILENAME = 'video.mp4'
      const API_KEY = '<YOUR API KEY HERE>' // <-- USE YOUR API KEY HERE
      const progress = document.getElementById('progress')
      document.getElementById('upload').addEventListener('change', e => {
        let body = new FormData()
        body.append('file', e.target.files[0], FILENAME)
        let client = new XMLHttpRequest()
        client.onerror = e => {
          console.log(e) 
          alert(`Error: Could not complete upload`)
        } 
        client.onload = e => {
          console.log(e)
          let status = e.target.status
          if (status == 200) {
            alert('Success. Video has been updated')
          } else if (status == 403) {
            alert('Error: Uploading permission denied')
          } else {
            alert(`Error: Could not complete upload`)
          } 
        } 
        client.upload.onprogress = e => {
          progress.value = 1 / e.total * e.loaded
        } 
        client.open('POST', 'https://info-beamer.com/api/v1/asset/upload')
        client.setRequestHeader('Authorization', `Basic ${btoa(':'+API_KEY)}`)
        client.send(body)
      })
    </script>
  </body>
</html>
2 Likes