protonemedia / laravel-ffmpeg

This package provides an integration with FFmpeg for Laravel. Laravel's Filesystem handles the storage of the files.
https://protone.media/en/blog/how-to-use-ffmpeg-in-your-laravel-projects
MIT License
1.64k stars 194 forks source link

[Discussion] Rewrite of the package #158

Closed pascalbaljet closed 4 years ago

pascalbaljet commented 4 years ago

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!

Nks commented 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.

Nks commented 4 years ago

Also this will be really helpful to have ability to rewrite default HLS playlist.

Nks commented 4 years ago

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.

pascalbaljet commented 4 years ago

Thanks @Nks!

Nks commented 4 years ago

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?

pascalbaljet commented 4 years ago

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"