PHP結合Ffmpeg快速搭建流媒體服務的實踐記錄

這篇文章主要給大家介紹了關於使用PHP結合Ffmpeg快速搭建流媒體服務的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨着小編來一起學習學習吧

一、背景

ffmpeg應該是目前最強大的視頻管理程序,當你需要截取視頻第一幀,對視頻類型進行轉換,截取gif圖片等一系列對視頻的操作,ffmpeg絕對是最好的擴展

筆者想將自己收藏的一些電影放到網站上可以用來隨時播放,不過遇到了一個問題,便是如果直接將MP4文件放放到網站目錄當中,手機端必須下載整個視頻纔可以播放,而如果跨外網傳輸,這實在是不太現實。

爲了解決這個問題,便想着搭建一套流媒體服務,這樣手機就可以邊看邊下載,查詢了一些資料了瞭解到需要先將視頻分成一小片來傳輸,比如將MP4轉碼爲M3U8格式,查詢了相關轉碼方法,比較主流的方式是使用ffmpeg這個開源工具

二、操作概要

  • 安裝Ffmpeg
  • 服務搭建
  • 功能測試

三、搭建ffmpeg

視頻轉碼的工具可能有很多,但開源且使用人數最多的還是莫過於ffmpeg這個工具,具體功能筆者不在這裏詳細講解;安裝此工具的方式有很多,比如apt安裝、源碼安裝、docker安裝等等,不過docker是跨平臺的,因此筆者這裏將以docker方式安裝爲例

3.1 鏡像下載

首先筆者需要下載對應的docker鏡像,參考命令如下

docker pull jrottenberg/ffmpeg

命令執行過程中將會從遠處下載鏡像,這個時間由當前的網絡帶寬所決定,當下載完成之後,可以看到如下參考信息

Using default tag: latest
latest: Pulling from jrottenberg/ffmpeg
b234f539f7a1: Pull complete
55172d420b43: Pull complete
5ba5bbeb6b91: Pull complete
43ae2841ad7a: Pull complete
f6c9c6de4190: Pull complete
2a0ef76bfa54: Pull complete
40ddf796a4bb: Pull complete
32ba137d2764: Pull complete
Digest: sha256:bcf65375f593518de7e450fd6b775d16a047d3ded00957c2e794e2fe8f7e1590
Status: Downloaded newer image for jrottenberg/ffmpeg:latest

3.2 容器運行

當容器下載完畢之後,可以用一些命令進行驗證是否能夠正常運行,如下參考命令

docker run jrottenberg/ffmpeg

命令執行完畢之後,會返回如下結果

Hyper fast Audio and Video encoder
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...

Getting help:

..... 省略

Audio options:
-aframes number  set the number of audio frames to output
-aq quality   set audio quality (codec-specific)
-ar rate   set audio sampling rate (in Hz)
-ac channels  set number of audio channels
-an     disable audio
-acodec codec  force audio codec ('copy' to copy stream)
-vol volume   change audio volume (256=normal)
-af filter_graph set audio filters

Subtitle options:
-s size    set frame size (WxH or abbreviation)
-sn     disable subtitle
-scodec codec  force subtitle codec ('copy' to copy stream)
-stag fourcc/tag force subtitle tag/fourcc
-fix_sub_duration fix subtitles duration
-canvas_size size set canvas size (WxH or abbreviation)
-spre preset  set the subtitle options to the indicated preset

3.3 查看支持協議

FFmpeg所支持的輸入輸出協議非常多,比如可以選擇file協議作爲來源,使用hls協議作爲輸出結果,具體所支持的協議可以通過如下命令查看

docker run jrottenberg/ffmpeg -protocols

執行命令之後,參考結果如下

ffmpeg version 3.4.2 Copyright (c) 2000-2018 the FFmpeg developers
 built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.9) 20160609
 configuration: --disable-debug --disable-doc --disable-ffplay --enable-shared --enable-avresample --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-gpl --enable-libass --enable-libfreetype --enable-libvidstab --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libtheora --enable-libvorbis
 ..... 省略
 Supported file protocols:
