您的位置:

ffmpeg音频php源码成品,ffmpeg音视频高级开发实战

本文目录一览:

怎样使用ffmpeg 进行音频解码

安装完成ffmpeg后,就可以使用ffmpeg进行音频文件格式转换。比如 ./ffmpeg -i /media/1.mp3 /media/1.wav, 通过该命令行可以将/media文件夹下1.mp3文件转换成WAV格式的。

但是反过来 ./ffmpeg -i /media/1.WAV /media/1.MP3 却不能转换成Mp3格式,提示如下错误(找不到编码器):

Stream mapping:

Stream #0:0 - #0:0 (wav - ?)

Encoder (codec none) not found for output stream #0:0

如果强行指定编码器 ./ffmpeg -i /media/1.wav -acodec mp3 /media/1.mp3, 仍提示找不到编码器错误:

Unknown encoder 'mp3'

这是因为,ffmpeg虽然是个开源软件,但因为具体格式的版权原因,它并没有包含所有的编解码格式,或者有个格式只有对应的解码器,但没有编码器,比如 Mp3就只有解码器,能播放Mp3文件,但却没有Mp3的编码器,无法将其它格式转换成Mp3。可以通过命令行 ./ffmpeg -codecs 查询编解码配置,第一个D表示Decoder,该格式能够解码;E表示Encoder,该格式可以编码。从中可以看出Mp3不能编码,Mp2倒是即可解码 也可编码。如何解决这个问题呢?

D A D mp1 MP1 (MPEG audio layer 1)

D A D mp1float MP1 (MPEG audio layer 1)

DEA D mp2 MP2 (MPEG audio layer 2)

D A D mp2float MP2 (MPEG audio layer 2)

D A D mp3 MP3 (MPEG audio layer 3)

D A D mp3adu ADU (Application Data Unit) MP3 (MPEG audio layer 3)

D A D mp3adufloat ADU (Application Data Unit) MP3 (MPEG audio layer 3)

我的第一个方法是自己写代码来完成。源码文件中,Allcodecs.c中对各个格式进行注册,先修改Mp3的注册行,改为同时注册解码器和编码器:

REGISTER_ENCDEC (MP2, mp2);

REGISTER_DECODER (MP2FLOAT, mp2float);

REGISTER_DECODER (MP3, mp3) // 此行修改为 REGISTER_ENCDEC (MP3, mp3)

然后新增Mp3编码器的实现Struct,里面Init函数、encode函数、close函数使用Mp2的函数,因为我也不知道如何去实现Mp3的函数,或者说到代码实现级我也不知道Mp3和Mp2的区别在哪。

AVCodec ff_mp3_encoder = {

.name = "mp3",

.type = AVMEDIA_TYPE_AUDIO,

.id = CODEC_ID_MP3,

.priv_data_size = sizeof(MpegAudioContext),

.init = MPA_encode_init,

.encode = MPA_encode_frame,

.close = MPA_encode_close,

.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},

.supported_samplerates= (const int[]){44100, 48000, 32000, 22050, 24000, 16000, 0},

.long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"),

.defaults = mp3_defaults,

};

重新编译上线。 用命令行./ffmpeg -i /media/1.WAV /media/1.MP3 试了一下,能成功生成1.mp3文件,文件也能播放。似乎没有问题了,单用 file /media/1.mp3 查看了一下,发现文件不是Mp3格式的,而是Mp2格式的:

/media/1.mp3: MPEG ADTS, layer II, v1, 128 kbps, 44.1 kHz, Stereo

很遗憾,自行修改代码的方式行不通,因为不是每个编解码格式协议的专家,自行修改代码失败的风险很大,不仅是Mp3,还有一些其他格式比如AMR OGG H.263是没有编码器的。所以,第二个方案,使用成熟的第三方编码器和ffmpeg结合。

Mp3比较好的开源第三方库是libmp3lame(简称Lame)。我下了一个最新版本(3.99.4)的Lame源码,编译它:

首先配置: ./configure --prefix=/shared --enable-shared --enable-static

然后编译: make

make install

生成文件: 动态链接库 /shared/lib/libmp3lame.so 和 静态链接库 /shared/lib/libmp3lame.a。这里只需要使用动态链接库,将.so文件拷贝到/lib中,这个文件夹是动态链接库的默认搜索路径, 让ffmpeg运行时可以找到。

