$name = md5(date('YmdHis')).".png";
php
$from = "E:\\UPLOAD\\cw\\20150626\\558d0d11ae285.mp4";
html
$to = "E:\\UPLOAD\\cover_images\\";
git
$str = "ffmpeg -i ".$from." -y -f mjpeg -ss 3 -t 1 -s 740x500 ".$to.$name;
github
system($str);
web
本文將嘗試指出在PHP Web腳本中使用FFmpeg時須要瞭解的全部重要事項。它還將顯示一些使用示例,以使事情更清楚。這個想法也能夠應用到其餘web腳本語言。shell
網頁設計爲快速執行,以便瀏覽您的網站的人沒必要等待太多的響應。由於若是他們無聊的等待,他們只會導航到另外一個,更靈敏(一般是您的競爭對手的)網站。話雖如此,你能夠作的最糟糕的事情是從你的web腳本運行一個命令行工具(如ffmpeg),並等待它完成處理,以便可以將結果返回到等待在線用戶(異常這是小/快的工具,其執行時間過小而不能注意到)。數據庫
您想要作的是將命令行工具的長處理與Web腳本執行分開,以使腳本更具響應性。因此,你有至少兩個選項:ubuntu
這兩種方法看起來是同樣的,可是他們不是。最重要的區別是,第二種方法能夠更好地擴展更高的網站流量,由於它容許「工做」進程在徹底獨立的機器上運行。此外,能夠有幾個「工做」機器,一塊兒工做,分裂工做負載,涉及小的同步。安全
第一種方法一般是大多數想要快速完成工做的人的首選,可是在他們的網站變得流行的時間,他們的web服務器變得不那麼敏感,因爲不斷的cpu飢餓,由多個命令行工具(ffmpeg實例)在後臺運行。在那一刻,他們一般開始考慮第二種方法。服務器
如下示例適用於基於Linux的操做系統。對於基於Windows的操做系統,請繼續閱讀本文,而是你讀了以後,也看到瞭如何使用START和CMD後臺運行的過程。這將給你一個想法如何應用相同的邏輯到基於Windows的操做系統。
讓咱們考慮從PHP腳本運行ffmpeg的天然方式:
<?php echo "Starting ffmpeg...\n\n"; echo shell_exec("ffmpeg -i input.avi output.avi &"); echo "Done.\n"; ?>
這裏有幾個問題須要指出。第一個是,雖然咱們指定咱們但願在後臺執行ffmpeg(使用和號運算符「&」),PHP腳本將不會繼續執行,直到ffmpeg完成其執行。這是因爲這樣的事實,在該票據中說起了PHP的exec()函數,上面寫着:
若是程序使用此函數啓動,爲了使其在後臺繼續運行,程序的輸出必須重定向到文件或另外一個輸出流。若是不這樣作,將致使PHP掛起,直到程序的執行結束。
不要混淆的例子顯示了shell_exec()調用,而不是EXEC() 。全部的PHP的程序執行功能共享相同的代碼庫和限制。
因此,要解決這個問題,咱們須要作這樣的事情:
<?php echo "Starting ffmpeg...\n\n"; echo shell_exec("ffmpeg -i input.avi output.avi >/dev/null 2>/dev/null &"); echo "Done.\n"; ?>
該說的部分「 >的/ dev / null的 」將FFmpeg的實例的標準輸出(stdout)重定向到/ dev / null的(有效地忽略輸出)和「 2>的/ dev / null的 」將重定向標準錯誤(錯誤)到/ dev / null(有效地忽略任何錯誤日誌消息)。這兩個能夠組合成一個較短的表示:「 >的/ dev / null的2>&1 」。若是你喜歡,你能夠閱讀更多關於I / O重定向。
這裏應該提到一個重要的注意事項。ffmpeg命令行工具使用stderr輸出錯誤日誌消息,而且保留stdout用於可能使用的管道(將從ffmpeg生成的輸出媒體流重定向到其餘命令行工具)。也就是說,若是你在後臺運行你的ffmpeg,你極可能想把stderr重定向到一個日誌文件,以便可以檢查它。
須要注意的另外一件事是標準INPUT(stdin)。命令行ffmpeg工具被設計爲一個交互式實用程序,它接受用戶的輸入(一般來自鍵盤),並在用戶的當前屏幕/終端上報告錯誤日誌。當咱們在後臺運行ffmpeg時,咱們想要告訴ffmpeg沒有從stdin接受任何輸入(也不等待)。咱們能夠告訴這ffmpeg的,再次使用I / O重定向「 <的/ dev / null的 」,這樣最後一個例子,安全運行ffmpeg的命令行工具在後臺將與此相似:
<?php echo "Starting ffmpeg...\n\n"; echo shell_exec("ffmpeg -y -i input.avi output.avi </dev/null >/dev/null 2>/var/log/ffmpeg.log &"); echo "Done.\n"; ?>
在「-y」選項用於自動覆蓋輸出文件(output.avi)不要求是/否確認。若是須要相反的狀況,若是輸出文件已經存在,要自動取消整個過程,請改用「-n」選項。
一些PHP庫容許將ffmpeg調用包裝到PHP對象中,而且若是您不喜歡使用命令行,能夠爲您提供一個不錯的語法。其中之一是在積極維護PHP-FFmpeg的。它只須要你下載一個最新的ffmpeg和ffprobe從安裝PHP組件構建分開。而後你能夠這樣運行PHP代碼:
$ffmpeg = FFMpeg\FFMpeg::create(); $video = $ffmpeg->open('video.mpg'); $video->filters() ->resize(new FFMpeg\Coordinate\Dimension(320, 240)) ->synchronize(); $video->save(new FFMpeg\Format\Video\X264(), 'export-x264.mp4')
固然,你須要在後臺運行這樣的任務。圖書館如GearmanClient促成。
注: ffmpeg的- PHP的是,2007年以來未開發的擴展名(和要求「的ffmpeg-0.4.9_pre1或更高版本」),這意味着你僅限於使用一種很是古老的版本的ffmpeg,沒有可能把它更新到最新版本。因爲進行了大量的更改/改進,在ffmpeg的代碼中,天天,它使得ffmpeg-php與最新的ffmpeg不兼容。
案例成功測試結果:
<?php echo "正在啓動ffmpeg...\n\n"; echo shell_exec("ffmpeg -y -i rtmp://tinywan.123.com/live/4001483413136 -c copy -f flv rtmp://131.180/live/4001483492781?vhost=13.168 </dev/null >/dev/null 2>/var/log/ffmpeg.log &"); echo "完成.\n";
正在啓動ffmpeg... 完成.
日誌文件:
ffmpeg version 2.3.git Copyright (c) 2000-2014 the FFmpeg developers built on Sep 1 2014 19:01:47 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1) configuration: --prefix=/usr/local/ffmpeg/build --extra-cflags=-I/usr/local/ffmpeg/build/include --extra-ldflags=-L/usr/local/ffmpeg/build/lib --bindir=/usr/local/ffmpeg/bin --enable-gpl --enable-libass --enable-libfaac --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-nonfree --enable-openssl --enable-libspeex --enable-libxvid libavutil 54. 7.100 / 54. 7.100 libavcodec 56. 1.100 / 56. 1.100 libavformat 56. 3.100 / 56. 3.100 libavdevice 56. 0.100 / 56. 0.100 libavfilter 5. 0.103 / 5. 0.103 libswscale 3. 0.100 / 3. 0.100 libswresample 1. 1.100 / 1. 1.100 libpostproc 53. 0.100 / 53. 0.100 [flv @ 0x2862000] Stream discovered after head already parsed Last message repeated 1 times Input #0, flv, from 'rtmp://tinywan.3213.com/live/4001483413136': Metadata: Server : Tengine displayWidth : 1920 displayHeight : 1080 fps : 25 profile : level : Duration: 00:00:00.00, start: 765.097000, bitrate: N/A Stream #0:0: Video: h264 (High), yuv420p(tv, bt709), 1920x1080, 1048 kb/s, 25 fps, 25 tbr, 1k tbn, 2k tbc Stream #0:1: Data: none Stream #0:2: Audio: aac, 44100 Hz, stereo, fltp Output #0, flv, to 'rtmp://1232130/live/4001483492781?vhost=321312': Metadata: Server : Tengine displayWidth : 1920 displayHeight : 1080 fps : 25 profile : level : encoder : Lavf56.3.100 Stream #0:0: Video: h264 ([7][0][0][0] / 0x0007), yuv420p, 1920x1080, q=2-31, 1048 kb/s, 25 fps, 1k tbn, 1k tbc Stream #0:1: Audio: aac ([10][0][0][0] / 0x000A), 44100 Hz, stereo Stream mapping: Stream #0:0 -> #0:0 (copy) Stream #0:2 -> #0:1 (copy) Press [q] to stop, [?] for help
測試成功!