Skip to content

Commit 95defb3

Browse files
add auto generate rep
fixes some minor bugs
1 parent bea08eb commit 95defb3

File tree

10 files changed

+236
-62
lines changed

10 files changed

+236
-62
lines changed

README.md

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# PHP FFMPEG Video Streaming
22

3-
This package provides an integration with FFmpeg and exports well-known video streaming such as DASH, HLS, and Live Streaming.
3+
This package provides an integration with [PHP-FFmpeg](https://github.com/PHP-FFMpeg/PHP-FFMpeg) and exports well-known video streaming techniques such as DASH, HLS, and Live Streaming(DASH,HLS).
44

55
## Features
66
* Easily exports all your videos into DASH, HLS, and Live video streaming.
@@ -28,55 +28,75 @@ use AYazdanpanah\FFMpegStreaming\FFMpeg
2828

2929
``` php
3030
$config = [
31-
'ffmpeg.binaries' => '/usr/local/bin/ffmpeg', // the path to the FFMpeg binary
32-
'ffprobe.binaries' => '/usr/local/bin/ffprobe', // the path to the FFProbe binary
33-
'timeout' => 3600, // the timeout for the underlying process
34-
'ffmpeg.threads' => 12, // the number of threads that FFMpeg should use
31+
'ffmpeg.binaries' => '/usr/local/bin/ffmpeg', // the path to the FFMpeg binary
32+
'ffprobe.binaries' => '/usr/local/bin/ffprobe', // the path to the FFProbe binary
33+
'timeout' => 3600, // the timeout for the underlying process
34+
'ffmpeg.threads' => 12, // the number of threads that FFMpeg should use
3535
];
3636

3737
$ffmpeg = new FFMpeg($config);
3838
```
3939

4040
## DASH
41-
4241
You can create an MPD playlist to do [DASH](https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP).
4342

43+
As of version 1.1.0 the ```autoGenerateRepresentations``` method has been added. This method allows you to auto generate multi representations base on original video size and bit rate:
44+
45+
``` php
46+
$ffmpeg->open('/var/www/media/videos/test.mp4') // the path to the video
47+
->DASH()
48+
->X264()
49+
->autoGenerateRepresentations()
50+
->setAdaption('id=0,streams=v id=1,streams=a')
51+
->save();
52+
```
53+
54+
or you can add representation manually by ```addRepresentation``` method:
55+
4456
``` php
45-
try {
46-
$rep_1 = (new Representation())->setKiloBitrate(800);
47-
$rep_2 = (new Representation())->setKiloBitrate(300)->setResize(320 , 170);
48-
$ffmpeg->open('/var/www/media/videos/test.mp4')
49-
->DASH()
50-
->X264()
51-
->addRepresentation($rep_1)
52-
->addRepresentation($rep_2)
53-
->setAdaption('id=0,streams=v id=1,streams=a')
54-
->save('/var/www/media/videos/test.mpd');
55-
} catch (Exception $e) {
56-
echo $e->getMassege();
57-
}
57+
$rep_1 = (new Representation())->setKiloBitrate(800);
58+
$rep_2 = (new Representation())->setKiloBitrate(300)->setResize(320 , 170);
59+
60+
$ffmpeg->open('/var/www/media/videos/test.mp4') // the path to the video
61+
->DASH()
62+
->X264()
63+
->addRepresentation($rep_1)
64+
->addRepresentation($rep_2)
65+
->setAdaption('id=0,streams=v id=1,streams=a')
66+
->save();
67+
5868
```
5969

70+
For more information about [FFMpeg](https://ffmpeg.org/) and its dash parameters please [click here](https://ffmpeg.org/ffmpeg-formats.html#dash-2).
6071
## HLS
6172

6273
Create an M3U8 playlist to do [HLS](https://en.wikipedia.org/wiki/HTTP_Live_Streaming).
74+
As of version 1.1.0 the ```autoGenerateRepresentations``` method has been added. This method allows you to auto generate multi representations base on original video size and bit rate:
75+
76+
``` php
77+
$ffmpeg->open('/var/www/media/videos/test.mp4') // the path to the video
78+
->HLS()
79+
->X264()
80+
->autoGenerateRepresentations()
81+
->setAdaption('id=0,streams=v id=1,streams=a')
82+
->save();
83+
```
84+
85+
or you can add representation manually by ```addRepresentation``` method:
6386

6487
``` php
65-
try {
66-
$rep_1 = (new Representation())->setKiloBitrate(1000);
67-
$rep_2 = (new Representation())->setKiloBitrate(500)->setResize(640 , 360);
68-
$rep_3 = (new Representation())->setKiloBitrate(200)->setResize(480 , 240);
69-
$ffmpeg->open('/var/www/media/videos/test.mp4')
70-
->HLS()
71-
->X264()
72-
->addRepresentation($rep_1)
73-
->addRepresentation($rep_2)
74-
->addRepresentation($rep_3)
75-
->setStreamMap('v:0,a:0 v:1,a:1')
76-
->save('/var/www/media/videos/test.m3u8');
77-
} catch (Exception $e) {
78-
echo $e->getMassege();
79-
}
88+
$rep_1 = (new Representation())->setKiloBitrate(1000);
89+
$rep_2 = (new Representation())->setKiloBitrate(500)->setResize(640 , 360);
90+
$rep_3 = (new Representation())->setKiloBitrate(200)->setResize(480 , 240);
91+
92+
$ffmpeg->open('/var/www/media/videos/test.mp4') // the path to the video
93+
->HLS()
94+
->X264()
95+
->addRepresentation($rep_1)
96+
->addRepresentation($rep_2)
97+
->addRepresentation($rep_3)
98+
->setStreamMap('v:0,a:0 v:1,a:1')
99+
->save();
80100
```
81101

82102
## Live Streaming
@@ -102,4 +122,4 @@ If you discover a security vulnerability within this package, please send an e-m
102122

103123
## License
104124

105-
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
125+
The MIT License (MIT). Please see [License File](https://github.com/aminyazdanpanah/PHP-FFmpeg-video-streaming/blob/master/LICENSE) for more information.

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@
3434

3535
"require": {
3636
"php": "^7.1.0",
37-
"php-ffmpeg/php-ffmpeg": "^0.13.0"
37+
"php-ffmpeg/php-ffmpeg": "^0.7.0@dev"
3838
}
3939
}

src/AutoRepresentations.php

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
namespace AYazdanpanah\FFMpegStreaming;
4+
5+
use AYazdanpanah\FFMpegStreaming\Exception\Exception;
6+
use FFMpeg\Coordinate\Dimension;
7+
use FFMpeg\FFProbe\DataMapping\Stream;
8+
9+
class AutoRepresentations
10+
{
11+
private $stream;
12+
13+
/**
14+
* AutoRepresentations constructor.
15+
* @param Stream $stream
16+
*/
17+
public function __construct(Stream $stream)
18+
{
19+
$this->stream = $stream;
20+
}
21+
22+
/**
23+
* @return Dimension
24+
*/
25+
private function getDimensions(): Dimension
26+
{
27+
return $this->stream->getDimensions();
28+
}
29+
30+
/**
31+
* @return mixed
32+
* @throws Exception
33+
*/
34+
private function getKiloBitRate(): int
35+
{
36+
if (!$this->stream->has('bit_rate')) {
37+
throw new Exception("Invalid stream");
38+
}
39+
return (int)$this->stream->get('bit_rate') / 1000;
40+
}
41+
42+
/**
43+
* @return array
44+
* @throws Exception
45+
*/
46+
public function get(): array
47+
{
48+
$dimension = $this->getDimensions();
49+
50+
$width = $dimension->getWidth();
51+
$height = $dimension->getHeight();
52+
53+
$param = [
54+
'aspect_ratio' => $width / $height,
55+
'bit_rate' => $this->getKiloBitRate(),
56+
];
57+
58+
if ($height > 1050) {
59+
$representations = [
60+
$this->addRepresentation($param, 4, 240),
61+
$this->addRepresentation($param, 2, 480),
62+
$this->addRepresentation($param, 4 / 3, 720),
63+
$this->addRepresentation($param, 1, $height)
64+
];
65+
} elseif ($height > 700) {
66+
$representations = [
67+
$this->addRepresentation($param, 4, 240),
68+
$this->addRepresentation($param, 2, 360),
69+
$this->addRepresentation($param, 4 / 3, 480),
70+
$this->addRepresentation($param, 1, $height)
71+
];
72+
} elseif ($height > 450) {
73+
$representations = [
74+
$this->addRepresentation($param, 4, 144),
75+
$this->addRepresentation($param, 2, 240),
76+
$this->addRepresentation($param, 4 / 3, 360),
77+
$this->addRepresentation($param, 1, $height)
78+
];
79+
} elseif ($height > 330) {
80+
$representations = [
81+
$this->addRepresentation($param, 3, 144),
82+
$this->addRepresentation($param, 3 / 2, 240),
83+
$this->addRepresentation($param, 1, $height),
84+
null
85+
];
86+
} elseif ($height > 210) {
87+
$representations = [
88+
$this->addRepresentation($param, 2, 144),
89+
$this->addRepresentation($param, 1, $height),
90+
];
91+
} else {
92+
$representations = [
93+
$this->addRepresentation($param, 1, $height),
94+
];
95+
}
96+
97+
return $representations;
98+
}
99+
100+
/**
101+
* @param $param
102+
* @param $divide
103+
* @param $height
104+
* @return Representation
105+
* @internal param $aspect_ratio
106+
* @throws Exception
107+
*/
108+
private function addRepresentation($param, $divide, $height): Representation
109+
{
110+
$width = intval($height * $param['aspect_ratio']);
111+
112+
if ($width % 2 == 1) $width++;
113+
114+
return (new Representation())
115+
->setKiloBitrate(intval($param['bit_rate'] / $divide))
116+
->setResize($width, $height);
117+
}
118+
}

src/DASH.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,6 @@ public function setAdaption(string $adaption): DASH
2626
return $this;
2727
}
2828

29-
/**
30-
* @return array
31-
*/
32-
public function getRepresentations(): array
33-
{
34-
return $this->representations;
35-
}
36-
3729
/**
3830
* @return Filter
3931
*/

src/Export.php

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ abstract class Export
1313
/** @var object */
1414
protected $media;
1515

16-
/** @var object */
17-
protected $format;
18-
1916
/** @var Filter */
2017
protected $filter;
2118

@@ -37,6 +34,26 @@ public function addRepresentation(Representation $representation): Export
3734
return $this;
3835
}
3936

37+
/**
38+
* @return array
39+
*/
40+
public function getRepresentations(): array
41+
{
42+
return $this->representations;
43+
}
44+
45+
/**
46+
* @return $this
47+
* @throws Exception
48+
*/
49+
public function autoGenerateRepresentations()
50+
{
51+
$this->representations = (new AutoRepresentations($this->media->getFirstStream()))
52+
->get();
53+
54+
return $this;
55+
}
56+
4057
/**
4158
* Export constructor.
4259
* @param Media $media
@@ -68,7 +85,7 @@ protected function setFormat($format): Export
6885
* @param string $path
6986
* @return Export
7087
*/
71-
public function save(string $path): Export
88+
public function save(string $path = null): Export
7289
{
7390
$this->setFilter();
7491

@@ -78,7 +95,7 @@ public function save(string $path): Export
7895

7996
$this->media->save(
8097
$this->getFormat(),
81-
$path
98+
$this->getPath($path)
8299
);
83100

84101
return $this;
@@ -89,10 +106,21 @@ public function save(string $path): Export
89106
*/
90107
abstract protected function getFilter(): Filter;
91108

92-
93109
/**
94110
* @return mixed
95111
*/
96112
abstract protected function setFilter();
97113

114+
private function getPath($path): string
115+
{
116+
if (null === $path) {
117+
if ($this instanceof DASH) {
118+
$path = $this->media->getPath() . '.mpd';
119+
} elseif ($this instanceof HLS) {
120+
$path = $this->media->getPath() . '.m3u8';
121+
}
122+
}
123+
124+
return $path;
125+
}
98126
}

src/FFMpeg.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public function __construct($config, $logger = null)
2525
*/
2626
public function open($path): Media
2727
{
28-
return new Media($this->ffmpeg->open($path));
28+
return new Media($this->ffmpeg->open($path), $path);
2929
}
3030

3131
/**

src/HLS.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,6 @@ public function setStreamMap(string $adaption): HLS
2626
return $this;
2727
}
2828

29-
/**
30-
* @return array
31-
*/
32-
public function getRepresentations(): array
33-
{
34-
return $this->representations;
35-
}
36-
3729
/**
3830
* @return Filter
3931
*/

0 commit comments

Comments
 (0)