ahmadyusri/php-ffmpeg-video-streaming

📼 PHP FFMpeg - 视频流 - DASH, HLS http://video.aminyazdanpanah.com. 由 Amin Yazdanpanah 重复提交

dev-master 2021-04-17 17:45 UTC

This package is auto-updated.

Last update: 2024-09-18 01:16:20 UTC


README

Build Status Build status Scrutinizer Code Quality Total Downloads Latest Version on Packagist Software License

概述

这个库是围绕 PHP-FFMpeg 的包装器,并为在线流媒体内容打包,如DASH和HLS。您还可以使用 DRM 对HLS打包进行数字版权管理。还有几种从云中打开文件并将文件保存到云的方法。

  • 完整文档 描述了所有功能和组件。
  • 对于使用加密和DRM,我 推荐 尝试 Shaka PHP,这是一个针对此用例的绝佳工具。

内容

要求

  1. 本软件包版本仅与 PHP 7.2 或更高版本兼容。

  2. 要使用此软件包,您需要 安装FFmpeg。您需要FFmpeg和FFProbe二进制文件才能使用它。

安装

通过 composer 安装软件包

composer require aminyazdanpanah/php-ffmpeg-video-streaming

或者,直接将依赖项添加到您的 composer.json 文件中

"require": {
    "aminyazdanpanah/php-ffmpeg-video-streaming": "^1.2"
}

快速入门

首先,您需要在代码中包含此软件包

require 'vendor/autoload.php'; // path to the autoload file

配置

此软件包将自动检测FFmpeg和FFprobe二进制文件。如果您想显式提供二进制路径,可以将数组作为配置传递。还可以传递一个 Psr\Logger\LoggerInterface 实例以记录二进制执行日志。

use Monolog\Handler\StreamHandler;
use Monolog\Logger;

$config = [
    'ffmpeg.binaries'  => '/usr/bin/ffmpeg',
    'ffprobe.binaries' => '/usr/bin/ffprobe',
    'timeout'          => 3600, // The timeout for the underlying process
    'ffmpeg.threads'   => 12,   // The number of threads that FFmpeg should use
];

$log = new Logger('FFmpeg_Streaming');
$log->pushHandler(new StreamHandler('/var/log/ffmpeg-streaming.log')); // path to log file
    
$ffmpeg = Streaming\FFMpeg::create($config, $log);

打开资源

有几种方法可以打开资源。

1. 从FFmpeg支持的资源

您可以将视频(或支持的资源)的本地路径传递给 open 方法

$video = $ffmpeg->open('/var/media/video.mp4');

有关支持的资源(如HTTP、FTP等)的更多信息,请参阅 FFmpeg协议文档

例如

$video = $ffmpeg->open('https://www.aminyazdanpanah.com/?"PATH TO A VIDEO FILE" or "PATH TO A LIVE HTTP STREAM"');

2. 从云中

您可以通过传递云配置数组到 openFromCloud 方法来从云中打开一个文件。

$video = $ffmpeg->openFromCloud($from_google_cloud);

访问 此页面 以查看从 Amazon S3Google Cloud StorageMicrosoft Azure Storage 和自定义云中打开文件的一些示例。

3. 捕获摄像头或屏幕(直播流)

您可以将支持连接的捕获设备(例如,摄像头的名称、相机、屏幕等)传递给 capture 方法,通过网络进行实时媒体流。

$capture = $ffmpeg->capture("CAMERA NAME OR SCREEN NAME");

要列出支持的、已连接的捕获设备,请参阅 FFmpeg 捕获摄像头FFmpeg 捕获桌面

DASH

HTTP动态自适应流(DASH),也称为MPEG-DASH,是一种自适应比特率流技术,它使得通过传统的HTTP网络服务器在互联网上传输高质量的多媒体内容成为可能。了解更多

创建DASH文件

$video->dash()
    ->x264() // Format of the video. Alternatives: hevc() and vp9()
    ->autoGenerateRepresentations() // Auto generate representations
    ->save(); // It can be passed a path to the method or it can be null

手动生成表示形式

use Streaming\Representation;

