這兩天研究了FFmpeg獲取DirectShow設備數據的方法,在此簡單記錄一下以作備忘。本文所述的方法主要是對應Windows平臺的。
1.?????? 列設備
[plain]?view plaincopy
ffmpeg?-list_devices?true?-f?dshow?-i?dummy??命令執行后輸出的結果如下(注:中文的設備會出現亂碼的情況)。列表顯示設備的名稱很重要,輸入的時候都是使用“-f dshow -i video="{設備名}"”的方式。
我自己的機器上列出了以下設備:
[plain]?view plaincopy
[dshow?@0388f5e0]?DirectShow?video?devices??[dshow?@0388f5e0]??"Integrated?Camera"??[dshow?@0388f5e0]?"screen-capture-recorder"??[dshow?@0388f5e0]?DirectShow?audio?devices??[dshow?@0388f5e0]??"鍐呰楹﹀厠椋?(Conexant20672?SmartAudi"??[dshow?@0388f5e0]??"virtual-audio-capturer"??下文的測試中,使用其中的兩個視頻輸入:"Integrated Camera"和"screen-capture-recorder"。
?注:音頻設備出現亂碼,這個問題的解決方法會隨后提到。
2.?????? 獲取攝像頭數據(保存為本地文件或者發送實時流)
2.1. 編碼為H.264,保存為本地文件
下面這條命令,實現了從攝像頭讀取數據并編碼為H.264,最后保存成mycamera.mkv。
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="Integrated?Camera"?-vcodec?libx264?mycamera.mkv??2.2. 直接播放攝像頭的數據
使用ffplay可以直接播放攝像頭的數據,命令如下:
[plain]?view plaincopy
ffplay?-f?dshow?-i?video="Integrated?Camera"??如果設備名稱正確的話,會直接打開本機的攝像頭,如圖所示。
注:除了使用DirectShow作為輸入外,使用VFW也可以讀取到攝像頭的數據,例如下述命令可以播放攝像頭數據:
[plain]?view plaincopy
ffplay?-f?vfwcap?-i?0??此外,可以使用FFmpeg的list_options查看設備的選項:
[plain]?view plaincopy
ffmpeg?-list_options?true?-f?dshow?-i?video="Integrated?Camera"??輸出如下:
[plain]?view plaincopy
[dshow?@?03845420]?DirectShow?video?device?options??[dshow?@?03845420]??Pin?"鎹曡幏"??[dshow?@?03845420]???pixel_format=bgr24??min?s=640x480?fps=15?max?s=640x480?fps=30??[dshow?@?03845420]???pixel_format=bgr24??min?s=640x360?fps=15?max?s=640x360?fps=30??[dshow?@?03845420]???pixel_format=bgr24??min?s=352x288?fps=15?max?s=352x288?fps=30??[dshow?@?03845420]???pixel_format=bgr24??min?s=320x240?fps=15?max?s=320x240?fps=30??[dshow?@?03845420]???pixel_format=bgr24??min?s=800x448?fps=1?max?s=800x448?fps=15??[dshow?@?03845420]???pixel_format=bgr24??min?s=960x544?fps=1?max?s=960x544?fps=10??[dshow?@?03845420]???pixel_format=bgr24??min?s=1280x720?fps=1?max?s=1280x720?fps=10??[dshow?@?03845420]???pixel_format=bgr24??min?s=424x240?fps=15?max?s=424x240?fps=30??[dshow?@?03845420]???pixel_format=yuyv422??min?s=640x480?fps=15?max?s=640x480?fps=30??[dshow?@?03845420]???pixel_format=yuyv422??min?s=640x360?fps=15?max?s=640x360?fps=30??[dshow?@?03845420]???pixel_format=yuyv422??min?s=352x288?fps=15?max?s=352x288?fps=30??[dshow?@?03845420]???pixel_format=yuyv422??min?s=320x240?fps=15?max?s=320x240?fps=30??[dshow?@?03845420]???pixel_format=yuyv422??min?s=800x448?fps=1?max?s=800x448?fps=15??[dshow?@?03845420]???pixel_format=yuyv422??min?s=960x544?fps=1?max?s=960x544?fps=10??[dshow?@?03845420]???pixel_format=yuyv422??min?s=1280x720?fps=1?max?s=1280x720?fps=10??[dshow?@?03845420]???pixel_format=yuyv422??min?s=424x240?fps=15?max?s=424x240?fps=30??[dshow?@?03845420]???vcodec=mjpeg??min?s=640x480?fps=15?max?s=640x480?fps=30??[dshow?@?03845420]???vcodec=mjpeg??min?s=640x360?fps=15?max?s=640x360?fps=30??[dshow?@?03845420]???vcodec=mjpeg??min?s=352x288?fps=15?max?s=352x288?fps=30??[dshow?@?03845420]???vcodec=mjpeg??min?s=320x240?fps=15?max?s=320x240?fps=30??[dshow?@?03845420]???vcodec=mjpeg??min?s=800x448?fps=15?max?s=800x448?fps=30??[dshow?@?03845420]???vcodec=mjpeg??min?s=960x544?fps=15?max?s=960x544?fps=30??[dshow?@?03845420]???vcodec=mjpeg??min?s=1280x720?fps=15?max?s=1280x720?fps=30??
可以通過輸出信息設置攝像頭的參數。
例如,設置攝像頭分辨率為1280x720
[plain]?view plaincopy
ffplay?-s?1280x720?-f?dshow?-i?video="Integrated?Camera"??設置分辨率為424x240
[plain]?view plaincopy
ffplay?-s?424x240?-f?dshow?-i?video="Integrated?Camera"??2.3. 編碼為H.264,發布UDP
下面這條命令,實現了:獲取攝像頭數據->編碼為H.264->封裝為UDP并發送至組播地址。
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="Integrated?Camera"?-vcodec?libx264?-preset:v?ultrafast?-tune:v?zerolatency?-f?h264?udp://233.233.233.223:6666??注1:考慮到提高libx264的編碼速度,添加了-preset:v ultrafast和-tune:v zerolatency兩個選項。
注2:高分辨率的情況下,使用UDP可能出現丟包的情況。為了避免這種情況,可以添加–s 參數(例如-s 320x240)調小分辨率。
2.4. 編碼為H.264,發布RTP
下面這條命令,實現了:獲取攝像頭數據->編碼為H.264->封裝為RTP并發送至組播地址。
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="Integrated?Camera"?-vcodec?libx264?-preset:v?ultrafast?-tune:v?zerolatency?-f?rtp?rtp://233.233.233.223:6666>test.sdp??注1:考慮到提高libx264的編碼速度,添加了-preset:v ultrafast和-tune:v zerolatency兩個選項。
注2:結尾添加“>test.sdp”可以在發布的同時生成sdp文件。該文件可以用于該視頻流的播放。
2.5. 編碼為H.264,發布RTMP
下面這條命令,實現了:獲取攝像頭數據->編碼為H.264->并發送至RTMP服務器。
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="Integrated?Camera"?-vcodec?libx264?-preset:v?ultrafast?-tune:v?zerolatency?-f?flv?rtmp://localhost/oflaDemo/livestream??發布rtsp:
ffmpeg -f dshow -i video="USB2.0 Camera" -vcodec libx264 -f rtsp rtsp://127.0.0.1:554/test
2.6. 編碼為MPEG2,發布UDP
與編碼為H.264類似,指明-vcodec即可。
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="Integrated?Camera"?-vcodec?mpeg2video?-f?mpeg2video?udp://233.233.233.223:6666??播放MPEG2的UDP流如下。指明-vcodec為mpeg2video即可
[plain]?view plaincopy
ffplay?-vcodec?mpeg2video?udp://233.233.233.223:6666???
3.?????? 屏幕錄制(Windows平臺下保存為本地文件或者發送實時流)
Linux下使用FFmpeg進行屏幕錄制相對比較方便,可以使用x11grab,使用如下的命令:
[plain]?view plaincopy
ffmpeg?-f?x11grab?-s?1600x900?-r?50?-vcodec?libx264?–preset:v?ultrafast?–tune:v?zerolatency?-crf?18?-f?mpegts?udp://localhost:1234??詳細時使用方式可以參考這篇文章:DesktopStreaming With FFmpeg for Lower Latency
Linux錄屏在這里不再贅述。在Windows平臺下屏幕錄像則要稍微復雜一些。在Windows平臺下,使用-dshow取代x11grab。一句話介紹:注冊錄屏dshow濾鏡(例如screen-capture-recorder),然后通過dshow獲取錄屏圖像然后編碼處理。
因此,在使用FFmpeg屏幕錄像之前,需要先安裝dshow濾鏡。在這里推薦一個軟件:screen capture recorder。安裝這個軟件之后,就可以通過FFmpeg屏幕錄像了。
?
screen capture recorder項目主頁:
http://sourceforge.net/projects/screencapturer/
下載地址:
http://sourceforge.net/projects/screencapturer/files
下載完后,一路“Next”即可安裝完畢。注意,需要Java運行環境(Java Runtime Environment),如果沒有的話下載一個就行。
screen capture recorder本身就可以錄屏,不過這里我們使用FFmpeg進行錄屏。
3.1. 編碼為H.264,保存為本地文件
下面的命令可以將屏幕錄制后編碼為H.264并保存為本地文件。
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="screen-capture-recorder"?-r?5?-vcodec?libx264?-preset:v?ultrafast?-tune:v?zerolatency?MyDesktop.mkv??注:“-r 5”的意思是把幀率設置成5。 ? ? ? ??
最后得到的效果如下圖。
此外,也可以錄聲音,聲音輸入可以分成兩種:一種是真人說話的聲音,通過話筒輸入;一種是虛擬的聲音,即錄屏的時候電腦耳機里的聲音。下面兩條命令可以分別錄制話筒的聲音和電腦耳機里的聲音。
錄屏,伴隨話筒輸入的聲音
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="screen-capture-recorder"?-f?dshow?-i?audio="鍐呰楹﹀厠椋?(Conexant?20672?SmartAudi"?-r?5?-vcodec?libx264?-preset:v?ultrafast?-tune:v?zerolatency?-acodec?libmp3lame?MyDesktop.mkv??上述命令有問題:audio那里有亂碼,把亂碼ANSI轉UTF-8之后,開始測試不行,后來發現是自己疏忽大意,亂碼部分轉碼后為“內裝麥克風 ”,然后接可以正常使用了。因此,命令應該如下圖所示:
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="screen-capture-recorder"?-f?dshow?-i?audio="內裝麥克風?(Conexant?20672?SmartAudi"?-r?5?-vcodec?libx264?-preset:v?ultrafast?-tune:v?zerolatency?-acodec?libmp3lame?MyDesktop.mkv??注:
如果不熟悉ANSI轉碼UTF-8的話,還有一種更簡單的方式查看設備的名稱。即不使用FFmpeg查看系統DirectShow輸入設備的名稱,而使用DirectShow SDK自帶的工具GraphEdit(或者網上下一個GraphStudioNext)查看輸入名稱。
打開GraphEdit選擇“圖像->插入濾鏡”
然后就可以通過查看Audio Capture Sources來查看音頻輸入設備的簡體中文名稱了。從圖中可以看出是“內裝麥克風 (Conexant 20672 SmartAudi”。
PS:感覺這條命令適合做講座之類的時候使用
?
錄屏,伴隨耳機輸入的聲音
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="screen-capture-recorder"?-f?dshow?-i?audio="virtual-audio-capturer"?-r?5?-vcodec?libx264?-preset:v?ultrafast?-tune:v?zerolatency?-acodec?libmp3lame?MyDesktop.mkv??PS:測這條命令的時候,這在聽歌,因此錄制的視頻中的音頻就是那首歌曲。
?
3.2. 編碼為H.264,發布UDP
下面的命令可以將屏幕錄制后編碼為H.264并封裝成UDP發送到組播地址
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="screen-capture-recorder"?-r?5?-vcodec?libx264?-preset:v?ultrafast?-tune:v?zerolatency?-f?h264?udp://233.233.233.223:6666??注1:考慮到提高libx264的編碼速度,添加了-preset:v ultrafast和-tune:v zerolatency兩個選項。
注2:高分辨率的情況下,使用UDP可能出現丟包的情況。為了避免這種情況,可以添加–s 參數(例如-s 320x240)調小分辨率。
3.3. 編碼為H.264,發布RTP
下面的命令可以將屏幕錄制后編碼為H.264并封裝成RTP并發送到組播地址
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="screen-capture-recorder"?-vcodec?libx264?-preset:v?ultrafast?-tune:v?zerolatency?-f?rtp?rtp://233.233.233.223:6666>test.sdp??注1:考慮到提高libx264的編碼速度,添加了-preset:v ultrafast和-tune:v zerolatency兩個選項。
注2:結尾添加“>test.sdp”可以在發布的同時生成sdp文件。該文件可以用于該視頻流的播放。如下命令即可播放:
[plain]?view plaincopy
ffplay?test.sdp??3.4. 編碼為H.264,發布RTMP
原理同上,不再贅述。
[plain]?view plaincopy
ffmpeg?-f?dshow?-i?video="Integrated?Camera"?-vcodec?libx264?-preset:v?ultrafast?-tune:v?zerolatency?-f?flv?rtmp://localhost/oflaDemo/livestream??注意:播放RTMP的時候,-max_delay參數會比較明顯的影響延遲,將此參數值設定小一些,有利于降低延時。
[plain]?view plaincopy
ffplay?-max_delay?100000?"rtmp://localhost/oflaDemo/livestream?live=1"??4.另一種屏幕錄制的方式(2014.10.1更新)
最近發現FFmpeg還有一個專門用于Windows下屏幕錄制的設備:gdigrab。gdigrab是基于GDI的抓屏設備,可以用于抓取屏幕的特定區域。在這里記錄一下gdigrab的用法。gdigrab通過設定不同的輸入URL,支持兩種方式的屏幕抓取:(1)“desktop”:抓取整張桌面。或者抓取桌面中的一個特定的區域。
(2)“title={窗口名稱}”:抓取屏幕中特定的一個窗口。
下面舉幾個例子。最簡單的抓屏:[plain]?view plaincopy
ffmpeg?-f?gdigrab?-i?desktop?out.mpg??從屏幕的(10,20)點處開始,抓取640x480的屏幕,設定幀率為5[plain]?view plaincopy
ffmpeg?-f?gdigrab?-framerate?5?-offset_x?10?-offset_y?20?-video_size?640x480?-i?desktop?out.mpg??
總結
以上是生活随笔為你收集整理的FFmpeg获取DirectShow设备数据(摄像头,录屏)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。