使用Laravel将youtube-dl输出流式传输到S3

时间:2019-01-25 14:05:42

标签: php laravel youtube-dl

背景:

我正在使用Laravel 5.3

我正在使用youtube-dlSymfony Process下载YouTube视频:

$command = '/usr/local/bin/youtube-dl -o '.$new_file_path.' '.$youtube_id;
$process = new Process($command);
$process->setTimeout(null);
$process->run();

运行Process之后,将下载的文件放在预期的位置。现在,我可以将其存储到S3中,如下所示:

\Storage::disk('s3')->putFile($s3_location, new File($new_file_path));

问题

如您所见,我正在将文件下载到本地存储,然后上传到S3。如果我可以直接写到S3,那就太好了。尤其是因为两个组件都支持流传输-Process类可以流输出,而S3 Storage可以存储流,如下所示:

// Process class supports streamed output
// https://symfony.com/doc/current/components/process.html

// note the '-' after '-o' parameter - it asks youtube-dl to give a stream output, which can be piped in a shell
$process = new Process('/usr/local/bin/youtube-dl -o - '.$youtube_id;);
$process->start();

foreach ($process as $type => $data) {
    if ($process::OUT === $type) {
        echo "\nRead from stdout: ".$data;
    } else { // $process::ERR === $type
        echo "\nRead from stderr: ".$data;
    }
}

然后

// S3 Storage supports streams
// https://laravel.com/docs/5.3/filesystem#storing-files
Storage::put('file.jpg', $resource);

我的问题是-是否可以将Process类的流输出包装为Resource / Stream对象,并将其传递给S3 Storage?

1 个答案:

答案 0 :(得分:0)

更正:由于file_get_contents将继续到达EOF

,因此脚本实际上上载了所有可用的块。

您需要确保有足够的可用内存,因为脚本无法处理可用内存的总大小与视频的总大小。

请注意,由于我没有s3帐户,因此我并未对此进行实际测试,请让我知道是否有任何问题可以纠正答案。

// create ramdrive
// bash $ mkdir /mnt/ram_disk
// bash $ mount -t tmpfs -o size=1024m new_ram_disk /mnt/ram_disk

$array_of_youtube_ids = ['abc001', 'abc002' , 'abc003'];
$storage_path = '/mnt/ram_disk/';



// start all downloads
$index = 0;
foreach ($array_of_youtube_ids as $id){

    $youtube_dls$index] = new YouTubeDlAsync($storage_path.$id, $id);
    $youtube_dls[$index]->start();
    $index ++;
}


// upload all downloads
$index = 0;
foreach ($array_of_youtube_ids as $id){

    $s3uploads[$index] = new UploadToS3($storage_path.$id, $resource);
    $s3uploads[$index]->start();

    $index ++;
}

// Wait for all downloads to finish
foreach ($youtube_dls as $youtube_dl)
    $youtube_dl->join();

// Wait for all uploads to finish
foreach ($s3uploads as $s3upload)
    $s3upload->join();

class YouTubeDlAsync extends Thread {

    public function __construct($new_file_path, $youtube_id) {
        $command = '/usr/local/bin/youtube-dl -o '.$new_file_path.' '.$youtube_id;
        exec($command);
    }
}

class UploadToS3 extends Thread {

    public function __construct($new_file_path, $resource) {
        Storage::put(file_get_contents('file.jpg'), $resource);
    }
}