What is direct video file access?
Each video hosted by SproutVideo has various video asset files associated with it that are created during the encoding process. By default, we protect these video assets to prevent access to them outside of our player, which gives our customers full control over the security of their content. However, it is possible to get the direct video asset file URLs if necessary. You may need these to use a third-party player, create your own app, or any number of other use cases.
There are two methods to access these files. The first way is to enable Insecure Direct Video File Access, either as your account-wide default, or for specific videos only. The second option is to create secure signed URLs using your SproutVideo API key.
Note: Playback of Direct File Assets happens outside of the video player we provide so videos viewed using Direct Video File Access will not be tracked in our Analytics and Video Engagement Metrics.
How to enable Insecure Direct Video File Access
When you need direct access to your video files without providing a signature, you’ll need to enable Insecure Direct Video File Access. You can choose to enable this as an account-wide default, or for select videos only.
Warning: Enabling ‘Insecure Direct Video File Access’ means anyone with access to the video asset file link will have unrestricted access to the file.
Enable Insecure Direct File Access for Individual Videos
We recommend only enabling this option for select videos to limit the risk of your content being unintentionally downloaded. To do this, simply navigate to any video settings page in your account.
On your video’s detailed settings page, open the ‘Advanced Video Settings’ menu located at the bottom of the settings pane (bottom left corner of the page):
With the ‘Advanced Video Settings’ menu expanded, scroll to the bottom again and find the ‘Advanced Security Options’ section. You’ll see a toggle to ‘Allow insecure access to video asset files’ here. Switch this setting to ‘ON’ to enable insecure direct access to this video only:
Once you’ve enabled this setting, be sure to save your changes. After saving, you can now access your video asset file links from the video’s download menu. Look for the “DOWNLOAD” button at the top right of your video’s settings page to open the download menu:
You’ll see a list of all of your video asset files available for download, including your video’s poster frame and the streaming-only HLS file. Click the link icon to copy the URL for any video asset file:
Enable Insecure Direct File Access for All Videos in Your Account
To enable Insecure Direct Video File Access for all videos in your account as your account-wide default, navigate to ‘Account Settings’ > ‘API’ and switch the toggle to ‘YES’ to “Allow video file access outside of SproutVideo player”. Click the ‘Save API Settings’ button to save your preference. (Only admin and owner roles have access to manage account-wide settings.)
Once you have enabled this setting, you’ll find your video asset file links in the “DOWNLOAD” menu from any video detailed settings page (mentioned above).
You can also request the direct URL with an API call or assemble the URL manually.
Note: If ‘Insecure Direct Video File Access’ is disabled, all video assets will revert back to their default protected state and will not be accessible outside of the SproutVideo player unless they are secured with a signature. However, per-video settings will always override any account default, so disabling this in your account default settings does not necessarily mean all of your videos are secure. If you’ve ever enabled this setting for any individual video, that per-video setting will be maintained.
How to Manually Assemble Video Asset Links
You can manually build the link for any video asset file by using the following URL structure:
https://api-files.sproutvideo.com/file/[video_id]/[security_token]/[resolution].mp4
Using any embed code provided by SproutVideo as a reference, replace [video_id]
with the video ID of your file, [security_token]
with the token from the embed code, and [resolution]
with the resolution of the video you want to use (such as ‘1080’).
Here’s an example using the SproutVideo default inline embed code:
<iframe class='sproutvideo-player' src='https://videos.sproutvideo.com/embed/a49bd0b41710e8c12c/0972a3ac5b0ea93d' width='630' height='332' frameborder='0' allowfullscreen></iframe>
The video_id
is the first string following https://videos.sproutvideo.com/embed/
, so in this example the video ID is: a49bd0b41710e8c12c
The security_token
is the last string: 0972a3ac5b0ea93d
We know that the highest-quality file available for this video is the 1080p version, so the resolution
we want should be 1080
Putting that all together, the direct link for this 1080p video file would be:
https://api-files.sproutvideo.com/file/a49bd0b41710e8c12c/0972a3ac5b0ea93d/1080.mp4
How to Access Video Asset Files Securely
It’s possible to access the video asset files directly for any video without compromising on security. To do this, you will simply need to create a signed URL for each video asset. Follow these steps for creating that signature using your SproutVideo API key:
Note: Do not enable the insecure direct file access setting mentioned above if you are using secure, signed video file links.
1. Find the URL you wish to sign
All of the video asset URLs will be returned in the “assets” section of the video’s API response. If you prefer, you may also use the steps above to manually build your video asset file URL.
For this guide, we’ll use the following URL as an example:
https://api-files.sproutvideo.com/file/a49bd0b41710e8c12c/0972a3ac5b0ea93d/1080.mp4
2. Generate the string to sign
To start, we must generate the base string that will be used to create the hash. The base string is composed of the following elements:
Request method: The request method in this case will always be GET
Host name: The host name in this case will always be api-files.sproutvideo.com
Request path: The request path is part of the URL after the host up to the first ? If the URL we are signing is https://api-files.sproutvideo.com/file/a098d2bbd33e1c328/7ca00d6d622a8e8d/1080.mp4
, the request path is /file/a098d2bbd33e1c328/7ca00d6d622a8e8d/1080.mp4
Sorted query parameters: First, we need to add the expiration parameter. Typically, you would pick a time a few minutes or so in the future. The time you pick should be in UTC, and the value should be represented as an integer number of seconds since the Epoch. For example, the time of May 02 2013, 10:21:43 PM (UTC)
would be represented as 1367533303
. Since this request doesn’t support any other query parameters, the expiration is all you need. The sorted query parameters for this example becomes: &expires=1367533243
Note: Ideally your system time should be synced using NTP or a similar protocol so your system uses the same time that SproutVideo’s system does.
Now that we have all of our components, we need to combine them into a single string formatted on multiple lines as shown below:
Request method Host name Request path Sorted query parameters
With our example URL above, the multi-line string would look like this:
GET api-files.sproutvideo.com /file/a098d2bbd33e1c328/7ca00d6d622a8e8d/1080.mp4 &expires=1367533243
Now that we have our string, it is time to sign it.
3. Calculating the signature
First you’ll need your API key to sign the string. You can find your API key here. Finally, the signature is calculated by passing the signature base string and signing key to the HMAC-SHA1 hashing algorithm. The details of the algorithm are explained in depth here, but thankfully there are implementations of HMAC-SHA1 available for every popular language. Ruby has the OpenSSL library and PHP has the hash_hmac function.
For example, the output given the example string and a signing key of 9ab4b003d47003df394191234c54506d
is \xD7\xD0\x18r\xE6\xB8q\b\xA61\xC0k*m\x04H\xCF\x0F\xE2\x1C
. That value, when converted to base64, is the signature for this request: 19AYcua4cQimMcBrKm0ESM8P4hw=
4. Building the final request URL
First, take the original URL:
https://api-files.sproutvideo.com/file/a49bd0b41710e8c12c/0972a3ac5b0ea93d/1080.mp4
Next add the sorted query parameters (expiration) to the URL:
https://api-files.sproutvideo.com/file/a098d2bbd33e1c328/7ca00d6d622a8e8d/1080.mp4?expires=1367533243
Finally, URI encode the ‘signature’ parameter, and add that to the end of the URL:
https://api-files.sproutvideo.com/file/a098d2bbd33e1c328/7ca00d6d622a8e8d/1080.mp4?expires=1367533243&signature=19AYcua4cQimMcBrKm0ESM8P4hw%3D
You can then use this final URL to directly access your MP4 files.
Code Samples
These code samples show how to generate the signed URL in several popular languages.
-
const host = "api-files.sproutvideo.com"; const videoID = "a098d2bbd33e1c328"; const securityToken = "7ca00d6d622a8e8d"; const apiKey = "9ab4b003d47003df394191234c54506d"; const file = "1080.mp4"; const expires = 1367533243; const params = { expires: expires }; const sortedParams = Object.keys(params) .sort() .map((key) => { return `${key}=${encodeURIComponent(params[key])}`; }) .join("&"); const stringToSign = `GET\n${host}\n/file/${videoID}/${securityToken}/${file}\n&${sortedParams}`; const signature = require("crypto") .createHmac("SHA1", apiKey) .update(stringToSign) .digest("base64"); const queryString = `${sortedParams}&signature=${encodeURIComponent(signature)}`; console.log( `https://${host}/file/${videoID}/${securityToken}/${file}?${queryString}`, );
-
require 'openssl' require 'uri' host = 'api-files.sproutvideo.com' video_id = 'a098d2bbd33e1c328' security_token = '7ca00d6d622a8e8d' file = '1080.mp4' api_key = '9ab4b003d47003df394191234c54506d' expires = 1367533243 params = { expires: expires } string_to_sign = "GET\n#{host}\n/file/#{video_id}/#{security_token}/#{file}\n&#{URI.encode_www_form(params.sort)}" signature = [ OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), api_key, string_to_sign) ].pack("m").strip query_string = URI.encode_www_form(params.merge(signature: signature)) puts "https://#{host}/file/#{video_id}/#{security_token}/#{file}?#{query_string}"
-
import urllib.parse import base64 import hmac from hashlib import sha1 host = 'api-files.sproutvideo.com' video_id = 'a098d2bbd33e1c328' security_token = '7ca00d6d622a8e8d' file = '1080.mp4' api_key = '9ab4b003d47003df394191234c54506d' expires = 1367533243 params = dict(expires=expires) query_string = urllib.parse.urlencode( sorted(params.items(), key=lambda x: x[0]) ) string_to_sign = f'GET\n{host}\n/file/{video_id}/{security_token}/{file}\n&{query_string}' signature = base64.b64encode( hmac.new(api_key.encode('ascii'), string_to_sign.encode('ascii'), sha1).digest() ).decode() params.update(signature=signature) query_string = urllib.parse.urlencode(params) print(f"https://{host}/file/{video_id}/{security_token}/{file}?{query_string}")
-
$host = 'api-files.sproutvideo.com'; $video_id = 'a098d2bbd33e1c328'; $security_token = '7ca00d6d622a8e8d'; $file = '1080.mp4'; $api_key = '9ab4b003d47003df394191234c54506d'; $expires = 1367533243; $params = array('expires' => $expires); ksort($params); $string_to_sign = "GET\n{$host}\n/file/{$video_id}/{$security_token}/{$file}\n&" . http_build_query($params); $params['signature'] = base64_encode( hash_hmac('sha1', $string_to_sign, $api_key, true) ); $query_string = http_build_query($params); $embed_url = "https://{$host}/file/{$video_id}/{$security_token}/{$file}?{$query_string}"; print_r($embed_url);
-
import java.net.URLEncoder; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.*; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; class Main { public static void main(String[] args) { String host = "api-files.sproutvideo.com"; String videoId = "a098d2bbd33e1c328"; String securityToken = "7ca00d6d622a8e8d"; String file = "1080.mp4"; String apiKey = "9ab4b003d47003df394191234c54506d"; int expires = 1367533243; Map<String, String> params = new HashMap<>(); params.put("expires", String.valueOf(expires)); String[] sortedKeys = params.keySet().toArray(new String[params.size()]); Arrays.sort(sortedKeys); StringJoiner query = new StringJoiner("&"); for (String key : sortedKeys) { String value = params.get(key); try { value = URLEncoder.encode(value, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } query.add(key + "=" + value); } String path = "/file/" + videoId + "/" + securityToken + "/" + file; String stringToSign = "GET\n" + host + "\n" + path + "\n&" + query.toString(); String signature = null; try { signature = URLEncoder.encode(computeSignature(apiKey, stringToSign), "UTF-8"); } catch (Exception e) { e.printStackTrace(); } String embedUrl = "https://" + host + path + "?signature=" + signature + "&" + query.toString(); System.out.println(embedUrl); } private static String computeSignature(String apiKey, String stringToSign) throws NoSuchAlgorithmException, InvalidKeyException { Mac mac = Mac.getInstance("HmacSHA1"); SecretKeySpec secret = new SecretKeySpec(apiKey.getBytes(), "HmacSHA1"); mac.init(secret); byte[] signatureBytes = mac.doFinal(stringToSign.getBytes()); return Base64.getEncoder().encodeToString(signatureBytes); } }
-
using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; public class Program { public static void Main() { string host = "api-files.sproutvideo.com"; string video_id = "a098d2bbd33e1c328"; string security_token = "7ca00d6d622a8e8d"; string file = "1080.mp4"; string api_key = "9ab4b003d47003df394191234c54506d"; int expires = 1367533243; var queryParams = new Dictionary<string, string> { { "expires", expires.ToString() } }; var sortedParams = string.Join("&", queryParams .OrderBy(x => x.Key) .Select(x => $"{x.Key}={Uri.EscapeDataString(x.Value)}")); var stringToSign = $"GET\n{host}\n/file/{video_id}/{security_token}/{file}\n&{sortedParams}"; var signature = Uri.EscapeDataString( Convert.ToBase64String( new HMACSHA1(Encoding.ASCII.GetBytes(api_key)) .ComputeHash(Encoding.ASCII.GetBytes(stringToSign)))); var embedUrl = $"https://{host}/file/{video_id}/{security_token}/{file}?{signature}&{sortedParams}"; Console.WriteLine(embedUrl); } }