ffmpeg使用总结
2019獨角獸企業重金招聘Python工程師標準>>>
下載安裝
下載地址
提供了可執行文件和動態庫,純命令行使用Architecture版本。
查看當前dshow可用的錄像設備和錄音設備
使用如下命令可以查看設備列表
ffmpeg -list_devices true -f dshow -i dummy可以從輸出中提取到設備名,進行視頻錄制時會使用到這個設備名
[dshow @ 0000023a33b3a680] DirectShow video devices (some may be both video and audio devices) [dshow @ 0000023a33b3a680] "USB 2.0 Webcam Device" [dshow @ 0000023a33b3a680] Alternative name "@device_pnp_\\?xxxx}\global" [dshow @ 0000023a33b3a680] "screen-capture-recorder" [dshow @ 0000023a33b3a680] Alternative name "@device_sw_{xxx}" [dshow @ 0000023a33b3a680] DirectShow audio devices [dshow @ 0000023a33b3a680] "麥克風 (Realtek High Definition Audio)" [dshow @ 0000023a33b3a680] Alternative name "@device_cm_{xxx}" [dshow @ 0000023a33b3a680] "virtual-audio-capturer" [dshow @ 0000023a33b3a680] Alternative name "@device_sw_{xxxx}"其中的 "screen-capture-recorder"和"virtual-audio-capturer"兩個是虛擬設備,用來輔助錄制屏幕和聲卡, (下載地址)[https://sourceforge.net/projects/screencapturer/files/]。
查看單個設備的可用配置可以用如下命令
ffmpeg -list_options true -f dshow -i video="{錄像設備名}"可以從輸出中得到攝像頭的可用分辨率
[dshow @ 000001d59c14a680] DirectShow video device options (from video devices) [dshow @ 000001d59c14a680] Pin "捕獲" (alternative pin name "0") [dshow @ 000001d59c14a680] pixel_format=yuyv422 min s=640x480 fps=5 max s=640x480 fps=30 [dshow @ 000001d59c14a680] pixel_format=yuyv422 min s=640x480 fps=5 max s=640x480 fps=30 ... [dshow @ 000001d59c14a680] pixel_format=yuyv422 min s=1280x720 fps=5 max s=1280x720 fps=10 [dshow @ 000001d59c14a680] vcodec=mjpeg min s=640x480 fps=5 max s=640x480 fps=30 [dshow @ 000001d59c14a680] vcodec=mjpeg min s=640x480 fps=5 max s=640x480 fps=30 ... [dshow @ 000001d59c14a680] vcodec=mjpeg min s=1280x720 fps=5 max s=1280x720 fps=30 2018-03-19 13:39:48,178 - video=USB 2.0 Webcam Device: Immediate exit requested獲取桌面信息
ffmpeg -list_options true -f gdigrab -i desktop可以從輸出中提取出桌面分辨率
[gdigrab @ 000001f1b84da680] Capturing whole desktop as 1920x1080x32 at (0,0)python代碼提取設備列表和配置信息
自己封裝的一個函數來獲取設備可用分辨率列表
__author__ = "Dalton Xiong" __license__ = "GPL" __version__ = "0.1" __email__ = "daltonxiong@gmail.com" ''' 使用ffmpeg讀取錄像設備列表及其支持的分辨率 '''import subprocess import re import logging from collections import namedtupleimport parselogging.basicConfig(level=logging.INFO,format='%(asctime)s - %(message)s')# 讀取設備列表, 忽略ffmpeg的錄屏和錄聲卡的插件程序 def device_list():cmd = 'ffmpeg -list_devices true -f dshow -i dummy'logging.info('讀取設備列表>>>>>>')logging.info(cmd)process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)output = process.stdout.read()lines = str(output, encoding='utf-8').split('\n')video_device_list = []audio_device_list = []video_device_name_flag = Falseaudio_device_name_flag = Falsefor l in lines:logging.info(l)l = l.strip()if '[dshow' in l:if 'DirectShow video devices' in l:video_device_name_flag = Trueaudio_device_name_flag = Falseelif 'DirectShow audio devices' in l:video_device_name_flag = Falseaudio_device_name_flag = Trueelif video_device_name_flag and 'Alternative name' not in l:video_device_name = re.search(r'\"(.*)\"', l) or Nonevideo_device_name = video_device_name and video_device_name.groups()[0]if video_device_name != 'screen-capture-recorder': # 忽略錄屏程序video_device_list.append(video_device_name)elif audio_device_name_flag and 'Alternative name' not in l:audio_device_name = re.search(r'\"(.*)\"', l) or Noneaudio_device_name = audio_device_name and audio_device_name.groups()[0]if audio_device_name != 'virtual-audio-capturer': # 忽略聲卡錄制程序audio_device_list.append(audio_device_name)return video_device_list, audio_device_list# 影像采集設備信息 def video_device_info(device_name):cmd = 'ffmpeg -list_options true -f dshow -i video="{}"'.format(device_name)logging.info('讀取影像采集設備({})的信息>>>>>>'.format(device_name))logging.info(cmd)process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)output = process.stdout.read()lines = str(output, encoding='utf-8').split('\n')pixel_format_set = set()vcodec_set = set()for l in lines:logging.info(l)l = l.strip()if '[dshow' not in l:continueif 'pixel_format' in l:result = parse.parse('{} pixel_format={} min s={} fps={} max s={}x{} fps={}', l)if result:pixel_format_set.add( (result[1], result[4], result[5], result[6]) )elif 'vcodec' in l:result = parse.parse('{} vcodec={} min s={} fps={} max s={}x{} fps={}', l)if result:vcodec_set.add( (result[1], result[4], result[5], result[6]) )else:continuereturn pixel_format_set, vcodec_set# 聲音采集設備信息 def audio_device_info(device_name):cmd = 'ffmpeg -list_options true -f dshow -i audio="{}"'.format(device_name)logging.info('讀取聲音采集設備({})的信息>>>>>>'.format(device_name))logging.info(cmd)process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)output = process.stdout.read()lines = str(output, encoding='utf-8').split('\n')format_set = set()for l in lines:logging.info(l)l = l.strip()if '[dshow' not in l:continueresult = parse.parse('{} min ch={} bits={} rate= {} max ch={} bits={} rate= {}', l)if result:format_set.add((result[4], result[5], result[6]))return format_set# 桌面分辨率大小 def desktop_device_info():cmd = 'ffmpeg -list_options true -f gdigrab -i desktop'logging.info('讀取桌面影像信息>>>>>>')logging.info(cmd)process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)output = process.stdout.read()lines = str(output, encoding='utf-8').split('\n')format_set = set()for l in lines:logging.info(l)l = l.strip()if '[gdigrab' not in l:continueresult = parse.parse('{} Capturing whole desktop as {}x{}x{} at (0,0)', l)if result:format_set.add( (result[1], result[2]) )return format_set# 獲取所有設備列表和可用配置信息 def device_config_list():video_device_list, audio_device_list = device_list()# 錄像設備VideoDeviceInfo = namedtuple('VideoDeviceInfo', ['width', 'height', 'fps'])vdevice_list = []for device_name in video_device_list:pixel_format_set, vcodec_set = video_device_info(device_name)format_set = vcodec_set or pixel_format_setformat_list = set()for (format, width, height, fps) in format_set:format_list.add( VideoDeviceInfo(width=int(width), height=int(height), fps=int(fps)) )format_list = list(format_list)format_list.sort(key=lambda x: (x.fps, x.width), reverse=True)device_info = {'name': device_name, 'format_list': format_list}vdevice_list.append(device_info)# 錄音設備AudioDeviceInfo = namedtuple('AudioDeviceInfo', ['channel', 'bits', 'rate'])adevice_list = []for device_name in audio_device_list:format_set = audio_device_info(device_name)format_list = set()for (channel, bits, rate) in format_set:format_list.add( AudioDeviceInfo(channel=int(channel), bits=int(bits), rate=int(rate)) )format_list = list(format_list)format_list.sort(key=lambda x: (x.channel, x.bits), reverse=True)device_info = {'name': device_name, 'format_list': format_list}adevice_list.append(device_info)# 計算機桌面desktop_format_set = desktop_device_info()if len(desktop_format_set) != 1:raise ValueError('屏幕分辨率讀取失敗')desktop_format_set = list(desktop_format_set)[0]DesktopDeviceInfo = namedtuple('DesktopDeviceInfo', ['width', 'height'])desktop_info = DesktopDeviceInfo(width=int(desktop_format_set[0]), height=int(desktop_format_set[1]))logging.info('錄像設備列表和可用配置如下:')logging.info('{}'.format(vdevice_list))logging.info('錄音設備列表和可用配置如下:')logging.info('{}'.format(adevice_list))logging.info('桌面分辨率為:{}x{}'.format(desktop_info.width, desktop_info.height))return vdevice_list,adevice_list,desktop_infoif __name__ == '__main__':vdevice_list, adevice_list, desktop_info = device_config_list()封裝了一個函數device_config_list返回了, 錄像設備列表,錄音設備列表, 桌面分辨率
錄像設備列表和可用配置如下: [{'name': 'USB 2.0 Webcam Device', 'format_list': [VideoDeviceInfo(width=1280, height=720, fps=30), VideoDeviceInfo(width=960, height=540, fps=30), VideoDeviceInfo(width=848, height=480, fps=30), VideoDeviceInfo(width=640, height=360, fps=30), VideoDeviceInfo(width=640, height=480, fps=30), VideoDeviceInfo(width=424, height=240, fps=30), VideoDeviceInfo(width=352, height=288, fps=30), VideoDeviceInfo(width=320, height=240, fps=30), VideoDeviceInfo(width=320, height=180, fps=30), VideoDeviceInfo(width=176, height=144, fps=30), VideoDeviceInfo(width=160, height=120, fps=30)]}] 錄音設備列表和可用配置如下: [{'name': '麥克風 (Realtek High Definition Audio)', 'format_list': [AudioDeviceInfo(channel=2, bits=16, rate=44100)]}] 桌面分辨率為:1920x1080其他
ffmpeg -list_devices true -f gdigrab -i dummy
把dshow換成gdigrab。。。可以看到提示讓你使用desktop或者對應的窗口名
采集攝像頭和桌面和麥克風
使用python啟動和停止錄制進程
啟動ffmpeg子進程
ffmpeg_process = subprocess.Popen('ffmpeg -f gdigrab -i desktop -y out.mp4', shell=True, stdin=subprocess.PIPE)停止子進程,ffmpeg命令行收到'q'就會自動退出
ffmpeg_process.communicate(b'q')效果1
在不變動桌面和攝像頭的分辨率情況下,讓桌面畫面和攝像頭并排顯示,hstack可以讓兩個畫面并排顯示,hstack函數要求兩邊的畫面的高度必須保持一致,因此加上pad函數來對高度短的畫面填充純色。
代碼分段加注釋之后如下
fmpeg -f gdigrab -i desktop # 輸入桌面畫面 -f dshow -i video="USB 2.0 Webcam Device" -s 1280*720 # 輸入攝像頭畫面 -filter_complex "[0:v]pad=1920:1080:0:0:black[left];[1:v]pad=1280:1080:0:0:black[right];[left][right]hstack" #濾鏡操作 -f dshow -i audio="麥克風 (Realtek High Definition Audio)" # 輸入麥克風 -y out.mp4 # 輸出到文件語法解析
濾鏡函數文檔
效果2
還是使用hstack來并排顯示兩個畫面,仍然需要將兩個畫面的高度調成一致,這邊使用scale函數來修改畫面的分辨率,將兩個畫面的高度調為兩者中的高值。
python組裝命令行代碼
cmd = '''ffmpeg-f gdigrab -i desktop-f dshow -i video="{vname}" -s {vwidth}*{vheight}-filter_complex "[0:v]scale=-1:{max_height}[left];[1:v]scale=-1:{max_height}[right];[left][right]hstack,scale=1980:-1"-f dshow -i audio="{aname}"-y out.mp4 '''.format(vname=vdevice['name'],vwidth=vdevice['format_list'][0].width,vheight=vdevice['format_list'][0].height,max_height = max(desktop_info.height, vdevice['format_list'][0].height),aname=adevice['name'] )cmd = cmd.replace('\n', ' ').replace(' ', ' ').replace(' ', ' ').replace(' ', ' ') #刪除富余的空格我的機器上最后執行的命令是
ffmpeg -f gdigrab -i desktop -f dshow -i video="USB 2.0 Webcam Device" -s 1280*720 -filter_complex "[0:v]scale=-1:1080[left];[1:v]scale=-1:1080[right];[left][right]hstack,scale=1980:-1" -f dshow -i audio="麥克風 (Realtek High Definition Audio)" -y out.mp4語法解析
效果3
讓攝像頭畫面浮動到桌面的右下角可以使用overlay方法
python組裝命令行代碼
cmd = '''ffmpeg-f gdigrab -i desktop-f dshow -i video="{vname}" -s {vwidth}*{vheight}-filter_complex "[0:v][1:v]overlay=main_w-overlay_w:main_h-overlay_h"-f dshow -i audio="{aname}"-y out.mp4 '''.format(vname=vdevice['name'],vwidth=vdevice['format_list'][0].width,vheight=vdevice['format_list'][0].height,max_height = max(desktop_info.height, vdevice['format_list'][0].height),aname=adevice['name'] )cmd = cmd.replace('\n', ' ').replace(' ', ' ').replace(' ', ' ').replace(' ', ' ') #刪除富余的空格我的機器上最后執行的命令是
ffmpeg -f gdigrab -i desktop -f dshow -i video="USB 2.0 Webcam Device" -s 1280*720 -filter_complex "[0:v][1:v]overlay=main_w-overlay_w:main_h-overlay_h" -f dshow -i audio="麥克風 (Realtek High Definition Audio)" -y o.mp4語法解析
轉載于:https://my.oschina.net/u/111188/blog/1647154
總結
以上是生活随笔為你收集整理的ffmpeg使用总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 理解C++ lvalue与rvalue
- 下一篇: 以太坊智能合约简介(Solidity)