首页 > 其他分享 >ffmpeg记录

ffmpeg记录

时间:2024-03-03 23:55:45浏览次数:34  
标签:return ffmpeg 记录 frame ctx codec file av

最近工作中有用到ffmpeg,这里做一下简单的记录:

1、虚拟机平台安装ffmpeg

使用apt进行安装

sudo apt update
sudo apt install ffmpeg

之后安装一些需要的安装包

sudo apt install libavcodec-dev libavformat-dev libavutil-dev libswscale-dev

这样就编译OK了,之后编译程序,使用下面的示例

gcc -o test test.c -lavcodec -lavformat -lavutil -lswscale

下面用一个示例程序

#include <stdio.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>

int main() {
    // 初始化 FFmpeg 库
    av_register_all();

    // 输出 FFmpeg 版本信息
    printf("FFmpeg version: %s\n", av_version_info());

    // 输出 libavcodec 版本信息
    printf("Libavcodec version: %d.%d.%d\n", LIBAVCODEC_VERSION_MAJOR, LIBAVCODEC_VERSION_MINOR, LIBAVCODEC_VERSION_MICRO);

    // 输出 libavformat 版本信息
    printf("Libavformat version: %d.%d.%d\n", LIBAVFORMAT_VERSION_MAJOR, LIBAVFORMAT_VERSION_MINOR, LIBAVFORMAT_VERSION_MICRO);

    return 0;
}

执行结果如下:

也可以手动安装:
去官网下载安装包,之后解压
https://ffmpeg.org/

之后先安装一下yasm

yasm

之后开始编译

./configure   --enable-shared  --prefix=/usr/local/ffmpeg  --enable-gpl --enable-libx264  --enable-libx265   

然后就是

make 
make install

加入链接

export LD_LIBRARY_PATH=/usr/local/ffmpeg/lib:$LD_LIBRARY_PATH

这样就可以使用了,和上面的区别是只能调库,不能直接用ffmpeg,但是占用的资源也是最小的,仅安装需要的库。

2、音频格式转化

ffmpeg实现音频格式转化如果使用命令行是很方便的,如下所示:

音频格式转换:

将 MP3 文件转换为 WAV 文件:

ffmpeg -i input.mp3 output.wav

将 WAV 文件转换为 MP3 文件:

ffmpeg -i input.wav -b:a 192k output.mp3

视频格式转换:

将 MP4 文件转换为 AVI 文件:

ffmpeg -i input.mp4 output.avi

将 AVI 文件转换为 MP4 文件:

ffmpeg -i input.avi -c:v libx264 -crf 23 -c:a aac -strict experimental output.mp4

图片格式转换:

将 JPG 文件转换为 PNG 文件:

ffmpeg -i input.jpg output.png

将 PNG 文件转换为 JPG 文件:

ffmpeg -i input.png -q:v 2 output.jpg

也可以使用程序实现,在嵌入式的平台上由于资源紧张,一般之后安装一些ffmpeg的库,因此无法直接执行ffmpeg的命令行,例如将MP3的格式转为wav

#include <stdio.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>

