Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First release #9

Merged
merged 3 commits into from
Sep 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ Once the last chunk has been uploaded, a `Jobtech\LaravelChunky\Jobs\MergeChunks

'mime_types' => [
'video/*' => \Jobtech\LaravelChunky\Strategies\VideoStrategy::class,
'audio/*' => \Jobtech\LaravelChunky\Strategies\AudioStrategy::class,
],

'connection' => env('CHUNKY_MERGE_CONNECTION', 'default'),
Expand Down Expand Up @@ -405,7 +406,7 @@ namespace App\MergeStrategies;
use Jobtech\LaravelChunky\Strategies\MergeStrategy;
use Jobtech\LaravelChunky\Strategies\Concerns\ChecksIntegrity;

class AudioStrategy extends MergeStrategy
class PDFStrategy extends MergeStrategy
{
use ChecksIntegrity;

Expand All @@ -414,7 +415,7 @@ class AudioStrategy extends MergeStrategy
*/
public function merge()
{
// Implement here your logic to merge audio chunks
// Implement here your logic to merge pdf chunks
}
}
```
Expand All @@ -432,8 +433,9 @@ Once completed, add your strategy into the configuration file, so you can automa

'mime_types' => [
'video/*' => \Jobtech\LaravelChunky\Strategies\VideoStrategy::class,
'audio/*' => \Jobtech\LaravelChunky\Strategies\AudioStrategy::class,
// Add here
'audio/*' => \App\MergeStrategies\AudioStrategy::class,
'application/pdf' => \App\MergeStrategies\PDFStrategy::class,
],
],

Expand All @@ -443,25 +445,30 @@ Once completed, add your strategy into the configuration file, so you can automa

## Testing

You can run the tests with:
You can run the tests with PHP unit:

```sh
$ vendor/bin/phpunit
```

or with the composer script
If you want to set custom environment variable, you can add a `.env` file for custom disks, queue or whatever you need. Tests anyway set a temporary local disk by default.

