FFmpeg进阶:视频滤镜大全

本文翻译了FFmpeg官方文档中的所有视频滤镜介绍,涵盖了丰富的视频特效,适合需要进行视频处理的读者参考。可能存在一些陌生概念,欢迎提出修改建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在做视频特效的时候,很多特效其实不用自己写,FFmpeg的视频滤镜里面提供了很丰富的滤镜特效。这里翻译了一下FFmpeg官方文档的所有视频滤镜的介绍,供大家参考。由于很多地方概念比较生疏,翻译的可能不恰当,欢迎反馈修改意见。

滤镜名称 滤镜介绍
addroi 在视频帧中标记感兴趣的区域
alphaextract 从输入中提取 alpha 分量作为灰度视频。
alphamerge 用第二个输入的灰度值添加或替换主输入的 alpha 分量。
amplify 放大当前像素与同一像素位置的相邻帧的像素之间的差异
ass 与字幕过滤器相同,它仅限于 ASS字幕文件
atadenoise 将自适应时间平均
<think>我们正在处理用户关于使用FFmpeg视频添加自定义封面的问题。根据提供的引用,特别是引用[1]和引用[2],我们可以知道FFmpeg支持多种视频解码器和格式处理,并且引用[3]提到了滤镜技术,但用户的问题不需要滤镜,而是添加封面。 添加封面通常有两种方法: 1. 将封面作为视频流(通常是第一个视频流)插入,这样播放器在显示时会优先使用该流作为封面。 2. 将封面嵌入到文件的元数据中,作为缩略图(thumbnail)或附件(attached picture),这通常用于音频文件(如MP3)或视频文件(如MP4)的封面。 对于视频文件(如MP4),我们通常希望封面在文件被浏览时显示(比如文件管理器中的缩略图),同时不影响视频播放。因此,我们可以将封面图片作为元数据中的缩略图嵌入。 但注意:有些播放器可能会显示第一个视频帧作为缩略图,而忽略嵌入的封面。因此,另一种做法是将封面作为视频的第一帧。用户可以根据需要选择。 方法一:将封面嵌入为元数据(作为缩略图) 使用`-map`选项来映射封面图片,并使用`-disposition`设置缩略图属性。 方法二:将封面作为第一帧 我们可以使用`concat`复用器将封面图片(转换为视频帧)和原始视频拼接起来。 由于用户明确要求“添加自定义封面”,我们通常理解为嵌入元数据的方式,因为这样不会改变视频内容。但是,FFmpeg默认情况下,对于MP4等格式,嵌入封面需要使用`-map`和`-disposition`。 具体步骤: 1. 准备一个封面图片(如cover.jpg)。 2. 使用FFmpeg命令将封面图片作为附加的流(通常是作为附件流)写入文件,并设置它为缩略图。 命令示例: ```bash ffmpeg -i input.mp4 -i cover.jpg -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic output.mp4 ``` 解释: - `-i input.mp4`:输入视频文件。 - `-i cover.jpg`:输入封面图片。 - `-map 0`:映射第一个输入(视频)的所有流。 - `-map 1`:映射第二个输入(图片)的流。 - `-c copy`:复制所有流(不重新编码),但注意,图片需要被编码视频流,所以后面我们覆盖了图片流的编码方式。 - `-c:v:1 png`:将第二个映射的流(即封面图片,索引为1的视频流)编码为PNG格式(也可以使用jpg,但注意原图片格式)。 - `-disposition:v:1 attached_pic`:将第二个视频流(索引为1)的disposition设置为attached_pic,即作为封面图片。 - `output.mp4`:输出文件。 注意:如果原始视频已经有封面(即已经有一个disposition为attached_pic的流),我们需要先移除它。可以使用`-disposition`覆盖,或者使用复杂的滤镜处理。但上述命令会添加一个新的视频流作为封面,而原始视频流不变。播放器在播放时会忽略封面流,但文件浏览器会使用它作为缩略图。 然而,有些格式(如MP4)支持嵌入多个封面,但通常只有一个会被使用(第一个封面流)。所以如果原视频已经有封面,我们可以选择不复制原封面流,或者先移除。 另一种更直接的方法(只嵌入一个封面,覆盖原有的): ```bash ffmpeg -i input.mp4 -i cover.jpg -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic -metadata:s:v:1 title="Album cover" -metadata:s:v:1 comment="Cover (front)" output.mp4 ``` 但是,如果原视频已经有封面流,我们可能希望移除它。在FFmpeg中,我们可以使用`-map`来避免选择原封面流,但原封面流可能和其他流混在一起,不容易区分。因此,我们可以先使用`-disposition`将原封面流的disposition移除,然后再添加新的。 然而,更简单的方法是:如果我们知道原封面流是第几个视频流(比如是第二个视频流),我们可以不映射它。但通常我们不知道,所以一个通用的方法是先移除所有流的disposition,然后再设置新的封面流。但这样可能会影响其他流的disposition(比如默认流)。 因此,对于一般用户,如果原视频没有封面,直接使用上面的命令即可。如果有封面,我们可以通过重新设置disposition来覆盖。 实际上,FFmpeg在添加新的封面流时,并不会自动移除原有的封面流。所以我们需要先移除原有的封面标记。我们可以使用以下步骤: 1. 将原视频的所有流复制(包括视频流),但移除所有流的封面标记(disposition)。 2. 添加新的封面图片流,并设置其disposition为attached_pic。 命令: ```bash ffmpeg -i input.mp4 -i cover.jpg -map 0 -map 1 -c copy -c:v:1 png -disposition:0 -disposition:v:1 attached_pic output.mp4 ``` 这里,`-disposition:0`表示移除第一个输入文件(即input.mp4)中所有流的disposition。然后我们为第二个视频流(即封面图片)设置disposition为attached_pic。 但是,这个命令会移除第一个输入中所有流的disposition,包括可能存在的默认流标记(比如默认音频流)。所以我们需要更精确的控制。 另一种方法:我们可以先复制所有流,然后仅移除原视频中已经存在的封面流的disposition。但是,我们不知道哪个流是封面流。因此,我们可以使用复杂过滤器来移除所有封面流的disposition,但这样更复杂。 实际上,我们也可以不管原有的封面流,因为当添加一个新的封面流并设置disposition时,播放器或文件浏览器可能会使用最新的(或者第一个)封面流。但为了确保唯一性,我们可以先删除原封面流。 考虑到简单性,我们推荐用户使用以下方法: 如果原视频没有封面,使用第一个简单命令;如果有,我们可以先提取原视频内容(不含封面流),然后再添加封面。但这样需要重新编码吗?不需要,我们可以复制流。 我们可以使用: ```bash ffmpeg -i input.mp4 -i cover.jpg -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic output.mp4 ``` 这个命令会保留原视频的所有流(包括可能存在的封面流),然后添加一个新的封面流。这样文件里会有两个封面流,这可能会导致混乱。 所以,更安全的方法是:只保留原视频的非封面流,然后添加新的封面流。我们可以通过移除原视频中所有disposition为attached_pic的流,然后再添加新的封面流。但FFmpeg没有直接的方法在复制流时过滤掉封面流,因为封面流也是视频流的一种。 因此,我们可能需要使用两个步骤: 1. 移除原视频的封面流(如果有): 我们可以先使用`-map`排除disposition为attached_pic的流。但是,FFmpeg的-map不支持按disposition排除。所以我们可以使用复杂的方法:先获取流信息,然后排除,但这样不适合命令行。 2. 另一种思路:我们可以先添加封面图片作为新的封面流,然后忽略原视频中的封面流(如果我们知道它的索引)。但通常我们不知道。 鉴于以上,一个更实用的方法是:不管原视频是否有封面,我们添加的封面流都作为唯一的封面(因为我们将它设置为封面流),并且希望播放器使用我们添加的封面。如果原视频有封面,那么它也会在文件中,但可能被忽略(因为播放器通常使用第一个封面流)。所以,我们可以将新封面流放在前面,以确保它被使用。 使用`-map`可以调整流的顺序,将封面流放在最前面: ```bash ffmpeg -i input.mp4 -i cover.jpg -map 1 -map 0 -c copy -c:v:0 png -disposition:v:0 attached_pic output.mp4 ``` 这里,我们先映射封面图片(成为第一个流),然后映射原视频的所有流。这样封面流就是第一个视频流(索引0)。然后我们设置这个流的disposition为attached_pic。同时,原视频的封面流(如果有)会被映射在后面(成为第二个视频流?),并且没有设置attached_pic的disposition(因为我们只设置了第一个视频流)。注意,原视频的封面流可能已经被映射为普通视频流(没有disposition),所以不会被当作封面。 但是,原视频的封面流可能仍然保留了attached_pic的disposition?因为我们在映射0时复制了所有流,包括它们的disposition。所以我们需要移除原视频中封面流的disposition。 我们可以使用`-disposition`来覆盖原视频中封面流的disposition。但不知道索引。所以我们可以先移除所有视频流的disposition,然后只设置我们添加的封面流的disposition。 命令: ```bash ffmpeg -i input.mp4 -i cover.jpg -map 1 -map 0 -c copy -c:v:0 png -disposition:v:0 attached_pic -disposition:v:1 0 output.mp4 ``` 解释:`-disposition:v:1 0` 表示将第二个视频流(索引1)的disposition清除(设置为0)。这样,原视频的封面流(如果有)就会失去封面标记,而我们的封面流(第一个视频流)是封面。 但是,如果原视频有多个视频流,我们可能不知道哪个是封面流。所以我们可以清除所有原视频流的disposition,然后只设置我们添加的封面流的disposition。注意,原视频流可能包含多个视频流(比如多个角度),但我们通常只保留一个主视频流。所以,我们可以: 1. 清除所有原视频流的disposition(包括视频流和其他流?但我们只关心视频流)。 2. 设置我们添加的封面流的disposition。 但注意,清除原视频流的disposition可能会影响默认流(比如默认音频流)。所以我们需要谨慎。 因此,我们推荐一个折中方案:先尝试添加封面,如果原视频有封面,那么它可能不会被覆盖(因为文件中有两个封面流),但我们可以调整顺序并清除原封面流的disposition。但是,如果我们不知道原封面流的索引,我们可以清除所有视频流的disposition(除了我们添加的封面流)。 命令: ```bash ffmpeg -i input.mp4 -i cover.jpg -map 1 -map 0 -c copy -c:v:0 png -disposition:v:0 attached_pic -disposition:v -0 output.mp4 ``` 注意:`-disposition:v -0` 这个写法并不存在。实际上,FFmpeg不支持按索引范围清除disposition。 所以,我们只能按索引清除。如果我们知道原视频只有一个视频流(索引0),那么原视频的封面流(如果有)就是那个视频流?不对,封面流是一个单独的视频流(通常分辨率很小,只有一帧)。所以原视频可能有两个视频流:一个是主视频流,一个是封面流。 因此,我们可以这样:先清除原视频中所有视频流的disposition(但注意,主视频流可能有默认disposition,我们不想清除默认disposition,只想清除封面disposition)。这很难。 鉴于以上,我们建议用户使用以下方法,它适用于大多数情况,即使原视频有封面,也会被新封面替换(因为新封面流是第一个视频流,并且我们清除了原视频中所有视频流的封面标记,同时保留了其他disposition): ```bash ffmpeg -i input.mp4 -i cover.jpg \ -map 0:v? -map 0:a? -map 0:s? -map 1 \ -disposition:v:0 attached_pic \ -c copy -c:v:0 png \ output.mp4 ``` 解释: - `-map 0:v?`:映射原视频的所有视频流(如果存在)。 - `-map 0:a?`:映射原视频的所有音频流(如果存在)。 - `-map 0:s?`:映射原视频的所有字幕流(如果存在)。 - `-map 1`:映射封面图片。 - `-c copy`:复制所有流(除了我们后面指定的)。 - `-c:v:0 png`:将第一个视频流(即封面图片)编码为PNG(因为封面图片被映射为第一个视频流)。 - `-disposition:v:0 attached_pic`:将第一个视频流(封面图片)设置为封面。 注意:这个命令中,原视频的封面流(如果有)会被包含在`0:v`中,但它的disposition没有被清除,所以它可能仍然有attached_pic标记。但是,我们只设置了第一个视频流的disposition(封面),而原视频的封面流在后面的视频流中。所以我们需要清除原视频中封面流的disposition。然而,我们不知道原视频封面流在`0:v`中的哪个索引。 所以,我们可以在映射原视频流时,使用`-disposition`将所有视频流的disposition清除,然后再单独设置封面流的disposition。但这样会清除所有视频流的disposition(包括默认标记),可能会影响播放。 因此,我们换一个思路:我们只添加封面流,并设置它为封面,同时保留原视频的所有流(包括原封面流),但是将原封面流的disposition清除。我们可以通过索引来清除,但不知道索引。所以我们可以先映射封面图片,然后映射原视频,并清除原视频中所有视频流的封面disposition(只保留我们添加的封面)。 命令: ```bash ffmpeg -i input.mp4 -i cover.jpg \ -map 1 -map 0 \ -c copy -c:v:0 png \ -disposition:v:0 attached_pic \ -disposition:v:1:0 # 这个命令不正确,无法清除所有后续视频流的disposition ``` 实际上,我们可以使用`-disposition`多次,为每个视频流清除attached_pic。例如,如果我们知道原视频有两个视频流(主视频流和封面流),我们可以: ```bash -disposition:v:1 0 # 清除第二个视频流(即原视频的第一个视频流)的disposition -disposition:v:2 0 # 清除第三个视频流(即原视频的第二个视频流)的disposition ``` 但是,我们不知道原视频有多少个视频流。所以,我们无法做到。 因此,我们只能接受:原视频的封面流可能还存在,并且也有attached_pic标记,这样文件中就有两个封面流。但播放器通常只使用第一个封面流(即我们添加的)。所以,我们可以忽略原封面流。 综上所述,我们推荐用户使用以下命令(简单且有效): ```bash ffmpeg -i input.mp4 -i cover.jpg -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic output.mp4 ``` 这个命令将封面图片作为第二个视频流添加,并设置其disposition为attached_pic。原视频的封面流(如果有)会作为第一个视频流,并且可能也有attached_pic标记。但是,一些播放器或文件浏览器可能会使用第一个封面流(即原封面),一些可能会使用第二个。所以,为了确保使用新封面,我们可以将封面流放在最前面: ```bash ffmpeg -i input.mp4 -i cover.jpg -map 1 -map 0 -c copy -c:v:0 png -disposition:v:0 attached_pic output.mp4 ``` 这样,新封面流成为第一个视频流,并且被标记为封面。原视频的封面流(如果有)成为第二个视频流,并且它的disposition没有被清除,所以它也有封面标记。这样文件中就有两个封面流。但播放器通常会使用第一个封面流。 因此,我们建议使用这个命令(将封面流放在最前面)来确保它被优先使用。 注意:如果原视频的封面流在文件管理器中仍然被显示(因为有些文件管理器可能会读取所有封面流),那么用户可能需要先移除原封面流。但是,移除原封面流需要知道它是哪个流,这可以通过FFmpeg的流分析得知,然后使用`-map`排除。但这不是一个通用命令。 所以,如果用户知道原视频有封面流并想替换它,可以先移除原封面流,然后再添加新封面。但移除原封面流需要知道它的索引,我们可以通过`ffmpeg -i input.mp4`查看流信息,找到disposition为attached_pic的流,然后在命令中排除(使用`-map 0 -map 1 -map -0:v:1`来排除索引为1的视频流,假设它是封面流)。 例如,如果原封面流是0:v:1(第一个输入文件的第二个视频流),那么命令如下: ```bash ffmpeg -i input.mp4 -i cover.jpg -map 0 -map 1 -map -0:v:1 -c copy -c:v:1 png -disposition:v:1 attached_pic output.mp4 ``` 但是,我们不知道索引,所以这种方法不通用。 因此,我们提供两种方案供用户选择: 方案一(简单,适用于大多数情况): ```bash ffmpeg -i input.mp4 -i cover.jpg -map 1 -map 0 -c copy -c:v:0 png -disposition:v:0 attached_pic output.mp4 ``` 方案二(先移除原封面流,但需要用户知道封面流的索引): 假设用户通过`ffmpeg -i input.mp4`发现封面流是0:v:1,则: ```bash ffmpeg -i input.mp4 -i cover.jpg -map 0 -map 1 -map -0:v:1 -c copy -c:v:1 png -disposition:v:1 attached_pic output.mp4 ``` 注意:在方案二中,我们移除了原封面流(0:v:1),然后添加新的封面流(映射为1),并设置其disposition。注意,移除原封面流后,新封面流的索引可能会改变(因为原视频流少了一个),但我们在`-map 1`后添加的封面流会作为最后一个视频流,所以我们在`-c:v:1`中指定它的编码器,并设置disposition为attached_pic。 但是,在方案二中,新封面流的索引取决于原视频移除封面流后还剩下多少个视频流。如果我们移除了一个视频流,那么新封面流的视频流索引就是(原视频流数-1)。例如,原视频有两个视频流(0:v:0和0:v:1),我们移除了0:v:1,那么原视频只剩下0:v:0,然后我们添加封面流,这个封面流在整个输出文件的视频流中索引为1(因为0是原视频的0:v:0)。所以`-c:v:1`指定了第二个视频流(即封面流)的编码器。 因此,方案二需要用户根据实际情况调整索引。 鉴于操作的复杂性,我们通常推荐方案一。 最后,注意封面图片的格式。我们使用PNG编码,因为PNG支持透明,但也可以使用JPEG。如果封面图片已经是JPEG,我们可以使用`-c:v:0 jpeg`。但为了通用,我们使用PNG,因为PNG是无损的。 另外,如果封面图片的分辨率很大,可能会影响播放器加载缩略图的速度,建议先将封面图片调整为合适的大小(比如640x480)。 总结: 我们推荐使用以下命令(将封面放在第一个流的位置): ```bash ffmpeg -i input.mp4 -i cover.png -map 1 -map 0 -c copy -c:v:0 png -disposition:v:0 attached_pic output.mp4 ``` 如果封面图片是JPEG格式,可以: ```bash ffmpeg -i input.mp4 -i cover.jpg -map 1 -map 0 -c copy -c:v:0 mjpeg -disposition:v:0 attached_pic output.mp4 ``` 注意:使用mjpeg编码器来处理jpg图片。 但是,注意输出格式(如MP4)支持哪些编码器。MP4通常支持H.264、H.265、MPEG-4等视频编码,同时也支持mjpeg和png作为视频流。但为了兼容性,mjpeg更通用。 因此,我们通常使用mjpeg编码器来处理封面图片(无论原图是jpg还是png,都可以转成mjpeg流)。 命令: ```bash ffmpeg -i input.mp4 -i cover.jpg -map 1 -map 0 -c copy -c:v:0 mjpeg -disposition:v:0 attached_pic output.mp4 ``` 如果封面图片是png,也可以使用这个命令,因为ffmpeg会自动将png图片转换为mjpeg(但会丢失透明通道,不过封面通常不需要透明)。 所以,我们最终推荐使用mjpeg编码。 示例命令: ```bash ffmpeg -i original_video.mp4 -i cover_image.jpg -map 1 -map 0 -c copy -c:v:0 mjpeg -disposition:v:0 attached_pic output_video.mp4 ``` 注意:这个命令会快速执行,因为`-c copy`复制了所有原视频流,只有封面图片被重新编码(为mjpeg视频流),并且封面图片被放在第一个视频流的位置,并设置为封面流。 如果用户希望封面图片不影响视频流(即不添加额外的视频流),那么可以考虑将封面嵌入到元数据中,但FFmpeg对于MP4的元数据封面支持是通过视频流实现的(即attached_pic)。所以,我们添加了一个视频流,但它只包含一帧(封面图片),并且播放器在播放时不会显示它(只作为封面)。 因此,这个方法就是标准做法。 最后,我们提醒用户,如果输出文件在播放时显示封面图片,但在文件浏览器中可能不会立即更新缩略图,因为文件浏览器可能缓存了旧的缩略图。可以尝试刷新或重新打开文件夹。 如果用户需要更高级的控制(比如调整封面图片的质量),可以在编码封面流时指定质量参数,例如: ```bash -c:v:0 mjpeg -q:v 2 ``` 其中,`-q:v 2`表示质量,值越低质量越好(但文件越大),对于mjpeg,通常范围是2-31(2最好,31最差)。默认值是2?不,默认值可能是根据编码器预设的,所以我们可以指定一个质量值,比如`-q:v 1`(高质量)或`-q:v 5`(中等)。 但封面图片通常很小,所以即使高质量也不会增加太多文件大小。所以,我们可以不指定,使用默认值。 综上所述,我们给出最终命令:</think>要使用FFmpeg视频添加自定义封面,可以通过将封面图片作为独立视频流嵌入文件元数据中实现。以下是详细步骤和命令示例: ### 解决方案 #### 方法1:嵌入封面作为元数据流(推荐) ```bash ffmpeg -i input.mp4 -i cover.jpg \ -map 0 -map 1 -c copy -c:v:1 mjpeg \ -disposition:v:1 attached_pic \ output.mp4 ``` #### 方法2:替换封面(若原视频已有封面) ```bash ffmpeg -i input.mp4 -i new_cover.jpg \ -map 0 -map 1 -c copy -c:v:1 mjpeg \ -disposition:v:0 -disposition:v:1 attached_pic \ output.mp4 ``` ### 关键参数说明 1. **`-map 0 -map 1`** 映射输入文件的所有流(`0`=原视频,`1`=封面图) 2. **`-c copy -c:v:1 mjpeg`** 复制所有流,但将封面图(第2个视频流)编码为MJPEG格式(兼容性最佳) 3. **`-disposition:v:1 attached_pic`** 标记第2个视频流为封面属性 4. **`-disposition:v:0`** (仅方法2)清除原视频的封面标记 ### 验证结果 ```bash ffprobe -show_streams -select_streams v output.mp4 | grep "disposition=attached_pic" ``` 应输出包含`attached_pic`的流信息,例如: ```bash disposition=attached_pic ``` ### 注意事项 1. **格式兼容性** MP4/MKV等容器支持此操作,FLV/WMV可能不兼容 2. **封面尺寸建议** 分辨率不超过1920×1080,文件大小<300KB以确保兼容性 3. **播放器支持** 文件管理器/主流播放器(VLC, MPC-HC)会优先显示`attached_pic`流作为封面 4. **编码选择** 优先使用`mjpeg`而非`png`,因部分设备对PNG封面支持有限[^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码农飞飞

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

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

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

打赏作者

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

抵扣说明:

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

余额充值