FFMPEG--最简单的视频网站(点播、直播)
本文記錄一個最簡單的視頻網(wǎng)站系統(tǒng)。此前做過一些基于JavaEE中的 SSH (Strut2 + Spring + Hibernate)的網(wǎng)站系統(tǒng),但是一直沒有做過一個視頻網(wǎng)站系統(tǒng),所以就打算做一個“精簡”的視頻網(wǎng)站系統(tǒng),以方便以后測試以及學習使用。本視頻網(wǎng)站支持直播(通過RTMP實現(xiàn))和點播(通過HTTP實現(xiàn))。為了保持精簡,這個視頻網(wǎng)站系統(tǒng)僅制作了網(wǎng)絡視頻的管理功能(增刪改查),以及相關(guān)的參數(shù)配置功能。由于自己在JavaEE方面沒有深入學習過,所以這個系統(tǒng)有部分功能還沒搞完,以后有時間再慢慢完善。
簡介
架構(gòu)
系統(tǒng)前臺顯示采用了Div + CSS+ Javascript技術(shù)。其中前臺顯示用了一些Javascript插件,例如說生成旋轉(zhuǎn)燈籠式效果的CloudCarousel,生成導航菜單的 ddsmoothmenu,用于表單驗證的jQuery Validation Engine等等。其中視頻播放器用了FlowPlayer(包含了RTMP插件)來支持HTTP的點播和RTMP的直播。按理說視頻文件上傳的時候可以使用Ajax實現(xiàn),但是考慮工作比較繁瑣,所以暫時還是使用直接文件上傳的方式。
系統(tǒng)的后臺使用了JavaEE系統(tǒng)中最傳統(tǒng)的三層架構(gòu):Action層,Service層以及DAO層。其中Action層使用了Struts2框架,用于處理前臺頁面?zhèn)鱽淼恼埱?#xff1b;DAO層使用了Hibernate框架,用于和數(shù)據(jù)庫的交互。Spring框架則用于將Action層,Service層以及 DAO層整合起來。系統(tǒng)的前后臺交互主要使用了JSTL標簽和EL表達式。此外考慮到國際化方面的要求,采用了Struts2的i18n方式,將所有頁面上的文字都抽取坐來保存到單獨的文件中,這樣就可以實現(xiàn)多種語言的顯示。
系統(tǒng)開始運行后,會開啟兩個線程VideoThumbnailThread和VideoTranscoderThread。 VideoThumbnailThread用于截取視頻的縮略圖,VideoTranscoderThread則用于轉(zhuǎn)碼上傳的視頻。這兩個線程都是通過調(diào)用ffmpeg.exe完成相應的功能。
此外,系統(tǒng)中還包含了查看媒體信息的功能。該功能通過調(diào)用MediaInfo.dll完成,不再詳述。
整個系統(tǒng)的框架如下圖所示,后文中再詳細記錄每部分的功能。
效果
系統(tǒng)主要包含了以下幾個頁面: 主頁(index.jsp):進入系統(tǒng)的第一個頁面。?視頻列表(videolist.jsp):列表顯示視頻資源的頁面。按照視頻源的類型的不同可以分為點播(VOD)視頻列表和直播(Live)視頻列表。?
視頻編輯(videoedit.jsp):編輯視頻資源的頁面。按照視頻源的類型的不同可以分為點播(VOD)編輯和直播(Live)編輯。按照操作的不同可以分為添加(Add)和編輯(Edit)。?
視頻內(nèi)容(videocontent.jsp):查看視頻的內(nèi)容的頁面。按照視頻源的類型的不同可以分為點播(VOD)視頻內(nèi)容和直播(Live)視頻內(nèi)容。?
設置(configure.jsp):設置頁面。用于配制系統(tǒng)的參數(shù)。?
關(guān)于(about.jsp):顯示系統(tǒng)相關(guān)的一些信息的頁面。
首頁
網(wǎng)站首頁的如下圖所示。Logo位于左上角,菜單欄位于右上角。為了美觀一些,頁面上方做了一個燈箱效果的特效,隨機顯示一些視頻的縮略圖。頁面下方則分別列出“點播列表”和“直播列表”中最近添加的幾個視頻。
點播列表
點播列表頁面如下圖所示。在該頁面中,可以對點播視頻進行簡單的管理:查看內(nèi)容,添加,修改以及刪除。
直播列表
點播列表頁面如下圖所示。直播列表實質(zhì)上使用了和點播列表相同的頁面。在該頁面中,可以對直播視頻進行簡單的管理:查看內(nèi)容,添加,修改以及刪除。
視頻內(nèi)容頁面
視頻內(nèi)容頁面如下所示。該頁面中包含了一個FlowPlayer播放器,該播放器用于播放視頻內(nèi)容。點播視頻內(nèi)容頁面如下所示。
直播視頻內(nèi)容頁面如下所示。盡管表面上看點播和直播頁面完全相似,但是實際上點播和直播的機制是不一樣的。點播依靠的是HTTP漸進式下載,而直播依靠的是FlowPlayer的RTMP組件。
視頻添加頁面
點播視頻添加頁面如下所示。該頁面用于上傳一個點播視頻。“名稱”輸入框用于指定視頻的名稱,“文件”用于指定上傳的視頻文件,“簡介”可以指定針對該視頻的一段簡介。其中,“名稱”和“文件”兩個輸入框為必填項,否則無法提交該頁面的表單。
直播視頻添加頁面如下所示。從圖中可以看出直播和點播的添加頁面很類似。它們的不同在于:點播是上傳一個視頻文件,而直播是指定一個URL(目前該URL只支持RTMP)。和點播類似,“名稱”和“URL”兩個輸入框為必填項,否則無法提交該頁面的表單。
視頻編輯頁面
點播視頻編輯頁面如下所示。該頁面用于編輯已經(jīng)完成上傳的點播視頻的信息。
直播視頻編輯頁面如下所示。該頁面用于編輯直播視頻的信息。
配置
系統(tǒng)的配置頁面如下圖所示。該頁面用于配置系統(tǒng)的各種設置(以轉(zhuǎn)碼設置為主)。每次配置完成后重啟系統(tǒng)后設置生效。包含以下參數(shù)。- 視頻編碼器:轉(zhuǎn)碼使用的視頻編碼器,默認值為“l(fā)ibx264”。
- 視頻碼率 (bps) :視頻編碼的碼率(單位為bps),默認值為500000(500kbps)。
- 視頻幀率 (fps) :視頻編碼的幀率(單位為fps),默認值為25。
- 音頻編碼器:轉(zhuǎn)碼時候使用的音頻編碼器,默認值為“l(fā)ibmp3lame”。
- 音頻采樣率 (Hz) :音頻編碼的采樣率(單位為Hz),默認值為22050(22.05kHz)。
- 音頻碼率 (bps) :音頻編碼的碼率(單位為bps),默認值為64000(64kbps)。
- 視頻寬 (pixel) :轉(zhuǎn)碼后視頻的寬(單位為pixel),默認值為640。
- 視頻高 (pixel) :轉(zhuǎn)碼后視頻的高(單位為pixel),默認值為360。
- 使用水印:選擇轉(zhuǎn)碼后的視頻是否加水印。如果該選項選擇“是”,則會在轉(zhuǎn)碼后的視頻中添加水印。
- 水印文件路徑:水印文件的路徑,此處為文件相對于網(wǎng)站根目錄的路徑,默認為“watermark/svw.png”。
- 水印位置-x坐標 (pixel) :水印在視頻中的位置——x坐標(單位為pixel),默認值為5。
- 水印坐標-y坐標 (pixel) :水印在視頻中的位置——y坐標(單位為pixel),默認值為5。
- 保持寬高比并且填充黑邊:選擇轉(zhuǎn)碼后是否保持寬高比。如果該選項選擇“是”,則轉(zhuǎn)碼后的視頻會保持寬高比,并且當輸入和輸出視頻寬高比不一樣的時候,會在輸出視頻中添加黑邊。如果該選項選擇“否”,則轉(zhuǎn)碼后的視頻會拉伸成輸出分辨率。
- 輸出視頻封裝格式:輸出視頻的封裝格式,默認為“flv”。
- 視頻截圖位置 (sec) :獲取視頻縮略圖的位置(單位為sec),默認為5sec。該默認值的含義是獲取視頻第5秒處的視頻幀作為視頻的縮略圖。
- 上傳視頻存放文件夾:用于存放上傳的視頻文件,默認值為“videoori”。
- 轉(zhuǎn)碼視頻存放文件夾:用于存放轉(zhuǎn)碼的視頻文件,默認值為“video”。
- 視頻截圖存放文件夾:用于存放視頻的截圖,默認值為“videothumbnail”。
MediaInfo信息
MediaInfo信息位于視頻內(nèi)容頁面中,在默認的情況下是不顯示的。通過修改網(wǎng)頁中代碼可以顯示視頻的MediaInfo信息。轉(zhuǎn)碼前文件信息如下圖所示,從圖中可以看出轉(zhuǎn)碼前的文件格式是MPEG-PS,視頻編碼為MPEG-1,音頻編碼為MP2。
轉(zhuǎn)碼后文件信息如下圖所示,從圖中可以看出轉(zhuǎn)碼前的文件是FLV格式的,視頻編碼為H.264,音頻編碼MP3。
多國語言
本系統(tǒng)支持多國語言。選擇右上角菜單的“語言”->“English”可以將系統(tǒng)切換到英文。英文界面如下圖所示。
英文版的視頻點播列表如下圖所示。
英文版的視頻內(nèi)容頁面如下圖所示。
英文版的配置界面如下圖所示。
網(wǎng)站部分
下面簡單記錄一下網(wǎng)站部分的關(guān)鍵源代碼。分成三個部分:數(shù)據(jù)庫、前臺和后臺。
數(shù)據(jù)庫
系統(tǒng)包含了4張表:video,videostate,category,configure。下面簡單記錄每個表的含義。
Video表
Video表用于存儲視頻記錄。每一個視頻對應Video表中的一條記錄。該表中的字段如下表所示。
備注
*其中點播視頻的URL為視頻文件的相對路徑。
下面例舉Video表中的幾項和URL有關(guān)數(shù)據(jù)(受限于篇幅,省略其它字段)。
Videostate表
Videostate表用于存儲視頻的狀態(tài)。該表中字段如下表所示。
目前按照執(zhí)行的順序定義了4種狀態(tài):等待上傳,等待截圖,等待轉(zhuǎn)碼,完成。其中“CSS樣式”用于輔助顯示視頻的狀態(tài)。該表的內(nèi)容如下
Category表
Category表用于存儲視頻的分類。該表可以用于確定視頻的分類,目前還沒有做太多開發(fā)。
Configure表
Configure表用于存儲系統(tǒng)配置信息。該表中字段如下表所示。
該表的內(nèi)容如下。
前臺
前臺部分沒有太多可以記錄的,基本上都是各種DIV和CSS的調(diào)整。其中使用了較多的JSTL標簽以及EL表達式。此外使用了Struts2標簽用于支持國際化。基本的jsp頁面只有6個: index.jsp:首頁。?
videolist.jsp:視頻列表——直播視頻列表,點播視頻列表。?
videoedit.jsp:視頻編輯——直播視頻添加,直播視頻編輯,點播視頻添加,點播視頻編輯。?
videocontent.jsp:視頻內(nèi)容——直播視頻內(nèi)容,點播視頻內(nèi)容。?
configure.jsp:配置頁面。?
about.jsp:關(guān)于頁面。 除了基本頁面之外,還有一些輔助頁面: cfooter.jsp:頁腳。?
cheader.jsp:標題欄。?
csidebar_recent.jsp:側(cè)邊欄(最近添加)。?
error.jsp:錯誤頁面。
FlowPlayer播放器
前臺頁面中用于視頻播放的播放器是FlowPlayer。FlowPlayer播放器安裝有3個步驟:?(1)包含F(xiàn)lowPlayer的Js文件 <script type="text/javascript" src="videoplayer/flowplayer-3.2.8.min.js"></script>
(2)添加一個<a>標記
<a href="http://www.mywebsite.com/myVideo.flv" style="display:block;width:425px;height:300px;" id="player"> </a>(3)添加一段Javascript代碼,其中要包含F(xiàn)lowPlayer的Swf文件
<script language="JavaScript"> flowplayer("player", "path/to/the/flowplayer-3.2.18.swf"); </script>FlowPlayer通過HTTP播放點播視頻文件的源代碼如下所示。${video.url}中保存了視頻的相對URL。
<a id="player" href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/${video.url}"> </a> <script> flowplayer("player", "videoplayer/flowplayer-3.2.8.swf"); </script>FlowPlayer 通過RTMP播放直播視頻文件的示例代碼如下所示。${video.url}中保存了視頻的URL。播放RTMP的時候用到了FlowPlayer的 RTMP Plugin。需要注意的是,RTMP的URL需要拆分開來分別填到不同的位置。在這里通過split(‘/’)函數(shù)按照“/”將字符串分離為字符串數(shù)組。然后將“protocol://server/app”填至plugins的netConnectionUrl字段,playpath填至clip的 url字段。
<a id="player"> </a> <!-- Parse RTMP URL --> <script> str='${video.url}'; arr=str.split('/'); //rtmp://server/app/playpath protocol=arr[0]; server=arr[2]; app=arr[3]; playpath=arr[4]; lowplayer("player", "videoplayer/flowplayer-3.2.8.swf",{ clip: { //scaling:'orig', url: playpath, provider: 'rtmp', live:'true' }, plugins: { rtmp: { url: 'videoplayer/flowplayer.rtmp-3.2.8.swf', netConnectionUrl: protocol+'//'+server+'/'+ app } } }); script>后臺
后臺部分采用了JavaEE的SSH (Struts2 + Spring + Hibernate)的三層架構(gòu),其中的代碼不再詳細記錄。三層分別為Action層、Service層和DAO層。其中Action層采用了 Struts2框架,DAO層采用了Hibernate框架,而Spring則整合了這三個層面。
BaseService/BaseDAO
SSH 三層架構(gòu)雖然在解耦合方面做得很好,但是卻導致開發(fā)起來非常繁瑣,嚴重降低了開發(fā)的速度。為了方便起見,本系統(tǒng)中在Service層編寫了 BaseService用于完成通用的Service操作;在DAO層也編寫了BaseDAO用于完成通用的DAO操作。這樣除非有特殊需求,一般情況下只要調(diào)用BaseService中的方法就可以完成各種基本的操作。BaseService包含的接口如下所示。
/** * 最簡單的視頻網(wǎng)站 * Simplest Video Website * * 雷霄驊 Lei Xiaohua * * leixiaohua1020@126.com * 中國傳媒大學/數(shù)字電視技術(shù) * Communication University of China / Digital TV Technology * http://blog.csdn.net/leixiaohua1020 * * 本程序是一個最簡單的視頻網(wǎng)站視頻。它支持 * 1.直播 * 2.點播 * This software is the simplest video website. * It support: * 1. live broadcast * 2. VOD */ package service; import java.util.List; /** * @author 雷霄驊 * 對Object的Service * 包含了一些通用的方法 */ public interface BaseService { /** * 保存一個對象 * @param object 一個對象 */ public void save(Object object); /** * 更新一個對象 * @param object 一個對象 */ public void update(Object object); /** * 刪除一個對象 * @param object 一個對象 */ public void delete(Object object); /** * 根據(jù)ID讀取一個指定名稱的對象 * @param targetName 對象的名稱 * @param id 對象的ID * @return 一個對象 */ public Object ReadByID(String targetName,int id); @SuppressWarnings("rawtypes") /** * 獲取指定類型的所有對象 * @param targetName 對象類型名稱 * @return 對象的列表 */ public List ReadAll(String targetName); @SuppressWarnings("rawtypes") /** * 根據(jù)“屬性-值”獲取多個指定類型的對象 * @param targetName 對象類型名稱 * @param propertyName 對象中屬性的名稱 * @param propertyValue 對象中屬性的值 * @return 對象的列表 */ public List ReadByProperty(String targetName,String propertyName,Object propertyValue); /** * 根據(jù)“屬性-值”獲取一個指定類型的對象 * @param targetName 對象類型名稱 * @param propertyName 對象中屬性的名稱 * @param propertyValue 對象中屬性的值 * @return 一個對象 */ public Object ReadSingle(String targetName,String propertyName,Object propertyValue); /** * 獲取多個指定類型的對象,可以限定獲取對象數(shù)目的多少,并且根據(jù)特定的屬性進行排序。 * @param targetName 對象類型名稱 * @param propertyName 對象中屬性的名稱,用于排序 * @param num 結(jié)果對象列表的最大數(shù)目 * @param order 排序方式,可以選擇“asc”或者“desc” * @return 對象的列表 */ public List ReadLimitedByOrder(String targetName,String propertyName,int num,String order); /** * 獲取指定類型的對象的數(shù)量。 * @param targetName 對象類型名稱 * @return 數(shù)量 */ public int ReadCount(String targetName); /** * 根據(jù)“屬性-值”為條件,獲取指定類型的對象的數(shù)量。 * @param targetName 對象類型名稱 * @param propertyName 對象中屬性的名稱 * @param propertyValue 對象中屬性的值 * @return 數(shù)量 */ public int ReadCountByProperty(final String targetName,String propertyName, Object value); /** * 兩個功能: * 1.根據(jù)“屬性-值”獲取多個指定類型的對象 * 2.限定獲取對象數(shù)目的多少,并且根據(jù)特定的屬性進行排序。 * @param targetName 對象類型名稱 * @param readpropertyName 對象中屬性的名稱,用于獲取對象 * @param readvalue 對象中屬性的值 * @param orderpropertyName 對象中屬性的名稱,用于排序 * @param num 結(jié)果對象列表的最大數(shù)目 * @param order 排序方式,可以選擇“asc”或者“desc” * @return */ public List ReadByPropertyAndLimitedByOrder(final String targetName, final String readpropertyName, final Object readvalue,final String orderpropertyName, final int num, final String order); }FFmpeg部分
截取縮略圖線程和轉(zhuǎn)碼線程
系統(tǒng)在啟動后會開啟兩個線程:VideoThumbnailThread和VideoTranscoderThread。其中 VideoThumbnailThread線程會不停的檢測需要截取縮略圖的視頻,調(diào)用相應的FFmpeg命令截取縮略圖;VideoTranscoderThread線程會不停的監(jiān)測需要轉(zhuǎn)碼的視頻,調(diào)用相應的FFmpeg命令轉(zhuǎn)碼視頻。何以確定視頻是否需要截取縮略圖以及是否需要轉(zhuǎn)碼?這是通過video表中的videostateid字段來標識的。視頻開始上傳后,該視頻記錄會被標記為“等待上傳”(第1步);上傳完畢后,該視頻記錄會被標記為“等待截圖”(第2步);截圖完畢后,該視頻記錄會被標記為“等待轉(zhuǎn)碼”(第3步);轉(zhuǎn)碼完畢后,該視頻記錄會被標記為“完成”(第4步)。VideoThumbnailThread會不停地檢查系統(tǒng)中“等待截圖”的視頻,截圖完成后將視頻標記為“等待轉(zhuǎn)碼”;VideoTranscoderThread會不停地檢查系統(tǒng)中“等待轉(zhuǎn)碼”的視頻,轉(zhuǎn)碼完成后將視頻標記為“完成”。
FFmpeg和Java的整合
FFmpeg和Java整合的過程中有以下幾個需要注意的地方:
(1)路徑的處理
FFmpeg處理視頻的時候需要用到絕對路徑,所以涉及到絕對路徑獲取的問題。使用ServletContext的getRealPath("/")方法可以獲得當前Web應用根目錄的絕對路徑。例如在自己的電腦上下述代碼可以獲得Web應用的據(jù)對路徑:
ServletContext servletContext; System.out.println(servletContext.getRealPath("/"));執(zhí)行完后輸出為:
D:\MyEclipseWorkspace\.metadata\.me_tcat\webapps\simplest_video_website\相對路徑中的URL中路徑的分隔采用“/”(正斜杠,Unix系統(tǒng)使用),而上述代碼中路徑的分隔采用“\”(反斜杠,Windows系統(tǒng)使用)。如果把相對文件路徑和絕對目錄路徑拼接起來傳遞給FFmpeg的話,FFmpeg是可以識別的,但是這樣一來路徑中一會“/”一會“\”會給人一種很別扭的感覺,因此可以使用String的replace()方法將“\”統(tǒng)一替換為“/”,這樣就整齊多了。例如下面代碼:
ServletContext servletContext; System.out.println(servletContext.getRealPath("/").replace('\\', '/'));執(zhí)行完后輸出為:
D:/MyEclipseWorkspace/.metadata/.me_tcat/webapps/simplest_video_website/(2)FFmpeg命令行的調(diào)用
FFmpeg命令行的的調(diào)用可以分成兩個步驟:
(a)生成符合設置的命令
這一步驟實際上就是一個簡單的字符串拼接的過程。根據(jù)配置的參數(shù)拼接成相應的轉(zhuǎn)碼命令。需要注意的是,在輸入和輸出的文件路徑兩邊要加上雙引號。否則當文件路徑中包含空格的時候,會導致路徑解析錯誤。
(b)調(diào)用命令行
調(diào)用命令行使用Runtime.getRuntime().exec(cmdstr)方法就可以了。其中cmdstr常見的格式有兩種:
cmd /c {FFmpeg Command} cmd /c start {FFmpeg Command}第一種格式是在本窗口中直接執(zhí)行命令,第二種格式是新打開一個窗口執(zhí)行命令。第一種方法我在JavaEE環(huán)境中測試有問題,而且不彈出窗口不便于調(diào)試,所以使用第二種執(zhí)行方法。
(c)等待調(diào)用的命令行執(zhí)行完畢
Runtime.getRuntime().exec()在調(diào)用命令后就直接返回當前線程了。這不符合實際的需求。實際中需要系統(tǒng)完成FFmpeg轉(zhuǎn)碼工作后,才能做下一步操作。可以用Process的waitFor()方法阻塞當先線程直至調(diào)用程序運行結(jié)束。
截取縮略圖命令
FFmpeg截取縮略圖命令如下: ffmpeg -y -i "ourtime.flv" -ss 5 -s 220x110 -f image2 -vframes 1 "thumbnail.jpg"參數(shù)含義如下:
-y:輸出文件重名的時候,自動覆蓋。?-i:輸入文件路徑(可以是相對路徑或者絕對路徑)。?
-ss:截取縮略圖的時間點,這里是5s處。?
-s:輸出縮略圖的分辨率,這里是220x110。?
-f:輸出文件格式,這里的image2代表文件格式為圖片。?
-vframes:輸出視頻幀的個數(shù),這里是1。?
最后一個參數(shù)為輸出的縮略圖文件路徑。
轉(zhuǎn)碼命令
FFmpeg轉(zhuǎn)碼命令如下: ffmpeg -y -i "ourtime.flv" -vcodec libx264 -b:v 500000 -r 25 -acodec libmp3lame -b:a 64000 -ar 22050 -vf scale=w=640:h=360:force_original_aspect_ratio=decrease,pad=w=640:h=360:x=(ow-iw)/2:y=(oh-ih)/2[aa];movie=svw.png[bb];[aa][bb]overlay=x=5:y=5 "ourtime_convert.flv"參數(shù)含義如下:
-y:輸出文件重名的時候,自動覆蓋。?-i:輸入文件路徑(可以是相對路徑或者絕對路徑)。?
-vcodec:視頻編碼器,這里是libx264。?
-b:v:視頻碼率,這里是500000bps。?
-r:視頻幀率,這里是25fps。?
-acodec:音頻編碼器,這里是libmp3lame。?
-b:a:音頻碼率,這里是64000bps。?
-ar:音頻采樣率,這里是22050Hz。?
-vf:濾鏡,用于圖像拉伸以及水印疊加。?
最后一個參數(shù)為輸出的視頻文件路徑。
Filter(濾鏡)配置
幾句話介紹一下Filter的配置:
- Filter配置參數(shù)使用在FFmpeg的-vf參數(shù)之后
- Filter 之間可以使用“,”連接,連接之后前一個Filter的輸出作為后一個Filter的輸入。幾個Filter構(gòu)成一個FilterChain(濾鏡鏈),每個FilterChain以“;”結(jié)尾。幾個Filter Chain可以構(gòu)成一個FilterGraph(濾鏡圖)。可以在Filter的Pad上添加“標簽”用于連接其它Filter,Filter標簽的形式為“[xx]”(其中“xx”可以隨意寫一些字符,只要可以起到標記作用就可以了)。
- Filter的可以使用多個參數(shù),參數(shù)之間使用“:”分割。
下面分別記錄幾個濾鏡的使用方法。
【scale濾鏡】
scale濾鏡使用libswscale對圖像進行拉伸。它的參數(shù)含義如下:
w:輸出圖像的寬。?h:輸出圖像的高。 force_original_aspect_ratio:保持視頻寬高比的方法,可以使用如下值:(1)disable——不保持寬高比;(2)decrease——需要的時候降低寬或者高;(3)increase——需要的時候提高寬或者高。 有關(guān)force_original_aspect_ratio可以舉個例子:輸入視頻分辨率是1920x800,設置濾鏡為: scale=w=640:h=360:force_original_aspect_ratio=decrease
輸出的視頻分辨率為640x266。?
【pad濾鏡】?
pad濾鏡用于給拉伸后的圖像加“黑邊”。經(jīng)過scale濾鏡處理之后,視頻的寬一定小于等于640,而視頻的高一定小于等于360,此時需要使用pad濾鏡填充視頻的兩邊(上下或者是左右),保證輸出的視頻的分辨率為640x360。?
Pad濾鏡有四個基本的參數(shù):
h:填充后視頻的高度?
x:輸入視頻的左上角在填充后視頻中的x坐標?
y:輸入視頻的左上角在填充后視頻中的y坐標 一個基本的如法如下所示: pad=w=640:h=480:x=0:y=40
上述濾鏡將視頻填充為640x480,同時將輸入視頻的左上角放在(0,40)的位置上。?
在給視頻加黑邊的過程中,需要把輸入的視頻放在填充后視頻的中央,而pad濾鏡中輸入視頻的位置是以左上角來確定的,因此確定輸入視頻的左上角的坐標是一個比較麻煩的事。對此,pad濾鏡提供了以下幾個變量。
ih:輸入視頻的高?
ow:輸出視頻的寬?
oh:輸出視頻的高 通過上述幾個變量,可以得知如果想把輸入視頻放在填充后視頻的中央,輸入視頻的x坐標應該為(ow-iw)/2,y坐標應該為(oh-ih)/2。?
【movie濾鏡】 ?
Movie 濾鏡屬于Source濾鏡,它用于讀取水印圖片文件(一般情況下是一個PNG文件)。有關(guān)movie濾鏡有一個地方需要特別注意:它在Windows下似乎不支持輸入路徑為絕對路徑。因為Windows下文件的絕對路徑通常為“D:\test\......\watermark.png”,即其中開頭的盤符后面跟著一個“:”。“:”在Filter中是一個特殊字符,會被解析成參數(shù)的分隔符,從而導致輸入的絕對路徑被解析為2個參數(shù),最后造成錯誤。這個問題當時我調(diào)試了半天仍然沒有得到解決。因此,Windows下使用movie濾鏡的時候,需要保證水印文件就在當前的工作目錄中,才能正常運行。?
【overlay濾鏡】 ?
Overlay濾鏡用于疊加兩路輸入。具體到本文的系統(tǒng)中就是疊加水印文件到視頻文件上。它常用的有兩個參數(shù): x:水印左上角的x坐標?
y:水印左上角的y坐標
經(jīng)過上述幾個濾鏡的處理,最終就可以得到一個分辨率為640x360,保持寬高比(加黑邊),疊加過水印的視頻。
項目主頁
Simplest Video Website
開源中國:http://git.oschina.net/leixiaohua1020/simplest_video_website
安裝步驟?
1.安裝JavaEE環(huán)境:?
(1)下載安裝JDK?
(2)下載安裝Tomcat?
(3)下載安裝MySQL?
2.FFmpeg?
(1)下載并且解壓縮FFmpeg可執(zhí)行程序?
(2)把FFmpeg的bin目錄(其中包含ffmpeg.exe)添加至系統(tǒng)的"path"環(huán)境變量(重要,這樣才可以在系統(tǒng)任意目錄中使用ffmpeg命令)?
3.復制程序?
(1)修改Webroot\WEB-INF\classes\hibernate.cfg.xml中數(shù)據(jù)庫的用戶名和密碼?
(2)拷貝WebRoot目錄至Tomcat的webapps目錄,重新取個名字(例如"svw")?
(3)在MySQL中創(chuàng)建數(shù)據(jù)庫"svw",在其中執(zhí)行svw.sql,創(chuàng)建數(shù)據(jù)庫中的表,并且添加測試數(shù)據(jù)?
4.啟動Tomcat?
5.使用瀏覽器訪問http://localhost:8080/svw
總結(jié)
以上是生活随笔為你收集整理的FFMPEG--最简单的视频网站(点播、直播)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java初中级工程师面试笔试题目及心得(
- 下一篇: 2020年中,已知本年中的第几天求解改天