ffmpeg获取音频


前面讲解了如何使用libavdevice采集摄像头图像

同样 libavdevice 也可以采集麦克风的声音。

下面就讲解麦克风声音的采集:

采集声音和采集摄像头本质上没有多大的却别,基本上就是换个名字:

其中"audio=麦克风 (Realtek High Definition Audio)"跟之前获取摄像头名字一样的方法,直接使用ffmpeg命令行获取即可,不懂得直接查看之前的教程传送门

成功打开麦克风之后,就是查找流然后打开解码器:

每一帧所发费的时间由pFrame->nb_samples * 1.0 / pCodecCtx->sample_rate;来获得。

上面总共采集了30秒,同时将采集得到的pcm音频数据写入了文件。

打开pcm数据可以使用cool edit这个软件。有需要的可以百度下载。

 pcm是最原始的音频数据,是不带有任何采集率以及声道的信息的。

因此我们需要手动告诉cool edit软件需要打开的pcm数据的采样率和声道信息,否则打开之后会是全部杂音。

我们这里采集到的是44100 双声道的。

接着就可以看到漂亮的波形图了,

cool edit的使用这里就不说了,自行琢磨吧。



#include <stdio.h>
#include <iostream>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
}
 
using namespace std;
//'1' Use Dshow
//'0' Use VFW
#define USE_DSHOW 0
//Show Dshow Device
void show_dshow_device(){
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary* options = NULL;
    av_dict_set(&options,"list_devices","true",0);
    AVInputFormat *iformat = av_find_input_format("dshow");
    printf("========Device Info=============\n");
    avformat_open_input(&pFormatCtx,"video=dummy",iformat,&options);
    printf("================================\n");
}
//Show Dshow Device Option
void show_dshow_device_option(){
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary* options = NULL;
    av_dict_set(&options,"list_options","true",0);
    AVInputFormat *iformat = av_find_input_format("dshow");
    printf("========Device Option Info======\n");
    avformat_open_input(&pFormatCtx,"video=Integrated Camera",iformat,&options);
    printf("================================\n");
}
//Show VFW Device
void show_vfw_device(){
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVInputFormat *iformat = av_find_input_format("vfwcap");
    printf("========VFW Device Info======\n");
    avformat_open_input(&pFormatCtx,"list",iformat,NULL);
    printf("=============================\n");
}
//Show AVFoundation Device
void show_avfoundation_device(){
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary* options = NULL;
    av_dict_set(&options,"list_devices","true",0);
    AVInputFormat *iformat = av_find_input_format("avfoundation");
    printf("==AVFoundation Device Info===\n");
    avformat_open_input(&pFormatCtx,"",iformat,&options);
    printf("=============================\n");
}
#define USE_DSHOW 1
int main(int argc, char* argv[])
{
    AVFormatContext	*pFormatCtx;
    int				i, audioindex;
    AVCodecContext	*pCodecCtx;
    AVCodec			*pCodec;
    av_register_all();
    avformat_network_init();
    avdevice_register_all();//Register Device
    show_dshow_device();
    pFormatCtx = avformat_alloc_context();
#if 1
    AVInputFormat *ifmt=av_find_input_format("dshow");
    //Set own video device's name
    if(avformat_open_input(&pFormatCtx,"audio=麦克风 (Realtek High Definition Au0",ifmt,NULL)!=0){
        printf("Couldn't open input stream.\n");
        return -1;
    }
#else
    AVInputFormat *ifmt=av_find_input_format("vfwcap");
    if(avformat_open_input(&pFormatCtx,"0",ifmt,NULL)!=0){
        printf("Couldn't open input stream.\n");
        return -1;
    }
#endif
    if(avformat_find_stream_info(pFormatCtx,NULL)<0)
    {
        printf("Couldn't find stream information.\n");
        return -1;
    }
    audioindex=-1;
    for(i=0; i<pFormatCtx->nb_streams; i++)
    {
        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)
        {
            audioindex=i;
        }
    }
    if(audioindex==-1)
    {
        printf("Couldn't find a audio stream.\n");
        return -1;
    }
    pCodecCtx=pFormatCtx->streams[audioindex]->codec;
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
    if(pCodec==NULL)
    {
        printf("Codec not found.\n");
        return -1;
    }
    if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
    {
        printf("Could not open codec.\n");
        return -1;
    }
 
    ///这里打印出音频的信息
    printf("audio info:");
    cout<<"audio info:"<<pCodecCtx->sample_fmt<<pCodecCtx->bit_rate<<pCodecCtx->sample_rate<<pCodecCtx->channels;
 
    FILE *fp_pcm=fopen("output.pcm","wb");
 
    AVPacket *packet= (AVPacket*)av_malloc(sizeof(AVPacket));
    AVFrame *pFrame = (AVFrame *)av_malloc(sizeof(AVFrame ));
    int got_picture = -1;
    float Time = 0;
    for(int i=0;;i++)
    {
        if (Time > 10) break; //就采集30秒
        if(av_read_frame(pFormatCtx, packet) < 0)
        {
            break;
        }
        if(packet->stream_index==audioindex)
        {
            int ret = avcodec_decode_audio4(pCodecCtx, pFrame, &got_picture, packet);
            if(ret < 0){
                printf("Decode Error.\n");
                return -1;
            }
            if(got_picture)
            {
                int pcmSize = av_samples_get_buffer_size(NULL,pCodecCtx->channels, pFrame->nb_samples,pCodecCtx->sample_fmt, 1);
               uint8_t * pcmBuffer = pFrame->data[0];
 
               float useTime = pFrame->nb_samples * 1.0 / pCodecCtx->sample_rate;
               Time += useTime;
               cout<<i<<Time<<useTime;
               fwrite(pcmBuffer,1,pcmSize,fp_pcm); //写入文件
            }
        }
        av_free_packet(packet);
    }
 
    fclose(fp_pcm);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);
    return 0;
}

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值