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

1、背景php

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

筆者想將本身收藏的一些電影放到網站上能夠用來隨時播放,不過遇到了一個問題,即是若是直接將MP4文件放放到網站目錄當中,手機端必須下載整個視頻才能夠播放,而若是跨外網傳輸,這實在是不太現實。nginx

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

2、操做概要面試

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

3、搭建ffmpegdocker

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

3.1 鏡像下載canvas

首先筆者須要下載對應的docker鏡像,參考命令以下ubuntu

?
1
docker pull jrottenberg /ffmpeg

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

?
1
2
3
4
5
6
7
8
9
10
11
12
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 容器運行

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

?
1
docker run jrottenberg /ffmpeg

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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協議做爲輸出結果,具體所支持的協議能夠經過以下命令查看

?
1
docker run jrottenberg /ffmpeg -protocols

執行命令以後,參考結果以下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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文件),參數最後則填寫文件輸出路徑,具體參考命令以下:

?
1
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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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文件都刪除,在下面將使用自動化完成。

4、服務搭建

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

4.1 建立虛擬主機

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

?
1
sudo nginx -t

獲得結果以下,在結果中能夠即可以看到nginx的配置文件存放位置

?
1
2
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配置文件

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

而後在配置文件中加入以下參考配置信息

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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能夠獲取到目錄的視頻列表,而後將其輸出到網頁當中,參考代碼以下所示

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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進行轉碼,參考代碼以下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?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、檢驗與測試

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

5.1 視頻列表

首先經過瀏覽器打開URL地址以下

?
1
http: //localhost :8089/

加載完成以後能夠看到以下的視頻列表

讀者若是將上方的代碼運行界面有稍有差別,由於筆者爲了節省文章篇幅,並無將樣式代碼放到文章當中,如需界面好看能夠自行編寫樣式代碼。

5.2 視頻轉碼

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

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

?
1
docker ps

返回的參考結果以下所示

?
1
2
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頁面美化一下。

 

 
2017 PHP高級實戰小程序商城 attach_img
360大牛全面解讀PHP面試–某課網價值266元實戰教程 attach_img
打造扛得住的MySQL數據庫架構 MySQL優化實戰案例教學 換個視角學習MySQL數據庫
WORDPRESS拼音連接插件:PINYIN PERMALINK(中文連接轉拼音) attach_img
WORDPRESS標題別名自動翻譯插件:WP SLUG TRANSLATE attach_img
尚硅谷Redis NoSQL最佳入門課程 Redis極速入門視頻教程 Redis NoSQL培訓視頻教程 attach_img ...2
兄弟連NoSQL數據庫之 Redis數據庫管理與基礎課程 Redis數據庫零基礎入門學習課程
童老師ThinkPHP5.0企業項目開發實戰 第二季
Laravel大神推薦-基礎入門+實戰+拓展視頻教程 attachment
2017 最新 Laravel5.4實戰快速開發自媒體網站 attach_img  ...2
PHP開發高可用高安全App後端 attach_img
PHP WEB開發框架:Laravel 4 快速上手系列教程 Laravel 4簡單輕鬆入門視頻教程 attach_img
Laravel 5.4 快速開發簡書-某課網價值199元實戰教程 attachment
Thinkphp 5.0 仿百度糯米開發多商家電商平臺-某課網價值189元實戰教程 attach_img
Yii 2.0開發一個仿京東商城平臺-某課網價值268元實戰教程 attach_img  ...2
2017最新全方位解讀Laravel框架
PHP在職提高必備之設計模式精講 attach_img
Drupal7系列培訓入門到精通視頻教程 開源內容管理框架Drupal7入門學習視頻教程 attachment
CodeIgniter項目實戰 PHP CI框架完美實戰視頻教程 四位老師傳智播客+後盾網+兄弟連等 attach_img
2017年全新Laravel實戰視頻 雲之夢Laravel實戰學習+項目學習課程 attach_img
相關文章
相關標籤/搜索