int main(int argc, char *argv[]) {
    if (argc < 3) {
        fprintf(stderr, "Usage: %s <input_mp3_file> <output_wav_file>\n", argv[0]);
        return 1;
    }

    const char *input_file = argv[1];
    const char *output_file = argv[2];

    av_register_all();
    avcodec_register_all();

    AVFormatContext *format_ctx = avformat_alloc_context();
    if (!format_ctx) {
        fprintf(stderr, "Error allocating format context\n");
        return 1;
    }

    if (avformat_open_input(&format_ctx, input_file, NULL, NULL) != 0) {
        fprintf(stderr, "Error opening input file\n");
        return 1;
    }

    if (avformat_find_stream_info(format_ctx, NULL) < 0) {
        fprintf(stderr, "Error finding stream information\n");
        return 1;
    }

    AVCodec *codec = NULL;
    int audio_stream_index = av_find_best_stream(format_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
    if (audio_stream_index < 0) {
        fprintf(stderr, "Error finding audio stream in input file\n");
        return 1;
    }

    AVCodecContext *codec_ctx = format_ctx->streams[audio_stream_index]->codec;
    codec = avcodec_find_decoder(codec_ctx->codec_id);
    if (!codec) {
        fprintf(stderr, "Error finding decoder\n");
        return 1;
    }

    if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
        fprintf(stderr, "Error opening codec\n");
        return 1;
    }

    FILE *output_file_ptr = fopen(output_file, "wb");
    if (!output_file_ptr) {
        fprintf(stderr, "Error opening output file\n");
        return 1;
    }

    AVPacket packet;
    av_init_packet(&packet);

    while (av_read_frame(format_ctx, &packet) >= 0) {
        if (packet.stream_index == audio_stream_index) {
            AVFrame *frame = av_frame_alloc();
            int frame_finished = 0;
            avcodec_decode_audio4(codec_ctx, frame, &frame_finished, &packet);
            if (frame_finished) {
                fwrite(frame->data[0], 1, frame->linesize[0], output_file_ptr);
            }
            av_frame_free(&frame);
        }
        av_packet_unref(&packet);
    }

    fclose(output_file_ptr);
    avformat_close_input(&format_ctx);

    printf("Conversion successful!\n");
    return 0;
}

可以扩展到将任意格式转为wav

#include <stdio.h>
#include <stdlib.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>

int main(int argc, char *argv[]) {
    if (argc < 3) {
        fprintf(stderr, "Usage: %s <input_audio_file> <output_wav_file>\n", argv[0]);
        return 1;
    }

    const char *input_file = argv[1];
    const char *output_file = argv[2];

    av_register_all();
    avcodec_register_all();

    AVFormatContext *format_ctx = avformat_alloc_context();
    if (!format_ctx) {
        fprintf(stderr, "Error allocating format context\n");
        return 1;
    }

    if (avformat_open_input(&format_ctx, input_file, NULL, NULL) != 0) {
        fprintf(stderr, "Error opening input file\n");
        return 1;
    }

    if (avformat_find_stream_info(format_ctx, NULL) < 0) {
        fprintf(stderr, "Error finding stream information\n");
        return 1;
    }

    AVCodec *codec = NULL;
    int audio_stream_index = av_find_best_stream(format_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
    if (audio_stream_index < 0) {
        fprintf(stderr, "Error finding audio stream in input file\n");
        return 1;
    }

    AVCodecContext *codec_ctx = format_ctx->streams[audio_stream_index]->codec;
    codec = avcodec_find_decoder(codec_ctx->codec_id);
    if (!codec) {
        fprintf(stderr, "Error finding decoder\n");
        return 1;
    }

    if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
        fprintf(stderr, "Error opening codec\n");
        return 1;
    }

    FILE *output_file_ptr = fopen(output_file, "wb");
    if (!output_file_ptr) {
        fprintf(stderr, "Error opening output file\n");
        return 1;
    }

    AVPacket packet;
    av_init_packet(&packet);

    while (av_read_frame(format_ctx, &packet) >= 0) {
        if (packet.stream_index == audio_stream_index) {
            AVFrame *frame = av_frame_alloc();
            int frame_finished = 0;
            avcodec_decode_audio4(codec_ctx, frame, &frame_finished, &packet);
            if (frame_finished) {
                // Convert to PCM S16LE format
                uint8_t *buffer;
                int buffer_size = av_samples_get_buffer_size(NULL, codec_ctx->channels, frame->nb_samples, AV_SAMPLE_FMT_S16, 0);
                buffer = (uint8_t *)av_malloc(buffer_size);
                if (!buffer) {
                    fprintf(stderr, "Error allocating memory for PCM buffer\n");
                    return 1;
                }
                SwrContext *swr_ctx = swr_alloc();
                if (!swr_ctx) {
                    fprintf(stderr, "Error allocating resampling context\n");
                    return 1;
                }
                av_opt_set_int(swr_ctx, "in_channel_layout", codec_ctx->channel_layout, 0);
                av_opt_set_int(swr_ctx, "out_channel_layout", codec_ctx->channel_layout, 0);
                av_opt_set_int(swr_ctx, "in_sample_rate", codec_ctx->sample_rate, 0);
                av_opt_set_int(swr_ctx, "out_sample_rate", codec_ctx->sample_rate, 0);
                av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", codec_ctx->sample_fmt, 0);
                av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
                swr_init(swr_ctx);
                swr_convert(swr_ctx, &buffer, buffer_size / codec_ctx->channels / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16), (const uint8_t **)frame->data, frame->nb_samples);
                fwrite(buffer, 1, buffer_size, output_file_ptr);
                av_freep(&buffer);
                swr_free(&swr_ctx);
            }
            av_frame_free(&frame);
        }
        av_packet_unref(&packet);
    }

    fclose(output_file_ptr);
    avformat_close_input(&format_ctx);

    printf("Conversion successful!\n");
    return 0;
}

