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