$r_144p  = (new Representation)->setKiloBitrate(95)->setResize(256, 144);
$r_240p  = (new Representation)->setKiloBitrate(150)->setResize(426, 240);
$r_360p  = (new Representation)->setKiloBitrate(276)->setResize(640, 360);
$r_480p  = (new Representation)->setKiloBitrate(750)->setResize(854, 480);
$r_720p  = (new Representation)->setKiloBitrate(2048)->setResize(1280, 720);
$r_1080p = (new Representation)->setKiloBitrate(4096)->setResize(1920, 1080);
$r_2k    = (new Representation)->setKiloBitrate(6144)->setResize(2560, 1440);
$r_4k    = (new Representation)->setKiloBitrate(17408)->setResize(3840, 2160);

$video->dash()
    ->x264()
    ->addRepresentations([$r_144p, $r_240p, $r_360p, $r_480p, $r_720p, $r_1080p, $r_2k, $r_4k])
    ->save('/var/media/dash-stream.mpd');

在文档中的 DASH部分 中查看更多示例。

HLS

HTTP实时流(也称为HLS) 是苹果公司作为其QuickTime、Safari、OS X和iOS软件的一部分实现的基于HTTP的自适应比特率流通信协议。Microsoft Edge、Firefox和一些版本的Google Chrome也提供了客户端实现。该技术在流媒体服务器中得到广泛支持。了解更多

创建HLS文件

$video->hls()
    ->x264()
    ->autoGenerateRepresentations([720, 360]) // You can limit the number of representatons
    ->save();

手动生成表示形式

use Streaming\Representation;

$r_360p  = (new Representation)->setKiloBitrate(276)->setResize(640, 360);
$r_480p  = (new Representation)->setKiloBitrate(750)->setResize(854, 480);
$r_720p  = (new Representation)->setKiloBitrate(2048)->setResize(1280, 720);

$video->hls()
    ->x264()
    ->addRepresentations([$r_360p, $r_480p, $r_720p])
    ->save();

在文档中的 HLS部分 中查看更多示例,例如Fragmented MP4、实时摄像头/屏幕等。

加密(DRM)

加密过程需要某种形式的秘密(密钥)以及加密算法。HLS使用AES的加密块链(CBC)模式。这意味着每个块都使用前一个块的密文进行加密。了解更多

您必须指定一个保存随机密钥到您本地计算机的路径,并且还必须指定一个URL(或路径)来访问您网站上的密钥(您要保存的密钥必须可以从您的网站访问)。您必须将这两个参数传递给 encryption 方法

单个密钥

以下代码为所有段文件生成一个密钥。

//A path you want to save a random key to your local machine
$save_to = '/home/public_html/"PATH TO THE KEY DIRECTORY"/key';

//An URL (or a path) to access the key on your website
$url = 'https://www.aminyazdanpanah.com/?"PATH TO THE KEY DIRECTORY"/key';
// or $url = '/"PATH TO THE KEY DIRECTORY"/key';

$video->hls()
    ->encryption($save_to, $url)
    ->x264()
    ->autoGenerateRepresentations([1080, 480, 240])
    ->save('/var/media/hls-stream.m3u8');
密钥轮换

您还可以将一个整数作为“密钥轮换周期”传递给 encryption 方法(例如 encryption($save_to, $url, 10)),为每个段集使用不同的密钥,在生成这么多段之后轮换到新密钥。例如,如果生成了10个段文件,则将生成一个新密钥。如果您将此值设置为 1,则每个段文件将使用新的加密密钥进行加密。这可以提高安全性并提供更多灵活性。

请参阅 示例 以获取更多信息。

重要:保护您网站上的密钥(密钥)非常重要。例如,您可以使用令牌(使用Get或Post HTTP方法)来检查用户是否有权访问密钥。您还可以在您的网站上使用会话(或cookie)来限制对密钥(密钥)的访问(强烈推荐)。

数字版权管理(DRM)

然而,FFmpeg支持用于HLS封装的AES加密,您可以加密内容,但这不是一个完整的 DRM 解决方案。如果您想使用完整的DRM解决方案,我建议尝试 FairPlay Streaming 解决方案,然后安全地交换密钥,并保护在设备上的播放。

除了 苹果的FairPlay DRM系统之外,您还可以使用其他DRM系统,例如 微软的PlayReady谷歌的Widevine

