使用 Wowza 和 Amazon Elastic Transcoder 的在線視頻

已發表: 2022-03-11

當今任何 Web 應用程序的成功和採用都高度依賴於其性能、靈活性和易用性。

尤其是在當今的 ADHD 世界中,如果頁面加載時間過長,用戶很快就會對應用失去耐心。 對於需要支持視頻處理(本質上是計算密集型和 I/O 密集型)的 Web 應用程序而言,這一挑戰尤為嚴峻。 儘管如此,用戶的要求越來越高,他們希望他們的視頻質量高加載速度快,即使是在智能手機或平板電腦上運行。

用戶也對不能在他們首選的瀏覽器或設備上運行的網絡應用程序,或者不支持他們需要加載或導出的數據格式的網絡應用程序失去了容忍度。 因此,需要支持的視頻格式的多樣性也使得將視頻支持整合到 Web 應用程序中尤其具有挑戰性。

這篇文章描述了我如何有效地利用開源技術和基於雲的服務將視頻功能整合到基於 PHP 的 Web 應用程序中。

使用 Wowza 和 Amazon Elastic Transcoder 在 PHP 中進行在線視頻處理

用例

我是一個團隊的一員,該團隊需要開發一個類似 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 的應用程序服務器或 Adob​​e 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 的網站。