Closed pascalbaljet closed 4 years ago
Here my old solution to store HLS for non-local disks:
private function syncWithGcs(string $path): void
{
$localStorage = Storage::disk(Video::$streamDisk);
$remoteStorage = Storage::disk(Video::$gcsStreamDisk);
if (!$localStorage->exists($path)) {
$this->error(sprintf(' Directory %s does not exists', $localStorage->path($path)));
return;
}
$contents = $localStorage->listContents($path, true);
$this->info(sprintf(' Starting copy stream to the GCS'));
$bar = $this->output->createProgressBar(count($contents));
foreach ($contents as $entry) {
$update = false;
if (!$remoteStorage->has($entry['path']) ||
($localStorage->getTimestamp($entry['path']) !== $remoteStorage->getTimestamp($entry['path']))) {
$update = true;
}
if ($update) {
$bar->setMessage(sprintf(' Copying %s to GCS', $entry['path']));
//Copy the local data to the google cloud CDN.
$remoteStorage->putStream($entry['path'], $localStorage->readStream($entry['path']), [
'metadata' => $this->getMetaDataForEntry($entry),
'visibility' => 'public',
]);
$bar->setMessage(sprintf(' Copied %s', $entry['path']));
}
$bar->advance();
}
$bar->finish();
$this->line('');
$this->info(sprintf(' All files copied to the GCS'));
$this->video->storage = Video::$gcsStreamDisk;
if ($this->video->save()) {
$localStorage->deleteDirectory($path);
Video::flushCache();
}
}
Also GCS, for example, asking for the metadata. Not sure about AWS:
private function getMetaDataForEntry(array $entry): array
{
if (!Arr::has($entry, ['path', 'extension'])) {
return [];
}
$localStorage = Storage::disk(Video::$streamDisk);
$contentType = 'text/plain';
if (!$localStorage->exists($entry['path'])) {
return [];
}
$ext = strtolower($entry['extension']);
switch ($ext) {
case 'm3u8':
$contentType = 'application/vnd.apple.mpegurl';
break;
case 'ts':
$contentType = 'video/mp2t';
break;
}
return [
'contentType' => $contentType,
'cacheControl' => 'no-cache',
];
}
Maybe this helps.
Also this will be really helpful to have ability to rewrite default HLS playlist.
Also note: for the GCS if we need to save files on it we also need allow cors. Here the file:
[
{
"origin": [
"https://domain.ltd",
],
"responseHeader": [
"Content-Type"
],
"method": [
"GET",
"HEAD",
"DELETE"
],
"maxAgeSeconds": 3600
}
]
And command:
gsutil cors set cors.json gs://gcs-storage
I think this should be documented for GCS support.
Thanks @Nks!
One other suggestion: Current workflow needed download file to the temp directory for transcode it locally. e.g. if we need convert file to HLS and create thumbnail for it then we copying file to the local, converting it, uploading to the GCS again. Same for the thumbnail. If file is big we making 2 requests to download the file: for HLS transcode and for thumbnail. This will be really helpful add an ability transcode video and generate thumbnail in one request. What do you think?
I've rewritten the package and it has support for HLS to external disks. Could you test the v7
branch? Almost no breaking changes except for some filter stuff in HLS exports.
https://github.com/pascalbaljetmedia/laravel-ffmpeg/tree/v7
composer require "pbmedia/laravel-ffmpeg:v7.x-dev"
In the coming weeks I'll be rewriting this package from scratch. We've used the underlying PHP-FFMpeg package for many years now (and with great success!) but the dependency problems are getting harder every release. Besides that, we need more flexibility to implement some of the most requested features. Here are some of the features I think would be great to have:
Is there anything I've missed or do you have a great idea? Please share!