关于音视频,看了很多的博客,发现都很难正确的打开设备与录制。然后就自己瞎搞,突然发现能正确的录制与打开了,故此记录一下。
一、官方wiki
https://trac.ffmpeg.org/wiki/Capture/ALSA
提取一句关于音频录制的命令:
ffmpeg -f alsa -channels 1 -sample_rate 44100 -i hw:0 -t 30 out.wav
linux选择alsa的设备,mac上是avfoundation,sample_rate指的是采样率,channels是通道数,视系统而定,笔者这里选择单通道会报错,错误如下:
[alsa @ 0x55b0f9f49780] cannot set channel count to 1 (Invalid argument)
hw:0: Input/output error
然后我修改成了双通道就ok了。这里还有一个坑就是插上耳机的时候,打开系统设置可以查看到相关的状态
主机分了两对插口MIC和SPK,一个是前置,一个是后置。MIC是麦克风,SPK是声音。坑就是无论-i 后面带的参数是什么,设备都无法正常打开,拔掉MIC的插口,设备就可以正常使用了,但是没麦接收音频录制下来,当然是什么都没有。这里卡了很久。所以就去官方wiki上查看相关参数,使用F6选择声卡,然而也并没有什么用。
报错信息是:
[alsa @ 0x55e15eb4b780] cannot open audio device hw:0 (Device or resource busy) hw:0: Input/output error
提示设备忙碌,麦克风被占用,但是拔了插都不行,重启也不行。最后发现正是因为打开了系统设置这个界面在占用中…,真的是吃了没文化的亏啊…
二、验证
使用ffplay out.wav
播放一下视频验证就好了。
三、使用ffmpeg的库录制音频
1、安装apt install ffmpeg
至于其他的依赖库,缺什么补什么就好了
2、代码实现
头文件
//
// Created by 黑桃k on 2021/3/8.
//
#ifndef LEANCPP_AV_H
#define LEANCPP_AV_H
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavdevice/avdevice.h"
#include "libavutil/common.h"
#include "libavutil/frame.h"
#include "libavformat/avformat.h"
};
#endif //LEANCPP_AV_H
主函数文件
#include
#include "av.h"
using namespace std;
int main() {
// register device
avdevice_register_all();
// set logger level
av_log_set_level(AV_LOG_DEBUG);
// get input device format
AVInputFormat *format = av_find_input_format("alsa");
// init context
AVFormatContext *fmt_ctx = nullptr;
std::string deviceName = "hw:0";
AVDictionary *options = nullptr;
// open audio device
int ret = avformat_open_input(&fmt_ctx, deviceName.c_str(), format, &options);
if (ret < 0) {
std::cout << "Failed to open audio device!" << std::endl;
}
AVPacket ptk;
av_init_packet(&ptk);
string filepath = "test.pcm";
FILE *out = fopen(filepath.c_str(), "wb");
int count = 0;
while (!ret && count++ < 1000) {
ret = av_read_frame(fmt_ctx, &ptk);
// write file
fwrite(ptk.data,ptk.size,1,out);
std::cout << "ptk.size:" << ptk.size << std::endl;
std::cout << "count:" << count << std::endl;
// release ptk
av_packet_unref(&ptk);
}
fflush(out);
fclose(out);
// close device
avformat_close_input(&fmt_ctx);
std::cout << "Hello, World!" << std::endl;
return 0;
}
CMakeList.txt
cmake_minimum_required(VERSION 3.17)
project(leanCpp)
set(CMAKE_CXX_STANDARD 14)
include_directories(include)
add_executable(leanCpp main.cpp include/av.h)
target_link_libraries(leanCpp avutil avdevice avformat avcodec)
测试:ffplay -ar 44100 -ac 2 -f s16le test.pcm
这里还是有坑的,代码默认的格式,笔者也不是很清楚,属于刚入坑的新手,后续阅读源码在更新吧。使用ffmpeg -formats | grep PCM
查看系统支持的pcm格式,然后试了s16le,发现可以正常播放了。
嗯嗯…记录一下这个坑,欢迎小白报团…