Specify temporary directory + fix for default ffmpeg-passes* temporary directory (#855)

This commit is contained in:
Pascal Baljet 2022-02-22 16:54:06 +01:00 committed by GitHub
commit bda300b69a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 119 additions and 35 deletions

View file

@ -2,6 +2,11 @@
All Notable changes to the library will be documented in this file All Notable changes to the library will be documented in this file
## 1.0.1 - 2022-02-22
- Added configuration key to customize the temporary directory used for passes.
- Fix for the path of the default `ffmpeg-passes*` temporary directory.
## 1.0.0 - 2022-02-09 ## 1.0.0 - 2022-02-09
Upgraded dependencies, integrated the Alchemy Binary library, and dropped support for anything below PHP 8.0 Upgraded dependencies, integrated the Alchemy Binary library, and dropped support for anything below PHP 8.0

View file

@ -79,6 +79,14 @@ $ffmpeg = FFMpeg\FFMpeg::create(array(
), $logger); ), $logger);
``` ```
You may pass a `temporary_directory` key to specify a path for temporary files.
```php
$ffmpeg = FFMpeg\FFMpeg::create(array(
'temporary_directory' => '/var/ffmpeg-tmp'
), $logger);
```
### Manipulate media ### Manipulate media
`FFMpeg\FFMpeg` creates media based on URIs. URIs could be either a pointer to a `FFMpeg\FFMpeg` creates media based on URIs. URIs could be either a pointer to a

View file

@ -57,7 +57,8 @@
"php-ffmpeg/extras": "A compilation of common audio & video drivers for PHP-FFMpeg" "php-ffmpeg/extras": "A compilation of common audio & video drivers for PHP-FFMpeg"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^9.5.10" "phpunit/phpunit": "^9.5.10",
"mockery/mockery": "^1.5"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@ -71,4 +72,4 @@
"Tests\\FFMpeg\\": "tests/FFMpeg" "Tests\\FFMpeg\\": "tests/FFMpeg"
} }
} }
} }

View file

@ -14,6 +14,7 @@ namespace FFMpeg\Media;
use FFMpeg\Driver\FFMpegDriver; use FFMpeg\Driver\FFMpegDriver;
use FFMpeg\FFProbe; use FFMpeg\FFProbe;
use FFMpeg\Filters\FiltersCollection; use FFMpeg\Filters\FiltersCollection;
use Spatie\TemporaryDirectory\TemporaryDirectory;
abstract class AbstractMediaType implements MediaTypeInterface abstract class AbstractMediaType implements MediaTypeInterface
{ {
@ -96,6 +97,18 @@ abstract class AbstractMediaType implements MediaTypeInterface
return $this->filters; return $this->filters;
} }
/**
* Returns a new instance of TemporaryDirectory with the optionally configured directory.
*
* @return \Spatie\TemporaryDirectory\TemporaryDirectory
*/
public function getTemporaryDirectory(): TemporaryDirectory
{
return new TemporaryDirectory(
$this->driver->getConfiguration()->get('temporary_directory') ?: ''
);
}
protected function cleanupTemporaryFile($filename) protected function cleanupTemporaryFile($filename)
{ {
if (file_exists($filename) && is_writable($filename)) { if (file_exists($filename) && is_writable($filename)) {

View file

@ -267,7 +267,7 @@ abstract class AbstractVideo extends Audio
} }
$this->fsId = uniqid('ffmpeg-passes'); $this->fsId = uniqid('ffmpeg-passes');
$this->fs = (new TemporaryDirectory($this->fsId))->create(); $this->fs = $this->getTemporaryDirectory()->name($this->fsId)->create();
$passPrefix = $this->fs->path(uniqid('pass-')); $passPrefix = $this->fs->path(uniqid('pass-'));
touch($passPrefix); touch($passPrefix);
$passes = []; $passes = [];

View file

@ -85,7 +85,7 @@ class Concat extends AbstractMediaType
*/ */
// Create the file which will contain the list of videos // Create the file which will contain the list of videos
$fs = (new TemporaryDirectory())->create(); $fs = $this->getTemporaryDirectory()->create();
$sourcesFile = $fs->path('ffmpeg.concat'); $sourcesFile = $fs->path('ffmpeg.concat');
// Set the content of this file // Set the content of this file

View file

@ -8,7 +8,7 @@ class AdvancedMediaTest extends AbstractMediaTestCase
{ {
public function testGetInputs() public function testGetInputs()
{ {
$driver = $this->getFFMpegDriverMock(); $driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock(); $ffprobe = $this->getFFProbeMock();
$advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe); $advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe);
@ -17,7 +17,7 @@ class AdvancedMediaTest extends AbstractMediaTestCase
public function testGetInputsCount() public function testGetInputsCount()
{ {
$driver = $this->getFFMpegDriverMock(); $driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock(); $ffprobe = $this->getFFProbeMock();
$advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe); $advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe);
@ -26,10 +26,48 @@ class AdvancedMediaTest extends AbstractMediaTestCase
public function testFiltersReturnFilters() public function testFiltersReturnFilters()
{ {
$driver = $this->getFFMpegDriverMock(); $driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock(); $ffprobe = $this->getFFProbeMock();
$advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe); $advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe);
$this->assertInstanceOf('FFMpeg\Filters\AdvancedMedia\ComplexFilters', $advancedMedia->filters()); $this->assertInstanceOf('FFMpeg\Filters\AdvancedMedia\ComplexFilters', $advancedMedia->filters());
} }
public function testGetTemporaryDirectoryWithoutCustomConfiguration()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$configuration = $this->getConfigurationMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->expects($this->once())
->method('get')
->with($this->equalTo('temporary_directory'))
->will($this->returnValue(null));
$advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe);
$this->assertEquals('', $advancedMedia->getTemporaryDirectory()->path());
}
public function testGetTemporaryDirectoryWithCustomConfiguration()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$configuration = $this->getConfigurationMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->expects($this->once())
->method('get')
->with($this->equalTo('temporary_directory'))
->will($this->returnValue('/var/ffmpeg'));
$advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe);
$this->assertEquals('/var/ffmpeg', $advancedMedia->getTemporaryDirectory()->path());
}
} }

View file

@ -3,13 +3,14 @@
namespace Tests\FFMpeg\Unit\Media; namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Media\Concat; use FFMpeg\Media\Concat;
use Mockery;
use Spatie\TemporaryDirectory\TemporaryDirectory; use Spatie\TemporaryDirectory\TemporaryDirectory;
class ConcatTest extends AbstractMediaTestCase class ConcatTest extends AbstractMediaTestCase
{ {
public function testGetSources() public function testGetSources()
{ {
$driver = $this->getFFMpegDriverMock(); $driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock(); $ffprobe = $this->getFFProbeMock();
$concat = new Concat([__FILE__, __FILE__], $driver, $ffprobe); $concat = new Concat([__FILE__, __FILE__], $driver, $ffprobe);
@ -18,7 +19,7 @@ class ConcatTest extends AbstractMediaTestCase
public function testFiltersReturnFilters() public function testFiltersReturnFilters()
{ {
$driver = $this->getFFMpegDriverMock(); $driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock(); $ffprobe = $this->getFFProbeMock();
$concat = new Concat([__FILE__, __FILE__], $driver, $ffprobe); $concat = new Concat([__FILE__, __FILE__], $driver, $ffprobe);
@ -27,7 +28,7 @@ class ConcatTest extends AbstractMediaTestCase
public function testAddFiltersAddsAFilter() public function testAddFiltersAddsAFilter()
{ {
$driver = $this->getFFMpegDriverMock(); $driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock(); $ffprobe = $this->getFFProbeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection') $filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
@ -50,13 +51,24 @@ class ConcatTest extends AbstractMediaTestCase
*/ */
public function testSaveFromSameCodecs($streamCopy, $commands) public function testSaveFromSameCodecs($streamCopy, $commands)
{ {
$driver = $this->getFFMpegDriverMock(); $driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock(); $ffprobe = $this->getFFProbeMock();
$pathfile = '/target/destination'; $pathfile = '/target/destination';
array_push($commands, $pathfile); array_push($commands, $pathfile);
$configuration = Mockery::mock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->shouldReceive('get')
->once()
->with('temporary_directory')
->andReturnNull();
$driver->expects($this->exactly(1)) $driver->expects($this->exactly(1))
->method('command') ->method('command')
->with($this->isType('array'), false, $this->anything()) ->with($this->isType('array'), false, $this->anything())
@ -79,7 +91,7 @@ class ConcatTest extends AbstractMediaTestCase
public function provideSaveFromSameCodecsOptions() public function provideSaveFromSameCodecsOptions()
{ {
$fs = (new TemporaryDirectory())->create(); $fs = (new TemporaryDirectory())->create();
$tmpFile = $fs->path('ffmpeg-concat'); $tmpFile = $fs->path('ffmpeg-concat');
touch($tmpFile); touch($tmpFile);
@ -109,9 +121,9 @@ class ConcatTest extends AbstractMediaTestCase
*/ */
public function testSaveFromDifferentCodecs($commands) public function testSaveFromDifferentCodecs($commands)
{ {
$driver = $this->getFFMpegDriverMock(); $driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock(); $ffprobe = $this->getFFProbeMock();
$format = $this->getFormatInterfaceMock(); $format = $this->getFormatInterfaceMock();
$pathfile = '/target/destination'; $pathfile = '/target/destination';

View file

@ -5,6 +5,7 @@ namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Exception\RuntimeException; use FFMpeg\Exception\RuntimeException;
use FFMpeg\Format\Video\X264; use FFMpeg\Format\Video\X264;
use FFMpeg\Media\Video; use FFMpeg\Media\Video;
use Mockery;
class VideoTest extends AbstractStreamableTestCase class VideoTest extends AbstractStreamableTestCase
{ {
@ -158,25 +159,27 @@ class VideoTest extends AbstractStreamableTestCase
$driver = $this->getFFMpegDriverMock(); $driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock(); $ffprobe = $this->getFFProbeMock();
$configuration = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock(); $configuration = Mockery::mock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any()) $driver->expects($this->any())
->method('getConfiguration') ->method('getConfiguration')
->will($this->returnValue($configuration)); ->will($this->returnValue($configuration));
$configuration->expects($this->once()) $configuration->shouldReceive('has')
->method('has') ->once()
->with($this->equalTo('ffmpeg.threads')) ->with('ffmpeg.threads')
->will($this->returnValue($threads)); ->andReturn($threads);
$configuration->shouldReceive('get')
->once()
->with('temporary_directory')
->andReturnNull();
if ($threads) { if ($threads) {
$configuration->expects($this->once()) $configuration->shouldReceive('get')
->method('get') ->once()
->with($this->equalTo('ffmpeg.threads')) ->with('ffmpeg.threads')
->will($this->returnValue(24)); ->andReturn(24);
} else {
$configuration->expects($this->never())
->method('get');
} }
$capturedCommands = []; $capturedCommands = [];
@ -585,21 +588,25 @@ class VideoTest extends AbstractStreamableTestCase
$driver = $this->getFFMpegDriverMock(); $driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock(); $ffprobe = $this->getFFProbeMock();
$configuration = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock(); $configuration = Mockery::mock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any()) $driver->expects($this->any())
->method('getConfiguration') ->method('getConfiguration')
->will($this->returnValue($configuration)); ->will($this->returnValue($configuration));
$configuration->expects($this->any()) $configuration->shouldReceive('has')
->method('has') ->with('ffmpeg.threads')
->with($this->equalTo('ffmpeg.threads')) ->andReturn(true);
->will($this->returnValue(true));
$configuration->expects($this->any()) $configuration->shouldReceive('get')
->method('get') ->once()
->with($this->equalTo('ffmpeg.threads')) ->with('ffmpeg.threads')
->will($this->returnValue(24)); ->andReturn(24);
$configuration->shouldReceive('get')
->once()
->with('temporary_directory')
->andReturnNull();
$capturedCommands = []; $capturedCommands = [];