字幕

您可以使用 subtitle 方法将字幕添加到HLS流中。

use Streaming\HLSSubtitle;

$persian = new HLSSubtitle('/var/subtitles/subtitles_fa.vtt', 'فارسی', 'fa');
$persian->default();
$english = new HLSSubtitle('/var/subtitles/subtitles_en.vtt', 'english', 'en');
$german  = new HLSSubtitle('/var/subtitles/subtitles_de.vtt', 'Deutsch', 'de');
$chinese = new HLSSubtitle('/var/subtitles/subtitles_zh.vtt', '中文', 'zh');
$spanish = new HLSSubtitle('/var/subtitles/subtitles_es.vtt', 'Español', 'es');

$video->hls()
    ->subtitles([$persian, $english, $german, $chinese, $spanish])
    ->x264()
    ->autoGenerateRepresentations([1080, 720])
    ->save('/var/media/hls-stream.m3u8');

注意:所有m3u8文件都将使用基于RFC 8216的规则生成。目前只接受WebVTT文件。

转码

一种格式也可以扩展FFMpeg\Format\ProgressableInterface以获取转码的实时信息。

$format = new Streaming\Format\X264();
$format->on('progress', function ($video, $format, $percentage){
    // You can update a field in your database or can log it to a file
    // You can also create a socket connection and show a progress bar to users
    echo sprintf("\rTranscoding...(%s%%) [%s%s]", $percentage, str_repeat('#', $percentage), str_repeat('-', (100 - $percentage)));
});

$video->dash()
    ->setFormat($format)
    ->autoGenerateRepresentations()
    ->save();
终端输出

transcoding

保存文件

有多种保存文件的方法。

1. 本地路径

您可以将本地路径传递给save方法。如果路径中没有目录,则包自动创建目录。

$dash = $video->dash()
            ->x264()
            ->autoGenerateRepresentations()
            
$dash->save('/var/media/dash-stream.mpd');

它也可以为null。保存文件的默认路径是输入路径。

$hls = $video->hls()
            ->x264()
            ->autoGenerateRepresentations();
            
$hls->save();

注意:如果您从云中打开文件,但没有为本地机器指定保存文件的路径,则必须将本地路径传递给save方法。

2. 云存储

您可以通过传递一个云配置数组到save方法将文件保存到云。

$dash->save(null, [$to_aws_cloud, $to_google_cloud, $to_microsoft_azure, $to_custom_cloud]);

您也可以传递一个路径来将文件的副本保存到本地机器。

$hls->save('/var/media/hls-stream.m3u8', [$to_google_cloud, $to_custom_cloud]);

访问此页面以查看保存到Amazon S3Google Cloud StorageMicrosoft Azure Storage和自定义云的一些示例。

注意:此选项(保存到云)仅适用于VOD(不支持实时流媒体)。

模式:关系是一对一

3. 立即保存到服务器

您可以将URL(或支持的资源,如FTP)传递给直播方法,使用HTTP PUT方法将所有段文件上传到HTTP服务器(或其他协议),并在每次刷新时更新清单文件。

// DASH
$dash->live('http://YOUR-WEBSITE.COM/live-stream/out.mpd');

// HLS
$hls
    ->setMasterPlaylist('/var/www/stream/live-master-manifest.m3u8')
    ->live('http://YOUR-WEBSITE.COM/live-stream/out.m3u8');

