使用FFmpeg实现抽取多媒体文件的音频并按照AAC格式进行保存--附源码
生活随笔
收集整理的這篇文章主要介紹了
使用FFmpeg实现抽取多媒体文件的音频并按照AAC格式进行保存--附源码
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
抽取音頻文件
注冊log與編解碼器
av_log_set_level(AV_LOG_INFO);
av_register_all();
打開多媒體文件
打開多媒體文件,并讀取頭部信息
/*** Open an input stream and read the header. The codecs are not opened.* The stream must be closed with avformat_close_input().** @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).* May be a pointer to NULL, in which case an AVFormatContext is allocated by this* function and written into ps.* Note that a user-supplied AVFormatContext will be freed on failure.* @param url URL of the stream to open.* @param fmt If non-NULL, this parameter forces a specific input format.* Otherwise the format is autodetected.* @param options A dictionary filled with AVFormatContext and demuxer-private options.* On return this parameter will be destroyed and replaced with a dict containing* options that were not found. May be NULL.** @return 0 on success, a negative AVERROR on failure.** @note If you want to use custom IO, preallocate the format context and set its pb field.*/ int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options); /*Open an input stream and read the header*/ int ret = avformat_open_input(&fmt_ctx, "/work/test/test.mp4", NULL, NULL); if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "can't open file.\n");return -1; }打開一個文件用于寫入音頻文件
char *pDst = NULL; pDst = "test.aac"; // write audio data to AAC file FILE *dst_fd = fopen(pDst, "wb"); if (dst_fd == NULL) {av_log(NULL, AV_LOG_ERROR, "open dst_fd failed.\n");avformat_close_input(&fmt_ctx);return -1; }輸出多媒體信息
輸出多媒體信息就是講多媒體的信息以及metadata信息打印出來
/** Print detailed information about the input or output format**/ av_dump_format(fmt_ctx, 0, "/work/test/test.mp4", 0);確保輸入的多媒體文件中有幀信息
// 2. get stream /*Read packets of a media file to get stream information.*/ ret = avformat_find_stream_info(fmt_ctx, NULL); if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "failed to find stream information.");avformat_close_input(&fmt_ctx);fclose(dst_fd);return -1; }提取音頻信息
提取音頻信息,并按照AAC格式將音頻信息寫入文件
AVPacket pkt; /*Initialize optional fields of a packet with default values.*/ av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; // 循環將音頻信息寫入AAC文件 int len = -1; /*保存原始數據,播放時需要添加AAC的音頻格式說明的頭*/ while (av_read_frame(fmt_ctx, &pkt) >= 0) {if (pkt.stream_index == audio_index) {/*每幀開頭都要寫*/char adts_header_buf[7];// 為每幀音頻添加AAC頭部信息adts_header(adts_header_buf, pkt.size);fwrite(adts_header_buf, 1, 7, dst_fd);len = fwrite(pkt.data, 1, pkt.size, dst_fd);cout << pkt.size << endl;if (len != pkt.size) {av_log(NULL, AV_LOG_ERROR, "waning, length is not equl size of pkt.\n");return -1;}}/*Wipe the packet.*/av_packet_unref(&pkt); } // 添加ADTS頭部信息 void adts_header(char *szAdtsHeader, int dataLen) {int audio_object_type = 2;int sampling_frequency_index = 7;int channel_config = 2;int adtsLen = dataLen + 7;szAdtsHeader[0] = 0xff; //syncword:0xfff 高8bitsszAdtsHeader[1] = 0xf0; //syncword:0xfff 低4bitsszAdtsHeader[1] |= (0 << 3); //MPEG Version:0 for MPEG-4,1 for MPEG-2 1bitszAdtsHeader[1] |= (0 << 1); //Layer:0 2bitsszAdtsHeader[1] |= 1; //protection absent:1 1bitszAdtsHeader[2] =(audio_object_type - 1) << 6; //profile:audio_object_type - 1 2bitsszAdtsHeader[2] |=(sampling_frequency_index & 0x0f) << 2; //sampling frequency index:sampling_frequency_index 4bitsszAdtsHeader[2] |= (0 << 1); //private bit:0 1bitszAdtsHeader[2] |=(channel_config & 0x04) >> 2; //channel configuration:channel_config 高1bitszAdtsHeader[3] = (channel_config & 0x03) << 6; //channel configuration:channel_config 低2bitsszAdtsHeader[3] |= (0 << 5); //original:0 1bitszAdtsHeader[3] |= (0 << 4); //home:0 1bitszAdtsHeader[3] |= (0 << 3); //copyright id bit:0 1bitszAdtsHeader[3] |= (0 << 2); //copyright id start:0 1bitszAdtsHeader[3] |= ((adtsLen & 0x1800) >> 11); //frame length:value 高2bitsszAdtsHeader[4] = (uint8_t) ((adtsLen & 0x7f8) >> 3); //frame length:value 中間8bitsszAdtsHeader[5] = (uint8_t) ((adtsLen & 0x7) << 5); //frame length:value 低3bitsszAdtsHeader[5] |= 0x1f; //buffer fullness:0x7ff 高5bitsszAdtsHeader[6] = 0xfc; }AAC結構說明參考
[AAC說明可以參考]: https://blog.csdn.net/leixiaohua1020/article/details/50535042
結束釋放資源
音頻寫好之后,釋放掉申請的資源
/*Close an opened input AVFormatContext*/ avformat_close_input(&fmt_ctx); if (dst_fd != NULL)fclose(dst_fd);完整代碼
// // Created by andrew on 2020/11/1. // #include <iostream> using namespace std; extern "C" { #include <libavutil/log.h> #include <libavformat/avformat.h> }void adts_header(char *szAdtsHeader, int dataLen) {int audio_object_type = 2;int sampling_frequency_index = 7;int channel_config = 2;int adtsLen = dataLen + 7;szAdtsHeader[0] = 0xff; //syncword:0xfff 高8bitsszAdtsHeader[1] = 0xf0; //syncword:0xfff 低4bitsszAdtsHeader[1] |= (0 << 3); //MPEG Version:0 for MPEG-4,1 for MPEG-2 1bitszAdtsHeader[1] |= (0 << 1); //Layer:0 2bitsszAdtsHeader[1] |= 1; //protection absent:1 1bitszAdtsHeader[2] =(audio_object_type - 1) << 6; //profile:audio_object_type - 1 2bitsszAdtsHeader[2] |=(sampling_frequency_index & 0x0f) << 2; //sampling frequency index:sampling_frequency_index 4bitsszAdtsHeader[2] |= (0 << 1); //private bit:0 1bitszAdtsHeader[2] |=(channel_config & 0x04) >> 2; //channel configuration:channel_config 高1bitszAdtsHeader[3] = (channel_config & 0x03) << 6; //channel configuration:channel_config 低2bitsszAdtsHeader[3] |= (0 << 5); //original:0 1bitszAdtsHeader[3] |= (0 << 4); //home:0 1bitszAdtsHeader[3] |= (0 << 3); //copyright id bit:0 1bitszAdtsHeader[3] |= (0 << 2); //copyright id start:0 1bitszAdtsHeader[3] |= ((adtsLen & 0x1800) >> 11); //frame length:value 高2bitsszAdtsHeader[4] = (uint8_t) ((adtsLen & 0x7f8) >> 3); //frame length:value 中間8bitsszAdtsHeader[5] = (uint8_t) ((adtsLen & 0x7) << 5); //frame length:value 低3bitsszAdtsHeader[5] |= 0x1f; //buffer fullness:0x7ff 高5bitsszAdtsHeader[6] = 0xfc; }/** 從多媒體文件中抽取媒體信息* */int main(int argc, char *argv[]) {AVFormatContext *fmt_ctx = NULL;av_log_set_level(AV_LOG_INFO);/*所有進行操作前,先執行以下,否則需要自己制定類型*/av_register_all();// 1. 讀取多媒體文件char *pSrc = NULL;char *pDst = NULL;pSrc = (char *) "/work/test/test.mp4";pDst = "test.aac";/*Open an input stream and read the header*/int ret = avformat_open_input(&fmt_ctx, "/work/test/test.mp4", NULL, NULL);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "can't open file.\n");return -1;}// write audio data to AAC fileFILE *dst_fd = fopen(pDst, "wb");if (dst_fd == NULL) {av_log(NULL, AV_LOG_ERROR, "open dst_fd failed.\n");avformat_close_input(&fmt_ctx);return -1;}// 2. get stream/*Read packets of a media file to get stream information.*/ret = avformat_find_stream_info(fmt_ctx, NULL);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "failed to find stream information.");avformat_close_input(&fmt_ctx);fclose(dst_fd);return -1;}/** Print detailed information about the input or output format* */av_dump_format(fmt_ctx, 0, "/work/test/test.mp4", 0);int audio_index = -1;audio_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);if (audio_index < 0) {av_log(NULL, AV_LOG_ERROR, "ret = %d\n", ret);avformat_close_input(&fmt_ctx);fclose(dst_fd);return -1;}AVPacket pkt;/*Initialize optional fields of a packet with default values.*/av_init_packet(&pkt);pkt.data = NULL;pkt.size = 0;int len = -1;/*保存原始數據,播放時需要添加AAC的音頻格式說明的頭*/while (av_read_frame(fmt_ctx, &pkt) >= 0) {if (pkt.stream_index == audio_index) {/*每幀開頭都要寫*/char adts_header_buf[7];adts_header(adts_header_buf, pkt.size);fwrite(adts_header_buf, 1, 7, dst_fd);len = fwrite(pkt.data, 1, pkt.size, dst_fd);cout << pkt.size << endl;if (len != pkt.size) {av_log(NULL, AV_LOG_ERROR, "waning, length is not equl size of pkt.\n");return -1;}}/*Wipe the packet.*/av_packet_unref(&pkt);}/*Close an opened input AVFormatContext*/avformat_close_input(&fmt_ctx);if (dst_fd != NULL)fclose(dst_fd);return 0; }總結
以上是生活随笔為你收集整理的使用FFmpeg实现抽取多媒体文件的音频并按照AAC格式进行保存--附源码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FFmpeg中实现对多媒体信息的获取与打
- 下一篇: 【数字逻辑设计】核心知识归纳总结