Skip to content

Instantly share code, notes, and snippets.

@martin-juul
Last active December 7, 2019 21:42
Show Gist options
  • Save martin-juul/1bf21487beb9302904bbd2366e295db7 to your computer and use it in GitHub Desktop.
Save martin-juul/1bf21487beb9302904bbd2366e295db7 to your computer and use it in GitHub Desktop.
hls live transcoding
<?php
namespace App\Transcode\FFMpeg;
use Illuminate\Support\Arr;
use Symfony\Component\Process\Process;
abstract class AbstractProcess
{
abstract protected function getBinaryPath(): string;
protected function getProcess(array $args): Process
{
$file = $args[0];
unset($args[0]);
if (!is_file($file) || !is_readable($file)) {
throw new \RuntimeException('Could not read file at ' . $file);
}
$cmd = array_merge([$this->getBinaryPath()], is_array($args) ? Arr::flatten($args, 1) : $args);
$cmd[] = ' ' . $file;
$cmd = escapeshellcmd(implode(' ', $cmd));
return Process::fromShellCommandline(
$cmd,
null,
null,
null,
300
);
return new Process($cmd);
}
}
<?php
namespace App\Transcode\FFMpeg\Output;
use Spatie\DataTransferObject\DataTransferObject;
class Frame extends DataTransferObject
{
/** @var string */
public $type;
/** @var float|int */
public $pkt_pts_time;
/** @var float */
public $best_effort_timestamp_time;
/** @var int */
public $pkt_pos;
/** @var int */
public $pkt_size;
/** @var string */
public $pict_type;
public function __construct(array $parameters = [])
{
foreach ($parameters as $parameter => $value)
{
if (in_array($parameter, ['pkt_pts_time', 'best_effort_timestamp_time'])) {
$parameters[$parameter] = (float)$value;
}
if (in_array($parameter, ['pkt_pos', 'pkt_size']))
{
$parameters[$parameter] = (int)$value;
}
}
parent::__construct($parameters);
}
}
<?php
namespace App\Http\Controllers\Transcode;
use App\Http\Controllers\Controller;
use App\Models\Video;
use App\Transcode\FFMpeg\Probe;
use App\Transcode\HlsIframePlaylist;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
class HlsController extends Controller
{
public function getPlaylist(Request $request, string $id)
{
$video = Video::whereId($id)->firstOrFail();
$playlist = (new HlsIframePlaylist)->buildPlaylist($video);
return response($playlist, 200, [
'Content-Type' => 'application/x-mpegURL',
]);
}
}
<?php
namespace App\Transcode;
use App\Models\Video;
use App\Transcode\FFMpeg\Output\Frame;
class HlsIframePlaylist
{
public function buildPlaylist(Video $video, $targetDuration = 10): string
{
if ($video->playlist) {
return $video->playlist;
}
$iframeData = $this->createIframeSegments($video->getIframes());
$playlist = <<<EOS
#EXTM3U
#EXT-X-TARGETDURATION:{$targetDuration}
#EXT-X-VERSION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-I-FRAMES-ONLY
#EXT-X-PLAYLIST-TYPE:VOD
EOS;
foreach ($iframeData as $index => [$seg_duration, $pkt_size, $pkt_pos, $pkt_time]) {
$playlist .= $this->byteRangeChunk(
$seg_duration,
$pkt_size,
$pkt_pos,
$video->id . '.ts'
);
}
$playlist .= "\n#EXT-X-ENDLIST";
$video->playlist = $playlist;
$video->save();
return $playlist;
}
protected function createIframeSegments(array $packetsAndFrames)
{
[$packets, $frames] = $packetsAndFrames;
$next_pkt_pts_time = null;
$iframeCount = count($frames);
$iframesData = [];
/**
* @var int $index
* @var Frame $iframe
*/
foreach ($frames as $index => $iframe) {
$pkt_pts_time = $next_pkt_pts_time || $iframe->pkt_size;
if ($index < $iframeCount - 1) {
$extinf = bcsub($frames[$index + 1]->best_effort_timestamp_time, $iframe->best_effort_timestamp_time, 5);
} else {
$last_frame_time = end($frames)->best_effort_timestamp_time;
$extinf = bcsub($last_frame_time, $iframe->best_effort_timestamp_time, 5);
}
$iframesData[] = [
$extinf,
$iframe->pkt_size,
$iframe->pkt_pos,
(float)number_format($pkt_pts_time, 5),
];
}
return $iframesData;
}
protected function byteRangeChunk($duration, $size, $pos, $file)
{
$byterange = "$size@$pos";
return "\n#EXTINF:$duration,"
. "\n#EXT-X-BYTERANGE:$byterange\n"
. route('hls.stream', [
'video' => $file,
'byterange' => urlencode($byterange),
]);
}
}
<?php
namespace App\Transcode\FFMpeg\Output;
use Spatie\DataTransferObject\DataTransferObject;
class Packet extends DataTransferObject
{
/** @var string */
public $type;
/** @var string */
public $codec_type;
/** @var float */
public $pts_time;
/** @var int */
public $pos;
public function __construct(array $parameters = [])
{
foreach ($parameters as $parameter => $value) {
if ($parameter === 'pts_time') {
$parameters[$parameter] = (float)$value;
}
if ($parameter === 'pos') {
$parameters[$parameter] = (int)$value;
}
}
parent::__construct($parameters);
}
}
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-I-FRAMES-ONLY
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:8.33333,
#EXT-X-BYTERANGE:1116@236997
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=1116%2540236997
#EXTINF:7.90000,
#EXT-X-BYTERANGE:200477@2155641
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=200477%25402155641
#EXTINF:3.86666,
#EXT-X-BYTERANGE:491651@7764158
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=491651%25407764158
#EXTINF:7.30000,
#EXT-X-BYTERANGE:139243@9938214
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=139243%25409938214
#EXTINF:8.33333,
#EXT-X-BYTERANGE:547319@11385326
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=547319%254011385326
#EXTINF:3.96666,
#EXT-X-BYTERANGE:536936@17259730
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=536936%254017259730
#EXTINF:8.33333,
#EXT-X-BYTERANGE:354768@19863234
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=354768%254019863234
#EXTINF:4.03333,
#EXT-X-BYTERANGE:257759@22381467
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=257759%254022381467
#EXTINF:8.33333,
#EXT-X-BYTERANGE:397608@23582676
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=397608%254023582676
#EXTINF:4.63333,
#EXT-X-BYTERANGE:105090@27059058
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=105090%254027059058
#EXTINF:3.13333,
#EXT-X-BYTERANGE:140856@27818926
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=140856%254027818926
#EXTINF:5.60000,
#EXT-X-BYTERANGE:331704@28534159
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=331704%254028534159
#EXTINF:1.90000,
#EXT-X-BYTERANGE:234508@30585761
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=234508%254030585761
#EXTINF:2.16666,
#EXT-X-BYTERANGE:421589@30984547
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=421589%254030984547
#EXTINF:2.06666,
#EXT-X-BYTERANGE:98867@31675106
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=98867%254031675106
#EXTINF:4.43333,
#EXT-X-BYTERANGE:285812@32420439
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=285812%254032420439
#EXTINF:8.33333,
#EXT-X-BYTERANGE:130415@35330810
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=130415%254035330810
#EXTINF:1.43333,
#EXT-X-BYTERANGE:215534@37233295
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=215534%254037233295
#EXTINF:1.66666,
#EXT-X-BYTERANGE:269017@37587388
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=269017%254037587388
#EXTINF:8.33333,
#EXT-X-BYTERANGE:235075@38475983
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=235075%254038475983
#EXTINF:4.16666,
#EXT-X-BYTERANGE:463454@39786703
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=463454%254039786703
#EXTINF:8.33333,
#EXT-X-BYTERANGE:115667@41246719
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=115667%254041246719
#EXTINF:5.73333,
#EXT-X-BYTERANGE:56969@43252190
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=56969%254043252190
#EXTINF:2.90000,
#EXT-X-BYTERANGE:269913@45355451
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=269913%254045355451
#EXTINF:2.60000,
#EXT-X-BYTERANGE:204815@46837960
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=204815%254046837960
#EXTINF:3.40000,
#EXT-X-BYTERANGE:229270@47880429
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=229270%254047880429
#EXTINF:8.33333,
#EXT-X-BYTERANGE:253025@48789297
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=253025%254048789297
#EXTINF:8.33333,
#EXT-X-BYTERANGE:266944@51669856
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=266944%254051669856
#EXTINF:2.83333,
#EXT-X-BYTERANGE:203013@55013957
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=203013%254055013957
#EXTINF:2.73333,
#EXT-X-BYTERANGE:876612@55949169
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=876612%254055949169
#EXTINF:6.90000,
#EXT-X-BYTERANGE:313572@57120897
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=313572%254057120897
#EXTINF:4.83333,
#EXT-X-BYTERANGE:395026@59617927
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=395026%254059617927
#EXTINF:1.46666,
#EXT-X-BYTERANGE:304506@60682166
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=304506%254060682166
#EXTINF:1.00000,
#EXT-X-BYTERANGE:108734@61384299
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=108734%254061384299
#EXTINF:2.93333,
#EXT-X-BYTERANGE:312382@61709061
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=312382%254061709061
#EXTINF:1.76666,
#EXT-X-BYTERANGE:146588@62856106
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=146588%254062856106
#EXTINF:1.56666,
#EXT-X-BYTERANGE:294259@63211538
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=294259%254063211538
#EXTINF:6.56666,
#EXT-X-BYTERANGE:113003@63990927
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=113003%254063990927
#EXTINF:1.60000,
#EXT-X-BYTERANGE:257551@65322540
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=257551%254065322540
#EXTINF:2.76666,
#EXT-X-BYTERANGE:259248@66340007
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=259248%254066340007
#EXTINF:8.33333,
#EXT-X-BYTERANGE:271612@67205422
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=271612%254067205422
#EXTINF:5.83333,
#EXT-X-BYTERANGE:155380@71409468
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=155380%254071409468
#EXTINF:2.26666,
#EXT-X-BYTERANGE:96993@73607648
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=96993%254073607648
#EXTINF:2.90000,
#EXT-X-BYTERANGE:127215@74942282
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=127215%254074942282
#EXTINF:4.33333,
#EXT-X-BYTERANGE:188788@75541950
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=188788%254075541950
#EXTINF:1.76666,
#EXT-X-BYTERANGE:159486@76826521
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=159486%254076826521
#EXTINF:1.53333,
#EXT-X-BYTERANGE:191336@77173651
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=191336%254077173651
#EXTINF:1.40000,
#EXT-X-BYTERANGE:151381@77832313
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=151381%254077832313
#EXTINF:4.93333,
#EXT-X-BYTERANGE:157407@78218674
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=157407%254078218674
#EXTINF:6.70000,
#EXT-X-BYTERANGE:161860@81597562
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=161860%254081597562
#EXTINF:3.30000,
#EXT-X-BYTERANGE:95191@83539249
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=95191%254083539249
#EXTINF:2.46666,
#EXT-X-BYTERANGE:682367@84261876
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=682367%254084261876
#EXTINF:3.66666,
#EXT-X-BYTERANGE:128344@86235867
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=128344%254086235867
#EXTINF:2.53333,
#EXT-X-BYTERANGE:612818@87557879
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=612818%254087557879
#EXTINF:8.33333,
#EXT-X-BYTERANGE:196327@88440986
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=196327%254088440986
#EXTINF:1.23333,
#EXT-X-BYTERANGE:158218@90213316
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=158218%254090213316
#EXTINF:1.46666,
#EXT-X-BYTERANGE:560512@90701653
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=560512%254090701653
#EXTINF:7.26666,
#EXT-X-BYTERANGE:423157@92030120
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=423157%254092030120
#EXTINF:1.23333,
#EXT-X-BYTERANGE:79874@95625809
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=79874%254095625809
#EXTINF:1.66666,
#EXT-X-BYTERANGE:76807@95960562
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=76807%254095960562
#EXTINF:1.66666,
#EXT-X-BYTERANGE:380137@96730376
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=380137%254096730376
#EXTINF:1.66666,
#EXT-X-BYTERANGE:107783@97477701
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=107783%254097477701
#EXTINF:1.66666,
#EXT-X-BYTERANGE:339474@97826092
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=339474%254097826092
#EXTINF:0.83333,
#EXT-X-BYTERANGE:117720@98630659
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=117720%254098630659
#EXTINF:1.66666,
#EXT-X-BYTERANGE:548266@98996533
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=548266%254098996533
#EXTINF:1.66666,
#EXT-X-BYTERANGE:97775@100024357
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=97775%2540100024357
#EXTINF:1.66666,
#EXT-X-BYTERANGE:250320@100437204
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=250320%2540100437204
#EXTINF:1.66666,
#EXT-X-BYTERANGE:228358@101105883
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=228358%2540101105883
#EXTINF:4.16666,
#EXT-X-BYTERANGE:184834@101619619
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=184834%2540101619619
#EXTINF:5.63333,
#EXT-X-BYTERANGE:442199@102852538
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=442199%2540102852538
#EXTINF:1.96666,
#EXT-X-BYTERANGE:81965@106472514
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=81965%2540106472514
#EXTINF:1.76666,
#EXT-X-BYTERANGE:349620@107140271
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=349620%2540107140271
#EXTINF:1.70000,
#EXT-X-BYTERANGE:338079@108230701
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=338079%2540108230701
#EXTINF:3.30000,
#EXT-X-BYTERANGE:183802@109275321
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=183802%2540109275321
#EXTINF:7.50000,
#EXT-X-BYTERANGE:581891@110626283
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=581891%2540110626283
#EXTINF:3.33333,
#EXT-X-BYTERANGE:141960@112270274
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=141960%2540112270274
#EXTINF:1.56666,
#EXT-X-BYTERANGE:234545@113742541
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=234545%2540113742541
#EXTINF:8.10000,
#EXT-X-BYTERANGE:150285@114239742
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=150285%2540114239742
#EXTINF:3.13333,
#EXT-X-BYTERANGE:405984@118388911
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=405984%2540118388911
#EXTINF:4.16666,
#EXT-X-BYTERANGE:544118@120082061
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=544118%2540120082061
#EXTINF:4.70000,
#EXT-X-BYTERANGE:273771@121727257
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=273771%2540121727257
#EXTINF:2.00000,
#EXT-X-BYTERANGE:243914@124462924
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=243914%2540124462924
#EXTINF:2.96666,
#EXT-X-BYTERANGE:158270@125643964
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=158270%2540125643964
#EXTINF:1.53333,
#EXT-X-BYTERANGE:210035@127321208
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=210035%2540127321208
#EXTINF:8.33333,
#EXT-X-BYTERANGE:287673@127745739
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=287673%2540127745739
#EXTINF:2.30000,
#EXT-X-BYTERANGE:242443@132239342
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=242443%2540132239342
#EXTINF:5.43333,
#EXT-X-BYTERANGE:141449@133116714
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=141449%2540133116714
#EXTINF:8.33333,
#EXT-X-BYTERANGE:422815@134522096
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=422815%2540134522096
#EXTINF:8.33333,
#EXT-X-BYTERANGE:271537@139341026
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=271537%2540139341026
#EXTINF:8.33333,
#EXT-X-BYTERANGE:400137@145096828
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=400137%2540145096828
#EXTINF:6.53333,
#EXT-X-BYTERANGE:352487@151079519
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=352487%2540151079519
#EXTINF:1.40000,
#EXT-X-BYTERANGE:274085@155195915
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=274085%2540155195915
#EXTINF:2.66666,
#EXT-X-BYTERANGE:316713@155982381
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=316713%2540155982381
#EXTINF:2.96666,
#EXT-X-BYTERANGE:387155@156718059
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=387155%2540156718059
#EXTINF:2.83333,
#EXT-X-BYTERANGE:299723@157896891
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=299723%2540157896891
#EXTINF:8.33333,
#EXT-X-BYTERANGE:222487@158765813
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=222487%2540158765813
#EXTINF:1.30000,
#EXT-X-BYTERANGE:222564@160231852
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=222564%2540160231852
#EXTINF:1.70000,
#EXT-X-BYTERANGE:118584@160667576
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=118584%2540160667576
#EXTINF:2.00000,
#EXT-X-BYTERANGE:737474@161146119
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=737474%2540161146119
#EXTINF:1.63333,
#EXT-X-BYTERANGE:168961@162104810
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=168961%2540162104810
#EXTINF:3.56666,
#EXT-X-BYTERANGE:170163@162544078
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=170163%2540162544078
#EXTINF:5.26666,
#EXT-X-BYTERANGE:47559@163702766
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=47559%2540163702766
#EXTINF:5.46666,
#EXT-X-BYTERANGE:569518@164946795
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=569518%2540164946795
#EXTINF:1.70000,
#EXT-X-BYTERANGE:205624@166615144
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=205624%2540166615144
#EXTINF:4.00000,
#EXT-X-BYTERANGE:242783@167501684
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=242783%2540167501684
#EXTINF:1.20000,
#EXT-X-BYTERANGE:217699@168990275
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=217699%2540168990275
#EXTINF:2.70000,
#EXT-X-BYTERANGE:265375@169548777
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=265375%2540169548777
#EXTINF:1.83333,
#EXT-X-BYTERANGE:182174@170319434
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=182174%2540170319434
#EXTINF:2.46666,
#EXT-X-BYTERANGE:563374@171970269
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=563374%2540171970269
#EXTINF:2.10000,
#EXT-X-BYTERANGE:67000@175500682
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=67000%2540175500682
#EXTINF:1.06666,
#EXT-X-BYTERANGE:584933@176113759
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=584933%2540176113759
#EXTINF:1.80000,
#EXT-X-BYTERANGE:219445@178581800
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=219445%2540178581800
#EXTINF:4.40000,
#EXT-X-BYTERANGE:57660@179396574
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=57660%2540179396574
#EXTINF:2.46666,
#EXT-X-BYTERANGE:70602@184211142
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=70602%2540184211142
#EXTINF:4.43333,
#EXT-X-BYTERANGE:98644@185658397
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=98644%2540185658397
#EXTINF:4.30000,
#EXT-X-BYTERANGE:145445@187014416
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=145445%2540187014416
#EXTINF:6.86666,
#EXT-X-BYTERANGE:186215@191271724
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=186215%2540191271724
#EXTINF:6.53333,
#EXT-X-BYTERANGE:234544@193190363
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=234544%2540193190363
#EXTINF:8.33333,
#EXT-X-BYTERANGE:141672@195043608
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=141672%2540195043608
#EXTINF:4.70000,
#EXT-X-BYTERANGE:235319@201514671
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=235319%2540201514671
#EXTINF:1.53333,
#EXT-X-BYTERANGE:148495@204788600
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=148495%2540204788600
#EXTINF:7.33333,
#EXT-X-BYTERANGE:391939@205123957
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=391939%2540205123957
#EXTINF:1.46666,
#EXT-X-BYTERANGE:178236@207300877
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=178236%2540207300877
#EXTINF:2.16666,
#EXT-X-BYTERANGE:42612@207649470
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=42612%2540207649470
#EXTINF:2.46666,
#EXT-X-BYTERANGE:175057@207921113
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=175057%2540207921113
#EXTINF:4.23333,
#EXT-X-BYTERANGE:371430@208888453
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=371430%2540208888453
#EXTINF:8.33333,
#EXT-X-BYTERANGE:35283@209908619
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=35283%2540209908619
#EXTINF:8.33333,
#EXT-X-BYTERANGE:76435@211586766
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=76435%2540211586766
#EXTINF:8.33333,
#EXT-X-BYTERANGE:129695@214328553
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=129695%2540214328553
#EXTINF:8.33333,
#EXT-X-BYTERANGE:112518@217929090
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=112518%2540217929090
#EXTINF:8.33333,
#EXT-X-BYTERANGE:113725@221630213
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=113725%2540221630213
#EXTINF:8.33333,
#EXT-X-BYTERANGE:81391@224983266
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=81391%2540224983266
#EXTINF:8.33333,
#EXT-X-BYTERANGE:263083@229630445
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=263083%2540229630445
#EXTINF:8.33333,
#EXT-X-BYTERANGE:292508@234610910
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=292508%2540234610910
#EXTINF:8.33333,
#EXT-X-BYTERANGE:313745@241010226
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=313745%2540241010226
#EXTINF:8.33333,
#EXT-X-BYTERANGE:124565@246794050
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=124565%2540246794050
#EXTINF:8.33333,
#EXT-X-BYTERANGE:126713@250065934
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=126713%2540250065934
#EXTINF:8.33333,
#EXT-X-BYTERANGE:361475@256042112
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=361475%2540256042112
#EXTINF:8.33333,
#EXT-X-BYTERANGE:295967@263460657
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=295967%2540263460657
#EXTINF:8.33333,
#EXT-X-BYTERANGE:254226@269871512
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=254226%2540269871512
#EXTINF:7.13333,
#EXT-X-BYTERANGE:29907@272417671
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=29907%2540272417671
#EXTINF:8.33333,
#EXT-X-BYTERANGE:43273@272990149
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=43273%2540272990149
#EXTINF:0.00000,
#EXT-X-BYTERANGE:51011@274397658
http://127.0.0.1:8000/stream/bbb_sunflower_1080p_30fps_normal.mp4?byterange=51011%2540274397658
#EXT-X-ENDLIST
<?php
namespace App\Transcode\FFMpeg;
use App\Transcode\FFMpeg\Output\AudioStreamOutput;
use App\Transcode\FFMpeg\Output\Frame;
use App\Transcode\FFMpeg\Output\Packet;
use App\Transcode\FFMpeg\Output\ProbeOutput;
use App\Transcode\FFMpeg\Output\VideoStreamFrameOutput;
use App\Transcode\FFMpeg\Output\VideoStreamOutput;
use Symfony\Component\Process\Exception\ProcessFailedException;
class Probe extends AbstractProcess
{
public const TYPE_STREAMS = 'streams';
public const TYPE_FORMAT = 'format';
public const TYPE_VIDEO_FORMAT = 'video_format';
/**
* @param string $filePath
*
* @return null|ProbeOutput
* @throws ProcessFailedException
* @throws \RuntimeException
*/
public function format(string $filePath)
{
return $this->probe($filePath, '-show_format', self::TYPE_FORMAT);
}
/**
* @param string $filePath
*
* @return (AudioStreamOutput|AudioStreamOutput)[]|null
*/
public function streams(string $filePath)
{
return $this->probe($filePath, '-show_streams', self::TYPE_STREAMS);
}
/**
* @param string $filePath
*
* @return array
*/
public function frames(string $filePath)
{
$flags = [
'-loglevel',
'error',
'-select_streams',
'v',
'-skip_frame',
'nokey',
'-show_entries',
'packet=pts_time,codec_type,pos:frame=pict_type,pkt_pts_time,pkt_size,pkt_pos,best_effort_timestamp_time',
'-of',
'json',
];
$probe = $this->probe($filePath, $flags, self::TYPE_VIDEO_FORMAT);
$probe = json_decode($probe, true);
$packets = [];
$frames = [];
foreach ($probe['packets_and_frames'] as $item) {
if ($item['type'] === 'packet' && $item['codec_type'] === 'video') {
$packets[] = new Packet($item);
}
if ($item['type'] === 'frame' && $item['pict_type'] === 'I') {
$frames[] = new Frame($item);
}
}
return [$packets, $frames];
}
/**
* @param string $filePath
* @param string|array $command
* @param string $type
* @param bool $json
*
* @return ProbeOutput|VideoStreamFrameOutput|AudioStreamOutput|VideoStreamOutput|null
*/
protected function probe(string $filePath, $command, string $type, $json = false)
{
if (!is_file($filePath)) {
throw new \RuntimeException('File does not exist at ' . $filePath);
}
$args = [0 => $filePath, 1 => $command];
if ($json) {
$args[] = '-print_format json';
$args[] = 'json';
}
$proc = $this->getProcess($args);
$proc->mustRun();
switch ($type) {
case self::TYPE_FORMAT:
$outputParser = new ProbeFormatOutputParser();
break;
case self::TYPE_STREAMS:
$outputParser = new ProbeStreamsOutputParser();
break;
case self::TYPE_VIDEO_FORMAT:
$outputParser = new ProbeVideoFormatOutputParser();
break;
}
if (!isset($outputParser)) {
return null;
}
return $outputParser->parse($proc->getOutput());
}
protected function getBinaryPath(): string
{
return config('transcoding.ffprobe_bin');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment