ffmpeg入门

ffmpeg入------安装

Fmpeg地址

FFmpeg源码地址:https://github.com/FFmpeg/FFmpeg

FFmpeg可执行文件地址:https://ffmpeg.org/download.html

Windows平台

Windows平台下载解压后如图所示(文件名称以-share结尾的是开发库)

FFmpeg库介绍

◆ ffmpeg.exe:用于音视频转码, 也可以从url/现场音频/视频源抓取输入源。

◆ ffplay.exe:一个非常简单和可移植的媒体播放器,使用FFmpeg库和SDL库。

◆ ffprobe.exe:查看多媒体文件的信息

将FFmpeg可执行文件加入系统环境变量,如下图所示:

Linux

ffmpeg官方 GitHub - FFmpeg/FFmpeg: Mirror of https://git.ffmpeg.org/ffmpeg.git

下载压缩包 或者 直接clone

  1. 直接clone:git clone https://github.com/FFmpeg/FFmpeg.git![](https://file.jishuzhan.net/article/1781211365344546818/2f5876dd7b5bbdc73519b3a0100c85aa.webp)![](https://file.jishuzhan.net/article/1781211365344546818/b642ff01c30bc463711b56e5026ff786.webp)
  2. 下载完成,执行./configure

如果出现了错误 nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.

这是因为 FFMPEG为了提高编译速度,使用了汇编指令,如MMX和SSE等。如果系统中没有yasm指令的话,就会该错误。

1)下载:wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz

2)解压:tar zxvf yasm-1.3.0.tar.gz

3)切换路径: cd yasm-1.3.0

4)执行配置: ./configure

5)编译:make

6)安装:make install

3.make && sudo make install

测试代码:

cpp 复制代码
#include<stdio.h>
#include<libavutil/log.h>


int main()
{
	av_log_set_level(AV_LOG_DEBUG);            //设置日志等级
	av_log(NULL, AV_LOG_INFO, "Hello~~~\n");       // INFO等级,输出hello

	return 0;
}

编译链接: gcc -o ff_log ff_log.c -lavutil

或者 gcc -o ff_log ff_log.c `pkg-config --cflags --libs libavutil`

("pk g-config 工具:1)会检查库的版本号。如果所需要的库的版本不满足要求,它会打印出错误信息,避免链接错误版本的库文件;2)会获得编译预处理参数,如宏定义,头文件的位置。3)还会获得链接参数,如库及依赖的其它库的位置,文件名及其它一些连接参数

选项*--cflags** 它是用来指定程序在编译时所需要头文件所在的目录, 选项 --libs则是指定程序在链接时所需要的动态链接库的目录。*

ffmpeg------log日志系统

log日志位于libavutil模块,log level的声明位于log.h

日志级别:

cpp 复制代码
// 静默模式,不打印日志
#define AV_LOG_QUIET    -8
 
// 立即崩溃,退出程序
#define AV_LOG_PANIC     0
 
// 严重出错,无法修复
#define AV_LOG_FATAL     8
 
// 程序出错
#define AV_LOG_ERROR    16
 
// 警告
#define AV_LOG_WARNING  24
 
// 信息
#define AV_LOG_INFO     32
 
// 详细信息
#define AV_LOG_VERBOSE  40
 
// 调试日志
#define AV_LOG_DEBUG    48
 
// 跟踪日志
#define AV_LOG_TRACE    56

设置日志等级的方法set_log_level()位于log.c,其中av_log_level是个静态全局变量,具体如下

cpp 复制代码
static int av_log_level = AV_LOG_INFO;
 
void av_log_set_level(int level)
{
    av_log_level = level;
}

常用的打印日志方法av_log(),声明位于log.h:

cpp 复制代码
/** 
 * 发送特定消息到小于等于当前等级的日志,默认全部发送到stderr
 *
 * @param avcl  指向任意结构体的指针,结构体第一个变量为AVClass或NULL
 * @param level 日志等级
 * @param fmt   字符串格式
 */
void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4);

