Skip to content

Commit 1d1353f

Browse files
authored
Merge pull request #196 from pascalbaljetmedia/v7-hls-audio-bugfix
HLS audio bugfix
2 parents ed08d35 + 8240cae commit 1d1353f

File tree

10 files changed

+174
-80
lines changed

10 files changed

+174
-80
lines changed

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@
22

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

5+
## 7.0.2 - 2020-06-01
6+
7+
### Added
8+
9+
- Nothing
10+
11+
### Deprecated
12+
13+
- Nothing
14+
15+
### Fixed
16+
17+
- Audio bugfix for HLS exports with filters
18+
19+
### Removed
20+
21+
- Nothing
22+
23+
524
## 7.0.1 - 2020-05-28
625

726
### Added

src/Drivers/PHPFFMpeg.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Illuminate\Support\Collection;
1717
use Illuminate\Support\Traits\ForwardsCalls;
1818
use ProtoneMedia\LaravelFFMpeg\FFMpeg\LegacyFilterMapping;
19+
use ProtoneMedia\LaravelFFMpeg\Filesystem\Media;
1920
use ProtoneMedia\LaravelFFMpeg\Filesystem\MediaCollection;
2021

2122
class PHPFFMpeg
@@ -137,7 +138,13 @@ public function openAdvanced(MediaCollection $mediaCollection): self
137138

138139
public function getStreams(): array
139140
{
140-
return iterator_to_array($this->media->getStreams());
141+
if (!$this->isAdvancedMedia()) {
142+
return iterator_to_array($this->media->getStreams());
143+
}
144+
145+
return $this->mediaCollection->map(function (Media $media) {
146+
return $this->fresh()->open(MediaCollection::make([$media]))->getStreams();
147+
})->collapse()->all();
141148
}
142149

143150
public function getFilters(): array
@@ -170,6 +177,16 @@ public function getDurationInMiliseconds(): int
170177
}
171178
}
172179

180+
/**
181+
* Gets the first audio streams of the media.
182+
*/
183+
public function getAudioStream(): ?Stream
184+
{
185+
return Arr::first($this->getStreams(), function (Stream $stream) {
186+
return $stream->isAudio();
187+
});
188+
}
189+
173190
/**
174191
* Gets the first video streams of the media.
175192
*/

src/Exporters/HLSExporter.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,11 @@ public function save(string $path = null): MediaOpener
194194
}
195195
}
196196

197-
$this->addFormatOutputMapping($format, $disk->makeMedia($formatPlaylistPath), [$keysWithFilters[$key] ?? '0']);
197+
$outs = array_key_exists($key, $keysWithFilters)
198+
? array_filter([$keysWithFilters[$key], $this->getAudioStream() ? "0:a" : null])
199+
: ['0'];
200+
201+
$this->addFormatOutputMapping($format, $disk->makeMedia($formatPlaylistPath), $outs);
198202

