From b2ffb28fd3c8ede47a9756e2d81d915ea8961031 Mon Sep 17 00:00:00 2001 From: alex-phillips Date: Sat, 21 May 2016 11:38:16 -0400 Subject: [PATCH] added support for determining to transcode or not via the URL as well as specifying the bitrate, also added support for starting transcode stream at specific point in time of the file --- app/Http/Controllers/API/SongController.php | 17 ++++++++++++--- app/Http/Streamers/TranscodingStreamer.php | 24 +++++++++++++++++++-- app/Http/routes.php | 2 +- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/API/SongController.php b/app/Http/Controllers/API/SongController.php index ee3d4381..c747b9bb 100644 --- a/app/Http/Controllers/API/SongController.php +++ b/app/Http/Controllers/API/SongController.php @@ -18,10 +18,21 @@ class SongController extends Controller * * @param Song $song */ - public function play(Song $song) + public function play(Song $song, $transcode = null, $bitrate = null) { - if (ends_with(mime_content_type($song->path), 'flac')) { - return (new TranscodingStreamer($song))->stream(); + if (is_null($bitrate)) { + $bitrate = env('OUTPUT_BIT_RATE', 128); + } + + // If transcode parameter isn't passed, the default is to only transcode flac + if (is_null($transcode) && ends_with(mime_content_type($song->path), 'flac')) { + $transcode = true; + } else { + $transcode = (bool) $transcode; + } + + if ($transcode) { + return (new TranscodingStreamer($song, $bitrate, request()->input('time', 0)))->stream(); } switch (env('STREAMING_METHOD')) { diff --git a/app/Http/Streamers/TranscodingStreamer.php b/app/Http/Streamers/TranscodingStreamer.php index 77935023..53ff06a9 100644 --- a/app/Http/Streamers/TranscodingStreamer.php +++ b/app/Http/Streamers/TranscodingStreamer.php @@ -6,9 +6,25 @@ use App\Models\Song; class TranscodingStreamer extends Streamer implements StreamerInterface { - public function __construct(Song $song) + /** + * Bitrate which the stream should be transcoded as. + * + * @var int + */ + private $bitrate; + + /** + * Time point to start transcoding from. + * + * @var int + */ + private $startTime; + + public function __construct(Song $song, $bitrate, $startTime = 0) { parent::__construct($song); + $this->bitrate = $bitrate; + $this->startTime = $startTime; } /** @@ -20,7 +36,7 @@ class TranscodingStreamer extends Streamer implements StreamerInterface abort(500, 'Transcoding requires valid ffmpeg settings.'); } - $bitRate = filter_var(env('OUTPUT_BIT_RATE', 128), FILTER_SANITIZE_NUMBER_INT); + $bitRate = filter_var($this->bitrate, FILTER_SANITIZE_NUMBER_INT); // Since we can't really know the content length of a file while it's still being transcoded, // "calculating" it (like below) will be much likely to result in net::ERR_CONTENT_LENGTH_MISMATCH errors. @@ -42,6 +58,10 @@ class TranscodingStreamer extends Streamer implements StreamerInterface '-', ]; + if ($this->startTime) { + array_unshift($args, "-ss {$this->startTime}"); + } + passthru("$ffmpeg ".implode($args, ' ')); } } diff --git a/app/Http/routes.php b/app/Http/routes.php index 006ad27a..dcab65ce 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -22,7 +22,7 @@ Route::group(['prefix' => 'api', 'namespace' => 'API'], function () { Route::post('settings', 'SettingController@store'); - Route::get('{song}/play', 'SongController@play'); + Route::get('{song}/play/{transcode?}/{bitrate?}', 'SongController@play'); Route::post('{song}/scrobble/{timestamp}', 'ScrobbleController@store')->where([ 'timestamp' => '\d+', ]);