Skip to content

Instantly share code, notes, and snippets.

@jbboehr
Last active September 26, 2016 20:53
Show Gist options
  • Save jbboehr/1a3a46e3c670bfea7ad11070be5fafb3 to your computer and use it in GitHub Desktop.
Save jbboehr/1a3a46e3c670bfea7ad11070be5fafb3 to your computer and use it in GitHub Desktop.
<?php
// @codingStandardsIgnoreStart
$help = array(
'-i, --input' => 'Input file',
'--endpoint' => 'API endpoint',
'--token' => 'Access token',
'--chunk-size' => 'Chunk size',
'--client' => "Client ID",
'--key' => "Client key",
'--secret' => 'Client Secret',
'--no-ssl-verify' => "Do not verify SSL peer"
);
$options = getopt('i:', array(
'input:', 'chunk-size:', 'token:', 'endpoint:', 'client:', 'no-ssl-verify', 'key:', 'secret:'
));
if( empty($options) || isset($options['help']) || isset($options['h']) ) {
// Show usage
echo $argv[0], ' [OPTIONS]', PHP_EOL;
foreach( $help as $k => $v ) {
printf("\t%-16s%-32s\n", $k, $v);
}
exit(0);
}
if( isset($options['i']) ) {
$options['input'] = $options['i'];
unset($options['i']);
}
$options = array_merge(array(
'client' => null,
'key' => null,
'secret' => null,
'token' => null,
// Minimum chunk size may be changed to 5MB in the future
'chunk-size' => 5 * 1024 * 1024,
'endpoint' => 'https://api.vid.me',
'input' => null,
), $options);
$endpoint = rtrim($options['endpoint'], '/') . '/';
$file = $options['input'];
$token = $options['token'];
$chunkSize = $options['chunk-size'];
$client = $options['client'];
$key = $options['key'];
$secret = $options['secret'];
$shouldSslVerify = empty($options['no-ssl-verify']);
if( !$endpoint || !$file || !file_exists($file) ) {
echo "need endpoint and valid file\n";
exit(1);
}
// Check endpoint
if( false === strpos($endpoint, 'http') ) {
if( false !== strpos($endpoint, 'vid.me') ) {
$endpoint = 'https://' . $endpoint;
} else {
$endpoint = 'http://' . $endpoint;
}
}
$endpoint = rtrim($endpoint, '/') . '/';
function makeHeaders($headers = array(), $method = 'GET', $uri = null) {
global $token, $client, $key, $secret;
if( $token ) {
$headers[] = 'AccessToken: ' . $token;
}
if( $method && $uri && $key && $secret ) {
$uri = '/' . ltrim($uri, '/');
$now = time();
$ttl = 600;
$expires = $now + $ttl;
$stringToSign = $method . ' ' . $uri;
$stringToSign .= (false === strpos($uri, '?') ? '?' : '&');
$stringToSign .= 'expires=' . urlencode($expires);
$stringToSign .= '&';
$stringToSign .= 'secret=' . urlencode($secret);
$signature = hash('sha256', $stringToSign);
$headers[] = 'X-Vidme-Date: ' . gmdate('D, d M Y H:i:s T', $now);
$headers[] = 'X-Vidme-TTL: ' . $ttl;
$headers[] = 'Authorization: VIDME1-SHA256 ' . base64_encode($key . ':' . $signature);
} else if( $client ) {
$headers[] = 'Authorization: Basic ' . base64_encode($client . ':');
}
$headers[] = 'Host: api.vid.me';
return $headers;
}
function dump_request($uri, $headers) {
echo "Request >>>\n";
echo 'POST', ' ', $uri, "\n";
echo join("\n", $headers), "\n";
echo "<<<\n\n";
}
function dump_response($info, $response) {
echo "Response >>>\n";
echo 'HTTP/1.1 ', $info['http_code'], "\n\n";
echo $response;
echo "<<<\n\n\n";
}
function initCurl($method, $headers = array()) {
global $endpoint, $shouldSslVerify;
$ch = curl_init($endpoint . $method);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
if( $shouldSslVerify ) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
}
$headers = makeHeaders($headers, 'POST', $method);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
dump_request($endpoint . $method, $headers);
return $ch;
}
// Utility functions
function checkAuthToken()
{
$ch = initCurl('auth/check');
$response = curl_exec($ch);
$info = curl_getinfo($ch);
dump_response($info, $response);
if( $info['http_code'] != 200 ) {
exit(1);
}
$responseData = json_decode($response);
if( !$responseData->status ) {
exit(1);
}
return $responseData;
}
function requestIdentity($filename)
{
$ch = initCurl('video/request?no_ssl=1');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
'filename' => basename($filename),
)));
$response = curl_exec($ch);
$info = curl_getinfo($ch);
dump_response($info, $response);
if( $info['http_code'] != 200 ) {
exit(1);
}
$responseData = json_decode($response);
if( !$responseData->status ) {
exit(1);
}
return $responseData;
}
function requestUpload($code, $size)
{
$ch = initCurl('upload/create?no_ssl=1');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
'size' => $size,
'code' => $code,
)));
$response = curl_exec($ch);
$info = curl_getinfo($ch);
dump_response($info, $response);
if( $info['http_code'] != 200 ) {
exit(1);
}
$responseData = json_decode($response);
if( !$responseData->status ) {
exit(1);
}
return $responseData;
}
function uploadAllChunks($filename, $uploadId, $videoCode)
{
global $chunkSize;
$size = filesize($filename);
$offset = 0;
do {
uploadChunk($filename, $uploadId, $videoCode, $offset, $chunkSize);
$offset += $chunkSize;
} while( $offset < $size );
}
function uploadChunk($filename, $uploadId, $videoCode, $offset, $length)
{
global $endpoint, $token;
$size = filesize($filename);
$end = $offset + $length - 1;
if( $end >= $size ) {
$end = $size - 1;
$length = $end - $offset + 1;
}
// Read specified chunk
$fh = fopen($filename, 'rb');
fseek($fh, $offset);
$data = fread($fh, $length);
fclose($fh);
// sanity
assert(strlen($data) == $length);
// send request
$uri = 'upload/chunk?' . http_build_query(array(
'upload' => $uploadId,
'code' => $videoCode,
'no_ssl' => 1,
));
$headers = makeHeaders(array(
sprintf('Content-Length: %d', $length),
sprintf('Content-Range: bytes %d-%d/%d', $offset, $end, $size),
), 'POST', $uri);
//dump_request($uri, $headers);
$ch = initCurl($uri, $headers);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
dump_response($info, $response);
if( $info['http_code'] !== 200 ) {
echo $info['http_code'], ' ', $response, PHP_EOL;
exit(1);
}
var_dump($response);
}
// Check token
if( $token ) {
checkAuthToken();
}
// Request video
$data = requestIdentity($file);
printf("Video %d %s\n", $data->video->video_id, $data->video->url);
// Request upload
$data2 = requestUpload($data->video->url, filesize($file));
printf("Upload %d\n", $data2->upload->upload_id);
// Send data
uploadAllChunks($file, $data2->upload->upload_id, $data->video->url);
// @codingStandardsIgnoreEnd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment