多媒體開發(2):錄製視頻

上一節介紹了用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:
record的workflows

script的設置以下:
workflow的設置

找到這個workflow的目錄,增長一個cmd.sh文件,這個文件用來初始化python環境,並執行上面的mian.py文件:
cmd.sh

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.

相關文章
相關標籤/搜索