```sh
$ composer test
```
CHUNKY_CHUNK_DISK=s3
CHUNKY_MERGE_DISK=public
CHUNKY_AUTO_MERGE=false
CHUNKY_MERGE_CONNECTION=redis
CHUNKY_MERGE_QUEUE=my-custom-queue
```

## Roadmap

See the [open issues](https://github.com/jobtech-dev/laravel-chunky/issues) for a list of proposed features (and known issues).

We're working on:

* Implement more merge strategies
* Implement more merge strategies for specific mime types
* Video and audio should have dedicated strategy for each codec.
* Integrate frontend chunk upload (Not sure if necessary... there are so many packages that does it)
* Better tests
* Laravel 5.5+ compatibility
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
}
],
"require": {
"php": "^7.2",
"php": "^7.3",
"ext-fileinfo": "*",
"ext-json": "*",
"illuminate/contracts": "~5.8.0|^6.0|^7.0",
Expand Down
33 changes: 33 additions & 0 deletions scrutinizer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
filter:
excluded_paths: [tests/*]
checks:
php:
code_rating: true
remove_extra_empty_lines: true
remove_php_closing_tag: true
remove_trailing_whitespace: true
fix_use_statements:
remove_unused: true
preserve_multiple: false
preserve_blanklines: true
order_alphabetically: true
fix_php_opening_tag: true
fix_linefeed: true
fix_line_ending: true
fix_identation_4spaces: true
fix_doc_comments: true
tools:
external_code_coverage: false
php_analyzer: true
php_code_coverage: false
php_code_sniffer:
config:
standard: PSR2
filter:
paths: ['src']
php_loc:
enabled: true
excluded_dirs: [vendor, tests]
php_cpd:
enabled: true
excluded_dirs: [vendor, tests]
51 changes: 51 additions & 0 deletions src/Strategies/AudioStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Jobtech\LaravelChunky\Strategies;

use FFMpeg\Format\Audio\Aac;
use FFMpeg\Format\Audio\Flac;
use FFMpeg\Format\Audio\Mp3;
use FFMpeg\Format\Audio\Vorbis;
use FFMpeg\Format\Audio\Wav;
use Illuminate\Support\Arr;
use Jobtech\LaravelChunky\Strategies\Concerns\ChecksIntegrity;
use Jobtech\LaravelChunky\Strategies\Concerns\HandlesFFMpeg;
use ProtoneMedia\LaravelFFMpeg\FFMpeg\CopyFormat;

class AudioStrategy extends MergeStrategy
{
use ChecksIntegrity,
HandlesFFMpeg;

public function merge()
{
$this->mergeWithFFMpeg();

$this->deleteChunks($this->folder);

return $this->mergeContents();
}

/**
* {@inheritdoc}
*/
public function guessFormat()
{
$extension = strtolower(Arr::last(explode('.', $this->destination())));

switch ($extension) {
case 'aac':
return new Aac;
case 'flac':
return new Flac;
case 'mp3':
return new Mp3;
case 'oog':
return new Vorbis;
case 'wav':
return new Wav;
default:
return new CopyFormat;
}
}
}
46 changes: 46 additions & 0 deletions src/Strategies/Concerns/HandlesFFMpeg.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Jobtech\LaravelChunky\Strategies\Concerns;

use Illuminate\Support\Arr;
use ProtoneMedia\LaravelFFMpeg\Support\FFMpeg;

trait HandlesFFMpeg
{
public function mergeWithFFMpeg(): void
{
$exporter = FFMpeg::fromDisk($this->manager->chunksFilesystem())
->open($this->mapChunksToArray())
->export()
->inFormat($this->guessFormat())
->concatWithoutTranscoding();

if (! empty($visibility = $this->visibility())) {
$exporter->withVisibility($visibility);
}

$exporter->toDisk(
$this->manager->getMergeDisk()
)->save($this->destination);
}

/**
* Retrieve visibility option.
*
* @return string|null
*/
public function visibility(): ?string
{
return Arr::get(
$this->manager->getMergeOptions(),
'visibility'
);
}

/**
* Guess format from destination file extension.
*
* @return mixed
*/
abstract public function guessFormat();
}
55 changes: 26 additions & 29 deletions src/Strategies/VideoStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,47 @@

namespace Jobtech\LaravelChunky\Strategies;

use FFMpeg\Format\Video\Ogg;
use FFMpeg\Format\Video\WebM;
use FFMpeg\Format\Video\WMV;
use FFMpeg\Format\Video\WMV3;
use FFMpeg\Format\Video\X264;
use Illuminate\Support\Arr;
use Jobtech\LaravelChunky\Strategies\Concerns\ChecksIntegrity;
use ProtoneMedia\LaravelFFMpeg\Support\FFMpeg;
use Jobtech\LaravelChunky\Strategies\Concerns\HandlesFFMpeg;
use ProtoneMedia\LaravelFFMpeg\FFMpeg\CopyFormat;

class VideoStrategy extends MergeStrategy
{
use ChecksIntegrity;
use ChecksIntegrity,
HandlesFFMpeg;

public function merge()
{
$this->handleVideoMerge();
$this->mergeWithFFMpeg();

$this->deleteChunks($this->folder);

return $this->mergeContents();
}

public function handleVideoMerge(): void
public function guessFormat()
{
$exporter = FFMpeg::fromDisk($this->manager->chunksFilesystem())
->open($this->mapChunksToArray())
->export();

$exporter->concatWithoutTranscoding();

if (! empty($visibility = $this->visibility())) {
$exporter->withVisibility($visibility);
$extension = strtolower(Arr::last(explode('.', $this->destination())));

switch ($extension) {
case 'oog':
return new Ogg;
case 'webm':
return new WebM;
case 'wmv':
return new WMV;
case 'wmv3':
return new WMV3;
case 'mp4':
return new X264;
default:
return new CopyFormat;
}

$exporter->toDisk(
$this->manager->getMergeDisk()
)->save($this->destination);
}

/**
* Retrieve visibility option.
*
* @return string|null
*/
public function visibility(): ?string
{
return Arr::get(
$this->manager->getMergeOptions(),
'visibility'
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Jobtech\LaravelChunky\Tests\Unit\Merge;
namespace Jobtech\LaravelChunky\Tests\Unit\Handlers;

use Jobtech\LaravelChunky\Handlers\MergeHandler;
use Jobtech\LaravelChunky\Strategies\Contracts\MergeStrategy;
Expand Down
80 changes: 80 additions & 0 deletions tests/Unit/Strategies/AudioStrategyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace Jobtech\LaravelChunky\Tests\Unit\Strategies;

use Illuminate\Support\Facades\Storage;
use Jobtech\LaravelChunky\ChunksManager;
use Jobtech\LaravelChunky\Strategies\AudioStrategy;
use Jobtech\LaravelChunky\Tests\TestCase;

class AudioStrategyTest extends TestCase
{
/**
* @var ChunksManager
*/
private $manager;

protected function setUp(): void
{
parent::setUp();

$this->manager = $this->app->make('chunky');
}

/** @test */
public function strategy_retrieves_visibility_from_options()
{
$mock = $this->mock(ChunksManager::class, function ($mock) {
$mock->shouldReceive('getMergeOptions')
->once()
->andReturn([]);

$mock->shouldReceive('getMergeOptions')
->once()
->andReturn([
'visibility' => 'public',
]);
});

$strategy = new AudioStrategy($mock);

$this->assertNull($strategy->visibility());
$this->assertEquals('public', $strategy->visibility());
}

/** @test */
public function strategy_merges_chunks_without_transcode()
{
$this->manager->chunksFilesystem()->makeDirectory('chunks');

$strategy = new AudioStrategy($this->manager);
$strategy->chunksFolder('resources/mp3');
$strategy->destination('foo/sample.mp3');

$strategy->merge();

Storage::assertExists('foo/sample.mp3');
Storage::assertMissing('chunks/resources/mp3/0_sample.mp3');
Storage::assertMissing('chunks/resources/mp3/1_sample.mp3');
Storage::assertMissing('chunks/resources/mp3/2_sample.mp3');
Storage::assertMissing('chunks/resources/mp3');
}

/** @test */
public function strategy_merges_chunks_with_transcode()
{
$this->manager->chunksFilesystem()->makeDirectory('chunks');

$strategy = new AudioStrategy($this->manager);
$strategy->chunksFolder('resources/mp3');
$strategy->destination('foo/sample.wav');

$strategy->merge();

Storage::assertExists('foo/sample.wav');
Storage::assertMissing('chunks/resources/mp3/0_sample.mp3');
Storage::assertMissing('chunks/resources/mp3/1_sample.mp3');
Storage::assertMissing('chunks/resources/mp3/2_sample.mp3');
Storage::assertMissing('chunks/resources/mp3');
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Jobtech\LaravelChunky\Tests\Unit\Merge\Strategies;
namespace Jobtech\LaravelChunky\Tests\Unit\Strategies;

use Illuminate\Support\Facades\Storage;
use Jobtech\LaravelChunky\Strategies\FlysystemStrategy;
Expand Down
Loading