Skip to content

Commit

Permalink
Merge pull request #201 from pascalbaljetmedia/v7-loops
Browse files Browse the repository at this point in the history
Improved support for loops
  • Loading branch information
pascalbaljet authored Jun 3, 2020
2 parents 152a80a + 7398613 commit 1323e47
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 0 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

All Notable changes to `pbmedia/laravel-ffmpeg` will be documented in this file

## 7.0.4 - 2020-06-03

### Added

- Added an `each` method to the `MediaOpener`

### Deprecated

- Nothing

### Fixed

- Nothing

### Removed

- Nothing

## 7.0.3 - 2020-06-01

### Added
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,28 @@ $contents = FFMpeg::open('video.mp4')
->getFrameContents();
```

### Multiple exports using loops

Chaining multiple conversions works because the `save` method of the `MediaExporter` returns a fresh instance of the `MediaOpener`. You can use this to loop through items, for example, to exports multiple frames from one video:

```php
$mediaOpener = FFMpeg::open('video.mp4');

foreach ([5, 15, 25] as $key => $seconds) {
$mediaOpener = $mediaOpener->getFrameFromSeconds($seconds)
->export()
->save("thumb_{$key}.png");
}
```

The `MediaOpener` comes with an `each` method as well. The example above could be refactored like this:

```php
FFMpeg::open('video.mp4')->each([5, 15, 25], function ($ffmpeg, $seconds, $key) {
$ffmpeg->getFrameFromSeconds($seconds)->export()->save("thumb_{$key}.png");
});
```

### Create a timelapse

You can create a timelapse from a sequence of images by using the `asTimelapseWithFramerate` method on the exporter
Expand Down
19 changes: 19 additions & 0 deletions src/MediaOpener.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use FFMpeg\Media\AbstractMediaType;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Traits\ForwardsCalls;
use ProtoneMedia\LaravelFFMpeg\Drivers\PHPFFMpeg;
use ProtoneMedia\LaravelFFMpeg\Exporters\HLSExporter;
Expand Down Expand Up @@ -56,6 +57,15 @@ public function __construct($disk = null, PHPFFMpeg $driver = null, MediaCollect
$this->collection = $mediaCollection ?: new MediaCollection;
}

public function clone(): self
{
return new MediaOpener(
$this->disk,
$this->driver,
$this->collection
);
}

/**
* Set the disk to open files from.
*/
Expand Down Expand Up @@ -156,6 +166,15 @@ public function cleanupTemporaryFiles(): self
return $this;
}

public function each($items, callable $callback): self
{
Collection::make($items)->each(function ($item, $key) use ($callback) {
return $callback($this->clone(), $item, $key);
});

return $this;
}

/**
* Returns the Media object from the driver.
*/
Expand Down
15 changes: 15 additions & 0 deletions tests/ExportTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,21 @@ public function it_can_chain_multiple_exports()
$this->assertTrue(Storage::disk('local')->has('new_video2.mp4'));
}

/** @test */
public function it_can_chain_multiple_exports_using_the_each_method()
{
$this->fakeLocalVideoFile();

(new MediaOpener)
->open('video.mp4')
->each(['new_video1.mp4', 'new_video2.mp4'], function ($ffmpeg, $filename) {
$ffmpeg->export()->inFormat($this->x264())->save($filename);
});

$this->assertTrue(Storage::disk('local')->has('new_video1.mp4'));
$this->assertTrue(Storage::disk('local')->has('new_video2.mp4'));
}

/** @test */
public function it_can_export_a_with_a_single_filter()
{
Expand Down
34 changes: 34 additions & 0 deletions tests/FrameTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Support\Facades\Storage;
use ProtoneMedia\LaravelFFMpeg\MediaOpener;
use ProtoneMedia\LaravelFFMpeg\Support\FFMpeg;

class FrameTest extends TestCase
{
Expand All @@ -23,6 +24,7 @@ public function it_can_only_export_a_frame_from_a_video_file()

$this->fail('Should have thrown an exception');
}

/** @test */
public function it_can_export_a_frame_using_seconds()
{
Expand All @@ -38,6 +40,38 @@ public function it_can_export_a_frame_using_seconds()
$this->assertTrue(Storage::disk('local')->has('thumb.png'));
}

/** @test */
public function it_can_loop_through_the_exporter()
{
$this->fakeLocalVideoFile();

$ffmpeg = FFMpeg::open('video.mp4');

foreach ([1,2,3] as $key => $frame) {
$ffmpeg = $ffmpeg->getFrameFromSeconds($frame)
->export()
->save("thumb_{$key}.png");
}

$this->assertTrue(Storage::disk('local')->has('thumb_0.png'));
$this->assertTrue(Storage::disk('local')->has('thumb_1.png'));
$this->assertTrue(Storage::disk('local')->has('thumb_2.png'));
}

/** @test */
public function it_can_loop_through_the_exporter_with_the_foreach_method()
{
$this->fakeLocalVideoFile();

FFMpeg::open('video.mp4')->each([1, 2, 3], function ($ffmpeg, $timestamp, $key) {
$ffmpeg->getFrameFromSeconds($timestamp)->export()->save("thumb_{$timestamp}.png");
});

$this->assertTrue(Storage::disk('local')->has('thumb_1.png'));
$this->assertTrue(Storage::disk('local')->has('thumb_2.png'));
$this->assertTrue(Storage::disk('local')->has('thumb_3.png'));
}

/** @test */
public function it_can_export_a_frame_as_base64()
{
Expand Down

0 comments on commit 1323e47

Please sign in to comment.