Input:
 async
 cache
 concat
 crypto
 data
 ..... 省略
Output:
 crypto
 file
 ..... 省略
 tls
 udp

3.4 轉換測試

現在筆者使用FFmpeg對視頻進行轉碼測試,命令非常簡單,首先需要通過-v將視頻所在的目錄掛載到容器中,然後使用-i選項找到容器中對應的視頻文件;

接着就可以對編碼進行一些選項,比如-hls_time 10便是將文件沒10秒輸出一個TS文件,-hls_list_size 0 則是在m3u8文件中記錄所以ts文件(默認是記錄最後五個TS文件),參數最後則填寫文件輸出路徑,具體參考命令如下:

docker run -v /Users/song/video:/root/download jrottenberg/ffmpeg:latest -i /root/download/1.mp4 -hls_time 10 -hls_list_size 0 -f hls /root/download/index.m3u8

命令執行過程中會展示轉換進度,參考如下返回所示

 Metadata:
 major_brand  : mp42
 minor_version : 0
 compatible_brands: mp42mp41
 encoder   : Lavf57.83.100
 Stream #0:0(eng): Video: h264 (libx264), yuv420p(progressive), 1920x1080, q=-1--1, 30 fps, 90k tbn, 30 tbc (default)
 Metadata:
  creation_time : 2018-08-21T15:09:24.000000Z
  handler_name : Alias Data Handler
  encoder   : Lavc57.107.100 libx264
 Side data:
  cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
 Stream #0:1(eng): Audio: aac, 48000 Hz, stereo, fltp, 128 kb/s (default)
 Metadata:
  creation_time : 2018-08-21T15:09:24.000000Z
  handler_name : Alias Data Handler
  encoder   : Lavc57.107.100 aac
frame= 82 fps= 12 q=29.0 size=N/A time=00:00:02.62 bitrate=N/A speed=0.381x

此時便可以在剛纔的掛載點查看TS文件,如下圖所示

現在筆者將剛纔的TS文件都刪除,在下面將使用自動化完成。

四、服務搭建

在上一步中筆者已經成功通過終端使用FFmpeg將視頻進行轉碼,下面筆者將結合PHP代碼將這些操作完全自動化實現,這樣便可以達到通過手機訪問網站,服務端自動完成轉碼播放的需求,這個過程包括創建虛擬主機、編寫展示視頻列表、視頻自動解碼三個部分

4.1 創建虛擬主機

首先筆者需要藉助nginx搭建一個web服務,這時便需要修改配置文件,但並不記得nginx配置文件存放位置,此時可以藉助如下命令

sudo nginx -t

得到結果如下,在結果中可以便可以看到nginx的配置文件存放位置

nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful

使用vim編輯器直接編輯nginx配置文件

vim /usr/local/etc/nginx/nginx.conf

然後在配置文件中加入如下參考配置信息

 server {
  listen  8089;
  server_name localhost;
  root /Users/song/mycode/work/test/video;
  location / {
   index index.html index.htm index.php; 
  }

  location ~ \.php$ {
   fastcgi_pass 127.0.0.1:9000;
   fastcgi_index index.php;
   fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
   include  fastcgi_params;
  }

 }

4.2 獲取視頻列表

nginx配置完成之後,便需要編寫PHP代碼,通過PHP可以獲取到目錄的視頻列表,然後將其輸出到網頁當中,參考代碼如下所示

<?php
 $list = scandir('/Users/song/video/');

 foreach ($list as $key => $val) {
  if (!in_array(pathinfo($val, PATHINFO_EXTENSION), ['mp4', 'rmvb', 'wmv'])) {
   continue;
  }

  ?>

  <a class="btn btn-default btn-video btn-lg" href="./encode.php?name=<?= $val ?>" role="button">
   <h2><?= $val ?></h2></a>

 <?php }
} ?>

在代碼中,首先通過scandir讀取文件夾下所有文件,然後進行foreach循環,通過後綴名來判斷是否爲視頻文件,如果是視頻文件,則輸出一個鏈接地址方便用戶選擇。

4.3 進行視頻轉碼

