使用 Wowza 和 Amazon Elastic Transcoder 的在线视频
已发表: 2022-03-11当今任何 Web 应用程序的成功和采用都高度依赖于其性能、灵活性和易用性。
尤其是在当今的 ADHD 世界中,如果页面加载时间过长,用户很快就会对应用失去耐心。 对于需要支持视频处理(本质上是计算密集型和 I/O 密集型)的 Web 应用程序而言,这一挑战尤为严峻。 尽管如此,用户的要求越来越高,他们希望他们的视频质量高且加载速度快,即使是在智能手机或平板电脑上运行。
用户也对不能在他们首选的浏览器或设备上运行的网络应用程序,或者不支持他们需要加载或导出的数据格式的网络应用程序失去了容忍度。 因此,需要支持的视频格式的多样性也使得将视频支持整合到 Web 应用程序中尤其具有挑战性。
这篇文章描述了我如何有效地利用开源技术和基于云的服务将视频功能整合到基于 PHP 的 Web 应用程序中。
用例
我是一个团队的一员,该团队需要开发一个类似 YouTube 的网站,注册用户可以在其中上传和分享他们的视频。
该系统需要允许注册用户以各种支持的格式上传他们的视频,然后将其转换为通用格式 (MP4)。 我们还需要生成一组缩略图和一个图像拼贴,用于在视频播放器中显示视频进度条上的帧。
由于客户要求阻止我们使用任何可用的 CDN 或转码 API,事情变得更加复杂,因此我们需要从头开始开发我们的解决方案。
视频上传
由于上传过程本身不需要特定于视频(我们只需要一个易于使用的文件上传功能),因此使用现有的开源解决方案而不是滚动我们自己的解决方案是有意义的。 我们选择了 jQuery-File-Upload,主要是因为它支持在我们的案例中必不可少的两个特性; 即,上传进度条和分块上传。
分块上传使我们能够允许用户上传几乎任何大小的视频文件(对于支持高清分辨率的视频文件尤其重要)。 使用这种方法,文件在前端被分成多个“块”,每个数据块调用上传操作(以及每个块的元数据,例如块编号和总文件大小)。 然后在后端重新组装完整的视频文件。 顺便说一句,在元数据中包含块编号被证明特别重要,因为某些浏览器(例如 Mobile Safari)倾向于以随机顺序传输块。
在线视频处理
视频处理可以像捕获静止图像一样简单,也可以涉及更复杂的操作,例如图像增强、稳定视频流等。 在我们的案例中,唯一的视频处理要求是 (a) 提取视频编解码器和其他关键元数据,以及 (b) 生成一组缩略图和图像拼贴(用于在视频播放器中显示视频进度中的帧酒吧)。
FFmpeg——一个广泛使用、自由分发的开源库——在满足这些要求方面非常有帮助。 FFmpeg 为录制、转换和流式传输音频和视频文件提供了一个完整的跨平台解决方案。 它还可以用于转换视频和进行简单的编辑(例如,修剪、剪切、添加水印等)。
出于我们的目的,我们能够使用 FFmpeg 将视频分成十个部分,然后为每个部分捕获一个缩略图以提供所需的功能。
不幸的是,FFmpeg 库没有 PHP 语言绑定。 因此,从 PHP 中利用 FFmpeg 的唯一方法是使用系统命令从命令行调用二进制文件。 在 PHP 中使用 FFmpeg 基本上有两种方法:
- 库。 Libav 是一个免费软件项目,2011 年从 FFmpeg 分叉出来,它生成用于处理多媒体数据的库和程序。 例如,在 Ubuntu 上,可以使用命令
sudo apt-get install libav-tools
。 libav 命令与 FFmpeg 和 avconv 兼容。 PHP 需要具有对ffmpeg/avconv
的命令行访问权限才能以编程方式使用它。 - PHP-FFMpeg。 PHP-FFMpeg 是 FFMpeg 二进制文件的面向对象的 PHP 驱动程序。 只需执行
composer update "php-ffmpeg/php-ffmpeg"
即可访问它。
我们使用 PHP-FFMpeg 是因为它可以轻松访问我们感兴趣的 FFmpeg 功能。例如,此包中的FFProbe
类使您能够接收有关编解码器或特定视频文件长度的信息,如下所示:
$ffprobe = FFMpeg\FFProbe::create(); $ffprobe ->format('/path/to/video/mp4') // extracts file informations ->get('duration');
FFmpeg 还可以轻松保存任何视频帧:
$ffmpeg = FFMpeg\FFMpeg::create(); $video = $ffmpeg->open('video.mpg'); $video ->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(10)) ->save('frame.jpg');
更详细的示例代码可在此处获得。
注意事项:由于某些专利法,并非所有编解码器都可以由 FFmpeg 处理,并且某些格式未正确(或完全)支持。 我记得几年前,例如,当必须支持功能手机时,使用.3gp
格式时遇到了困难。
排队
在获得视频的编解码器和其他元数据后,我们将视频推送到 FIFO(先进先出)转换队列。 该队列是使用一个简单的 cron 脚本实现的,该脚本在每次运行时选择给定数量的未处理视频并将它们传递给转换实用程序(此处提供示例源代码)。
转换实用程序调用 FFMpeg 来执行转换并将每个视频标记为已处理。
我们还开发了一个简单的等待时间估计机制,计算转换 1 分钟视频的平均时间。 使用这个平均值,我们可以根据视频剩余的处理时间来计算和显示视频上传完成后的估计剩余处理时间。
视频格式转换
某些普遍认可的格式(如 JPEG 和 GIF)已经出现,用于基本上由所有设备和图像处理软件支持的静止图像。 虽然某些视频格式比其他视频格式更常见,但视频还没有出现这种普遍支持的格式。
在我们的案例中,除了需要从多种格式转换为单一通用格式 (MPEG-4) 之外,我们还需要优化转换后的视频以流式传输到移动设备。
对于视频格式转换(至少满足我们的短期需求),使用基于云的Amazon Elastic Transcoder是最好的选择。 除了一般的易用性之外,转码器服务还负责优化和所有编码设置。 幸运的是,有一个适用于 PHP 的 AWS 开发工具包可用,它简化了从我们的 PHP 代码调用服务的过程。
注意:如果您想快速启动和运行,使用 Amazon Elastic Transcoder 等基于云的服务非常有用。 但是,请记住,此选项对您的客户来说可能会变得昂贵,特别是如果他们的商业模式可能需要大量使用大型视频。 另一个需要考虑的因素是,您不必假定您客户的视频或商业模式将与服务条款兼容。
Amazon 使用其基本存储和计算元素、S3(简单存储服务)和 EC2(弹性计算云)——结合 Auto Scaling 和 SNS(简单通知服务)——提供几乎即时扩展和缩减的能力。
aws-sdk的安装很简单,因为 Amazon 维护了一个 Composer 可安装版本的包。 只需将”aws/aws-sdk-php": "2.*"
添加到您的composer.json
文件并执行composer update
。
显然,访问 Amazon Elastic Transcoder 需要一个 Amazon 帐户,因此如果您(或您的客户)还没有帐户,您还需要设置它。
我们使用 Amazon Elastic Transcoder 服务需要首先将视频文件上传到 S3 上的适当存储桶。 然后,我们让转码器作业负责解码和生成缩略图,完成后,将 HTTP 请求发送到指定地址。 这确实需要在 AWS 面板中进行一些配置,但它非常简单,并且亚马逊提供了有关如何执行此操作的良好文档。

