上一节介绍了用 ffplay 来播放文件(或 url),这里有一个概念,如果是播放曾经存在的文件,那叫“回放”,也就是 Playback(从流媒体的角度也叫点播),如果播放的是正在录制的数据(边录边播),那叫直播。
不论是回放还是直播,都须要有媒体数据,那这个媒体数据是怎么来的呢?从已有的文件编辑而来是一个方法,但更间接更原始的方法是录制。
录制,就是通过硬件设施,把声音或者图像保留到文件(或者推到文件)。
在 FFmpeg 程序集中,有一个程序叫作 ffmpeg(小写),这个程序提供了录制的性能。在上一节小程介绍了 ffplay 的装置,而实际上 ffplay 依赖于 FFmpeg,所以当 ffplay 装置后,那 FFmpeg 程序集也就装置上了,也就是曾经能够应用 ffmpeg 程序。
本文介绍如何通过 ffmpeg 程序来实现声音、图像以及屏幕的录制。
(一)录制命令
对于图像,能够通过摄像头或者屏幕来录入,而对于声音则通过麦克风来录入。
因为我应用的是 mac 电脑,所以,有必要先查看一下 mac 电脑有没有录制的设施,也就是输出设施。
因为查看输出设施须要指定输出设施的格局类型,所以,先查看输出设施的格局类型:
ffmpeg -devices
在我的电脑上,有这样的输入:
avfoundation AVFoundation input device
lavfi Libavfilter virtual input device
qtkit QTKit input device
第一个类型,即 avfoundation,为本机输出设施的格局类型,有了这个类型,就能够进一步 查看输出设施 了:
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 320×240 -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 320×240 -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.