From 041b68f0c407a75b1b0c1f1871891f750f4bc87b Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 15 Mar 2021 19:44:29 -0700 Subject: [PATCH] [1.0] Introducing the "Simple Usage" API (#14) * wip * wip * wip * wip * Update CHANGELOG.md --- .github/workflows/{test.yml => run-tests.yml} | 34 ++-- CHANGELOG.md | 2 +- README.md | 11 +- config/config.php | 172 +---------------- src/Contracts/Converter.php | 38 ++++ src/Converters/MediaConvert.php | 96 ++++++++++ src/Facades/MediaConvert.php | 4 + .../DefaultMediaConvertJobSettings.php | 178 ++++++++++++++++++ tests/MediaConverterTest.php | 58 +++++- tests/MediaConverterTestCase.php | 13 +- 10 files changed, 406 insertions(+), 200 deletions(-) rename .github/workflows/{test.yml => run-tests.yml} (68%) create mode 100644 src/Helpers/DefaultMediaConvertJobSettings.php diff --git a/.github/workflows/test.yml b/.github/workflows/run-tests.yml similarity index 68% rename from .github/workflows/test.yml rename to .github/workflows/run-tests.yml index 35f09ab..dfb6b63 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/run-tests.yml @@ -1,16 +1,19 @@ -name: Test +name: Run Tests -on: [push] +on: + push: + pull_request: jobs: - test: + run-tests: runs-on: ubuntu-latest strategy: fail-fast: false matrix: - php: [7.3, 7.4, 8.0] + php: [7.4, 8.0] laravel: [7.*, 8.*] - dependency-version: [prefer-lowest, prefer-stable] + dependency-version: [prefer-stable] +# dependency-version: [prefer-lowest, prefer-stable] include: - laravel: 8.* testbench: 6.* @@ -21,20 +24,13 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} extensions: mbstring, intl, pdo, pdo_sqlite, sqlite, curl - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_DEFAULT_REGION: 'us-east-1' - AWS_MEDIACONVERT_ACCOUNT_URL: ${{ secrets.AWS_MEDIACONVERT_ACCOUNT_URL }} - AWS_IAM_ARN: ${{ secrets.AWS_IAM_ARN }} - AWS_QUEUE_ARN: ${{ secrets.AWS_QUEUE_ARN }} - name: Cache dependencies uses: actions/cache@v1 @@ -44,11 +40,15 @@ jobs: - name: Install dependencies run: | - composer require "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update + composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest - - name: Create .env file - run: touch .env # this can be an empty file, just need the test to pass. GitHub Actions uses GitHub Secrets - - name: Execute tests run: vendor/bin/pest + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: 'us-east-1' + AWS_MEDIACONVERT_ACCOUNT_URL: ${{ secrets.AWS_MEDIACONVERT_ACCOUNT_URL }} + AWS_IAM_ARN: ${{ secrets.AWS_IAM_ARN }} + AWS_QUEUE_ARN: ${{ secrets.AWS_QUEUE_ARN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index a5c6f5b..9ffca29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,6 @@ All notable changes to `laravel-media-converter` will be documented in this file. -## 1.0.0 - 202X-XX-XX +## 1.0.0 - 2021-03-15 - initial release diff --git a/README.md b/README.md index ee68cee..8a51174 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,20 @@ This is a wrapper package for AWS MediaConvert. Additional drivers may be added. use Meema\MediaConverter\Facades\MediaConvert; use Meema\MediaConverter\Jobs\CreateVideoConversion; -// run any of the following MediaConvert methods: +# simple usage +MediaConvert::path('video.mkv') // the s3 path to the file inside the bucket defined in your config (filesystems.disks.s3.bucket) + ->optimizeForWeb() // will generate an optmized MP4 for you + ->withThumbnails(int $framerateNumerator, int $framerateDenominator, int $maxCaptures, $width = null, $nameModifier = null, $imageQuality = 80) // will generate thumbnails from the video for you, e.g. poster images + ->saveTo('my-optimized-video.mp4'); // output file name + ->createJob(); + +# advanced usage $result = MediaConvert::cancelJob(string $id); $result = MediaConvert::createJob(array $settings, array $metaData = [], int $priority = 0); $result = MediaConvert::getJob(string $id); $result = MediaConvert::listJobs(array $options); -// you may also dispatch a job to convert a video +# you may also dispatch a job to convert a video dispatch(new CreateVideoConversion($jobSettings, $mediaId)); // $mediaId is optional & refers to the relating model's id ``` diff --git a/config/config.php b/config/config.php index 20304af..ad96069 100644 --- a/config/config.php +++ b/config/config.php @@ -65,175 +65,5 @@ */ 'statuses_to_track' => ['complete', 'error', 'new_warning', 'progressing', 'status_update', 'input_information', 'queue_hop'], - 'settings' => [ - 'OutputGroups' => [ - // thumbnail generation - [ - 'CustomName' => 'Thumbnails', - 'Name' => 'File Group', - 'Outputs' => [ - [ - 'ContainerSettings' => [ - 'Container' => 'RAW', - ], - 'VideoDescription' => [ - 'ScalingBehavior' => 'DEFAULT', - 'TimecodeInsertion' => 'DISABLED', - 'AntiAlias' => 'ENABLED', - 'Sharpness' => 50, - 'CodecSettings' => [ - 'Codec' => 'FRAME_CAPTURE', - 'FrameCaptureSettings' => [ - 'FramerateNumerator' => null, // to be set dynamically - 'FramerateDenominator' => null, // to be set dynamically - 'MaxCaptures' => null, // to be set dynamically - 'Quality' => 80, - ], - ], - 'AfdSignaling' => 'NONE', - 'DropFrameTimecode' => 'ENABLED', - 'RespondToAfd' => 'NONE', - 'ColorMetadata' => 'INSERT', - 'Width' => null, // to be set dynamically - ], - 'NameModifier' => '.$w$x$h$', // e.g. moderation-test-video.240x136.0000098.jpg - ], - ], - 'OutputGroupSettings' => [ - 'Type' => 'FILE_GROUP_SETTINGS', - 'FileGroupSettings' => [ - 'Destination' => null, // to be set dynamically - 'DestinationSettings' => [ - 'S3Settings' => [ - 'AccessControl' => [ - 'CannedAcl' => 'PUBLIC_READ', - ], - ], - ], - ], - ], - ], - - // optimize-mp4 output setting - [ - 'CustomName' => 'MP4', - 'Name' => 'File Group', - 'Outputs' => [ - [ - 'ContainerSettings' => [ - 'Container' => 'MP4', - 'Mp4Settings' => [ - 'CslgAtom' => 'INCLUDE', - 'FreeSpaceBox' => 'EXCLUDE', - 'MoovPlacement' => 'PROGRESSIVE_DOWNLOAD', - ], - ], - 'VideoDescription' => [ - 'ScalingBehavior' => 'DEFAULT', - 'TimecodeInsertion' => 'DISABLED', - 'AntiAlias' => 'ENABLED', - 'Sharpness' => 50, - 'CodecSettings' => [ - 'Codec' => 'H_264', - 'H264Settings' => [ - 'InterlaceMode' => 'PROGRESSIVE', - 'NumberReferenceFrames' => 3, - 'Syntax' => 'DEFAULT', - 'Softness' => 0, - 'GopClosedCadence' => 1, - 'GopSize' => 90, - 'Slices' => 1, - 'GopBReference' => 'DISABLED', - 'MaxBitrate' => 8000000, - 'SlowPal' => 'DISABLED', - 'SpatialAdaptiveQuantization' => 'ENABLED', - 'TemporalAdaptiveQuantization' => 'ENABLED', - 'FlickerAdaptiveQuantization' => 'DISABLED', - 'EntropyEncoding' => 'CABAC', - 'FramerateControl' => 'INITIALIZE_FROM_SOURCE', - 'RateControlMode' => 'QVBR', - 'QvbrSettings' => [ - 'QvbrQualityLevel' => 7, - 'QvbrQualityLevelFineTune' => 0, - ], - 'CodecProfile' => 'MAIN', - 'Telecine' => 'NONE', - 'MinIInterval' => 0, - 'AdaptiveQuantization' => 'HIGH', - 'CodecLevel' => 'AUTO', - 'FieldEncoding' => 'PAFF', - 'SceneChangeDetect' => 'ENABLED', - 'QualityTuningLevel' => 'SINGLE_PASS', - 'FramerateConversionAlgorithm' => 'DUPLICATE_DROP', - 'UnregisteredSeiTimecode' => 'DISABLED', - 'GopSizeUnits' => 'FRAMES', - 'ParControl' => 'INITIALIZE_FROM_SOURCE', - 'NumberBFramesBetweenReferenceFrames' => 2, - 'RepeatPps' => 'DISABLED', - ], - ], - 'AfdSignaling' => 'NONE', - 'DropFrameTimecode' => 'ENABLED', - 'RespondToAfd' => 'NONE', - 'ColorMetadata' => 'INSERT', - ], - 'AudioDescriptions' => [ - [ - 'AudioTypeControl' => 'FOLLOW_INPUT', - 'CodecSettings' => [ - 'Codec' => 'AAC', - 'AacSettings' => [ - 'AudioDescriptionBroadcasterMix' => 'NORMAL', - 'Bitrate' => 96000, - 'RateControlMode' => 'CBR', - 'CodecProfile' => 'LC', - 'CodingMode' => 'CODING_MODE_2_0', - 'RawFormat' => 'NONE', - 'SampleRate' => 48000, - 'Specification' => 'MPEG4', - ], - ], - 'LanguageCodeControl' => 'FOLLOW_INPUT', - ], - ], - ], - ], - 'OutputGroupSettings' => [ - 'Type' => 'FILE_GROUP_SETTINGS', - 'FileGroupSettings' => [ - 'Destination' => null, // to be set dynamically - 'DestinationSettings' => [ - 'S3Settings' => [ - 'AccessControl' => [ - 'CannedAcl' => 'PUBLIC_READ', - ], - ], - ], - ], - ], - ], - ], - 'AdAvailOffset' => 0, - 'Inputs' => [ - [ - 'AudioSelectors' => [ - 'Audio Selector 1' => [ - 'Offset' => 0, - 'DefaultSelection' => 'DEFAULT', - 'ProgramSelection' => 1, - ], - ], - 'VideoSelector' => [ - 'ColorSpace' => 'FOLLOW', - ], - 'FilterEnable' => 'AUTO', - 'PsiControl' => 'USE_PSI', - 'FilterStrength' => 0, - 'DeblockFilter' => 'DISABLED', - 'DenoiseFilter' => 'DISABLED', - 'TimecodeSource' => 'EMBEDDED', - 'FileInput' => null, // to be set dynamically - ], - ], - ], + 'job_settings' => \Meema\MediaConverter\Helpers\DefaultMediaConvertJobSettings::class, ]; diff --git a/src/Contracts/Converter.php b/src/Contracts/Converter.php index 4b7b9b6..db9f014 100644 --- a/src/Contracts/Converter.php +++ b/src/Contracts/Converter.php @@ -4,6 +4,44 @@ interface Converter { + /** + * Sets the path of the file input. + * + * @param string $path + * @param string|null $bucket + * @return \Meema\MediaConverter\Converters\MediaConvert + */ + public function path(string $path, $bucket = null); + + /** + * Generates a web optimized MP4. + * + * @return \Meema\MediaConverter\Converters\MediaConvert + */ + public function optimizeForWeb(); + + /** + * Sets the settings required to generate the proper amount of thumbnails. + * + * @param int $framerateNumerator + * @param int $framerateDenominator + * @param int $maxCaptures + * @param int|null $width + * @param string|null $nameModifier + * @param int $imageQuality + * @return \Meema\MediaConverter\Converters\MediaConvert + */ + public function withThumbnails(int $framerateNumerator, int $framerateDenominator, int $maxCaptures, $width = null, $nameModifier = null, $imageQuality = 80); + + /** + * Sets the path & executes the job. + * + * @param string $s3Path + * @param string|null $s3bucket + * @return \Aws\Result + */ + public function saveTo(string $s3Path, $s3bucket = null); + /** * Cancels an active job. * diff --git a/src/Converters/MediaConvert.php b/src/Converters/MediaConvert.php index c0de9ad..7c9e026 100644 --- a/src/Converters/MediaConvert.php +++ b/src/Converters/MediaConvert.php @@ -15,6 +15,13 @@ class MediaConvert implements Converter */ protected $client; + /** + * The MediaConvert job's settings. + * + * @var array + */ + public array $jobSettings; + /** * Construct converter. * @@ -24,6 +31,8 @@ public function __construct(MediaConvertClient $client) { $config = config('media-converter'); + $this->jobSettings = (new $config['job_settings'])::get(); + $this->client = new MediaConvertClient([ 'version' => $config['version'], 'region' => $config['region'], @@ -42,6 +51,80 @@ public function getClient(): MediaConvertClient return $this->client; } + /** + * Sets the path of the file input. + * + * @param string $path - represents the S3 path, e.g path/to/file.mp4 + * @param string|null $bucket - reference to the S3 Bucket name. Defaults to config value. + * @return \Meema\MediaConverter\Converters\MediaConvert + */ + public function path(string $path, $bucket = null): MediaConvert + { + $this->setFileInput($path, $bucket); + + return $this; + } + + /** + * Generates a web optimized MP4. + * + * @return \Meema\MediaConverter\Converters\MediaConvert + */ + public function optimizeForWeb(): MediaConvert + { + // At the moment, we can simply return $this, because this method is simply used for readability purposes. + // The "default job" has all the proper settings already to generate a web optimized mp4. + return $this; + } + + /** + * Sets the settings required to generate the proper amount of thumbnails. + * + * @param int $framerateNumerator + * @param int $framerateDenominator + * @param int $maxCaptures + * @param int|null $width + * @param string|null $nameModifier + * @param int $imageQuality + * @return \Meema\MediaConverter\Converters\MediaConvert + */ + public function withThumbnails(int $framerateNumerator, int $framerateDenominator, int $maxCaptures, $width = null, $nameModifier = null, $imageQuality = 80): MediaConvert + { + $this->jobSettings['OutputGroups'][0]['Outputs'][0]['VideoDescription']['CodecSettings']['FrameCaptureSettings'] = [ + 'FramerateNumerator' => $framerateNumerator, + 'FramerateDenominator' => $framerateDenominator, + 'MaxCaptures' => $maxCaptures, + 'Quality' => $imageQuality, + ]; + + if ($width) { + $this->jobSettings['OutputGroups'][0]['Outputs'][0]['VideoDescription']['Width'] = $width; + } + + if ($nameModifier) { + $this->jobSettings['OutputGroups'][0]['Outputs'][0]['NameModifier'] = $nameModifier; + } + + return $this; + } + + /** + * Sets the S3 path & executes the job. + * + * @param string $s3Path + * @param string|null $s3bucket + * @return \Meema\MediaConverter\Converters\MediaConvert + */ + public function saveTo(string $s3Path, $s3bucket = null): MediaConvert + { + $destination = 's3://'.($s3bucket ?? config('filesystems.disks.s3.bucket')); + + $this->jobSettings['OutputGroups'][0]['OutputGroupSettings']['FileGroupSettings']['Destination'] = $destination.'/thumbnails/'; + $this->jobSettings['OutputGroups'][1]['OutputGroupSettings']['FileGroupSettings']['Destination'] = $destination.'/mp4/'; + + return $this; + } + /** * Cancels an active job. * @@ -110,4 +193,17 @@ protected function getStatusUpdateInterval(): string return 'SECONDS_60'; // gracefully default to this value, in case the config value is missing or incorrect } + + /** + * Sets the S3 input file path. + * + * @param string $path + * @param string|null $bucket + */ + protected function setFileInput(string $path, $bucket = null) + { + $fileInput = 's3://'.($bucket ?? config('filesystems.disks.s3.bucket')).'/'.$path; + + $this->jobSettings['Inputs'][0]['FileInput'] = $fileInput; + } } diff --git a/src/Facades/MediaConvert.php b/src/Facades/MediaConvert.php index 0cbe8ab..7273cd3 100644 --- a/src/Facades/MediaConvert.php +++ b/src/Facades/MediaConvert.php @@ -6,6 +6,10 @@ /** * @method static \Aws\MediaConvert\MediaConvertClient getClient() + * @method static \Meema\MediaConverter\Converters\MediaConvert path(string $s3Path, $s3bucket = null) + * @method static \Meema\MediaConverter\Converters\MediaConvert optimizeForWeb() + * @method static \Meema\MediaConverter\Converters\MediaConvert withThumbnails(int $framerateNumerator, int $framerateDenominator, int $maxCaptures, $width = null, $nameModifier = null, $imageQuality = 80) + * @method static \Aws\Result saveTo(string $s3Path, $s3bucket = null) * @method static \Aws\Result cancelJob(string $id) * @method static \Aws\Result createJob(array $settings, array $metaData = [], int $priority = 0) * @method static \Aws\Result getJob(string $id) diff --git a/src/Helpers/DefaultMediaConvertJobSettings.php b/src/Helpers/DefaultMediaConvertJobSettings.php new file mode 100644 index 0000000..b61d16e --- /dev/null +++ b/src/Helpers/DefaultMediaConvertJobSettings.php @@ -0,0 +1,178 @@ + [ + [ + 'CustomName' => 'Thumbnails', + 'Name' => 'File Group', + 'Outputs' => [ + [ + 'ContainerSettings' => [ + 'Container' => 'RAW', + ], + 'VideoDescription' => [ + 'ScalingBehavior' => 'DEFAULT', + 'TimecodeInsertion' => 'DISABLED', + 'AntiAlias' => 'ENABLED', + 'Sharpness' => 50, + 'CodecSettings' => [ + 'Codec' => 'FRAME_CAPTURE', + 'FrameCaptureSettings' => [ + 'FramerateNumerator' => null, // to be set dynamically + 'FramerateDenominator' => null, // to be set dynamically + 'MaxCaptures' => null, // to be set dynamically + 'Quality' => null, // to be set dynamically + ], + ], + 'AfdSignaling' => 'NONE', + 'DropFrameTimecode' => 'ENABLED', + 'RespondToAfd' => 'NONE', + 'ColorMetadata' => 'INSERT', + 'Width' => null, // to be set dynamically + ], + 'NameModifier' => null, // to be set dynamically + ], + ], + 'OutputGroupSettings' => [ + 'Type' => 'FILE_GROUP_SETTINGS', + 'FileGroupSettings' => [ + 'Destination' => null, // to be set dynamically + 'DestinationSettings' => [ + 'S3Settings' => [ + 'AccessControl' => [ + 'CannedAcl' => 'PUBLIC_READ', + ], + ], + ], + ], + ], + ], + [ + 'CustomName' => 'MP4', + 'Name' => 'File Group', + 'Outputs' => [ + [ + 'ContainerSettings' => [ + 'Container' => 'MP4', + 'Mp4Settings' => [ + 'CslgAtom' => 'INCLUDE', + 'FreeSpaceBox' => 'EXCLUDE', + 'MoovPlacement' => 'PROGRESSIVE_DOWNLOAD', + ], + ], + 'VideoDescription' => [ + 'ScalingBehavior' => 'DEFAULT', + 'TimecodeInsertion' => 'DISABLED', + 'AntiAlias' => 'ENABLED', + 'Sharpness' => 50, + 'CodecSettings' => [ + 'Codec' => 'H_264', + 'H264Settings' => [ + 'InterlaceMode' => 'PROGRESSIVE', + 'NumberReferenceFrames' => 3, + 'Syntax' => 'DEFAULT', + 'Softness' => 0, + 'GopClosedCadence' => 1, + 'GopSize' => 90, + 'Slices' => 1, + 'GopBReference' => 'DISABLED', + 'MaxBitrate' => 8000000, + 'SlowPal' => 'DISABLED', + 'SpatialAdaptiveQuantization' => 'ENABLED', + 'TemporalAdaptiveQuantization' => 'ENABLED', + 'FlickerAdaptiveQuantization' => 'DISABLED', + 'EntropyEncoding' => 'CABAC', + 'FramerateControl' => 'INITIALIZE_FROM_SOURCE', + 'RateControlMode' => 'QVBR', + 'QvbrSettings' => [ + 'QvbrQualityLevel' => 7, + 'QvbrQualityLevelFineTune' => 0, + ], + 'CodecProfile' => 'MAIN', + 'Telecine' => 'NONE', + 'MinIInterval' => 0, + 'AdaptiveQuantization' => 'HIGH', + 'CodecLevel' => 'AUTO', + 'FieldEncoding' => 'PAFF', + 'SceneChangeDetect' => 'ENABLED', + 'QualityTuningLevel' => 'SINGLE_PASS', + 'FramerateConversionAlgorithm' => 'DUPLICATE_DROP', + 'UnregisteredSeiTimecode' => 'DISABLED', + 'GopSizeUnits' => 'FRAMES', + 'ParControl' => 'INITIALIZE_FROM_SOURCE', + 'NumberBFramesBetweenReferenceFrames' => 2, + 'RepeatPps' => 'DISABLED', + ], + ], + 'AfdSignaling' => 'NONE', + 'DropFrameTimecode' => 'ENABLED', + 'RespondToAfd' => 'NONE', + 'ColorMetadata' => 'INSERT', + ], + 'AudioDescriptions' => [ + [ + 'AudioTypeControl' => 'FOLLOW_INPUT', + 'CodecSettings' => [ + 'Codec' => 'AAC', + 'AacSettings' => [ + 'AudioDescriptionBroadcasterMix' => 'NORMAL', + 'Bitrate' => 96000, + 'RateControlMode' => 'CBR', + 'CodecProfile' => 'LC', + 'CodingMode' => 'CODING_MODE_2_0', + 'RawFormat' => 'NONE', + 'SampleRate' => 48000, + 'Specification' => 'MPEG4', + ], + ], + 'LanguageCodeControl' => 'FOLLOW_INPUT', + ], + ], + ], + ], + 'OutputGroupSettings' => [ + 'Type' => 'FILE_GROUP_SETTINGS', + 'FileGroupSettings' => [ + 'Destination' => null, // to be set dynamically + 'DestinationSettings' => [ + 'S3Settings' => [ + 'AccessControl' => [ + 'CannedAcl' => 'PUBLIC_READ', + ], + ], + ], + ], + ], + ], + ], + 'AdAvailOffset' => 0, + 'Inputs' => [ + [ + 'AudioSelectors' => [ + 'Audio Selector 1' => [ + 'Offset' => 0, + 'DefaultSelection' => 'DEFAULT', + 'ProgramSelection' => 1, + ], + ], + 'VideoSelector' => [ + 'ColorSpace' => 'FOLLOW', + ], + 'FilterEnable' => 'AUTO', + 'PsiControl' => 'USE_PSI', + 'FilterStrength' => 0, + 'DeblockFilter' => 'DISABLED', + 'DenoiseFilter' => 'DISABLED', + 'TimecodeSource' => 'EMBEDDED', + 'FileInput' => null, // to be set dynamically + ], + ], + ]; + } +} diff --git a/tests/MediaConverterTest.php b/tests/MediaConverterTest.php index a8a46a9..1d17d0d 100644 --- a/tests/MediaConverterTest.php +++ b/tests/MediaConverterTest.php @@ -10,11 +10,63 @@ }); it('can successfully initialize settings', function () { - $this->assertTrue(is_array($this->settings)); + $converter = MediaConvert::path('my-video.mkv', 'test-bucket'); + $this->assertTrue(is_array($converter->jobSettings)); +}); + +it('can successfully set a path', function () { + $converter = MediaConvert::path('my-video.mkv', 'test-bucket'); + $fileInput = 's3://test-bucket/my-video.mkv'; + $this->assertEquals($converter->jobSettings['Inputs'][0]['FileInput'], $fileInput); +}); + +it('can successfully web optimize a video', function () { + $converter = MediaConvert::path('my-video.mkv', 'test-bucket')->optimizeForWeb(); + // todo: we could likely improve this by running an actual test and compare the output file + $this->assertEquals($converter->jobSettings['OutputGroups'][1]['CustomName'], 'MP4'); +}); + +it('can successfully set the settings to generate thumbnails', function () { + $framerateNumerator = 1; + $framerateDenominator = 2; + $maxCaptures = 3; + $imageQuality = 75; + $width = 100; + $nameModifier = '.$w$x$h$'; + + $converter = MediaConvert::path('my-video.mkv', 'test-bucket') + ->optimizeForWeb() + ->withThumbnails($framerateNumerator, $framerateDenominator, $maxCaptures, $width, $nameModifier, $imageQuality); + + $this->assertEquals($converter->jobSettings['OutputGroups'][0]['Outputs'][0]['VideoDescription']['CodecSettings']['FrameCaptureSettings'], [ + 'FramerateNumerator' => $framerateNumerator, + 'FramerateDenominator' => $framerateDenominator, + 'MaxCaptures' => $maxCaptures, + 'Quality' => $imageQuality, + ]); + + $this->assertEquals($converter->jobSettings['OutputGroups'][0]['Outputs'][0]['VideoDescription']['Width'], $width); + $this->assertEquals($converter->jobSettings['OutputGroups'][0]['Outputs'][0]['NameModifier'], $nameModifier); +}); + +it('can successfully update the output path', function () { + $inputName = 'my-video.mkv'; + $outputName = 'my-video.mp4'; + $bucket = 'test-bucket'; + + $converter = MediaConvert::path($inputName, 'test-bucket') + ->optimizeForWeb() + ->withThumbnails(1, 2, 3, 100) + ->saveTo($outputName, $bucket); + + $destination = 's3://test-bucket'; + + $this->assertEquals($converter->jobSettings['OutputGroups'][0]['OutputGroupSettings']['FileGroupSettings']['Destination'], $destination.'/thumbnails/'); + $this->assertEquals($converter->jobSettings['OutputGroups'][1]['OutputGroupSettings']['FileGroupSettings']['Destination'], $destination.'/mp4/'); }); it('can successfully create a job', function () { - $response = MediaConvert::createJob($this->settings); + $response = MediaConvert::createJob($this->jobSettings); $this->assertEquals($response['@metadata']['statusCode'], 201); }); @@ -30,7 +82,7 @@ }); it('can successfully cancel a job', function () { - $job = MediaConvert::createJob($this->settings, []); + $job = MediaConvert::createJob($this->jobSettings, []); $response = MediaConvert::cancelJob($job['Job']['Id']); diff --git a/tests/MediaConverterTestCase.php b/tests/MediaConverterTestCase.php index 63a9e10..12e1674 100644 --- a/tests/MediaConverterTestCase.php +++ b/tests/MediaConverterTestCase.php @@ -8,9 +8,7 @@ class MediaConverterTestCase extends TestCase { - public $settings = []; - - public $sizes = []; + public $jobSettings = []; protected function getPackageProviders($app): array { @@ -19,14 +17,16 @@ protected function getPackageProviders($app): array public function initializeDotEnv() { + if (! file_exists(__DIR__.'/../.env')) { + return; + } + $dotenv = \Dotenv\Dotenv::createImmutable(dirname(__DIR__)); $dotenv->load(); } public function initializeSettings() { - $configFile = file_get_contents(__DIR__.'/config/job.json'); - // let's make sure these config values are set Config::set('media-converter.credentials.key', env('AWS_ACCESS_KEY_ID')); Config::set('media-converter.credentials.secret', env('AWS_SECRET_ACCESS_KEY')); @@ -34,6 +34,7 @@ public function initializeSettings() Config::set('media-converter.iam_arn', env('AWS_IAM_ARN')); Config::set('media-converter.queue_arn', env('AWS_QUEUE_ARN')); - $this->settings = json_decode($configFile, true); + $configFile = file_get_contents(__DIR__.'/config/job.json'); + $this->jobSettings = json_decode($configFile, true); } }