也可以解码后直接将数据写入pcm文件中

#include <stdio.h>
#include <stdlib.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>

int main(int argc, char *argv[]) {
    if (argc < 3) {
        fprintf(stderr, "Usage: %s <input_audio_file> <output_pcm_file>\n", argv[0]);
        return 1;
    }

    const char *input_file = argv[1];
    const char *output_file = argv[2];

    av_register_all();
    avcodec_register_all();

    AVFormatContext *format_ctx = avformat_alloc_context();
    if (!format_ctx) {
        fprintf(stderr, "Error allocating format context\n");
        return 1;
    }

    if (avformat_open_input(&format_ctx, input_file, NULL, NULL) != 0) {
        fprintf(stderr, "Error opening input file\n");
        return 1;
    }

    if (avformat_find_stream_info(format_ctx, NULL) < 0) {
        fprintf(stderr, "Error finding stream information\n");
        return 1;
    }

    AVCodec *codec = NULL;
    int audio_stream_index = av_find_best_stream(format_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
    if (audio_stream_index < 0) {
        fprintf(stderr, "Error finding audio stream in input file\n");
        return 1;
    }

    AVCodecContext *codec_ctx = format_ctx->streams[audio_stream_index]->codec;
    codec = avcodec_find_decoder(codec_ctx->codec_id);
    if (!codec) {
        fprintf(stderr, "Error finding decoder\n");
        return 1;
    }

    if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
        fprintf(stderr, "Error opening codec\n");
        return 1;
    }

    FILE *output_file_ptr = fopen(output_file, "wb");
    if (!output_file_ptr) {
        fprintf(stderr, "Error opening output file\n");
        return 1;
    }

    AVPacket packet;
    av_init_packet(&packet);

    while (av_read_frame(format_ctx, &packet) >= 0) {
        if (packet.stream_index == audio_stream_index) {
            AVFrame *frame = av_frame_alloc();
            int frame_finished = 0;
            avcodec_decode_audio4(codec_ctx, frame, &frame_finished, &packet);
            if (frame_finished) {
                int data_size = av_get_bytes_per_sample(codec_ctx->sample_fmt) * codec_ctx->channels * frame->nb_samples;
                fwrite(frame->data[0], 1, data_size, output_file_ptr);
            }
            av_frame_free(&frame);
        }
        av_packet_unref(&packet);
    }

    fclose(output_file_ptr);
    avformat_close_input(&format_ctx);

    printf("Extraction successful!\n");
    return 0;
}

标签:return,ffmpeg,记录,frame,ctx,codec,file,av
From: https://www.cnblogs.com/lx2035/p/18051009