ffmpeg------文件的删除与重命名

  • avpriv_io_delete() //删除
  • avpriv_io_move() //重命名

编译链接: gcc xxx.c -o xxx -lavformat -lavutil

cpp 复制代码
#include <libavformat/avformat.h>
 
int main(int argc,char *argv[])
{
        int ret;
        set_av_log_level(AV_LOG_DEBUG);
        ret = avpriv_io_move("111.txt","222.txt");
        if(ret < 0)
        {
                av_log(NULL,AV_LOG_ERROR,"Failed to move file:%s\n","111.txt");
                return -1;
        }
 
        

        ret = avpriv_io_delete("./mytestfile.txt");
        if(ret < 0)
        {
                av_log(NULL,AV_LOG_ERROR,"Failed to delete file:%s\n","mytestfile.txt");
                return -1;
        }
 
        av_log(NULL,AV_LOG_DEBUG,"Success to delete file:%s\n","mytestfile.txt");
 
        return 0;
}

ffmpeg------目录操作

重要结构体:

AVIODirContext 操作目录的上下文(记录avio_open_dir打开目录信息)

AVIODirEntry 目录项。用于存放文件名,文件大小等信息

操作目录API:

  • avio_open_dir()
  • avio_read_dir()//读取目录中每一个文件的属性
  • avio_close_dir()

编译链接: gcc xxx.c -o xxx -lavformat -lavutil

cpp 复制代码
// 实现简单的ls命令

#include <libavutil/log.h>
#include <libavformat/avformat.h>
 
int main(int argc,char* argv[])
{
        int ret;
        AVIODirContext *ctx = NULL;
        AVIODirEntry *entry = NULL;
        av_log_set_level(AV_LOG_INFO);
 
        ret = avio_open_dir(&ctx,"./",NULL);
        if(ret < 0){
                av_log(NULL,AV_LOG_ERROR,"Cant open dir:%s\n",av_err2str(ret));
                return -1;
        }
 
        while(1){
                ret = avio_read_dir(ctx,&entry);//malloc entry
                if(ret < 0){
                        av_log(NULL,AV_LOG_ERROR,"Cant read dir:%s\n",av_err2str(ret));
                        avio_close_dir(&ctx);
                        return -1;
                }
                if(!entry){
                        //the end
                        break;
                }
 
                av_log(NULL,AV_LOG_INFO,"%12"PRId64" %s\n",
                        entry->size,
                        entry->name);
 
                avio_free_directory_entry(&entry);//free entry
        }
 
        avio_close_dir(&ctx);
        return 0;
}

ffmpeg------重要的结构体

  • AVIOContext(I/O上下文) // 实现文件或者流的I/O操作
  • AVFormatContext(封装格式上下文) // 管理媒体文件的格式和封装信息
  • AVCodecContext(编解码器上下文) // 控制和配置音视频编解码器的行为
  • AVStream(音视频流) // 描述音视频流的属性
  • AVPacket (数据包) // 用于在媒体文件、流之间传递数据
  • AVFrame(帧) // 存储和传递音视频数据
  • AVDictionary(字典) // 存储配置选项和元数据
  • AVFilterContext(滤镜上下文) // 处理音视频数据,应用滤镜效果。
  • SwsContext(图像转换上下文) // 进行图像处理和转换
  • SwrContext(音频重采样上下文) // 进行音频处理和转换

AVIOContext结构体,用于管理媒体文件或者网络流的输入和输出操作

AVCodecContext结构体,包含了音频和视频编解码器的配置信息,如编码参数、解码参数、码率控制等。部分字段说明:

