FFMPEG中的filter使用二

本文介绍了如何使用ffmpeg的参数形式来自动创建和链接过滤器,减少了手动操作,并提供了通过filtergraph语法构建处理流程的方法,包括使用AVFilterInOut结构链接滤镜以及avfilter_graph_parse_ptr函数的应用。
摘要由CSDN通过智能技术生成

上一篇我们在使用滤镜时是手动创建各种滤镜,然后根据处理链路手动链接不同的过滤器,有助于我们理解滤镜的流程。这一篇我们使用参数形式,让ffmpeg自动帮我们创建和链接过滤器,这样可以减少代码量,同时我们可以先使用参数测试后,直接将参数复制到代码中使用。

准备

ffmeg 4.4

一个MP4或flv格式视频文件

处理流程

这里我们需要说明下:

首先我们需要理解filtergraph语法,每个过滤器至少有一个输入和输出,对于多个输入和输出的过滤器如何指定那个输入和输出与其他过滤器进行链接呢,所以需要指定标签,如下面的命令

[in]scale=iw/2:ih/2[in_tmp];[in_tmp]split=2[in_1][in_2];[in_1]pad=iw*2:ih*2:color=yellow[a];[a][in_2]overlay=w[out]

上面的split的滤镜将输入的视频帧复制为2个输出并指定名称为[in_1]和[in_2],[in_2]作为overlay滤镜的第二个输入,[in_1]经过pad滤镜处理后作为overlay的第一个输入。

而[in]和[out]这两个名称是系统默认的。也可自行修改。

好了我们来看上面的流程图。

/*
    和 avfilter_graph_parse 类似。不同的是 inputs 和 outputs 参数,即做输入参数,也做输出参数。
        在函数返回时,它们将会保存 graph 中所有的处于 open 状态的 pad。返回的 inout 应该使用 avfilter_inout_free() 释放掉。
    
    注意:在字符串描述的 graph 中,第一个 filter 的输入如果没有被一个字符串标识,默认其标识为"in",最后一个 filter 的输出如果没有被标识,默认为"output"。
    
    intpus:作为输入参数是,用于保存已经存在的graph的open inputs,可以为NULL。
        作为输出参数,用于保存这个parse函数之后,仍然处于open的inputs,当然如果传入为NULL,则并不输出。
    outputs:同上。
*/
int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters,
                             AVFilterInOut **inputs, AVFilterInOut **outputs, void *log_ctx);

方法 avfilter_graph_parse_ptr解析filters字符串中滤镜,创建滤镜并将滤镜链接起来。里面用到了2个AVFilterInOut结构。如下:

    AVFilterInOut* outputs = avfilter_inout_alloc();
    AVFilterInOut* inputs = avfilter_inout_alloc();    

    outputs->name = av_strdup("in");
    outputs->filter_ctx = buffersrc_ctx;
    outputs->pad_idx = 0;
    outputs->next = NULL;

    inputs->name = av_strdup("out");
    inputs->filter_ctx = buffersink_ctx;
    inputs->pad_idx = 0;
    inputs->next = NULL;

outputs,inputs分别指定一个滤镜的上下文和引脚名称。这里其实就时buffer和buffersink.

然后avfilter_graph_parse_ptr 方法会将字符串的中滤镜输入引脚为in的滤镜与outputs链接,输出引脚为out的滤镜与inputs链接。这样就把buffer和buffersink滤镜加入到了整个滤镜链路中了,形成了完整的滤镜链路。

我们在创建buffer和buffersink时,分别命令了buffer的输出名称为in,buffersink的输入名称为out

这里我们看面的参数[in]............[out],其实就是为了将他们使用对应的名称链接起来。

   
const char* filter_descr = "[in]scale=iw/2:ih/2[in_tmp];[in_tmp]split=2[in_1][in_2];[in_1]pad=iw*2:ih*2:color=yellow[a];[a][in_2]overlay=w[out]";

 char args[512];
    int ret = 0;
    const AVFilter* buffersrc = avfilter_get_by_name("buffer");//预缓存帧数据。用于输入
    const AVFilter* buffersink = avfilter_get_by_name("buffersink");//缓冲视频帧,并使它们可用于过滤器图形的末尾。用于输出
    AVFilterInOut* outputs = avfilter_inout_alloc();
    AVFilterInOut* inputs = avfilter_inout_alloc();
    AVRational time_base = fmt_ctx->streams[video_stream_index]->time_base;
    enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };//注意输入的格式类型pix_fmts[0]

    filter_graph = avfilter_graph_alloc();
    if (!outputs || !inputs || !filter_graph) {
        ret = AVERROR(ENOMEM);
        goto end;
    }

    /* buffer video source: the decoded frames from the decoder will be inserted here. */
    snprintf(args, sizeof(args),
        "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
        dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
        time_base.num, time_base.den,
        dec_ctx->sample_aspect_ratio.num, dec_ctx->sample_aspect_ratio.den);

    //创建和初始化过滤器实例并将其添加到现有图形中。【输入】
    ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
        args, NULL, filter_graph);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
        goto end;
    }

    //创建和初始化过滤器实例并将其添加到现有图形中。【输出】
    /* buffer video sink: to terminate the filter chain. */
    ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
        NULL, NULL, filter_graph);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
        goto end;
    }

    //给buffersink_ctx设置参数
    ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts,
        AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");
        goto end;
    }

    /*
     * Set the endpoints for the filter graph. The filter_graph will
     * be linked to the graph described by filters_descr.
     */

  
    outputs->name = av_strdup("in");
    outputs->filter_ctx = buffersrc_ctx;
    outputs->pad_idx = 0;
    outputs->next = NULL;


    inputs->name = av_strdup("out");
    inputs->filter_ctx = buffersink_ctx;
    inputs->pad_idx = 0;
    inputs->next = NULL;

    //将字符串描述的图形添加到图形中。
    if ((ret = avfilter_graph_parse_ptr(filter_graph, filters_descr, &inputs, &outputs, NULL)) < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "Error avfilter_graph_parse_ptr\n");
        goto end;
    }

    //检查AVFilterGraph有效性
    if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "Error avfilter_graph_config\n");
        goto end;
    }

