Skip to content

Commit

Permalink
add subtitles
Browse files Browse the repository at this point in the history
  • Loading branch information
aminyazdanpanah committed Sep 17, 2020
1 parent 8333448 commit 76588f4
Show file tree
Hide file tree
Showing 7 changed files with 391 additions and 11 deletions.
28 changes: 24 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,17 +166,17 @@ See **[HLS section](https://video.aminyazdanpanah.com/start?r=hls#hls)** in the
#### Encryption(DRM)
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)

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:
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:

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

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

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

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

**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/)**.

#### Subtitles
You can add subtitles to a HLS stream using `subtitle` method.
```php
use Streaming\HLSSubtitle;

$persian = new HLSSubtitle('/var/subtitles/subtitles_fa.vtt', 'فارسی', 'fa');
$persian->default();
$english = new HLSSubtitle('/var/subtitles/subtitles_en.vtt', 'english', 'en');
$german = new HLSSubtitle('/var/subtitles/subtitles_de.vtt', 'Deutsch', 'de');
$chinese = new HLSSubtitle('/var/subtitles/subtitles_zh.vtt', '中文', 'zh');
$spanish = new HLSSubtitle('/var/subtitles/subtitles_es.vtt', 'Español', 'es');

$video->hls()
->subtitles([$persian, $english, $german, $chinese, $spanish])
->x264()
->autoGenerateRepresentations([1080, 720])
->save('/var/media/hls-stream.m3u8');
```
**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.

### Transcoding
A format can also extend `FFMpeg\Format\ProgressableInterface` to get realtime information about the transcoding.
```php
Expand Down
10 changes: 10 additions & 0 deletions src/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ public static function move(string $src, string $dst): void
static::remove($src);
}

/**
* @param string $src
* @param string $dst
* @param bool $force
*/
public static function copy(string $src, string $dst, bool $force = true): void
{
static::filesystem('copy', [$src, $dst, $force]);
}

/**
* @param $dir
*/
Expand Down
51 changes: 51 additions & 0 deletions src/HLS.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ class HLS extends Streaming
/** @var array */
private $flags = [];

/** @var array */
private $subtitles = [];

/**
* @return string
*/
Expand Down Expand Up @@ -141,6 +144,22 @@ public function encryption(string $save_to, string $url, int $key_rotation_perio
return $this;
}

public function subtitle(HLSSubtitle $subtitle)
{
array_push($this->subtitles, $subtitle);
return $this;
}

/**
* @param array $subtitles
* @return HLS
*/
public function subtitles(array $subtitles): HLS
{
array_walk($subtitles, [$this, 'subtitle']);
return $this;
}

/**
* @return string
*/
Expand Down Expand Up @@ -277,6 +296,10 @@ protected function getPath(): string
$path = $this->getFilePath();
$reps = $this->getRepresentations();

if(!empty($this->subtitles)){
$this->generateSubs($path);
}

$this->savePlaylist($path . ".m3u8");

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

/**
* @param string $path
*/
private function generateSubs(string $path)
{
$this->stream_des = array_merge($this->stream_des, [PHP_EOL]);

foreach ($this->subtitles as $subtitle) {
if($subtitle instanceof HLSSubtitle){
$subtitle->generateM3U8File("{$path}_subtitles_{$subtitle->getLanguageCode()}.m3u8", $this->getDuration());
array_push($this->stream_des, (string)$subtitle);
}
}
array_push($this->stream_des, PHP_EOL);

$this->getRepresentations()->map(function (Representation $rep){
return $rep->setHlsStreamInfo(["SUBTITLES" => "\"" . $this->subtitles[0]->getGroupId() . "\""]);
});
}

/**
* @return float
*/
private function getDuration():float
{
return $this->getMedia()->getFormat()->get("duration", 0);
}

/**
* Clear key info file if is a temp file
*/
Expand Down
20 changes: 13 additions & 7 deletions src/HLSPlaylist.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
namespace Streaming;


use FFMpeg\Exception\ExceptionInterface;

class HLSPlaylist
{
/** @var HLS */
private $hls;

private const DEFAULT_AUDIO_BITRATE = 131072;
private const DEFAULT_AUDIO_BITRATE = 0; //131072;

/**
* HLSPlaylist constructor.
Expand Down Expand Up @@ -104,11 +106,15 @@ private function getAudioBitrate(Representation $rep): int
*/
private function getOriginalAudioBitrate(): int
{
return $this->hls
->getMedia()
->getStreams()
->audios()
->first()
->get('bit_rate', static::DEFAULT_AUDIO_BITRATE);
try {
return $this->hls
->getMedia()
->getStreams()
->audios()
->first()
->get('bit_rate', static::DEFAULT_AUDIO_BITRATE);
} catch (ExceptionInterface $e) {
return static::DEFAULT_AUDIO_BITRATE;
}
}
}
Loading

0 comments on commit 76588f4

Please sign in to comment.