ffmpeg记录

最近工作中有用到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;
}

posted @   LX2020  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示