|---------------|----------------------------------------------|
| codec | 编解码器的AVCodec,比如指向AVCodec ff_aac_latm_decoder |
| width, height | 图像的宽高(只针对视频) |
| pix_fmt | 像素格式(只针对视频) |
| sample_rate | 采样率(只针对音频) |
| channels | 声道数(只针对音频) |
| sample_fmt | 采样格式(只针对音频 |

AVFormatContext结构体,是与多媒体文件格式相关的结构体,用于打开、读取和写入媒体文件。它包含了文件的格式信息、音视频流、文件I/O操作等。部分字段说明:

|--------------------------------|---------------------------------------------------------------|
| struct AVInputFormat* iformat | 输入媒体的AVInputFormat(输入数据的封装格式),比如指向AVInputFormatff_flv_demuxer |
| AVIOContext *pb | 输入数据的缓存 |
| unsigned int nb_streams; | 输出数据封装格式 |
| unsigned int nb_streams | 输入媒体的AVStream 个数 |
| AVStream** streams | 输入媒体的AVStream []数组 |
| int64_t duration | 输入媒体的时长(以微秒为单位),计算方式可以参考av_dump_format()函数 |
| int bit_rate | 输入媒体的码率 |

AVStream结构体,代表了音频或视频流,包括编解码参数、时间基准、时间戳等信息。部分字段说明

|----------------|--------------------------------|
| index | 标识该视频/音频流 |
| time_base | 该流的时基, PTS*time_base=真正的时间(秒) |
| avg_frame_rate | 该流的帧率 |
| duration | 该视频/音频流长度 |
| codecpar | 编解码器参数属性 |

AVPacket结构体,用于存储音频或视频数据包,包括编码后的数据和时间戳。部分字段说明:

|--------------|-------------|
| pts | 显示时间戳 |
| dts | 解码时间戳 |
| data | 压缩编码数据 |
| size | 压缩编码数据大小 |
| pos | 数据的偏移地址 |
| stream_index | 所属的AVStream |

AVFrame结构体,用于存储音频或视频帧的数据。它包括像素数据、采样数据、时间戳等。部分字段说明:

|---------------|---------------------------------|
| data | 解码后的图像像素数据(音频采样数据) |
| linesize | 对视频来说是图像中一行像素的大小;对音频来说是整个音频帧的大小 |
| width, height | 图像的宽高(只针对视频) |
| key_frame | 是否为关键帧(只针对视频) |
| pict_type | 帧类型(只针对视频) 。例如I, P, B |
| sample_rate | 音频采样率(只针对音频) |
| nb_samples | 音频每通道采样数(只针对音频) |
| pts | 显示时间戳 |

AVDictionary结构体,用于存储键值对,通常用于配置选项的传递和存储。

SwrContext结构体,用于音频重采样,支持不同采样率、通道数之间的转换

SwsContext结构体,用于图像转换,支持不同的像素格式和大小之间的转换

AVFilterContext结构体,用于配置和管理滤镜,包括音频滤镜和视频滤镜。

ffmpeg------多媒体文件

多媒体文件是一个容器(也可以理解为包装盒,常见的mp4、flv、mkv都是不同的包装盒 ),可以存放很多数据,最常见的有字幕数据、视频数据、音频数据。

容器中有很多流(Stream/Track),流媒体文件中不同的流之数据不会相交的,比如音频流和视频流就是各自独立的。

**每种流是由不同的编码器编码的,**每条流数据在多媒体文件中是经过压缩的,但是其使用压缩的编码器都是不一样的。比如音频有可能是MP3,有可能是AAC,视频常见的压缩器有可能是H264或者H265。

从流中读出的数据称为包,在一个包中包含着一个或者多个帧。

ffmpeg操作流数据的基本步骤:

API:

打开读取输入流报头:

cpp 复制代码
/* 打开一个输入流并读取报头。编解码器没有打开。流必须用avformat_close_input()关闭。


参数:
    @param ps指向用户提供的AVFormatContext(由avformat_alloc_context)。可能是指向NULL的指针,在这种情况下,AVFormatContext由this分配函数并写入ps。注意,用户提供的AVFormatContext将被释放失败。

    @param url打开的流的url。

    @param fmt如果非null,该参数强制使用特定的输入格式。否则格式自动检测。

    @param options一个由AVFormatContext和demuxer-private填充的字典选项。返回时,此参数将被销毁并替换为包含未找到的选项的字典。可能为NULL。


成功时返回0,失败时返回负AVERROR。
*/

int avformat open input(AVFormatContext *ps, 
                        const char *url, 
                        const AVinputFormat *fmt,
                        AVDictionary **options)
cpp 复制代码
/*
    在文件中找到"最佳"流。最佳流是根据各种启发式确定的,因为最可能是用户期望的。如果decoder参数非null, av_find_best_stream将为流的编解码器找到默认的解码器;找不到解码器的流将被忽略。


参数:

    *  @param ic                 媒体文件句柄
    * @param type                 视频,音频,字幕等
    * @param wanted_stream_nb    用户请求的流编号或-1为自动选择
    * @param related_stream    尝试找到一个流相关(例如:在同一个程序中)到这个,如果没有,则为-1
    * @param decoder_ret       如果非null,返回所选流的解码器
    * @param flags             当前没有定义


@return
    如果成功,返回非负的流号,如果没有找到请求类型的流,返回AVERROR_STREAM_NOT_FOUND,如果找到流但没有解码器,返回AVERROR_DECODER_NOT_FOUND

@note
如果av_find_best_stream返回成功并且decoder_ret不是NULL,那么*decoder_ret保证被设置为有效的AVCodec。

*/
int av_find_best_stream(AVFormatContext *ic,
                        enum AVMediaType type,
                        int wanted_stream_nb,
                        int related_stream,
                        const AVCodec **decoder_ret,
                        int flags);
cpp 复制代码
//分配一个AVFormatContext。
// avformat_free_context()可以用来释放上下文和框架在其中分配的所有内容。

AVFormatContext *avformat_alloc_context(void);
cpp 复制代码
/*返回与所提供参数最匹配的已注册输出格式列表中的输出格式,如果没有匹配则返回NULL。

@param short_name    if non-NULL检查short_name是否与注册格式的名称匹配
@param filename     if non-NULL检查filename是否以注册格式的扩展名结束
@param mime_type     if non-NULL检查mime_type是否与注册格式的MIME类型匹配

*/

const AVOutputFormat *av_guess_format(const char *short_name,
                                      const char *filename,
                                      const char *mime_type);
cpp 复制代码
/*向媒体文件添加新的流。
    在解模时,由read_header()中的解模器调用。如果标志AVFMTCTX_NOHEADER在s.ctx_flags中设置,那么它也可以在read_packet()中被调用

    当复用时,应该在avformat_write_header()之前由用户调用。
    用户需要调用avformat_free_context()来清理分配,由avformat_new_stream()。

参数:
    @param s  媒体文件句柄
    @param c  未使用,不做任何事情

@return 新创建的流,错误时返回NULL。

*/

AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);
相关推荐
问道飞鱼4 小时前
【工具介绍】Ffmpeg工具介绍与简单使用
ffmpeg·视频工具
l***77529 小时前
从MySQL5.7平滑升级到MySQL8.0的最佳实践分享
ffmpeg
ZouZou老师15 小时前
FFmpeg性能优化经典案例
性能优化·ffmpeg
aqi0017 小时前
FFmpeg开发笔记(九十)采用FFmpeg套壳的音视频转码百宝箱FFBox
ffmpeg·音视频·直播·流媒体
齐齐大魔王19 小时前
FFmpeg
ffmpeg
你好音视频21 小时前
FFmpeg RTSP拉流流程深度解析
ffmpeg
IFTICing1 天前
【环境配置】ffmpeg下载、安装、配置(Windows环境)
windows·ffmpeg
haiy20111 天前
FFmpeg 编译
ffmpeg
aqi001 天前
FFmpeg开发笔记(八十九)基于FFmpeg的直播视频录制工具StreamCap
ffmpeg·音视频·直播·流媒体
八月的雨季 最後的冰吻2 天前
FFmepg--28- 滤镜处理 YUV 视频帧:实现上下镜像效果
ffmpeg·音视频