相关文章

  • 2024-2-26启 记录
    2-26~3-3(5题)寒假又tm荒废了,今年应该是我在OI道路上的最后一年了,可能确切地说是六个月,不多说什么了,时间不多了,做什么事都要高效起来。开学第一个星期,有点不适应,shabby一中搞半月假,周考也炸了。摸了几题前缀和的题目做,算是练练手,感觉差不多找回来了。现在大致的计划是先......
  • 2023.3 做题记录
    2023.3做题记录注:只摘录具有较高思考价值以及较高思维含量的题目(说白了就是颓出来的题)。[JSOI2008]火星人我们只考虑查询操作,方法很多,例如KMP、哈希、SA。此时考虑修改,由于KMP、SA不好维护修改后的数组,因此考虑哈希。我们利用二分答案的方式求出长度,利用哈希检查即可。......
  • 6. 活动记录 | 2. Tiger 编译器的栈帧
    栈帧栈帧是指函数在被调用时,所拥有的一块独立的用于存放函数所使用的状态和变量的栈空间。每个函数都对应有至少一个栈帧。同一个函数多次进入,每次可能会分配到不同的栈帧。整个栈的内容在同一个时刻可以看作是由许多栈帧依序“堆叠”组成的。两层抽象Translate模块frame......
  • 红米note4x mido移植Ubuntu20.04过程记录
    mido设备移植Ubuntu20.04一、初始化环境1.安装编译依赖环境#这里宿主机使用Ubuntu20.04系统sudoaptinstallbinfmt-supportqemu-user-staticgcc-10-aarch64-linux-gnukernel-packagefakerootsimg2imgimg2simgmkbootimgbisonflexgcc-aarch64-linux-gnupkg-config......
  • 利用单例模式与阻塞队列实现异步的日志系统,记录服务器运行状态
    目录类结构概述主要特性总结Log类是一个用于日志记录的C++类,其设计具有以下特点和功能:类结构概述类成员变量:path_:日志文件存储路径。suffix_:日志文件后缀名。MAX_LINES_:每个日志文件允许的最大行数。lineCount_:当前日志文件已写的行数。toDay_:当前日志文......
  • 牛客大厂真题刷题记录
    1、问题:统计在有用户互动的最近一个月(按包含当天在内的近30天算,比如10月31日的近30天为10.2~10.31之间的数据)中,每类视频的转发量和转发率(保留3位小数)。注:转发率=转发量÷播放量。结果按转发率降序排序。selecttag,sum(if_retweet)retweet_cut,round(sum(if_retweet)/coun......
  • SQL intern 29题记录及心得
    表结构21、豹子手机号用户(4个连续数字,如6666)和非豹子号用户的笔均消费金额分别是多少?withbas(selectusr_id,casewhenphone_numREGEXP'[0-9](?=\\1{3})'THEN'Leopard'`else'no-Leopard'`endasis_豹子fromid_inf)selectavg(a.trx_amt),is_豹......
  • Windows 系统日志是记录操作系统活动的重要组成部分,对于入侵排查和溯源来说,分析系统日
    Windows系统日志是记录操作系统活动的重要组成部分,对于入侵排查和溯源来说,分析系统日志是非常关键的一步。以下是针对Windows系统日志分析和溯源的基础技术原理:事件日志:Windows操作系统生成多个类型的事件日志,包括应用程序日志、安全日志和系统日志。了解不同类型的事件日......
  • PowerShell中,你可以使用以下命令来操作Windows防火墙并记录流量信息
    在PowerShell中,你可以使用以下命令来操作Windows防火墙并记录流量信息:操作Windows防火墙:查看当前的防火墙规则:powershellCopyCodeGet-NetFirewallRule创建新的防火墙规则:powershellCopyCodeNew-NetFirewallRule-DisplayName"MyFirewallRule"-DirectionInbound-A......
  • 随笔记录篇——C++iostream库 以及std
    这篇文章非原创,来自我学习过程中看到的其他博主发的一些资料,解决了我的疑问,在此进行整理。C语言的标准输入输出库是stdio.h库,是一个函数库,而不是类库。其中包含了我们其中所用的scanfpringf都是一些独立的全局函数,因为C语言是不支持类的。C++的标准输入输出库iostream是一个类......