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


簡介

本文將嘗試指出在PHP Web腳本中使用FFmpeg時需要了解的所有重要事項。它還將顯示一些使用示例,以使事情更清楚。這個想法也可以應用到其他web腳本語言。

從PHP腳本調用命令行工具

選擇一個模型

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

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

  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的它只需要你下載一個最新的ffmpegffprobe從安裝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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM