上一节介绍了用ffplay来播放文件(或url),这里有一个概念,若是是播放已经存在的文件,那叫“回放”,也就是Playback(从流媒体的角度也叫点播),若是播放的是正在录制的数据(边录边播),那叫直播。python
无论是回放仍是直播,都须要有媒体数据,那这个媒体数据是怎么来的呢?从已有的文件编辑而来是一个办法,但更直接更原始的办法是录制。程序员
录制,就是经过硬件设备,把声音或者图像保存到文件(或者推到文件)。app
在FFmpeg程序集中,有一个程序叫做ffmpeg(小写),这个程序提供了录制的功能。在上一节小程介绍了ffplay的安装,而实际上ffplay依赖于FFmpeg,因此当ffplay安装后,那FFmpeg程序集也就安装上了,也就是已经可使用ffmpeg程序。ide
本文介绍如何经过ffmpeg程序来实现声音、图像以及屏幕的录制。oop
对于图像,能够经过摄像头或者屏幕来录入,而对于声音则经过麦克风来录入。测试
由于我使用的是mac电脑,因此,有必要先查看一下mac电脑有没有录制的设备,也就是输入设备。ui
由于查看输入设备须要指定输入设备的格式类型,因此,先查看输入设备的格式类型:编码
ffmpeg -devices
在个人电脑上,有这样的输出:url
avfoundation AVFoundation input device lavfi Libavfilter virtual input device qtkit QTKit input device
第一个类型,即avfoundation,为本机输入设备的格式类型,有了这个类型,就能够进一步查看输入设备了:spa
ffmpeg -list_devices true -f avfoundation -i ""
能够看到这样的信息:
[AVFoundation input device @ 0x7f97326002e0] AVFoundation video devices: [AVFoundation input device @ 0x7f97326002e0] [0] FaceTime HD Camera [AVFoundation input device @ 0x7f97326002e0] [1] Capture screen 0 [AVFoundation input device @ 0x7f97326002e0] AVFoundation audio devices: [AVFoundation input device @ 0x7f97326002e0] [0] Built-in Microphone
上面的信息能够知道,视频输入(video devices)有两个设备,设备0为摄像头,设备1为屏幕,而声音输入(audio devices)则只有设备0,也就是麦克风。
在知道设备号以后,就能够启用这个设备来录制,好比只打开摄像头进行录制(按'q'结束录制):
ffmpeg -f avfoundation -framerate 30 -i "0" -s 320x240 -vsync 2 -y cam.mp4
framerate是录制帧率,也就是一秒取多少帧,这些概念之后小程再详细介绍。-i "0"就是0号设备即摄像头,-s指定分辨率,好比能够设置一个在手机上较佳的使用分辨率。最后面的文件名,表示保存数据的文件。
但须要注意,参数并不是能够随意改动的,由于参数的值跟输入设备有关,好比个人mac只支持帧率30,并且分辨率也只有几个能够选择,因此,参数不能乱写。若是出错了,那应该根据出错信息做出修正。并且,参数的顺序也不能乱写,不然是可能出错的!
另外,不一样的ffmpeg的版本,对参数的要求也不同,好比ffmpeg3.x须要指定framerate跟分辨率,而ffmpeg2.x则不须要,但出错后都有相应的信息提醒,你能够按指引来修正。
若是想同时录制到声音,那就同时打开摄像头跟麦克风,进行录制:
ffmpeg -f avfoundation -framerate 30 -i "0:0" -s 320x240 -vsync 2 -y cam2.mp4
0:0,前面为图像设备,后面为声音设备。
若是只录制声音,则:
ffmpeg -f avfoundation -i ":0" sound.aac 或者: ffmpeg -f avfoundation -i ":0" -acodec libmp3lame sound2.mp3
aac是音频的一种编码格式,我用的FFmpeg3.1.2会编码成aac格式(FFmpeg3.x内置aac编码),固然也能够指定编码成mp3,但要借助libmp3lame这个组件。你能够先忽略这些编码细节,只须要知道有这样一个功能就好。
我在这里给出一个只用摄像头录制的效果,那是小程家里的灯,经过mac电脑录制到的视频:
若是只想录制屏幕,那只须要把-i "0"换成-i "1",也就是指定从屏幕录制。
如今录制的命令有了,可是,做为一个追求便利的程序员,怎么才能快速而方便地进行启动录制呢?分明,我要再次使用以前介绍过的alfred跟python界面了。
先来写一个Python的界面,用来设置录制的各个参数,代码以下:
from tkinter import * import tkinter.messagebox as msgbox import os import threading audiovalue = 0 widthvalue = "" heightvalue = "" recordsourcevalue = "" def recordThreadFunc(): global audiovalue, widthvalue, heightvalue, recordsourcevalue parms = recordsourcevalue.get() if (audiovalue.get()==1): parms = parms + ":0" recordtemppath = "'%s'/recordtemp.mp4" % os.getcwd() recordpath = "'%s'/record.mp4" % os.getcwd() ffstr = "ffmpeg -f avfoundation" if (recordsourcevalue.get()=="0"): ffstr = ffstr + " -framerate 30" ffstr = ffstr + " -i '%s' -s %sx%s -vsync 2 -y %s" % (parms, widthvalue.get(), heightvalue.get(), recordtemppath) print(ffstr) os.system("touch tempsh.sh") with open("tempsh.sh", "w") as f: f.write(ffstr) f.write("\nffmpeg -i %s -pix_fmt yuv420p -y %s" % (recordtemppath, recordpath)) f.write("\nrm %s" % recordtemppath) os.system("chmod +x tempsh.sh") os.system("open -a Terminal.app tempsh.sh") print("%d, %s, %s, %s" % (audiovalue.get(), widthvalue.get(), heightvalue.get(), recordsourcevalue.get())) os.system("open '%s'" % os.getcwd()) pass def recordFunc(): t1 = threading.Thread(target=recordThreadFunc) t1.start() def main(): global audiovalue, widthvalue, heightvalue, recordsourcevalue window = Tk() window.title("录制控制台") window.geometry("320x320+100+100") audiovalue = IntVar() audioCheckBtn = Checkbutton(window, text="录入声音", variable=audiovalue, onvalue=1, offvalue=0) audioCheckBtn.place(x=10, y=10) label1 = Label(window, text="视频分辨率:") label1.place(x=10, y=50) widthlabel = Label(window, text="宽:") heightlabel = Label(window, text="高:") widthvalue = StringVar() heightvalue = StringVar() widthEntry = Entry(window, textvariable=widthvalue, width=10) heightEntry = Entry(window, textvariable=heightvalue, width=10) widthlabel.place(x=20, y=70) widthEntry.place(x=50, y=70) heightlabel.place(x=20, y=100) heightEntry.place(x=50, y=100) tiplabel = Label(window, text="如:320/1920/1280等") tiplabel.place(x=140, y=70) tiplabel = Label(window, text="如:240/1080/720等") tiplabel.place(x=140, y=100) recordsourcevalue = StringVar() rsourceRadioBtn1 = Radiobutton(window, text="从摄像头录制", value="0", variable=recordsourcevalue) rsourceRadioBtn2 = Radiobutton(window, text="从屏幕录制", value="1", variable=recordsourcevalue) rsourceRadioBtn1.place(x=20, y=170) rsourceRadioBtn2.place(x=140, y=170) tiplabel = Label(window, text="从哪里录制:") tiplabel.place(x=10, y=150) recordBtn = Button(window, text="开启录制", command=recordFunc) recordBtn.place(x=20, y=200) window.mainloop() if __name__ == '__main__': main()
代码所在的文件叫main.py,运行这段代码能够看到这样的界面:
在界面上设置好参数,点击“开启录制”就可能看到你的摄像头打开了,可是,每次都要找到这个python脚原本执行是不完美的,因此,alfred出场了。
一样,建立一个script filter:
script的设置以下:
找到这个workflow的目录,增长一个cmd.sh文件,这个文件用来初始化python环境,并执行上面的mian.py文件:
cmd.sh的内容以下:
cd '/Users/freejet/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.0490D960-6C02-4F29-8265-51890350F2B4' source ~/Desktop/pyenv/bin/activate python3 main.py
再把上面的main.py拷贝到这个目录,大功告成,用alfred来打下“record”,就能够来录制了,效果以下:
gif看不太清楚?无法子,视频转过来又要兼容大小,是这样的啦,这里又不能上传视频。
好了,总结一下,本文主要介绍经过ffmpeg来录制声音或者视频。录制每每只是某件事情的一个环节,好比:在拿视频测试样本时能够本身录制、在直播时须要录制、在截屏时能够用录屏的方式来实现,等等。因此,理解这个环节的一个实现是有价值的。有缘再见,see you.