Skip to content

Commit 76588f4

Browse files
add subtitles
1 parent 8333448 commit 76588f4

File tree

7 files changed

+391
-11
lines changed

7 files changed

+391
-11
lines changed

README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,17 +166,17 @@ See **[HLS section](https://video.aminyazdanpanah.com/start?r=hls#hls)** in the
166166
#### Encryption(DRM)
167167
The encryption process requires some kind of secret (key) together with an encryption algorithm. HLS uses AES in cipher block chaining (CBC) mode. This means each block is encrypted using the ciphertext of the preceding block. [Learn more](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
168168

169-
You must specify a path to save a random key to your local machine and also a URL(or a path) to access the key on your website(the key you will save must be accessible from your website). You must pass both these parameters to the `encryption` method:
169+
You must specify a path to save a random key to your local machine and also specify an URL(or a path) to access the key on your website(the key you will save must be accessible from your website). You must pass both these parameters to the `encryption` method:
170170

171171
##### Single Key
172172
The following code generates a key for all segment files.
173173

174174
```php
175175
//A path you want to save a random key to your local machine
176-
$save_to = '/home/public_html/"PATH TO THE KEY DIRECTORY"/key'
176+
$save_to = '/home/public_html/"PATH TO THE KEY DIRECTORY"/key';
177177

178-
//A URL (or a path) to access the key on your website
179-
$url = 'https://www.aminyazdanpanah.com/?"PATH TO THE KEY DIRECTORY"/key'
178+
//An URL (or a path) to access the key on your website
179+
$url = 'https://www.aminyazdanpanah.com/?"PATH TO THE KEY DIRECTORY"/key';
180180
// or $url = '/"PATH TO THE KEY DIRECTORY"/key';
181181

182182
$video->hls()
@@ -198,6 +198,26 @@ However FFmpeg supports AES encryption for HLS packaging, which you can encrypt
198198

199199
**Besides [Apple's FairPlay](https://developer.apple.com/streaming/fps/)** DRM system, you can also use other DRM systems such as **[Microsoft's PlayReady](https://www.microsoft.com/playready/overview/)** and **[Google's Widevine](https://www.widevine.com/)**.
200200

201+
#### Subtitles
202+
You can add subtitles to a HLS stream using `subtitle` method.
203+
```php
204+
use Streaming\HLSSubtitle;
205+
206+
$persian = new HLSSubtitle('/var/subtitles/subtitles_fa.vtt', 'فارسی', 'fa');
207+
$persian->default();
208+
$english = new HLSSubtitle('/var/subtitles/subtitles_en.vtt', 'english', 'en');
209+
$german = new HLSSubtitle('/var/subtitles/subtitles_de.vtt', 'Deutsch', 'de');
210+
$chinese = new HLSSubtitle('/var/subtitles/subtitles_zh.vtt', '中文', 'zh');
211+
$spanish = new HLSSubtitle('/var/subtitles/subtitles_es.vtt', 'Español', 'es');
212+
213+
$video->hls()
214+
->subtitles([$persian, $english, $german, $chinese, $spanish])
215+
->x264()
216+
->autoGenerateRepresentations([1080, 720])
217+
->save('/var/media/hls-stream.m3u8');
218+
```
219+
**NOTE:** All m3u8 files will be generated using rules based on **[RFC 8216](https://tools.ietf.org/html/rfc8216#section-3.5)**. Only **[WebVTT](https://www.w3.org/TR/webvtt1/)** files are acceptable for now.
220+
201221
### Transcoding
202222
A format can also extend `FFMpeg\Format\ProgressableInterface` to get realtime information about the transcoding.
203223
```php

src/File.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ public static function move(string $src, string $dst): void
127127
static::remove($src);
128128
}
129129

130+
/**
131+
* @param string $src
132+
* @param string $dst
133+
* @param bool $force
134+
*/
135+
public static function copy(string $src, string $dst, bool $force = true): void
136+
{
137+
static::filesystem('copy', [$src, $dst, $force]);
138+
}
139+
130140
/**
131141
* @param $dir
132142
*/

src/HLS.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ class HLS extends Streaming
5353
/** @var array */
5454
private $flags = [];
5555

56+
/** @var array */
57+
private $subtitles = [];
58+
5659
/**
5760
* @return string
5861
*/
@@ -141,6 +144,22 @@ public function encryption(string $save_to, string $url, int $key_rotation_perio
141144
return $this;
142145
}
143146

147+
public function subtitle(HLSSubtitle $subtitle)
148+
{
149+
array_push($this->subtitles, $subtitle);
150+
return $this;
151+
}
152+
153+
/**
154+
* @param array $subtitles
155+
* @return HLS
156+
*/
157+
public function subtitles(array $subtitles): HLS
158+
{
159+
array_walk($subtitles, [$this, 'subtitle']);
160+
return $this;
161+
}
162+
144163
/**
145164
* @return string
146165
*/
@@ -277,6 +296,10 @@ protected function getPath(): string
277296
$path = $this->getFilePath();
278297
$reps = $this->getRepresentations();
279298

299+
if(!empty($this->subtitles)){
300+
$this->generateSubs($path);
301+
}
302+
280303
$this->savePlaylist($path . ".m3u8");
281304

282305
return $path . "_" . $reps->end()->getHeight() . "p.m3u8";
@@ -291,6 +314,34 @@ public function savePlaylist(string $path): void
291314
$mater_playlist->save($this->master_playlist ?? $path, $this->stream_des);
292315
}
293316