然后对ffmpeg配置libmp3lame: ./configure --enable-libmp3lame

重新编译ffmpeg,运行转化命令,看看效果如何。

首先执行 ./ffmpeg -codecs 查看可用编解码的变化,可以看到多出了libmp3lame编码器,带E的:

D V D lagarith Lagarith lossless

EA libmp3lame libmp3lame MP3 (MPEG audio layer 3)

EV ljpeg Lossless JPEG

D V D loco LOCO

然后执行 ./ffmpeg -i /media/1.WAV /media/1.MP3, 生成1.mp3,用File命令查看,确实是Mp3文件。

/media/1.mp3: Audio file with ID3 version 2.4.0, contains: MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo

大功告成,问题解决。

也可在命令行中指定编解码生成Mp3文件:./ffmpeg -i /media/1.WAV -acodec libmp3lame /media/1.MP3.

windows下编译ffmpeg源码及常见问题

由于公司项目中会用到ffmpeg,而且会用到h265转码h264的功能,想要学习ffmpeg,先从编译开始吧。我编译的过程主要是从以下博客中学习的,此文主要是记录中间遇到的问题及解决方法。

CC=cl ./configure --enable-shared

这个可能是因为 pdk-config 的 PKG-CONFIG-PATH 配置问题,我是在etc/profile文件里找到PKG-CONFIG-PATH的配置路径(我的是/usr/lib/pkgconfig),然后将pkgconfig里面的三个 .pc文件复制到/usr/lib/pkgconfig文件夹里即可

因为博客中只提到将编译好的x265文件夹中的lib目录复制过去,其实include文件夹也要复制过去,我把bin、include和lib都复制到usr/local对应的目录中

不要将msys64装在带空格的文件夹中,否则编译失败,也不要将原先装好的文件夹整个复制到另一个没有空格的文件夹中,这样编译也会报错。

求ffmpeg音频压缩代码(wav压缩成wma)

这个简单。大致的思路是

1.打开wav文件

2.打开要输出的wma文件

3.不停的读取数据帧

4.读取以后解码并写入wma

5.关闭wav文件

6.关闭wma文件

重新写例子太麻烦贴点代码吧

#include "Debug.h"

#include "FFMpegAVFileReader.h"

#include "FFMpegAVFileReaderFactory.h"

#include sstream

#include "yk_convert.h"

static char h264_head[4] = {(char)0x00,(char)0x00,(char)0x00,(char)0x01};

namespace YK

{

FFMpegAVFileReader::FFMpegAVFileReader()

{

ffmpeg_avcodec_init();

ffmpeg_av_register_all();

av_log_set_callback(ffmpeg_log_callback);

m_format_context = 0;

m_input_format = 0;

m_format_parameters = 0;

m_packet = (AVPacket*)av_mallocz(sizeof(AVPacket));

}

FFMpegAVFileReader::~FFMpegAVFileReader()

{

Close();

av_free(m_packet);

}

avfile_reader_param_t* FFMpegAVFileReader::GetParam()

{

//YK::AutoLock l(m_lock);

return m_param;

}

void FFMpegAVFileReader::Seek(int pts)

{

YK::AutoLock l(m_lock);

int ret = av_seek_frame(m_format_context,-1,(YK::int64_t)pts * (YK::int64_t)1000,AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY);

//if(ret = 0)

//{

// for(int i = 0; i m_format_context-nb_streams; i++)

// {

// avcodec_flush_buffers( m_format_context-streams[i]-codec );

// }

//}

//std::stringstream ss;

//ss "pts = " pts

// " ret = " ret std::endl;

//OutputDebugString(ss.str().data());

}

void FFMpegAVFileReader::GetDuration(double start,double end)

{

//YK::AutoLock l(m_lock);

start = (double)(m_start_time / 1000000);

end = start + (double)(m_duration / 1000000);

}

service_error_t FFMpegAVFileReader::Open(int time_out)

{

YK::AutoLock l(m_lock);

service_error_t service_error;

// 打开文件

if (av_open_input_file(m_format_context,TToANSI(m_param.input_file_path).data(),m_input_format,0,m_format_parameters) 0)

{

service_error.init(service_error_type_failed,"av_open_input_file failed");

return service_error;

}

// 查询流信息

if(av_find_stream_info(m_format_context) 0)

{

service_error.init(service_error_type_failed,"av_find_stream_info failed");

return service_error;

}

m_start_time = m_format_context-start_time;

m_duration = m_format_context-duration;

#ifdef _DEBUG

pFile = fopen("D:/1.out","w+b");

#endif

// 保存流信息

av_stream_info_t av_stream_info;

for(unsigned int i = 0; i m_format_context-nb_streams; i++)

{

AVStream *st = m_format_context-streams[i];

AVCodecContext *enc = st-codec;

if(enc-codec_type == AVMEDIA_TYPE_AUDIO)

{

// 音频

av_stream_info.av_stream_info_type = av_stream_info_type_audio;

av_stream_info.codec_id = codec_id_none;

//channel_layout = enc-channel_layout;

av_stream_info.audio_channels = enc-channels;

av_stream_info.audio_samplepersec = enc-sample_rate;

av_stream_info.audio_bitpersample = yk_sample_format(enc-sample_fmt);

//audio_sample_fmt = enc-sample_fmt;

//input_codecs[nb_icodecs++] = avcodec_find_decoder_by_name(audio_codec_name);

av_stream_info.codec_id = yk_code_id(enc-codec_id);

av_stream_info.extradata_size = enc-extradata_size;

if(av_stream_info.extradata_size)

memcpy(av_stream_info.extradata,enc-extradata,enc-extradata_size);

if(av_stream_info.codec_id == codec_id_mp3)

{

av_stream_info.extradata_size = sizeof(mpeg1_waveformat_extradata);

mpeg1_waveformat_extradata* pMpeg1WaveFormat = (mpeg1_waveformat_extradata*)av_stream_info.extradata;

pMpeg1WaveFormat-dwHeadBitrate = enc-bit_rate;

pMpeg1WaveFormat-dwPTSHigh = 0;

pMpeg1WaveFormat-dwPTSLow = 0;

pMpeg1WaveFormat-fwHeadFlags = 25;

pMpeg1WaveFormat-fwHeadLayer = ACM_MPEG_LAYER3;

pMpeg1WaveFormat-fwHeadMode = ACM_MPEG_STEREO;

pMpeg1WaveFormat-fwHeadModeExt = 1;

pMpeg1WaveFormat-wHeadEmphasis = 1;

}

AddStreamInfo(av_stream_info);

m_stream_audio_index = i;

}

else if(enc-codec_type == AVMEDIA_TYPE_VIDEO)

{

// 视频

av_stream_info.av_stream_info_type = av_stream_info_type_video;

av_stream_info.codec_id = codec_id_none;

av_stream_info.video_width = enc-width;

av_stream_info.video_height = enc-height;

av_stream_info.video_profile = enc-profile;

av_stream_info.video_level = enc-level;

if(av_stream_info.video_profile 0)

{

av_stream_info.video_profile = 77;

}

if(av_stream_info.video_level 0)

{

av_stream_info.video_level = 30;

}

av_stream_info.extradata_size =

iOS利用FFmpeg解码音频数据并播放

利用FFmepg解析并解码音频流数据,然后将解码后的音频数据送给Audio Queue以实现播放.

利用FFmpeg解析音频数据流, 利用FFmpeg解码音频数据为PCM格式. 利用Audio Queue Player实现音频数据播放.

本例以一个苹果原生相机录制的.MOV文件为例, 将该文件使用FFmpeg解析并解码,将解码后的数据放入传输队列中,然后开启audio queue player, 播放器在回调函数中轮循取出队列中的数据实现播放.

FFmpeg parse流程

FFmpeg解码流程

为了每次能够重新播放,这里需要标记当前是否为解码的第一帧数据,以重新启动播放器. 另一点是使用NSTimer等待音频数据放入队列再开始播放,因为audio queue是驱动播放模式,所以必须等音频数据放入传输队列再开始播放.

从Parse模块中可以获取当前文件对应FFmepg的上下文对象 AVFormatContext .因此音频流解码器信息可以直接获取.

AVFrame 作为解码后原始的音视频数据的容器.AVFrame通常被分配一次然后多次重复(例如,单个AVFrame以保持从解码器接收的帧)。在这种情况下,av_frame_unref()将释放框架所持有的任何引用,并在再次重用之前将其重置为其原始的清理状态。

调用avcodec_send_packet将压缩数据发送给解码器.最后利用循环接收avcodec_receive_frame解码后的音视频数据.