随意使用我们的转码器包,它有助于简化 Symfony 2 的集成。它包括一个使用说明并提供一个控制器,用于快速实施亚马逊发送的通知服务,以收集有关已处理视频的信息。 此处提供了一个使用示例。
此外,这里还提供了一个处理亚马逊通知的示例控制器,它还实现了订阅地址的确认。 该服务将首先发布要访问的 URL,以确认这是有效的通知接收者。 那么真正需要的就是将视频标记为已处理。 从那时起,我们可以使用存储在云端的转码视频。
流媒体
视频流是一种需要高性能的能力:用户对不间断流的期望很高,而对延迟的容忍度极低。 由于需要将视频同时实时流式传输到多个客户端,这一挑战通常会加剧。
在我们的案例中,我们需要支持每个用户制作自己的视频频道并开始广播。 我们的解决方案由三个部分组成:
- 仪表板。 用作流媒体仪表板的应用程序,提供提供视频的能力。
- 查看器。 消费和显示视频流的视频客户端。
- 流媒体引擎。 基于云的视频流服务。
除了视频点播 (VOD) 技术仍在发展这一事实之外,我们面临的另一个问题是摄像机访问没有得到很好的支持,并且仅提供 P2P 连接。 此外,我们的目标是为多个并发用户提供在线广播。 此外,对getUserMedia/Stream
API(以前设想为<device>
元素)的支持在现代浏览器中还不一致。 基于这些因素,我决定使用 Flash 技术,因为它确实是唯一合理的选择。 因此,这两个应用程序(仪表板和查看器)都是使用Flex 和 ActionScript实现的。
对于流媒体引擎,我们使用了Wowza 。 尽管还有其他非商业解决方案(例如 Red5,它本质上是作为 Wowza 的替代品销售的),但在我们的案例中,商业产品支持是一个重要因素。 此外,至少在我们构建系统时,Wowza 提供了更好的文档,这是一个额外的优势。 (请注意,您可以免费获得 30 天的 Wowza 试用版,还有开发者的试用版,您可以使用长达 180 天。但有一些限制;流媒体只能为两个客户端工作,并且有限制关于最大连接数。)
Wowza 流媒体引擎
我们使用了 Wowza 提供的 LiveStream 应用程序。 要对其进行配置,请将applications/app_name
留空,然后在conf/app_name
中复制conf
目录中的Application.xml
文件。 编辑文件以配置<Streams>
部分,如下所示:
<Streams> <StreamType>live</StreamType> <StorageDir>${com.wowza.wms.context.VHostConfigHome}/content</StorageDir> <KeyDir>${com.wowza.wms.context.VHostConfigHome}/keys</KeyDir> <LiveStreamPacketizers></LiveStreamPacketizers> <Properties></Properties> </Streams>
关键参数是<StreamType>live</StreamType>
,它定义这将是来自实时视频馈送(例如,摄像机)的流。 请注意,编辑并保存此文件后,您需要重新启动 Wowza。
Flash (Flex/ActionScript) 应用程序
Flash 提供了一个完全集成的系统,可以将摄像头和麦克风连接到 Wowza 流媒体服务器。 如果您对 ActionScript 的经验有限,这将特别有用。
整个应用程序本质上是基于以下对象之间的交互:
- 网络连接。 NetConnection 类在客户端和服务器之间创建双向连接。 客户端可以是 Flash Player 或 AIR 应用程序。 服务器可以是 Web 服务器、Flash Media Server、运行 Flash Remoting 的应用程序服务器或 Adobe Stratus 服务。
- 相机。 Camera 类用于从客户端系统或设备摄像头捕获视频。
- 麦克风。 Microphone 类用于监视或捕获来自麦克风的音频。
- 网流。 NetStream 类通过 NetConnection 打开单向流式传输通道。
首先,我们使用 NetConnection 实例连接到 Wowza 流媒体服务器,然后附加将监听网络连接状态变化的事件监听器:
nc = new NetConnection(); nc.connect(serverAddress:string); nc.addEventListener( NetStatusEvent.NET_STATUS, // event type eNetStatus, // listener function false, // use capture? 0, // priority true // use weak reference? );
这是将相机和麦克风连接到流服务器的事件侦听器的简约示例:
private function eNetStatus(e:NetStatusEvent):void { switch (e.info.code) { case "NetConnection.Connect.Success": camera = Camera.getCamera(); mic = Microphone.getMicrophone(); ns = new NetStream(nc); ns.publish(streamName, "live"); ns.attachCamera(camera); ns.attachAudio(mic); break; case "NetConnection.Connect.Closed": // debug trace... display user message break; }
客户端代码非常相似,只是我们只是在用户端显示视频输入。 这是通过将流连接到Video
对象来完成的,如下面的简单示例所示:
if(event.info.code == "NetConnection.Connect.Success") { ns = new NetStream(nc); ns.client = nsClient; ns.addEventListener(NetStatusEvent.NET_STATUS, nsClient.onNetStatus); ns.play(streamName); video = new Video(); addChild(video); // this will display video video.attachNetStream(ns); // connect NetStream to video }
包起来
预计实时流媒体和视频将在移动和 Web 应用程序中发挥越来越重要的作用。 因此,对于 Web 开发人员来说,熟悉视频转码、处理和流式传输非常重要。 当今有许多工具、库和服务用于将这些功能整合到 Web 应用程序中。 本文展示了我们如何利用和集成这些技术,以相对轻松地成功创建一个基本的类似 YouTube 的网站。