当用户继续在youtube中观看时,需要显示s3的视频,但它完全加载,然后在laravel phps3中播放



使用这个类,我在laravel网站上显示我的视频,但视频首先被完全加载,然后开始播放,但我需要在用户继续观看时播放,就像在youtube上一样。请帮我解决这个问题。如何在不加载完整视频的情况下立即播放视频?

class S3FileStream
{
/**
* @var LeagueFlysystemAwsS3v3AwsS3Adapter
*/
private $adapter;
/**
* @var AwsS3S3Client
*/
private $client;
/**
* @var file end byte
*/
private $end;
/**
* @var string
*/
private $filePath;
/**
* @var bool storing if request is a range (or a full file)
*/
private $isRange = false;
/**
* @var length of bytes requested
*/
private $length;
/**
* @var
*/
private $return_headers = [];
/**
* @var file size
*/
private $size;
/**
* @var start byte
*/
private $start;
/**
* S3FileStream constructor.
* @param string $filePath
* @param string $adapter
*/
public function __construct(string $filePath, string $adapter = 's3')
{
$this->filePath   = $filePath;
$this->filesystem = Storage::disk($adapter)->getDriver();
$this->adapter    = Storage::disk($adapter)->getAdapter();
$this->client     = $this->adapter->getClient();
}
/**
* Output file to client
*/
public function output()
{
return $this->setHeaders()->stream();
}
/**
* Output headers to client
* @return $this
*/
protected function setHeaders()
{
$object = $this->client->headObject([
'Bucket' => $this->adapter->getBucket(),
'Key'    => $this->filePath,
]);
$this->start = 0;
$this->size  = $object['ContentLength'];
$this->end   = $this->size - 1;
//Set headers
$this->return_headers                        = [];
$this->return_headers['Last-Modified']       = $object['LastModified'];
$this->return_headers['Accept-Ranges']       = 'bytes';
$this->return_headers['Content-Type']        = $object['ContentType'];
$this->return_headers['Content-Disposition'] = 'inline; filename=' . basename($this->filePath);
if (!is_null(request()->server('HTTP_RANGE'))) {
$c_start = $this->start;
$c_end   = $this->end;
[$_, $range] = explode('=', request()->server('HTTP_RANGE'), 2);
if (strpos($range, ',') !== false) {
headers('Content-Range: bytes ' . $this->start . '-' . $this->end . '/' . $this->size);
return response('416 Requested Range Not Satisfiable', 416);
}
if ($range == '-') {
$c_start = $this->size - substr($range, 1);
} else {
$range   = explode('-', $range);
$c_start = $range[0];
$c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $c_end;
}
$c_end = ($c_end > $this->end) ? $this->end : $c_end;
if ($c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size) {
headers('Content-Range: bytes ' . $this->start . '-' . $this->end . '/' . $this->size);
return response('416 Requested Range Not Satisfiable', 416);
}
$this->start                            = $c_start;
$this->end                              = $c_end;
$this->length                           = $this->end - $this->start + 1;
$this->return_headers['Content-Length'] = $this->length;
$this->return_headers['Content-Range']  = 'bytes ' . $this->start . '-' . $this->end . '/' . $this->size;
$this->isRange                          = true;
} else {
$this->length                           = $this->size;
$this->return_headers['Content-Length'] = $this->length;
unset($this->return_headers['Content-Range']);
$this->isRange = false;
}
return $this;
}
/**
* Stream file to client
* @throws Exception
*/
protected function stream()
{
$this->client->registerStreamWrapper();
// Create a stream context to allow seeking
$context = stream_context_create([
's3' => [
'seekable' => true,
],
]);
// Open a stream in read-only mode
if (!($stream = fopen("s3://{$this->adapter->getBucket()}/{$this->filePath}", 'rb', false, $context))) {
throw new Exception('Could not open stream for reading export [' . $this->filePath . ']');
}
if (isset($this->start)) {
fseek($stream, $this->start, SEEK_SET);
}

$remaining_bytes = $this->length ?? $this->size;
$chunk_size      = 512;
$video = response()->stream(
function () use ($stream, $remaining_bytes, $chunk_size) {
while (!feof($stream) && $remaining_bytes > 0) {
echo fread($stream, $chunk_size);
$remaining_bytes -= $chunk_size;
flush();
}
fclose($stream);
},
($this->isRange ? 206 : 200),
$this->return_headers
);
return $video;
}
}

首先,我完全建议不要通过PHP为视频文件执行此操作。流式文件数据适用于PDF等小文件。但是对于大文件,这样做只会增加节点的网络开销。如果您在S3上为内容创建一个签名的URL,然后让用户直接从S3流式传输,效果会更好。但这不会是流媒体。它将是一个渐进式下载。

我建议使用以下建议:https://stackoverflow.com/a/41365111/6670698

或者,如果你知道任何Go编程,你可以尝试根据你的需要修改代码样本或Tube,或者可能检查使用CloudFlix或paas-s3-video-stream 之类的东西的可行性

如果你只想通过PHP做到这一点,请尝试Mux

最新更新