199203
return $this->getDisk()->makeMedia($formatPlaylistPath);
200204
})->pipe(function ($playlistMedia) use ($path) {

tests/AddFilterTest.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use FFMpeg\Filters\Audio\SimpleFilter;
77
use FFMpeg\Filters\Video\VideoFilters;
88
use FFMpeg\Format\AudioInterface;
9-
use FFMpeg\Format\Video\X264;
109
use FFMpeg\Media\Audio;
1110
use Illuminate\Support\Arr;
1211
use ProtoneMedia\LaravelFFMpeg\FFMpeg\LegacyFilterMapping;
@@ -130,7 +129,7 @@ public function it_can_add_a_complex_filter_object_with_a_input_and_output()
130129
->open(['video.mp4', 'video2.mp4'])
131130
->addFilter('[0:v][1:v]', 'hstack', '[v]')
132131
->export()
133-
->addFormatOutputMapping(new X264, Media::make('local', 'output.mp4'), ['0:a', '[v]'])
132+
->addFormatOutputMapping($this->x264(), Media::make('local', 'output.mp4'), ['0:a', '[v]'])
134133
->getCommand();
135134

136135
$this->assertStringContainsString('-filter_complex [0:v][1:v]hstack[v] -map 0:a -map [v]', $command);
@@ -149,7 +148,7 @@ public function it_can_add_a_basic_filter_to_an_advanced_media_object_using_a_fi
149148
->open(['video.mp4', 'video2.mp4'])
150149
->addFilterAsComplexFilter('[0]', '[v0]', $resizeFilter)
151150
->export()
152-
->addFormatOutputMapping(new X264, Media::make('local', 'output.mp4'), ['[v0]'])
151+
->addFormatOutputMapping($this->x264(), Media::make('local', 'output.mp4'), ['[v0]'])
153152
->save();
154153

155154
$this->assertEquals(
@@ -169,7 +168,7 @@ public function it_can_add_a_basic_filter_to_an_advanced_media_object_using_a_cl
169168
$filters->resize(new \FFMpeg\Coordinate\Dimension(1280, 960));
170169
})
171170
->export()
172-
->addFormatOutputMapping(new X264, Media::make('local', 'output.mp4'), ['[v0]'])
171+
->addFormatOutputMapping($this->x264(), Media::make('local', 'output.mp4'), ['[v0]'])
173172
->save();
174173

175174
$this->assertEquals(

tests/ExportTest.php

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use FFMpeg\Filters\Video\ClipFilter;
77
use FFMpeg\Format\Audio\Mp3;
88
use FFMpeg\Format\Video\WMV;
9-
use FFMpeg\Format\Video\X264;
109
use Illuminate\Support\Facades\Storage;
1110
use ProtoneMedia\LaravelFFMpeg\FFMpeg\ProgressListenerDecorator;
1211
use ProtoneMedia\LaravelFFMpeg\Filesystem\Media;
@@ -23,7 +22,7 @@ public function it_can_export_a_single_video_file()
2322
(new MediaOpener)
2423
->open('video.mp4')
2524
->export()
26-
->inFormat(new X264)
25+
->inFormat($this->x264())
2726
->save('new_video.mp4');
2827

2928
$this->assertTrue(Storage::disk('local')->has('new_video.mp4'));
@@ -49,7 +48,7 @@ public function it_can_bind_a_progress_listener_to_the_format()
4948

5049
$percentages = [];
5150

52-
$format = new X264;
51+
$format = $this->x264();
5352
$format->on('progress', function ($video, $format, $percentage) use (&$percentages) {
5453
$percentages[] = $percentage;
5554
});
@@ -70,7 +69,7 @@ public function it_can_decorate_the_format_to_get_access_to_the_progress_listene
7069

7170
$times = [];
7271

73-
$decoratedFormat = ProgressListenerDecorator::decorate(new X264);
72+
$decoratedFormat = ProgressListenerDecorator::decorate($this->x264());
7473

7574
(new MediaOpener)
7675
->open('video.mp4')
@@ -102,7 +101,7 @@ public function it_can_bind_a_dedicated_progress_listener_to_the_exporter()
102101
$remainings[] = $remaining;
103102
$rates[] = $rate;
104103
})
105-
->inFormat(new X264)
104+
->inFormat($this->x264())
106105
->save('new_video.mp4');
107106

108107
$this->assertNotEmpty($percentages);
@@ -118,10 +117,10 @@ public function it_can_chain_multiple_exports()
118117
(new MediaOpener)
119118
->open('video.mp4')
120119
->export()
121-
->inFormat(new X264)
120+
->inFormat($this->x264())
122121
->save('new_video1.mp4')
123122
->export()
124-
->inFormat(new X264)
123+
->inFormat($this->x264())
125124
->save('new_video2.mp4');
126125

127126
$this->assertTrue(Storage::disk('local')->has('new_video1.mp4'));
@@ -137,7 +136,7 @@ public function it_can_export_a_with_a_single_filter()
137136
->open('video.mp4')
138137
->addFilter(new ClipFilter(TimeCode::fromSeconds(1), TimeCode::fromSeconds(2)))
139138
->export()
140-
->inFormat(new X264)
139+
->inFormat($this->x264())
141140
->save('new_video.mp4');
142141

143142
$this->assertTrue(Storage::disk('local')->has('new_video.mp4'));
@@ -153,7 +152,7 @@ public function it_can_add_the_filter_after_calling_the_export_method()
153152
->open('video.mp4')
154153
->export()
155154
->addFilter(new ClipFilter(TimeCode::fromSeconds(1), TimeCode::fromSeconds(2)))
156-
->inFormat(new X264)
155+
->inFormat($this->x264())
157156
->save('new_video.mp4');
158157

