Linux上使用FFmpeg進(jìn)行錄音功能
使用的發(fā)行版
? ~ lsb_release -a No LSB modules are available. Distributor ID: Linuxmint Description: Linux Mint 22 Release: 22 Codename: wilma
創(chuàng)建一個(gè)Qt項(xiàng)目
創(chuàng)建名稱為audio
的Qt項(xiàng)目
下載FFmpeg
我們下載共享庫版本的FFmpeg
解壓縮
FFmepg下載解壓縮后放在和前面創(chuàng)建的Qt項(xiàng)目在一個(gè)同級別路徑下
修改Qt項(xiàng)目文件
修改Qt項(xiàng)目文件CmakeLists.txt
,引入頭文件和庫,添加內(nèi)容如下
# 設(shè)置變量 set(ffmpeg444 "../ffmpeg444") # 引入頭文件目錄 include_directories(${ffmpeg444}/include/) # 引入庫文件目錄,注意link_directories要放在add_executable之前 link_directories(${ffmpeg444}/lib/) # 鏈接庫中添加avdevice avutil avformat target_link_libraries(audio PRIVATE Qt${QT_VERSION_MAJOR}::Widgets avdevice avutil avformat)
添加一個(gè)開始錄音的按鈕
注冊設(shè)備
設(shè)備只需要注冊一次,因?yàn)槲覀冊?code>main.cpp文件中添加
#include "mainwindow.h" #include <QApplication> extern "C" { // 設(shè)備相關(guān) #include <libavdevice/avdevice.h> } int main(int argc, char *argv[]) { // 注冊設(shè)備,程序整個(gè)運(yùn)行過程只需要注冊一次 avdevice_register_all(); QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
開始錄音
查看系統(tǒng)上的音頻輸入設(shè)備
查看下所有設(shè)備
? ~ ffmpeg -hide_banner -devices Devices: D. = Demuxing supported .E = Muxing supported -- DE fbdev Linux framebuffer D kmsgrab KMS screen capture D lavfi Libavfilter virtual input device DE oss OSS (Open Sound System) playback DE pulse Pulse audio output E sdl,sdl2 SDL2 output device DE video4linux2,v4l2 Video4Linux2 output device D x11grab X11 screen capture, using XCB
我們可以使用arecord -l
查看下系統(tǒng)上的音頻硬件設(shè)備
? arecord -l **** List of CAPTURE Hardware Devices **** card 0: K66 [K66], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: PCH [HDA Intel PCH], device 0: ALC897 Analog [ALC897 Analog] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: PCH [HDA Intel PCH], device 2: ALC897 Alt Analog [ALC897 Alt Analog] Subdevices: 1/1 Subdevice #0: subdevice #0 card 4: Camera [USB 2.0 Camera], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0
錄音按鈕點(diǎn)擊相關(guān)代碼, 修改mainwindow.cpp文件
內(nèi)容如下
#include "mainwindow.h" #include "./ui_mainwindow.h" #include <QDebug> #include <QFile> extern "C" { #include <libavdevice/avdevice.h> #include <libavformat/avformat.h> #include <libavutil/avutil.h> } #define BUF_SIZE 1024 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_audioButton_clicked() { const char* fmtName = "pulse"; //設(shè)置輸入設(shè)備格式名稱 // 獲取輸入格式對象 AVInputFormat *fmt = av_find_input_format(fmtName); if (!fmt) { qDebug() << "獲取輸入格式對象失敗" << fmtName; return; } AVFormatContext *ctx = nullptr; // 打開的設(shè)備上下文對象,可以利用這個(gè)上下文對象來操作設(shè)備 // 設(shè)備名稱,可以使用 arecord -l查看設(shè)備 const char* deviceName = "hw:0"; // 使用card 0, arecord -l命令列出的第一個(gè)設(shè)備 AVDictionary* options = nullptr; // 選項(xiàng) // 利用輸入格式對象打開設(shè)備 int ret = avformat_open_input(&ctx, deviceName, fmt, &options); if (ret < 0) { char errbuf[BUF_SIZE] = {0}; // av_strerror獲取錯(cuò)誤原因 av_strerror(ret, errbuf, BUF_SIZE); qDebug() << "打開設(shè)備失?。? << errbuf; return; } // 錄音保存的文件 const char* fileName = "out.pcm"; // 采集的數(shù)據(jù)是原始pcm數(shù)據(jù) QFile file(fileName); // 打開文件 // WriteOnly: 只寫模式,如果文件不存在,則創(chuàng)建文件。如果文件存在,則清空文件內(nèi)容 if (!file.open(QIODevice::WriteOnly)) { qDebug() << "文件打開失敗" << fileName; avformat_close_input(&ctx); // 關(guān)閉設(shè)備 return; } // 開始采集數(shù)據(jù) int count = 50; // 采集數(shù)據(jù)的次數(shù) AVPacket pkt; // 數(shù)據(jù)包 while(count-- > 0 && av_read_frame(ctx, &pkt) == 0) { // 一直采集數(shù)據(jù),當(dāng)為0時(shí)說明數(shù)據(jù)采集成功了 // 將數(shù)據(jù)寫入文件 file.write((const char *)pkt.data, pkt.size); } // 釋放資源 file.close(); // 關(guān)閉文件 avformat_close_input(&ctx); // 關(guān)閉設(shè)備 }
關(guān)于設(shè)備部分,我們可以使用條件編譯
#ifdef Q_OS_LINUX const char* fmtName = "pulse"; //設(shè)置輸入設(shè)備格式名稱 #elif Q_OS_WIN const char* fmtName = "dshow"; //設(shè)置輸入設(shè)備格式名稱 #endif #ifdef Q_OS_LINUX // 設(shè)備名稱,可以使用 arecord -l查看設(shè)備 const char* deviceName = "hw:0"; #elif Q_OS_WIN const char* deviceName = "audio=麥克風(fēng) (K66)"; #endif
開始錄音
點(diǎn)擊開始錄音,稍等一會兒,發(fā)現(xiàn)二進(jìn)制程序目錄下多了一個(gè)out.pcm
我們錄制的音頻文件
播放
我們可以使用ffplay
播放我們剛才錄制的pcm音頻數(shù)據(jù)
查看PCM的格式
使用ffmpeg -hide_banner -formats
我們可以輸出所有的格式
? ~ ffmpeg -hide_banner -formats | grep PCM DE alaw PCM A-law DE f32be PCM 32-bit floating-point big-endian DE f32le PCM 32-bit floating-point little-endian DE f64be PCM 64-bit floating-point big-endian DE f64le PCM 64-bit floating-point little-endian DE mulaw PCM mu-law DE s16be PCM signed 16-bit big-endian DE s16le PCM signed 16-bit little-endian DE s24be PCM signed 24-bit big-endian DE s24le PCM signed 24-bit little-endian DE s32be PCM signed 32-bit big-endian DE s32le PCM signed 32-bit little-endian DE s8 PCM signed 8-bit DE u16be PCM unsigned 16-bit big-endian DE u16le PCM unsigned 16-bit little-endian DE u24be PCM unsigned 24-bit big-endian DE u24le PCM unsigned 24-bit little-endian DE u32be PCM unsigned 32-bit big-endian DE u32le PCM unsigned 32-bit little-endian DE u8 PCM unsigned 8-bit DE vidc PCM Archimedes VIDC
播放
- -ar 指定采樣率
- -ac 指定聲道數(shù)
- -f 指定音頻格式, s16le表示有符號的16位小端模式
ffplay -ar 44100 -ac 2 -f s16le out.pcm
以上就是Linux上使用FFmpeg進(jìn)行錄音功能的詳細(xì)內(nèi)容,更多關(guān)于Linux FFmpeg錄音的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Shell腳本處理浮點(diǎn)數(shù)的運(yùn)算和比較實(shí)例
這篇文章主要介紹了Shell腳本處理浮點(diǎn)數(shù)的運(yùn)算和比較實(shí)例,文中分別使用了bc或awk實(shí)現(xiàn),需要的朋友可以參考下2014-06-06windows下寫的shell腳本在linux執(zhí)行出錯(cuò)的解決辦法
這篇文章主要介紹了windows下寫的shell腳本在linux執(zhí)行出錯(cuò)的解決辦法,需要的朋友可以參考下2014-03-03linux shell進(jìn)度條實(shí)現(xiàn)方法
linux shell實(shí)現(xiàn)的一咱進(jìn)度條,代碼很簡單,供大家參考2013-11-11Linux?systemd?定時(shí)任務(wù)原理解析
說到?Linux?定時(shí)任務(wù),大家用得最多的就是?crond?服務(wù),但其實(shí)?systemd?也有類似的功能,我們不但可以通過?systemd?來管理服務(wù),還能設(shè)置定時(shí)任務(wù),那就是?systemd?timer,接下來通過本文介紹Linux?systemd?定時(shí)任務(wù)的相關(guān)知識,需要的朋友可以參考下2024-04-04用shell腳本實(shí)現(xiàn)自動切換內(nèi)網(wǎng)和外網(wǎng)實(shí)現(xiàn)高可用
因?yàn)楣镜姆?wù)器這段時(shí)間內(nèi)網(wǎng)網(wǎng)卡老是出現(xiàn)問題,然后就導(dǎo)致了網(wǎng)站的各種問題,因?yàn)槲覀兊臄?shù)據(jù)庫鏈接,redis還有sphinx鏈接都是走的內(nèi)網(wǎng),,所以就寫了這個(gè)腳本,在線上也跑了一段時(shí)間了,,也沒出過什么問題2013-06-06