### 回答1: Ffmpeg是一款开源的视频处理软件,可以通过Filter进行视频处理。Filter可以对视频进行裁剪、缩放、色彩调整、添加水印等各种处理。下面是使用Filter的一些示例命令: 1. 裁剪视频: ``` ffmpeg -i input.mp4 -vf "crop=720:480:20:20" output.mp4 ``` 该命令将输入视频裁剪为720x480的大小,左边和上边各留出20像素的边距。 2. 缩放视频: ``` ffmpeg -i input.mp4 -vf "scale=320:240" output.mp4 ``` 该命令将输入视频缩放为320x240的大小。 3. 调整视频色彩: ``` ffmpeg -i input.mp4 -vf "eq=brightness=0.2:saturation=1.5" output.mp4 ``` 该命令将输入视频亮度降低20%,饱和度增加50%。 4. 添加水印: ``` ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=10:10" output.mp4 ``` 该命令将输入视频和水印图片叠加在一起,水印位置为视频左上角偏移10像素。 以上仅是Filter的一些示例,Ffmpeg支持更多的Filter,可根据需要自行查阅文档使用。 ### 回答2: FFmpeg是一款开源的多媒体处理工具,可以实现视频和音频的录制、转码、编辑等功能。在使用FFmpeg进行视频处理时,Filter是一项重要的功能,可以用来对视频进行各种处理和效果的添加。 FFmpegFilter是通过-vf(video filter)参数来实现的。在命令行加入-vf参数后,可以添加各种不同的Filter,以达到不同的视频效果。例如,可以使用Filter来实现对视频的裁剪、旋转、缩放等操作。 具体使用Filter的语法如下: -vf "filter_name=parameter1:value1,parameter2:value2,..." 其filter_name表示要使用Filter名称,parameter表示该Filter的具体参数,value表示参数的值。不同的Filter会有不同的参数,需要根据具体需求进行设置。 例如,要对视频进行旋转的话,可以使用rotate Filter。具体使用方法如下: -vf "rotate=angle=30" 通过以上命令,即可将视频旋转30度。同样的方式,对于其他Filter,只需要将filter_name和parameter替换为对应的值即可。 另外,在Filter还可以使用Filter链,即将多个Filter串联使用,实现复杂的效果。通过在-vf参数添加多个Filter,并使用逗号分隔,可以将多个Filter依次执行。 总之,FFmpegFilter功能强大且灵活,可以实现对视频进行各种处理和效果的添加。通过适当的命令行参数设置,可以轻松实现对视频进行裁剪、旋转、缩放等操作,丰富视频的视觉效果。 ### 回答3: FFmpeg 是一款功能强大的多媒体处理工具,可以用于音视频文件的转换、剪辑、处理等。FilterFFmpeg 的一个重要功能,可以用来对音视频进行各种滤镜处理。 使用 FFmpeg 进行滤镜处理一般需要以下几个步骤: 1. 首先,需要了解 FFmpeg 支持的滤镜和其参数。可以通过命令 `ffmpeg -filters` 查看所有可用滤镜列表,以及命令 `ffmpeg -h filter=<滤镜名称>` 查看特定滤镜的详细参数信息。 2. 选择合适的滤镜后,需要通过命令行指定输入文件和输出文件,以及滤镜参数。下面是一个使用 FFmpeg 添加文本水印的命令示例: ``` ffmpeg -i input.mp4 -vf "drawtext=text='Hello World':fontfile=Arial.ttf:fontsize=24:fontcolor=white:x=10:y=10" output.mp4 ``` 这个命令会将输入文件 `input.mp4` 进行滤镜处理,添加一个文本水印,输出为 `output.mp4`。其,`drawtext` 是指定滤镜为文本水印,后面的参数是具体的水印文字内容、字体文件、字体大小、字体颜色以及位置等信息。 3. 根据需要,可以添加多个滤镜和参数。可以通过 `;` 或者 `,` 分隔多个滤镜。例如: ``` ffmpeg -i input.mp4 -vf "scale=640:480,rotate=30*PI/180" output.mp4 ``` 这个命令会先将输入文件 `input.mp4` 进行尺寸缩放,然后再旋转一定角度后输出为 `output.mp4`。 4. 最后,运行命令进行滤镜处理。运行命令后,FFmpeg 会按照指定参数进行滤镜处理,并生成输出文件。 需要注意的是,在使用 FFmpeg 进行滤镜处理时,可以根据实际需求选择不同的滤镜和参数,也可以自定义滤镜,以实现特定的效果。同时,滤镜的顺序也可能会影响最终的效果,所以需要根据具体情况进行调整。 总之,FFmpeg 的滤镜功能强大且灵活,可以应用于音视频的各种处理场景,帮助我们实现更多的创意和效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

破浪征程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值