├── Changelog.md ├── ElasticTranscoder.php └── README.md /Changelog.md: -------------------------------------------------------------------------------- 1 | Change Log 2 | ============================ 3 | ### Version 1.0.2 ### 4 | * Fixed incorrect signature bug for GET requests following a POST request 5 | * Updated `createPipeline()` to accept an array of options 6 | 7 | ### Version 1.0.1 ### 8 | * Fixed duplicate header bug for multiple calls 9 | 10 | Special thanks to exuvis for pointing this out. -------------------------------------------------------------------------------- /ElasticTranscoder.php: -------------------------------------------------------------------------------- 1 | array( 50 | 'Key' => $input['Key'], 51 | 'FrameRate' => (array_key_exists('FrameRate', $input)) ? $input['FrameRate'] : 'auto', 52 | 'Resolution' => (array_key_exists('Resolution', $input)) ? $input['Resolution'] : 'auto', 53 | 'AspectRatio' => (array_key_exists('AspectRatio', $input)) ? $input['AspectRatio'] : 'auto', 54 | 'Interlaced' => (array_key_exists('Interlaced', $input)) ? $input['Interlaced'] : 'auto', 55 | 'Container' => (array_key_exists('Container', $input)) ? $input['Container'] : 'auto' 56 | ) 57 | ); 58 | if ($outputKeyPrefix !== null) { 59 | $requestBody['OutputKeyPrefix'] = $outputKeyPrefix; 60 | } 61 | $requestBody['Outputs'] = array(); 62 | $num = sizeof($outputs); 63 | for ($i=0; $i<$num; $i++) { 64 | $requestBody['Outputs'][$i] = array( 65 | 'Key' => $outputs[$i]['Key'], 66 | 'ThumbnailPattern' => (array_key_exists('ThumbnailPattern', $outputs[$i])) ? $outputs[$i]['ThumbnailPattern'] : '', 67 | 'Rotate' => (array_key_exists('Rotate', $outputs[$i])) ? $outputs[$i]['Rotate'] : 'auto', 68 | 'PresetId' => $outputs[$i]['PresetId'] 69 | ); 70 | if (array_key_exists('SegmentDuration', $outputs[$i])) { 71 | $requestBody['Outputs'][$i]['SegmentDuration'] = $outputs[$i]['SegmentDuration']; 72 | } 73 | } 74 | if (!empty($playlists)) { 75 | $requestBody['Playlists'] = array( 76 | 'Format' => 'HLSv3', 77 | 'Name' => $playlists['Name'] 78 | ); 79 | if (array_key_exists('OutputKeys', $playlists)) { 80 | $requestBody['Playlists']['OutputKeys'] = $playlists['OutputKeys']; 81 | } 82 | } 83 | if (!empty($usermetadata)) { 84 | $requestBody['UserMetadata'] = $usermetadata; 85 | } 86 | $requestBody['PipelineId'] = $pipelineId; 87 | $requestBody = json_encode($requestBody); 88 | self::setRequestBody($requestBody); 89 | $result = self::sendRequest(); 90 | return $result; 91 | } 92 | 93 | /** 94 | * Get all jobs for a pipeline 95 | * 96 | * @param string $pipelineId pipeline ID 97 | * @param boolean $ascending results in ascending order 98 | * @return array | false 99 | */ 100 | public static function listJobsByPipeline($pipelineId, $ascending = true) { 101 | self::resetProps(); 102 | self::$HttpRequestMethod = 'GET'; 103 | if ($ascending) { 104 | $ascending = 'true'; 105 | } else { 106 | $ascending = 'false'; 107 | } 108 | self::$Uri = '/2012-09-25/jobsByPipeline/'.$pipelineId.'?Ascending='.$ascending; 109 | $result = self::sendRequest(); 110 | return $result; 111 | } 112 | 113 | /** 114 | * Get all jobs that have a given status 115 | * 116 | * @param string $Status job status 117 | * @return array | false 118 | */ 119 | public static function listJobsByStatus($status) { 120 | self::resetProps(); 121 | self::$HttpRequestMethod = 'GET'; 122 | self::$Uri = '/2012-09-25/jobsByStatus/'.$status; 123 | $result = self::sendRequest(); 124 | return $result; 125 | } 126 | 127 | /** 128 | * Get details of a job 129 | * 130 | * @param string $jobId job ID 131 | * @return array | false 132 | */ 133 | public static function readJob($jobId) { 134 | self::resetProps(); 135 | self::$HttpRequestMethod = 'GET'; 136 | self::$Uri = '/2012-09-25/jobs/'.$jobId; 137 | $result = self::sendRequest(); 138 | return $result; 139 | } 140 | 141 | /** 142 | * Cancel a job 143 | * 144 | * @param string $jobId job ID 145 | * @return array | false 146 | */ 147 | public static function cancelJob($jobId) { 148 | self::resetProps(); 149 | self::$HttpRequestMethod = 'DELETE'; 150 | self::$Uri = '/2012-09-25/jobs/'.$jobId; 151 | $result = self::sendRequest(); 152 | return $result; 153 | } 154 | 155 | /** 156 | * Create a new pipeline 157 | * 158 | * @param array $options settings 159 | * @return array | false 160 | */ 161 | public static function createPipeline($options = array()) { 162 | self::resetProps(); 163 | self::$HttpRequestMethod = 'POST'; 164 | self::$Uri = '/2012-09-25/pipelines'; 165 | $requestBody = array( 166 | 'Name' => $options['Name'], 167 | 'Role' => $options['Role'], 168 | 'InputBucket' => $options['InputBucket'], 169 | 'Notifications' => array( 170 | 'Progressing' => (array_key_exists('Notifications', $options) && array_key_exists('Progressing', $options['Notifications']['Progressing'])) ? $options['Notifications']['Progressing'] : '', 171 | 'Completed' => (array_key_exists('Notifications', $options) && array_key_exists('Completed', $options['Notifications']['Completed'])) ? $options['Notifications']['Completed'] : '', 172 | 'Warning' => (array_key_exists('Notifications', $options) && array_key_exists('Warning', $options['Notifications']['Warning'])) ? $options['Notifications']['Warning'] : '', 173 | 'Error' => (array_key_exists('Notifications', $options) && array_key_exists('Error', $options['Notifications']['Error'])) ? $options['Notifications']['Error'] : '' 174 | ) 175 | ); 176 | // Either OutputBucket or ContentConfig with ThumbnailConfig are required 177 | if (array_key_exists('OutputBucket', $options)) { 178 | $requestBody['OutputBucket'] = $options['OutputBucket']; 179 | } elseif (array_key_exists('ContentConfig', $options) && array_key_exists('ThumbnailConfig', $options)) { 180 | $requestBody['ContentConfig'] = $options['ContentConfig']; 181 | $requestBody['ThumbnailConfig'] = $options['ThumbnailConfig']; 182 | } else { 183 | self::setErrorMsg('Missing parameters. OutputBucket or ContentConfig with ThumbnailConfig are required.'); 184 | return false; 185 | } 186 | $requestBody = json_encode($requestBody); 187 | self::setRequestBody($requestBody); 188 | $result = self::sendRequest(); 189 | return $result; 190 | } 191 | 192 | /** 193 | * Get a list of pipelines associated with account 194 | * 195 | * @return array | false 196 | */ 197 | public static function listPipelines() { 198 | self::resetProps(); 199 | self::$HttpRequestMethod = 'GET'; 200 | self::$Uri = '/2012-09-25/pipelines'; 201 | $result = self::sendRequest(); 202 | return $result; 203 | } 204 | 205 | /** 206 | * Get info about a pipeline 207 | * 208 | * @param string $pipelineId pipeline ID 209 | * @return array | false 210 | */ 211 | public static function readPipeline($pipelineId) { 212 | self::resetProps(); 213 | self::$HttpRequestMethod = 'GET'; 214 | self::$Uri = '/2012-09-25/pipelines/'.$pipelineId; 215 | $result = self::sendRequest(); 216 | return $result; 217 | } 218 | 219 | /** 220 | * Update settings for a pipeline 221 | * 222 | * @param string $pipelineId pipeline ID 223 | * @param array $updates updates 224 | * @return array | false 225 | */ 226 | public static function updatePipeline($pipelineId, $updates) { 227 | self::resetProps(); 228 | self::$HttpRequestMethod = 'PUT'; 229 | self::$Uri = '/2012-09-25/pipelines/'.$pipelineId; 230 | $requestBody = json_encode($updates); 231 | self::setRequestBody($requestBody); 232 | $result = self::sendRequest(); 233 | return $result; 234 | } 235 | 236 | /** 237 | * Update pipeline status (active/paused) 238 | * 239 | * @param string $pipelineId pipeline ID 240 | * @param array $status new status 241 | * @return array | false 242 | */ 243 | public static function updatePipelineStatus($pipelineId, $status) { 244 | self::resetProps(); 245 | self::$HttpRequestMethod = 'POST'; 246 | self::$Uri = '/2012-09-25/pipelines/'.$pipelineId.'/status'; 247 | $requestBody = json_encode(array('Status' => $status)); 248 | self::setRequestBody($requestBody); 249 | $result = self::sendRequest(); 250 | return $result; 251 | } 252 | 253 | /** 254 | * Update pipeline notification settings 255 | * 256 | * @param string $pipelineId pipeline ID 257 | * @param array $notifications new notification settings 258 | * @return array | false 259 | */ 260 | public static function updatePipelineNotifications($pipelineId, $notifications = array()) { 261 | self::resetProps(); 262 | self::$HttpRequestMethod = 'POST'; 263 | self::$Uri = '/2012-09-25/pipelines/'.$pipelineId.'/notifications'; 264 | $requestBody = json_encode(array( 265 | 'Id' => $pipelineId, 266 | 'Notifications' => array( 267 | 'Progressing' => (array_key_exists('Progressing', $notifications)) ? $notifications['Progressing'] : '', 268 | 'Completed' => (array_key_exists('Completed', $notifications)) ? $notifications['Completed'] : '', 269 | 'Warning' => (array_key_exists('Warning', $notifications)) ? $notifications['Warning'] : '', 270 | 'Error' => (array_key_exists('Error', $notifications)) ? $notifications['Error'] : '' 271 | ) 272 | )); 273 | self::setRequestBody($requestBody); 274 | $result = self::sendRequest(); 275 | return $result; 276 | } 277 | 278 | /** 279 | * Delete a pipeline 280 | * 281 | * @param string $pipelineId pipeline ID 282 | * @return array | false 283 | */ 284 | public static function deletePipeline($pipelineId) { 285 | self::resetProps(); 286 | self::$HttpRequestMethod = 'DELETE'; 287 | self::$Uri = '/2012-09-25/pipelines/'.$pipelineId; 288 | $result = self::sendRequest(); 289 | return $result; 290 | } 291 | 292 | /** 293 | * Test the settings for a pipeline 294 | * 295 | * @param string $inputBucket input bucket ID 296 | * @param string $outBucket output bucket ID 297 | * @param string $role The IAM Amazon Resource Name (ARN) for role to use for transcoding jobs 298 | * @param array $topics The ARNs of one or more Amazon Simple Notification Service (Amazon SNS) topics 299 | * @return array | false 300 | */ 301 | public static function testRole($inputBucket, $outputBucket, $role, $topics = array()) { 302 | self::resetProps(); 303 | self::$HttpRequestMethod = 'POST'; 304 | self::$Uri = '/2012-09-25/roleTests'; 305 | $requestBody = json_encode(array( 306 | 'InputBucket' => $inputBucket, 307 | 'OutputBucket' => $outputBucket, 308 | 'Role' => $role, 309 | 'Topics' => $topics 310 | )); 311 | self::setRequestBody($requestBody); 312 | $result = self::sendRequest(); 313 | return $result; 314 | } 315 | 316 | /** 317 | * Create a new preset 318 | * 319 | * @param string $name name of the preset 320 | * @param string $description preset description 321 | * @param string $container container type for output file 322 | * @param array $audio audio settings 323 | * @param array $video video settings 324 | * @param array $thumbnails thumbnail settings 325 | * @return array | false 326 | */ 327 | public static function createPreset($name, $description, $container = 'mp4', $audio = array(), $video = array(), $thumbnails = array()) { 328 | self::resetProps(); 329 | self::$HttpRequestMethod = 'POST'; 330 | self::$Uri = '/2012-09-25/presets'; 331 | $requestBody = array( 332 | 'Name' => $name, 333 | 'Description' => $description, 334 | 'Container' => $container, 335 | 'Audio' => array( 336 | 'Codec' => (array_key_exists('Codec', $audio)) ? $audio['Codec'] : 'AAC', 337 | 'SampleRate' => (array_key_exists('SampleRate', $audio)) ? $audio['SampleRate'] : 'auto', 338 | 'BitRate' => (array_key_exists('BitRate', $audio)) ? $audio['BitRate'] : '64', 339 | 'Channels' => (array_key_exists('Channels', $audio)) ? $audio['Channels'] : 'auto' 340 | ), 341 | 'Video' => array( 342 | 'Codec' => (array_key_exists('Codec', $video)) ? $video['Codec'] : 'H.264', 343 | 'CodecOptions' => array( 344 | 'Profile' => (array_key_exists('CodecOptions', $video) && array_key_exists('Profile', $video['CodecOptions'])) ? $video['CodecOptions']['Profile'] : 'baseline', 345 | 'Level' => (array_key_exists('CodecOptions', $video) && array_key_exists('Level', $video['CodecOptions'])) ? $video['CodecOptions']['Level'] : '1', 346 | 'MaxReferenceFrames' => (array_key_exists('CodecOptions', $video) && array_key_exists('MaxReferenceFrames', $video['CodecOptions'])) ? $video['CodecOptions']['MaxReferenceFrames'] : '0', 347 | 'MaxBitRate' => (array_key_exists('CodecOptions', $video) && array_key_exists('MaxBitRate', $video['CodecOptions'])) ? $video['CodecOptions']['MaxBitRate'] : '16', 348 | 'BufferSize' => (array_key_exists('CodecOptions', $video) && array_key_exists('BufferSize', $video['CodecOptions'])) ? $video['CodecOptions']['BufferSize'] : '10' 349 | ), 350 | 'KeyframesMaxDist' => (array_key_exists('KeyframesMaxDist', $video)) ? $video['KeyframesMaxDist'] : '1', 351 | 'FixedGOP' => (array_key_exists('FixedGOP', $video)) ? $video['FixedGOP'] : 'true', 352 | 'BitRate' => (array_key_exists('BitRate', $video)) ? $video['BitRate'] : 'auto', 353 | 'FrameRate' => (array_key_exists('FrameRate', $video)) ? $video['FrameRate'] : 'auto', 354 | 'MaxFrameRate' => (array_key_exists('MaxFrameRate', $video)) ? $video['MaxFrameRate'] : '10', 355 | 'MaxWidth' => (array_key_exists('MaxWidth', $video)) ? $video['MaxWidth'] : 'auto', 356 | 'MaxHeight' => (array_key_exists('MaxHeight', $video)) ? $video['MaxHeight'] : 'auto', 357 | 'SizingPolicy' => (array_key_exists('SizingPolicy', $video)) ? $video['SizingPolicy'] : 'Fit', 358 | 'PaddingPolicy' => (array_key_exists('PaddingPolicy', $video)) ? $video['PaddingPolicy'] : 'Pad', 359 | 'DisplayAspectRatio' => (array_key_exists('DisplayAspectRatio', $video)) ? $video['DisplayAspectRatio'] : 'auto' 360 | ) 361 | ); 362 | if (isset($video['Resolution']) && isset($video['AspectRatio'])) { 363 | unset($requestBody['Video']['MaxWidth']); 364 | unset($requestBody['Video']['MaxHeight']); 365 | unset($requestBody['Video']['SizingPolicy']); 366 | unset($requestBody['Video']['PaddingPolicy']); 367 | unset($requestBody['Video']['DisplayAspectRatio']); 368 | $requestBody['Video']['Resolution'] = $video['Resolution']; 369 | $requestBody['Video']['AspectRatio'] = $video['AspectRatio']; 370 | } 371 | if (isset($video['Watermarks'])) { 372 | $requestBody['Video']['Watermarks'] = array( 373 | 'Id' => $video['Watermarks']['Id'], 374 | 'MaxWidth' => (array_key_exists('MaxWidth', $video['Watermarks'])) ? $video['Watermarks']['MaxWidth'] : '16', 375 | 'MaxHeight' => (array_key_exists('MaxHeight', $video['Watermarks'])) ? $video['Watermarks']['MaxHeight'] : '16', 376 | 'SizingPolicy' => (array_key_exists('SizingPolicy', $video['Watermarks'])) ? $video['Watermarks']['SizingPolicy'] : 'Fit', 377 | 'HorizontalAlign' => (array_key_exists('HorizontalAlign', $video['Watermarks'])) ? $video['Watermarks']['HorizontalAlign'] : 'Left', 378 | 'HorizontalOffset' => (array_key_exists('HorizontalOffset', $video['Watermarks'])) ? $video['Watermarks']['HorizontalOffset'] : '0%', 379 | 'VerticalAlign' => (array_key_exists('VerticalAlign', $video['Watermarks'])) ? $video['Watermarks']['VerticalAlign'] : 'Top', 380 | 'VerticalOffset' => (array_key_exists('VerticalOffset', $video['Watermarks'])) ? $video['Watermarks']['VerticalOffset'] : '0%', 381 | 'Opacity' => (array_key_exists('Opacity', $video['Watermarks'])) ? $video['Watermarks']['Opacity'] : '0', 382 | 'Target' => (array_key_exists('Target', $video['Target'])) ? $video['Watermarks']['Target'] : 'Content' 383 | ); 384 | } 385 | $requestBody['Thumbnails'] = array( 386 | 'Format' => (array_key_exists('Format', $thumbnails)) ? $thumbnails['Format'] : 'jpg', 387 | 'Interval' => (array_key_exists('Interval', $thumbnails)) ? $thumbnails['Interval'] : '120', 388 | 'MaxWidth' => (array_key_exists('MaxWidth', $thumbnails)) ? $thumbnails['MaxWidth'] : 'auto', 389 | 'MaxHeight' => (array_key_exists('MaxHeight', $thumbnails)) ? $thumbnails['MaxHeight'] : 'auto', 390 | 'SizingPolicy' => (array_key_exists('SizingPolicy', $thumbnails)) ? $thumbnails['SizingPolicy'] : 'Fit', 391 | 'PaddingPolicy' => (array_key_exists('PaddingPolicy', $thumbnails)) ? $thumbnails['PaddingPolicy'] : 'Pad' 392 | ); 393 | // Resolution and AspectRatio aren't recommended per AWS docs 394 | if (isset($thumbnails['Resolution']) && isset($thumbnails['AspectRatio'])) { 395 | unset($requestBody['Thumbnails']['MaxWidth']); 396 | unset($requestBody['Thumbnails']['MaxHeight']); 397 | unset($requestBody['Thumbnails']['SizingPolicy']); 398 | unset($requestBody['Thumbnails']['PaddingPolicy']); 399 | $requestBody['Thumbnails']['Resolution'] = $thumbnails['Resolution']; 400 | $requestBody['Thumbnails']['AspectRatio'] = $thumbnails['AspectRatio']; 401 | } 402 | $requestBody = json_encode($requestBody); 403 | self::setRequestBody($requestBody); 404 | $result = self::sendRequest(); 405 | return $result; 406 | } 407 | 408 | /** 409 | * Get a list of all presets 410 | * 411 | * @return array | false 412 | */ 413 | public static function listPresets() { 414 | self::resetProps(); 415 | self::$HttpRequestMethod = 'GET'; 416 | self::$Uri = '/2012-09-25/presets'; 417 | $result = self::sendRequest(); 418 | return $result; 419 | } 420 | 421 | /** 422 | * Get info about a preset 423 | * 424 | * @param string $presetId preset ID 425 | * @return array | false 426 | */ 427 | public static function readPreset($presetId) { 428 | self::resetProps(); 429 | self::$HttpRequestMethod = 'GET'; 430 | self::$Uri = '/2012-09-25/presets/'.$presetId; 431 | $result = self::sendRequest(); 432 | return $result; 433 | } 434 | 435 | /** 436 | * Delete a preset 437 | * 438 | * @param string $presetId preset ID 439 | * @return array | false 440 | */ 441 | public static function deletePreset($presetId) { 442 | self::resetProps(); 443 | self::$HttpRequestMethod = 'DELETE'; 444 | self::$Uri = '/2012-09-25/presets/'.$presetId; 445 | $result = self::sendRequest(); 446 | return $result; 447 | } 448 | 449 | /** 450 | * Set AWS credentials 451 | * 452 | * @param string $awsAccessKey AWS access key 453 | * @param string $awsPrivateKey AWS private key 454 | * @return void 455 | */ 456 | public static function setAuth($awsAccessKey, $awsPrivateKey) { 457 | self::$AwsAccessKey = $awsAccessKey; 458 | self::$AwsPrivateKey = $awsPrivateKey; 459 | } 460 | 461 | /** 462 | * Set Amazon region 463 | * 464 | * @param string $region AWS region 465 | * @return void 466 | */ 467 | public static function setRegion($region) { 468 | self::$Region = strtolower($region); 469 | } 470 | 471 | /** 472 | * Get the response HTTP status code 473 | * 474 | * @return integer 475 | */ 476 | public static function getStatusCode() { 477 | return self::$ResponseStatus; 478 | } 479 | 480 | /** 481 | * Get server response 482 | * 483 | * @return mixed 484 | */ 485 | public static function getResponse() { 486 | return self::$Response; 487 | } 488 | 489 | /** 490 | * Get error message after unsuccessful request 491 | * 492 | * @return string 493 | */ 494 | public static function getErrorMsg() { 495 | return self::$ErrorMsg; 496 | } 497 | 498 | /** 499 | * Set error message 500 | * 501 | * @param string $error error message 502 | * @return void 503 | */ 504 | private static function setErrorMsg($error) { 505 | self::$ErrorMsg = $error; 506 | } 507 | 508 | /** 509 | * Set request body 510 | * 511 | * @param mixed $body request body 512 | * @return void 513 | */ 514 | private static function setRequestBody($body) { 515 | self::$RequestBody = $body; 516 | } 517 | 518 | /** 519 | * Set request header 520 | * 521 | * @param string $key key 522 | * @param string $value value 523 | * @return void 524 | */ 525 | private static function setHeader($key, $value) { 526 | self::$Headers[$key] = $value; 527 | } 528 | 529 | /** 530 | * Reset property values 531 | * 532 | * @return void 533 | */ 534 | private static function resetProps() { 535 | self::$Headers = array(); 536 | self::$Date = new DateTime('UTC'); 537 | self::$RequestBody = null; 538 | self::$ResponseStatus = null; 539 | self::$Response = null; 540 | self::$ErrorMsg = null; 541 | } 542 | 543 | /** 544 | * Executes server request 545 | * 546 | * @return array | false 547 | */ 548 | private static function sendRequest() { 549 | $endpoint = 'elastictranscoder.'.self::$Region.'.amazonaws.com'; 550 | self::setHeader('Host', $endpoint); 551 | self::setHeader('x-amz-date', self::$Date->format('Ymd\THis\Z')); 552 | self::setAuthorizationHeader(); 553 | 554 | $curl = curl_init(); 555 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, self::$HttpRequestMethod); 556 | $url = 'https://'.$endpoint . self::$Uri; 557 | 558 | if (self::$HttpRequestMethod == 'POST' || self::$HttpRequestMethod == 'PUT') { 559 | self::setHeader('Content-Type', 'application/json'); 560 | self::setHeader('Content-Length', strlen(self::$RequestBody)); 561 | curl_setopt($curl, CURLOPT_POSTFIELDS, self::$RequestBody); 562 | } 563 | 564 | $headers = array(); 565 | foreach (self::$Headers as $header => $value) { 566 | if (strlen($value) > 0) 567 | $headers[] = $header.': '.$value; 568 | } 569 | 570 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 571 | curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); 572 | curl_setopt($curl, CURLOPT_HEADER, false); 573 | curl_setopt($curl, CURLOPT_URL, $url); 574 | 575 | $result = curl_exec($curl); 576 | 577 | if ($result === false) 578 | self::setErrorMsg('Curl failed. Error code: '.curl_errno($curl).' Message: '.curl_error($curl)); 579 | else 580 | self::$ResponseStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE); 581 | 582 | @curl_close($curl); 583 | 584 | if ($result === false) 585 | return false; 586 | 587 | $response = json_decode($result, true); 588 | self::$Response = $response; 589 | 590 | if (in_array(self::$ResponseStatus, array(200, 201, 202))) 591 | return $response; 592 | 593 | // Apparently "Message" is not always capitalized 594 | if (isset($response['message'])) 595 | self::setErrorMsg($response['message']); 596 | if (isset($response['Message'])) 597 | self::setErrorMsg($response['Message']); 598 | return false; 599 | } 600 | 601 | private static function hex16($val) { 602 | $unpack = unpack('H*', $val); 603 | return reset($unpack); 604 | } 605 | 606 | private static function parseCanonicalUri($url) { 607 | $parts = parse_url($url); 608 | $str = ''; 609 | if (isset($parts['scheme'])) { 610 | $str .= $parts['scheme']; 611 | } 612 | if (isset($parts['host'])) { 613 | $str .= $parts['host']; 614 | } 615 | if (isset($parts['path'])) { 616 | $str .= $parts['path']; 617 | } 618 | return $str; 619 | } 620 | 621 | private static function parseQueryString($url) { 622 | $pos = strpos($url, '?'); 623 | if (!$pos) 624 | return false; 625 | $url = substr($url, $pos + 1); 626 | if (empty($url)) 627 | return false; 628 | $pairs = explode('&', $url); 629 | $urlVars = array(); 630 | foreach ($pairs as $pair) { 631 | list($param, $value) = explode('=', $pair, 2); 632 | $urlVars[$param] = $value; 633 | } 634 | return $urlVars; 635 | } 636 | 637 | /** 638 | * Builds and sets authorization header 639 | * 640 | * @return array | false 641 | */ 642 | private static function setAuthorizationHeader() { 643 | $canonicalRequest = array(); 644 | $canonicalRequest[] = self::$HttpRequestMethod; 645 | $canonicalRequest[] = str_replace('%2F', '/', rawurlencode(self::parseCanonicalUri(self::$Uri))); 646 | 647 | // Format any query string 648 | $queryParams = self::parseQueryString(self::$Uri); 649 | if (!$queryParams) { 650 | $canonicalRequest[] = ''; 651 | } else { 652 | $qs = ''; 653 | ksort($queryParams); 654 | foreach($queryParams as $param => $value) { 655 | $qs .= rawurlencode($param) . '=' . rawurlencode($value) . '&'; 656 | } 657 | $qs = substr($qs, 0, -1); 658 | $canonicalRequest[] = $qs; 659 | } 660 | 661 | $headers = array(); 662 | $canonicalHeaders = array(); 663 | $signedHeaders = array(); 664 | 665 | foreach (self::$Headers as $key => $value) { 666 | $headers[strtolower($key)] = trim($value); 667 | } 668 | 669 | ksort($headers); 670 | 671 | foreach ($headers as $key => $value) { 672 | $signedHeaders[] = $key; 673 | $canonicalHeaders[] = $key . ':' . $value; 674 | } 675 | 676 | $signedHeaders = implode(';', $signedHeaders); 677 | 678 | $canonicalRequest[] = implode("\n", $canonicalHeaders); 679 | $canonicalRequest[] = ''; 680 | $canonicalRequest[] = $signedHeaders; 681 | $canonicalRequest[] = self::hex16(hash('sha256', self::$RequestBody, true)); 682 | $canonicalRequest = implode("\n", $canonicalRequest); 683 | 684 | $stringToSign = array(); 685 | $stringToSign[] = 'AWS4-HMAC-SHA256'; 686 | $stringToSign[] = self::$Date->format('Ymd\THis\Z'); 687 | 688 | $credentialScope = array(self::$Date->format('Ymd')); 689 | $credentialScope[] = self::$Region; 690 | $credentialScope[] = 'elastictranscoder'; 691 | $credentialScope[] = 'aws4_request'; 692 | $credentialScope = implode('/', $credentialScope); 693 | 694 | $stringToSign[] = $credentialScope; 695 | $stringToSign[] = self::hex16(hash('sha256', $canonicalRequest, true)); 696 | $stringToSign = implode("\n", $stringToSign); 697 | 698 | $kSecret = 'AWS4'.self::$AwsPrivateKey; 699 | $kDate = hash_hmac('sha256', self::$Date->format('Ymd'), $kSecret, true); 700 | $kRegion = hash_hmac('sha256', self::$Region, $kDate, true); 701 | $kService = hash_hmac('sha256', 'elastictranscoder', $kRegion, true); 702 | $kSigning = hash_hmac('sha256', 'aws4_request', $kService, true); 703 | $signature = hash_hmac('sha256', $stringToSign, $kSigning, true); 704 | 705 | $auth = 'AWS4-HMAC-SHA256 Credential='.self::$AwsAccessKey.'/'.$credentialScope; 706 | $auth .= ',SignedHeaders='.$signedHeaders; 707 | $auth .= ',Signature='.self::hex16($signature); 708 | self::setHeader('Authorization', $auth); 709 | } 710 | 711 | } 712 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Elastic Transcoder PHP Class 2 | ==================== 3 | 4 | PHP class for interacting with Amazon Elastic Transcoder that does not require PEAR. 5 | 6 | #### Usage ### 7 | 8 | Object-oriented method: 9 | 10 | ```php 11 | $et = new AWS_ET($awsAccessKey, $awsSecretKey, $awsRegion); 12 | ``` 13 | 14 | Statically: 15 | 16 | ```php 17 | AWS_ET::setAuth($awsAccessKey, $awsSecretKey, $awsRegion); 18 | ``` 19 | 20 | Note: us-east-1 is the default AWS region setting. The third parameter is optional for us-east-1 users. 21 | 22 | #### Job Operations #### 23 | 24 | Creating a transcoding job: 25 | 26 | ```php 27 | $pipelineId = 'pipelineId'; 28 | $input = array('Key' => 'inputFile'); 29 | $output = array( 30 | 'Key' => 'outputFile.mp4', 31 | 'PresetId' => 'presetId' 32 | ); 33 | 34 | $result = AWS_ET::createJob($input, array($output), $pipelineId); 35 | 36 | if (!$result) { 37 | echo AWS_ET::getErrorMsg(); 38 | } else { 39 | echo 'New job ID: ' . $result['Job']['Id']; 40 | } 41 | ``` 42 | 43 | List jobs by pipeline: 44 | 45 | ```php 46 | AWS_ET::listJobsByPipeline( string $pipelineId [, boolean $ascending = true ] ); 47 | ``` 48 | 49 | List jobs by status: 50 | 51 | ```php 52 | AWS_ET::listJobsByStatus( string $status ); 53 | ``` 54 | 55 | Get job info: 56 | 57 | ```php 58 | AWS_ET::readJob( string $jobId ); 59 | ``` 60 | 61 | Cancel a job: 62 | 63 | ```php 64 | AWS_ET::cancelJob( string $jobId ); 65 | ``` 66 | 67 | #### Pipeline Operations #### 68 | 69 | Create a new pipeline: 70 | 71 | ```php 72 | AWS_ET::createPipeline( string $name, string $inputBucket, string $outputBucket, string $role [, array $notifications ] ); 73 | ``` 74 | 75 | Get a list pipelines: 76 | 77 | ```php 78 | AWS_ET::listPipelines(); 79 | ``` 80 | 81 | Get info about a pipeline: 82 | 83 | ```php 84 | AWS_ET::readPipeline( string $pipelineId ); 85 | ``` 86 | 87 | Update pipeline settings: 88 | 89 | ```php 90 | AWS_ET::updatePipeline( string $pipelineId, array $updates ); 91 | ``` 92 | 93 | Change the status of a pipeline (active/paused): 94 | 95 | ```php 96 | AWS_ET::updatePipelineStatus( string $pipelineId, string $status ); 97 | ``` 98 | 99 | Update pipeline notification settings: 100 | 101 | ```php 102 | AWS_ET::updatePipelineNotifications( string $pipelineId [, array $notifications ] ); 103 | ``` 104 | 105 | Delete a pipeline: 106 | 107 | ```php 108 | AWS_ET::deletePipeline( string $pipelineId ); 109 | ``` 110 | 111 | Test the settings for a pipeline: 112 | 113 | ```php 114 | AWS_ET::testRole( string $inputBucket, string $outputBucket, string $role, array $topics ); 115 | ``` 116 | 117 | #### Preset Operations #### 118 | 119 | Create a preset: 120 | 121 | ```php 122 | AWS_ET::createPreset( array $options ); 123 | ``` 124 | 125 | List all presets: 126 | 127 | ```php 128 | AWS_ET::listPresets(); 129 | ``` 130 | 131 | Get info about a preset: 132 | 133 | ```php 134 | AWS_ET::readPreset( string $presetId ); 135 | ``` 136 | 137 | Delete a preset: 138 | 139 | ```php 140 | AWS_ET::deletePreset( string $presetId ); 141 | ``` 142 | 143 | #### Misc. #### 144 | 145 | Set AWS authentication credentials: 146 | 147 | ```php 148 | AWS_ET::setAuth( string $awsAccessKey, string $awsSecretKey ); 149 | ``` 150 | 151 | Set AWS region: 152 | 153 | ```php 154 | AWS_ET::setRegion( string $region = 'us-east-1' ); 155 | ``` 156 | 157 | Get HTTP status code of server response: 158 | 159 | ```php 160 | AWS_ET::getStatusCode(); 161 | ``` 162 | 163 | Get server response: 164 | 165 | ```php 166 | AWS_ET::getResponse(); 167 | ``` 168 | 169 | Get error message, if any: 170 | 171 | ```php 172 | AWS_ET::getErrorMsg(); 173 | ``` 174 | 175 |
176 | More Information:
177 | Getting Started with Elastic Transcoder 178 | 179 | #### License #### 180 | 181 | Released under the MIT license. 182 | 183 | [![githalytics.com alpha](https://cruel-carlota.pagodabox.com/429c074cf07de7bee3ca6af902cd8141 "githalytics.com")](http://githalytics.com/LPology/ElasticTranscoderPHP) --------------------------------------------------------------------------------