上面的代碼在列出視頻列表之後,當用戶點擊鏈接後就需要使用FFmpeg進行轉碼,參考代碼如下

<?php

//接收必要參數
$name = $_GET['name'] ?? '1.mp4';
$forced = $_GET['forced'] ?? 0;
$fileName = getFileName($name);

$outPath = '/Users/song/video';
$inPath = '/root/download';
$dir = __DIR__;

//判斷之前是否已經轉碼,如果不強制轉碼便先返回
if (is_dir("$outPath/$fileName") && empty($forced)) {
 header("location:./static/{$fileName}/index.m3u8");
 die;
}

//將目標映射過來
system("ln -s {$outPath} {$dir}/static");

//先創建文件夾
system("mkdir -p {$outPath}/{$fileName}");

//進行轉碼
$ffmpeg = "docker run -v $outPath:/root/download jrottenberg/ffmpeg:latest";
$cmd = "nohup $ffmpeg -i {$inPath}/{$name} -hls_time 10 -hls_list_size 0 -f hls -r 25 {$inPath}/{$fileName}/index.m3u8 >> ./code.log &";
system($cmd);


//延時執行跳轉
returnUrl($fileName);

function getFileName($filename)
{
 $houzhui = substr(strrchr($filename, '.'), 1);
 $result = basename($filename, "." . $houzhui);

 return $result;

}

function returnUrl($fileName)
{
 echo "<a class='btn btn-video btn-lg' href='./static/{$fileName}/index.m3u8'><h1>正在處理中...點擊進行跳轉</h1></a>";
 die;
}

在上面代碼當中,考慮文件是否已經被轉碼,如果已經轉碼過了直接返回播放地址,否則創建一個存放TS文件的文件夾,然後進行轉碼,轉碼的時候使用nohup命令可以讓FFmpeg異步執行,然後PHP返回播放地址。

五、檢驗與測試

通過前面的步驟,筆者已經完整的搭建了一套流媒體服務器,下面將檢驗這些服務是否能否正常運行,包括視頻列表展示、視頻轉碼是否正常、已經轉碼的視頻能否播放

5.1 視頻列表

首先通過瀏覽器打開URL地址如下

http://localhost:8089/

加載完成之後可以看到如下的視頻列表

讀者如果將上方的代碼運行界面有稍有差異,因爲筆者爲了節省文章篇幅,並沒有將樣式代碼放到文章當中,如需界面好看可以自行編寫樣式代碼。

5.2 視頻轉碼

在視頻列表點擊一個鏈接之後,後臺PHP程序將會執行轉碼任務,然後返回一個鏈接地址,如下圖所示

此時便代表FFmpeg已經在後臺運行,可以通過如下命令進行查看FFmpeg這個容器的運行狀態,參考命令如下

docker ps

返回的參考結果如下所示

CONTAINER ID  IMAGE      COMMAND     CREATED    STATUS    PORTS    NAMES
ac3e7233eb9f  jrottenberg/ffmpeg:latest "ffmpeg -i /root/dow…" 1 hours ago  Up 1 hours        keen_feynman

從上面的返回結果當中可以看出當前正有一個任務處於運行狀態,此時打開視頻輸出目錄,會看到有多個ts格式的視頻文件,這些文件是剛在通過PHP自動執行所產生的,如下圖所示

當看到如上圖的轉碼視頻文件時,便可以通過瀏覽器進行訪問

5.3 視頻播放

這裏需要記住,HLS協議是蘋果公司所開發的,因此除了蘋果的瀏覽器外,其他瀏覽器默認都是不支持m3u8的解析的,如果需要使用其他瀏覽器播放,需要安裝插件;蘋果的默認就支持則不需要

筆者重新通過Safari瀏覽器打開頁面,然後再次選擇1.mp4視頻,則直接跳轉到了播放頁面,如下圖所示

看到這裏,搭建流媒體就基本已經完成了,如果需要將更多視頻播放,只需要將視頻文件存放到指定的視頻目錄,網頁中便會自動讀取出來,頁面可能太簡化,讀者可以根據自己的需要將html頁面美化一下。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對神馬文庫的支持。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章