317+
/**
318+
* @param string $path
319+
*/
320+
private function generateSubs(string $path)
321+
{
322+
$this->stream_des = array_merge($this->stream_des, [PHP_EOL]);
323+
324+
foreach ($this->subtitles as $subtitle) {
325+
if($subtitle instanceof HLSSubtitle){
326+
$subtitle->generateM3U8File("{$path}_subtitles_{$subtitle->getLanguageCode()}.m3u8", $this->getDuration());
327+
array_push($this->stream_des, (string)$subtitle);
328+
}
329+
}
330+
array_push($this->stream_des, PHP_EOL);
331+
332+
$this->getRepresentations()->map(function (Representation $rep){
333+
return $rep->setHlsStreamInfo(["SUBTITLES" => "\"" . $this->subtitles[0]->getGroupId() . "\""]);
334+
});
335+
}
336+
337+
/**
338+
* @return float
339+
*/
340+
private function getDuration():float
341+
{
342+
return $this->getMedia()->getFormat()->get("duration", 0);
343+
}
344+
294345
/**
295346
* Clear key info file if is a temp file
296347
*/

src/HLSPlaylist.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
namespace Streaming;
1313

1414

15+
use FFMpeg\Exception\ExceptionInterface;
16+
1517
class HLSPlaylist
1618
{
1719
/** @var HLS */
1820
private $hls;
1921

20-
private const DEFAULT_AUDIO_BITRATE = 131072;
22+
private const DEFAULT_AUDIO_BITRATE = 0; //131072;
2123

2224
/**
2325
* HLSPlaylist constructor.
@@ -104,11 +106,15 @@ private function getAudioBitrate(Representation $rep): int
104106
*/
105107
private function getOriginalAudioBitrate(): int
106108
{
107-
return $this->hls
108-
->getMedia()
109-
->getStreams()
110-
->audios()
111-
->first()
112-
->get('bit_rate', static::DEFAULT_AUDIO_BITRATE);
109+
try {
110+
return $this->hls
111+
->getMedia()
112+
->getStreams()
113+
->audios()
114+
->first()
115+
->get('bit_rate', static::DEFAULT_AUDIO_BITRATE);
116+
} catch (ExceptionInterface $e) {
117+
return static::DEFAULT_AUDIO_BITRATE;
118+
}
113119
}
114120
}

0 commit comments

Comments
 (0)