Skip to content

Instantly share code, notes, and snippets.

@ToshY
Last active July 17, 2023 04:44
Show Gist options
  • Save ToshY/0b1b818b080bf9528dfbcc375b937a08 to your computer and use it in GitHub Desktop.
Save ToshY/0b1b818b080bf9528dfbcc375b937a08 to your computer and use it in GitHub Desktop.
BunnyCDN VOD HLS Token Authentication V2 with directory tokens
<?php
/*
VOD HLS streaming for BunnyCDN with Token authentication V2
NOTES:
> Credits to Dejan from BunnyCDN Support for the function for token authentication V2
> I've created this snippet to show how to use HLS streaming with the directory tokens.
This is a workaround which works by appending the token query string for every request to the TS segments (see JS below)
> Please add the appropriate CORS headers if enabled in the BunnyCDN panel (for HLS add 'm3u8, ts')
> Chromecast with HLS streaming and the usage of directory tokens will not.
If you really want to have it work with Chromecast, I suggest using MP4 instead and use the option "Optimize for video delivery"
in BunnyCDN's control panel. Especially if you have high bitrate videos or segments (>15 Mbps), the Chromecast (V3) is able to
handle MP4 much better than TS (hanging).
> Tested with VideoJS 7.5.5 (19-6-2020 working)
*/
function sign_bcdn_url($url, $securityKey, $expiration_time = 3600, $user_ip = NULL, $path_allowed = NULL, $countries_allowed = NULL, $countries_blocked = NULL)
{
if(!is_null($countries_allowed))
{
$url .= (parse_url($url, PHP_URL_QUERY) == "") ? "?" : "&";
$url .= "token_countries={$countries_allowed}";
}
if(!is_null($countries_blocked))
{
$url .= (parse_url($url, PHP_URL_QUERY) == "") ? "?" : "&";
$url .= "token_countries_blocked={$countries_blocked}";
}
$url_scheme = parse_url($url, PHP_URL_SCHEME);
$url_host = parse_url($url, PHP_URL_HOST);
$url_path = parse_url($url, PHP_URL_PATH);
$url_query = parse_url($url, PHP_URL_QUERY);
$parameters = array();
parse_str($url_query, $parameters);
// Check if the path is specified and ovewrite the default
$signature_path = $url_path;
if(!is_null($path_allowed))
{
$signature_path = $path_allowed;
$parameters["token_path"] = $signature_path;
}
// Expiration time
$expires = time() + $expiration_time;
// Construct the parameter data
ksort($parameters); // Sort alphabetically, very important
$parameter_data = "";
$parameter_data_url = "";
if(sizeof($parameters) > 0)
{
foreach ($parameters as $key => $value)
{
if(strlen($parameter_data) > 0)
$parameter_data .= "&";
$parameter_data_url .= "&";
$parameter_data .= "{$key}=" . $value;
$parameter_data_url .= "{$key}=" . $value;
}
}
// Generate the toke
$hashableBase = $securityKey.$signature_path.$expires.$parameter_data;
// If using IP validation
if(!is_null($user_ip))
{
$hashableBase .= $user_ip;
}
// Generate the token
$token = hash('sha256', $hashableBase, true);
$token = base64_encode($token);
$token = strtr($token, '+/', '-_');
$token = str_replace('=', '', $token);
//$url_path = str_replace("%2F", "/", urlencode($url_path)); // URL encode everything but slashes for the URL data
$query_string = "?token={$token}{$parameter_data_url}&expires={$expires}&token_ver=2";
return [$query_string, "{$url_scheme}://{$url_host}{$url_path}{$query_string}"];
}
list($query_string, $secure_url) = sign_bcdn_url("https://mydomain.b-cdn.net/test/bigbuck.m3u8", "a1b2c3d4-e5f6-g7h8-i9j1-k2l3m4n5o6p7", 3600, NULL, "/test/");
?>
<html>
<head>
<link href="https://vjs.zencdn.net/7.5.5/video-js.css" rel="stylesheet" type="text/css">
<link href="https://cdn.jsdelivr.net/npm/@silvermine/[email protected]/dist/css/quality-selector.css" rel="stylesheet" type="text/css">
<link href="https://cdn.jsdelivr.net/npm/@silvermine/[email protected]/dist/silvermine-videojs-chromecast.css" rel="stylesheet" type="text/css">
</head>
<body>
<video
id="MyPlayer"
class="video-js vjs-16-9 vjs-big-play-centered"
controls
preload="auto"
poster=""
data-title=""
data-poster=""
>
<source src="<?php echo $secure_url; ?>" type="application/x-mpegURL" label="" />
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a
web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank"
>supports HTML5 video</a
>
</p>
</video>
</body>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
<script src="https://vjs.zencdn.net/7.5.5/video.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@silvermine/[email protected]/dist/js/silvermine-videojs-quality-selector.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@silvermine/[email protected]/dist/silvermine-videojs-chromecast.js"></script>
<script>
// current source
csource = $('#MyPlayer source').attr('src')
titles = {
csource: $('#MyPlayer').attr('data-title')
}
// options for chromecast
options = {
controls: true,
techOrder: [ 'chromecast', 'html5' ],
chromecast: {
requestTitleFn: function(source) {
return titles[csource.url];
}
},
plugins: {
chromecast: {}
}
};
// append the token query string to the TS segments
videojs.Hls.xhr.beforeRequest = function(options) {
if(options.uri.includes('.ts')) options.uri += '<?php echo $query_string; ?>';
return options;
};
var vjplayer = videojs("MyPlayer", options);
</script>
</html>
@ChangC2
Copy link

ChangC2 commented Jul 17, 2023

Is this the code to play the video stream in bunny cdn?
I tested this code. worked perfectly.
Could you provide the php code to upload the live streaming from camera input?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment