PHP基礎知識之————PHP Web腳本中使用FFmpeg

使用PHP調用系統命令實現ffmpeg的調用 . https://blog.csdn.net/weyla/article/details/46756897

測試用例:

 
  1. $name = md5(date('YmdHis')).".png";php

  2. $from = "E:\\UPLOAD\\cw\\20150626\\558d0d11ae285.mp4";html

  3. $to = "E:\\UPLOAD\\cover_images\\";git

  4. $str = "ffmpeg -i ".$from." -y -f mjpeg -ss 3 -t 1 -s 740x500 ".$to.$name;github

  5. system($str);web

簡介

本文將嘗試指出在PHP Web腳本中使用FFmpeg時須要瞭解的全部重要事項。它還將顯示一些使用示例,以使事情更清楚。這個想法也能夠應用到其餘web腳本語言。shell

從PHP腳本調用命令行工具

選擇一個模型

網頁設計爲快速執行,以便瀏覽您的網站的人沒必要等待太多的響應。由於若是他們無聊的等待,他們只會導航到另外一個,更靈敏(一般是您的競爭對手的)網站。話雖如此,你能夠作的最糟糕的事情是從你的web腳本運行一個命令行工具(如ffmpeg),並等待它完成處理,以便可以將結果返回到等待在線用戶(異常這是小/快的工具,其執行時間過小而不能注意到)。數據庫

您想要作的是將命令行工具的長處理與Web腳本執行分開,以使腳本更具響應性。因此,你有至少兩個選項:ubuntu

  1. 運行命令行工具(使用了shell_exec()在後臺爲例),並繼續與web腳本執行,按期刷新狀態頁面,顯示當前進度

 

  1. 建立一個新的「做業」(一般是數據庫表中的一個新行),並有一些背景「工做」進程(cron做業,shell腳本,批處理腳本),它將監視「做業列表」須要處理的新工做

 

這兩種方法看起來是同樣的,可是他們不是。最重要的區別是,第二種方法能夠更好地擴展更高的網站流量,由於它容許「工做」進程在徹底獨立的機器上運行。此外,能夠有幾個「工做」機器,一塊兒工做,分裂工做負載,涉及小的同步。安全

第一種方法一般是大多數想要快速完成工做的人的首選,可是在他們的網站變得流行的時間,他們的web服務器變得不那麼敏感,因爲不斷的cpu飢餓,由多個命令行工具(ffmpeg實例)在後臺運行。在那一刻,他們一般開始考慮第二種方法。服務器

在後臺運行的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

複製代碼

測試成功!

 

參考文獻:http://trac.ffmpeg.org/wiki/PHP

相關文章
相關標籤/搜索