注意:在HLS格式中,您必须手动上传主播放列表到服务器。(将/var/www/stream/live-master-manifest.m3u8文件上传到http://YOUR-WEBSITE.COM

有关更多信息,请参阅FFmpeg协议文档

元数据

您可以使用以下代码从多媒体流和视频文件中获取信息。

$hls = $hls->save();
$metadata = $hls->metadata()->export();

print_r($metadata);

有关更多信息,请参阅示例

转换

您可以将流转换为文件或将流转换为其他流协议。您应该将流的清单传递给open方法

1. HLS 转 DASH

$stream = $ffmpeg->open('https://www.aminyazdanpanah.com/?PATH/TO/HLS-MANIFEST.M3U8');

$stream->dash()
    ->x264()
    ->addRepresentations([$r_360p, $r_480p]) 
    ->save('/var/media/dash-stream.mpd');

2. DASH 转 HLS

$stream = $ffmpeg->open('https://www.aminyazdanpanah.com/?PATH/TO/DASH-MANIFEST.MPD');

$stream->hls()
           ->x264()
           ->autoGenerateRepresentations([720, 360])
           ->save('/var/media/hls-stream.m3u8');

3. 流(DASH或HLS)转文件

$format = new Streaming\Format\x264();
$format->on('progress', function ($video, $format, $percentage){
    echo sprintf("\rTranscoding...(%s%%) [%s%s]", $percentage, str_repeat('#', $percentage), str_repeat('-', (100 - $percentage)));
});

$stream->stream2file()
           ->setFormat($format)
           ->save('/var/media/new-video.mp4');

其他高级功能

您可以在PHP-FFMpeg库中轻松使用其他高级功能。实际上,当您使用open方法(或openFromCloud)打开文件时,它包含属于PHP-FFMpeg的媒体对象。

$ffmpeg = Streaming\FFMpeg::create();
$video = $ffmpeg->openFromCloud($from_cloud, '/var/media/new/video.mp4');

提取图像

您可以使用FFMpeg\Media\Video::frame方法在任何时间码提取一个帧。

$frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(42));
$frame->save('/var/media/poster.jpg');

注意:您可以使用此图像作为视频的封面。

Gif

Gif是从视频序列中提取的动画图像。

您可以使用FFMpeg\Media\Gif::save方法保存Gif文件。

$video
    ->gif(FFMpeg\Coordinate\TimeCode::fromSeconds(2), new FFMpeg\Coordinate\Dimension(640, 480), 3)
    ->save('/var/media/animated_image.gif');

此方法有一个可选的第三个布尔参数,即动画的持续时间。如果您不设置它,您将得到一个固定的Gif图像。

注意:您可以使用Gif作为视频的缩略图。

要查看更多示例,请访问PHP-FFMpeg文档页面。

异步任务执行

包装过程可能需要一些时间,建议在后台(或在云中,例如AWS)运行。有一些库可以用于此用途。

  • Symphony(控制台组件): 您可以使用此库创建命令行命令。您的控制台命令可以用于任何重复性任务,例如cron作业、导入或其他批处理作业。了解更多

  • Laravel(队列): 如果您正在使用Laravel进行开发,Laravel队列是此用途的一个非常好的工具。它允许您创建一个作业并发送它。了解更多

注意:您也可以创建一个脚本并在cron作业中运行它。

多个开源播放器

您可以使用这些库来播放流。

常见问题解答

我已创建流文件,现在应该将什么传递给播放器? 您必须将一个 主播放列表(manifest)URL(例如 https://www.aminyazdanpanah.com/?"PATH TO STREAM DIRECTORY"/dash-stream.mpd/PATH_TO_STREAM_DIRECTORY/hls-stream.m3u8)传递给播放器。请参阅这些播放器的演示页面以获取更多信息(hls.js 演示dash.js 演示videojs 演示等)。

我的播放器没有显示质量选择按钮来更改视频质量? 一些播放器没有内置的质量选择按钮来更改此选项,您应该安装(或添加)用于此用途的插件。例如,如果您正在使用Videojs来播放流,您可以使用 videojs-hls-quality-selector 来显示质量选择器。对于添加其他播放器的插件,您可以轻松地通过Google搜索它!

我已经将流文件上传到云,但它在我的网站上无法播放? 如果您将流内容保存到云(例如 Amazon S3),请确保您的文件是 公开的。如果不是,您必须更改访问控制。

IOS支持DASH流吗? 不,IOS没有对DASH的原生支持。尽管有一些库(例如 ViblastMPEGDASH-iOS-Player)支持这种技术,但我从未测试过它们。因此,也许其中一些可能无法正常工作。

请参阅 此页面 以获取更多常见问题解答。

贡献和报告错误

我很乐意在改进、纠正和添加规范方面得到您的帮助。请 提交问题提交拉取请求

  • 请参阅更多信息,请见 贡献文件
  • 如果您在此包中发现安全漏洞,请参阅 安全文件 以获取更多信息。

鸣谢

许可证

MIT许可(MIT)。更多信息请参阅 许可文件