PHP結(jié)合Ffmpeg快速搭建流媒體服務(wù)的實(shí)踐記錄
一、背景
ffmpeg應(yīng)該是目前最強(qiáng)大的視頻管理程序,當(dāng)你需要截取視頻第一幀,對(duì)視頻類(lèi)型進(jìn)行轉(zhuǎn)換,截取gif圖片等一系列對(duì)視頻的操作,ffmpeg絕對(duì)是最好的擴(kuò)展
筆者想將自己收藏的一些電影放到網(wǎng)站上可以用來(lái)隨時(shí)播放,不過(guò)遇到了一個(gè)問(wèn)題,便是如果直接將MP4文件放放到網(wǎng)站目錄當(dāng)中,手機(jī)端必須下載整個(gè)視頻才可以播放,而如果跨外網(wǎng)傳輸,這實(shí)在是不太現(xiàn)實(shí)。
為了解決這個(gè)問(wèn)題,便想著搭建一套流媒體服務(wù),這樣手機(jī)就可以邊看邊下載,查詢了一些資料了了解到需要先將視頻分成一小片來(lái)傳輸,比如將MP4轉(zhuǎn)碼為M3U8格式,查詢了相關(guān)轉(zhuǎn)碼方法,比較主流的方式是使用ffmpeg這個(gè)開(kāi)源工具
二、操作概要
- 安裝Ffmpeg
- 服務(wù)搭建
- 功能測(cè)試
三、搭建ffmpeg
視頻轉(zhuǎn)碼的工具可能有很多,但開(kāi)源且使用人數(shù)最多的還是莫過(guò)于ffmpeg這個(gè)工具,具體功能筆者不在這里詳細(xì)講解;安裝此工具的方式有很多,比如apt安裝、源碼安裝、docker安裝等等,不過(guò)docker是跨平臺(tái)的,因此筆者這里將以docker方式安裝為例
3.1 鏡像下載
首先筆者需要下載對(duì)應(yīng)的docker鏡像,參考命令如下
docker pull jrottenberg/ffmpeg
命令執(zhí)行過(guò)程中將會(huì)從遠(yuǎn)處下載鏡像,這個(gè)時(shí)間由當(dāng)前的網(wǎng)絡(luò)帶寬所決定,當(dāng)下載完成之后,可以看到如下參考信息
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 容器運(yùn)行
當(dāng)容器下載完畢之后,可以用一些命令進(jìn)行驗(yàn)證是否能夠正常運(yùn)行,如下參考命令
docker run jrottenberg/ffmpeg
命令執(zhí)行完畢之后,會(huì)返回如下結(jié)果
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 查看支持協(xié)議
FFmpeg所支持的輸入輸出協(xié)議非常多,比如可以選擇file協(xié)議作為來(lái)源,使用hls協(xié)議作為輸出結(jié)果,具體所支持的協(xié)議可以通過(guò)如下命令查看
docker run jrottenberg/ffmpeg -protocols
執(zhí)行命令之后,參考結(jié)果如下
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 轉(zhuǎn)換測(cè)試
現(xiàn)在筆者使用FFmpeg對(duì)視頻進(jìn)行轉(zhuǎn)碼測(cè)試,命令非常簡(jiǎn)單,首先需要通過(guò)-v
將視頻所在的目錄掛載到容器中,然后使用-i
選項(xiàng)找到容器中對(duì)應(yīng)的視頻文件;
接著就可以對(duì)編碼進(jìn)行一些選項(xiàng),比如-hls_time 10
便是將文件沒(méi)10秒輸出一個(gè)TS文件,-hls_list_size 0
則是在m3u8文件中記錄所以ts
文件(默認(rèn)是記錄最后五個(gè)TS文件),參數(shù)最后則填寫(xiě)文件輸出路徑,具體參考命令如下:
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
命令執(zhí)行過(guò)程中會(huì)展示轉(zhuǎn)換進(jìn)度,參考如下返回所示
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
此時(shí)便可以在剛才的掛載點(diǎn)查看TS文件,如下圖所示
現(xiàn)在筆者將剛才的TS文件都刪除,在下面將使用自動(dòng)化完成。
四、服務(wù)搭建
在上一步中筆者已經(jīng)成功通過(guò)終端使用FFmpeg將視頻進(jìn)行轉(zhuǎn)碼,下面筆者將結(jié)合PHP代碼將這些操作完全自動(dòng)化實(shí)現(xiàn),這樣便可以達(dá)到通過(guò)手機(jī)訪問(wèn)網(wǎng)站,服務(wù)端自動(dòng)完成轉(zhuǎn)碼播放的需求,這個(gè)過(guò)程包括創(chuàng)建虛擬主機(jī)、編寫(xiě)展示視頻列表、視頻自動(dòng)解碼三個(gè)部分
4.1 創(chuàng)建虛擬主機(jī)
首先筆者需要借助nginx搭建一個(gè)web服務(wù),這時(shí)便需要修改配置文件,但并不記得nginx配置文件存放位置,此時(shí)可以借助如下命令
sudo nginx -t
得到結(jié)果如下,在結(jié)果中可以便可以看到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配置完成之后,便需要編寫(xiě)PHP代碼,通過(guò)PHP可以獲取到目錄的視頻列表,然后將其輸出到網(wǎng)頁(yè)當(dāng)中,參考代碼如下所示
<?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 } } ?>
在代碼中,首先通過(guò)scandir讀取文件夾下所有文件,然后進(jìn)行foreach循環(huán),通過(guò)后綴名來(lái)判斷是否為視頻文件,如果是視頻文件,則輸出一個(gè)鏈接地址方便用戶選擇。
4.3 進(jìn)行視頻轉(zhuǎn)碼
上面的代碼在列出視頻列表之后,當(dāng)用戶點(diǎn)擊鏈接后就需要使用FFmpeg進(jìn)行轉(zhuǎn)碼,參考代碼如下
<?php //接收必要參數(shù) $name = $_GET['name'] ?? '1.mp4'; $forced = $_GET['forced'] ?? 0; $fileName = getFileName($name); $outPath = '/Users/song/video'; $inPath = '/root/download'; $dir = __DIR__; //判斷之前是否已經(jīng)轉(zhuǎn)碼,如果不強(qiáng)制轉(zhuǎn)碼便先返回 if (is_dir("$outPath/$fileName") && empty($forced)) { header("location:./static/{$fileName}/index.m3u8"); die; } //將目標(biāo)映射過(guò)來(lái) system("ln -s {$outPath} {$dir}/static"); //先創(chuàng)建文件夾 system("mkdir -p {$outPath}/{$fileName}"); //進(jìn)行轉(zhuǎn)碼 $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); //延時(shí)執(zhí)行跳轉(zhuǎn) 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>正在處理中...點(diǎn)擊進(jìn)行跳轉(zhuǎn)</h1></a>"; die; }
在上面代碼當(dāng)中,考慮文件是否已經(jīng)被轉(zhuǎn)碼,如果已經(jīng)轉(zhuǎn)碼過(guò)了直接返回播放地址,否則創(chuàng)建一個(gè)存放TS文件的文件夾,然后進(jìn)行轉(zhuǎn)碼,轉(zhuǎn)碼的時(shí)候使用nohup命令可以讓FFmpeg異步執(zhí)行,然后PHP返回播放地址。
五、檢驗(yàn)與測(cè)試
通過(guò)前面的步驟,筆者已經(jīng)完整的搭建了一套流媒體服務(wù)器,下面將檢驗(yàn)這些服務(wù)是否能否正常運(yùn)行,包括視頻列表展示、視頻轉(zhuǎn)碼是否正常、已經(jīng)轉(zhuǎn)碼的視頻能否播放
5.1 視頻列表
首先通過(guò)瀏覽器打開(kāi)URL地址如下
http://localhost:8089/
加載完成之后可以看到如下的視頻列表
讀者如果將上方的代碼運(yùn)行界面有稍有差異,因?yàn)楣P者為了節(jié)省文章篇幅,并沒(méi)有將樣式代碼放到文章當(dāng)中,如需界面好看可以自行編寫(xiě)樣式代碼。
5.2 視頻轉(zhuǎn)碼
在視頻列表點(diǎn)擊一個(gè)鏈接之后,后臺(tái)PHP程序?qū)?huì)執(zhí)行轉(zhuǎn)碼任務(wù),然后返回一個(gè)鏈接地址,如下圖所示
此時(shí)便代表FFmpeg已經(jīng)在后臺(tái)運(yùn)行,可以通過(guò)如下命令進(jìn)行查看FFmpeg這個(gè)容器的運(yùn)行狀態(tài),參考命令如下
docker ps
返回的參考結(jié)果如下所示
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ac3e7233eb9f jrottenberg/ffmpeg:latest "ffmpeg -i /root/dow…" 1 hours ago Up 1 hours keen_feynman
從上面的返回結(jié)果當(dāng)中可以看出當(dāng)前正有一個(gè)任務(wù)處于運(yùn)行狀態(tài),此時(shí)打開(kāi)視頻輸出目錄,會(huì)看到有多個(gè)ts格式的視頻文件,這些文件是剛在通過(guò)PHP自動(dòng)執(zhí)行所產(chǎn)生的,如下圖所示
當(dāng)看到如上圖的轉(zhuǎn)碼視頻文件時(shí),便可以通過(guò)瀏覽器進(jìn)行訪問(wèn)
5.3 視頻播放
這里需要記住,HLS協(xié)議是蘋(píng)果公司所開(kāi)發(fā)的,因此除了蘋(píng)果的瀏覽器外,其他瀏覽器默認(rèn)都是不支持m3u8的解析的,如果需要使用其他瀏覽器播放,需要安裝插件;蘋(píng)果的默認(rèn)就支持則不需要
筆者重新通過(guò)Safari瀏覽器打開(kāi)頁(yè)面,然后再次選擇1.mp4
視頻,則直接跳轉(zhuǎn)到了播放頁(yè)面,如下圖所示
看到這里,搭建流媒體就基本已經(jīng)完成了,如果需要將更多視頻播放,只需要將視頻文件存放到指定的視頻目錄,網(wǎng)頁(yè)中便會(huì)自動(dòng)讀取出來(lái),頁(yè)面可能太簡(jiǎn)化,讀者可以根據(jù)自己的需要將html頁(yè)面美化一下。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- PHP+FFMPEG實(shí)現(xiàn)將視頻自動(dòng)轉(zhuǎn)碼成H264標(biāo)準(zhǔn)Mp4文件
- PHP中使用FFMPEG獲取視頻縮略圖和視頻總時(shí)長(zhǎng)實(shí)例
- PHP使用FFmpeg獲取視頻播放總時(shí)長(zhǎng)與碼率等信息
- php使用ffmpeg獲取視頻信息并截圖的實(shí)現(xiàn)方法
- php使用FFmpeg接口獲取視頻的播放時(shí)長(zhǎng)、碼率、縮略圖以及創(chuàng)建時(shí)間
- php 調(diào)用ffmpeg獲取視頻信息的簡(jiǎn)單實(shí)現(xiàn)
- php利用ffmpeg提取視頻中音頻與視頻畫(huà)面的方法詳解
- Centos 6.5下PHP 5.3安裝ffmpeg擴(kuò)展的步驟詳解
- php使用ffmpeg向視頻中添加文字字幕的實(shí)現(xiàn)方法
- PHP基于ffmpeg實(shí)現(xiàn)轉(zhuǎn)換視頻,截圖及生成縮略圖的方法
相關(guān)文章
php將字符串轉(zhuǎn)換為數(shù)組實(shí)例講解
在本篇文章里小編給大家分享的是關(guān)于php將字符串轉(zhuǎn)換為數(shù)組實(shí)例講解,需要的朋友們可以學(xué)習(xí)下。2020-05-05PHP實(shí)現(xiàn)HTML頁(yè)面靜態(tài)化的方法
這篇文章主要介紹了PHP實(shí)現(xiàn)HTML頁(yè)面靜態(tài)化的方法,分享了靜態(tài)處理的方法,靜態(tài)處理后的優(yōu)勢(shì),并提供了多種靜態(tài)的方法,感興趣的小伙伴們可以參考一下2015-11-11php中判斷一個(gè)字符串包含另一個(gè)字符串的方法
這篇文章主要為大家分享一下一個(gè)字符串包含另一個(gè)字符串的方法,主要使用了strpos或數(shù)組的方法實(shí)現(xiàn)2007-03-03php設(shè)計(jì)模式 Decorator(裝飾模式)
動(dòng)態(tài)的給一個(gè)對(duì)象添加一些額外的職責(zé),就擴(kuò)展功能而言比生成子類(lèi)方式更為靈活2011-06-06php 定義404頁(yè)面的實(shí)現(xiàn)代碼
今天需要用php輸出一個(gè)404錯(cuò)誤頁(yè)面,然后加載404頁(yè)面輸出,各個(gè)方便給用戶與搜索引擎好的用戶體驗(yàn)2012-11-11php解析字符串函數(shù)sscanf的實(shí)用方法
在PHP編程中,有時(shí)需要對(duì)字符串進(jìn)行解析,而sscanf函數(shù)就是一種非常方便的解析工具,本文詳細(xì)介紹了sscanf函數(shù)的用法,包括基本用法和高級(jí)用法,通過(guò)大量的示例代碼,展示了如何使用sscanf函數(shù)解析各種不同格式的字符串2023-09-09