本人之前写过一些用ffmpeg录制系统声音,麦克风声音的博客;比如ffmpeg录制系统声音
,由于采取的是ffmpeg自带的aac音频编码器,故最终的音频编码的格式一直是AV_SAMPLE_FMT_FLTP,即float平面模式,故在编码时,经常需要声音样例从packed模式转化为planar模式,故本人写过不少这样的代码:
uint8_t *audio_buf[2] = {
0 };
audio_buf[0] = (uint8_t *)frame_mic_encode->data[0];
audio_buf[1] = (uint8_t *)frame_mic_encode->data[1];
int nb = swr_convert(m_pAudioConvertCtx, audio_buf, dst_nb_samples, (const uint8_t**)frame_mix->data, frame_mix->nb_samples);
现如今,janus里面的音频采取OPUS编码,采样位数为16,本人欲用ffmpeg将音频录制下来,若依然用AV_SAMPLE_FMT_FLTP,则由于此种格式采样位数为32,无疑增加了文件大小。故本人决定采取AV_SAMPLE_FMT_S16P格式,但是ffmpeg自带的aac音频编码器不支持这种格式,报下列错误:
aac @ 0x7fffb8072b30] [0m[1;31mSpecified sample format s16p is invalid or not supported
显然编码器不支持此种采样格式,编码器支持的采样格式可以通过下列代码进行枚举
int i = 0;
enum AVSampleFormat sampleFmt;
sampleFmt = m_pCodecEncode_Audio->sample_fmts[i];
while (sampleFmt != AV_SAMPLE_FMT_NONE)
{
i++;
sampleFmt = m_pCodecEncode_Audio->sample_fmts[i];
}
后面本人采取fdk_aac作为音频编码格式,发现其不支持AV_SAMPLE_FMT_S16P,而是支持AV_SAMPLE_FMT_S16,这个可以通过如下代码验证:
m_pCodecEncode_Audio = (AVCodec *)avcodec_find_encoder_by_name("libfdk_aac");
m_pCodecEncodeCtx_Audio = avcodec_alloc_context3(m_pCodecEncode_Audio);
if (!m_pCodecEncodeCtx_Audio)
{
break;
}
int i = 0;
enum AVSampleFormat sampleFmt;
sampleFmt = m_pCodecEncode_Audio->sample_fmts[i];
while (sampleFmt != AV_SAMPLE_FMT_NONE)
{
i++;
sampleFmt = m_pCodecEncode_Audio->sample_fmts[i];
}
fdk_aac仅支持AV_SAMPLE_FMT_S16这一种样例格式。
很明显这是非平面模式,故对应的转换代码如下:
uint8_t *audio_buf[1] = {
0 };
audio_buf[0] = (uint8_t *)frame_mic_encode->data[0];
int nb = swr_convert(m_pAudioConvertCtx, audio_buf, num_frames_to_read, (const uint8_t**)&p_audio_data, num_frames_to_read);
可以看到这里面的audio_buf的数组长度为1.
下面本人将重写系统音频的录制,将最终的编码格式由AV_SAMPLE_FMT_FLTP转换成AV_SAMPLE_FMT_S16,注意用windows api采取系统声音时,声音格式是AV_SAMPLE_FMT_S32,如果系统声音是AV_SAMPLE_FMT_S16,则无需进行重采样。
代码如下:
main函数所在文件FfmpegGetSystemAudio.cpp
#include <iostream>
#include "GetSystemAudio.h"
int main()
{
CGetSystemAudio cCGetSystemAudio;
cCGetSystemAudio.SetSavePath("E:\\learn\\ffmpeg\\FfmpegTest\\x64\\Release");
cCGetSystemAudio.StartCapture();
Sleep(30000);
cCGetSystemAudio.StopCapture();
return 0;
}
GetSystemAudio.h文件内容如下:
#pragma once
#include <string>
#include <combaseapi.h>
#include <mmdeviceapi.h>
#include <audioclient.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavdevice/avdevice.h"
#include "libavutil/audio_fifo.h"
#include "libavutil/avutil.h"
#include "libavutil/fifo.h"
#include "libavutil/frame.h"
#include "libavutil/imgutils.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avdevice.lib")
#pragma comment(lib, "avfilter.lib")
#pragma comment(lib, "postproc.lib")
#pragma comment(lib, "swresample.lib")
#pragma comment(lib, "swscale.lib")
#ifdef __cplusplus
};
#endif
class CGetSystemAudio
{
public:
CGetSystemAudio();
~CGetSystemAudio();
public:
void SetSavePath(std::string st

最低0.47元/天 解锁文章
2128

被折叠的 条评论
为什么被折叠?