159158
$this->assertTrue(Storage::disk('local')->has('new_video.mp4'));
@@ -169,11 +168,11 @@ public function it_doesnt_migrate_filters_from_a_previous_export()
169168
->open('video.mp4')
170169
->addFilter(new ClipFilter(TimeCode::fromSeconds(1), TimeCode::fromSeconds(2)))
171170
->export()
172-
->inFormat(new X264)
171+
->inFormat($this->x264())
173172
->save('short_video.mp4')
174173

175174
->export()
176-
->inFormat(new X264)
175+
->inFormat($this->x264())
177176
->save('long_video.mp4');
178177

179178
$this->assertTrue(Storage::disk('local')->has('short_video.mp4'));
@@ -196,7 +195,7 @@ public function it_can_export_two_files_into_a_two_files_with_filters_and_a_prog
196195
->onProgress(function ($percentage) use (&$percentages) {
197196
$percentages[] = $percentage;
198197
})
199-
->addFormatOutputMapping(new X264, Media::make('local', 'new_video1.mp4'), ['0:v', '1:v'])
198+
->addFormatOutputMapping($this->x264(), Media::make('local', 'new_video1.mp4'), ['0:v', '1:v'])
200199
->addFormatOutputMapping(new WMV, Media::make('memory', 'new_video2.wmv'), ['0:v', '1:v'])
201200
->save();
202201

@@ -215,7 +214,7 @@ public function it_can_stack_two_videos_horizontally()
215214
->open(['video.mp4', 'video2.mp4'])
216215
->export()
217216
->addFilter('[0:v][1:v]', 'hstack', '[v]')
218-
->addFormatOutputMapping(new X264, Media::make('local', 'new_video.mp4'), ['[v]'])
217+
->addFormatOutputMapping($this->x264(), Media::make('local', 'new_video.mp4'), ['[v]'])
219218
->save();
220219

221220
$this->assertTrue(Storage::disk('local')->has('new_video.mp4'));
@@ -230,12 +229,13 @@ public function it_can_stack_two_videos_horizontally()
230229
public function it_can_mix_audio_and_video_files()
231230
{
232231
$this->fakeLocalVideoFile();
232+
$this->addTestFile('video_no_audio.mp4');
233233
$this->addTestFile('guitar.m4a');
234234

235235
FFMpeg::fromDisk('local')
236236
->open(['video.mp4','guitar.m4a'])
237237
->export()
238-
->addFormatOutputMapping(new X264('libmp3lame'), Media::make('local', 'new_video.mp4'), ['0:v', '1:a'])
238+
->addFormatOutputMapping($this->x264(), Media::make('local', 'new_video.mp4'), ['0:v', '1:a'])
239239
->save();
240240

241241
$this->assertTrue(Storage::disk('local')->has('new_video.mp4'));
@@ -249,7 +249,7 @@ public function it_can_export_a_single_media_file_to_an_external_location()
249249
(new MediaOpener)
250250
->open('video.mp4')
251251
->export()
252-
->inFormat(new X264)
252+
->inFormat($this->x264())
253253
->toDisk('memory')
254254
->save('new_video.mp4');
255255

@@ -265,7 +265,7 @@ public function it_can_create_a_timelapse_from_images()
265265
->open('feature_%04d.png')
266266
->export()
267267
->asTimelapseWithFramerate(1)
268-
->inFormat(new X264)
268+
->inFormat($this->x264())
269269
->save('timelapse.mp4');
270270

271271
$this->assertTrue(Storage::disk('local')->has('timelapse.mp4'));
@@ -292,7 +292,7 @@ public function it_can_concatenate_two_videos_using_the_concat_method()
292292
$media = (new MediaOpener)->fromDisk('local')->open('concat.mp4');
293293

294294
$this->assertEquals(
295-
7,
295+
9,
296296
$media->getDurationInSeconds()
297297
);
298298

@@ -311,15 +311,15 @@ public function it_can_concatenate_two_videos_using_a_complex_filter()
311311
->open(['video.mp4', 'video2.mp4'])
312312
->export()
313313
->concatWithTranscoding(true, false)
314-
->inFormat(new X264)
314+
->inFormat($this->x264())
315315
->save('concat.mp4');
316316

317317
$this->assertTrue(Storage::disk('local')->has('concat.mp4'));
318318

319319
$media = (new MediaOpener)->fromDisk('local')->open('concat.mp4');
320320

321321
$this->assertEquals(
322-
7,
322+
9,
323323
$media->getDurationInSeconds()
324324
);
325325

0 commit comments

Comments
 (0)