ffmpeg 各种视频特效 | 教程

ffmpeg命令行初学可以多使用使用“格式工厂”,格式工厂的底层是ffmpeg操作的所有步骤,都可以通过“选项-内部-open log”,
找到想要的命令行。无论是编码格式,视频拼接,视频裁剪,音频分离,混流,图片处理等等,都是比较好的处理方式。

在视频处理去重方面,可以使用CR VideoMate他的底层也是基于ffmpeg,熟悉软件的处理流程后,
可以“点击右下角-帮助-数据文件夹”找到ffmpeg的命令行log,参考学习。

字幕文件大部分都使用srt但实际ass更适用于做字幕特效,参数也会更多,使用起来比较困难,可以借助aegisub工具,
生成ass字幕文件,其中也内嵌了很多的特效和一些字体等等使用方法。

其他ffmpeg的界面化软件FFmpeg Batch AV Converter、WinFF、QWinFF、FFmpegYAG、Axiom、本人使用都不是很好用,
如果有大佬有更好的推荐,可以在评论区留言。谢谢

ffmpeg gl-transitions 图片合成视频 转场特效

插件本身支持 GPU 加速功能,需要用到 EGL 安装模式,本案例没有使用 EGL,部署环境为 Ubuntu 20.04
安装 :

sudo apt-get -y install gcc g++ make xorg-dev pkg-config  libglew-dev libglfw3-dev nasm yasm libx264-dev libx265-dev libvpx-dev libglu1-mesa-dev libmp3lame-dev libopus-dev libfdk-aac-dev

cd ~
git clone https://github.com/transitive-bullshit/ffmpeg-gl-transition.git
cd ffmpeg-gl-transition
git clone https://github.com/gl-transitions/gl-transitions.git
cd ..
wget https://www.ffmpeg.org/releases/ffmpeg-4.4.4.tar.gz
tar -zxvf ffmpeg-4.4.4.tar.gz
无法直接使用ffmpeg.diff
1. 拷贝vf_gltransition.c到libavfilter,将以下注释掉
#ifndef __APPLE__
# define GL_TRANSITION_USING_EGL // remove this line if you don't want to use EGL
#endif
2. 在libavfilter/Makefile里加入
OBJS-$(CONFIG_GLTRANSITION_FILTER)           += vf_gltransition.o
3. 在libavfilter/allfilters.c加入
extern AVFilter ff_vf_gltransition;
修改完后开始编译:
请查看下边的编译命令./configure
make -j
sudo make install
sudo apt-get -y install xvfb
安装完成!!!!

验证:ffmpeg——————————————证明安装成功
在这里插入图片描述
查看视频编码格式

ffprobe file.mp4 -show_streams -select_streams v -print_format json 

改变视频编码为h264

ffmpeg -i input.mp4 -c:v libx264 out.mp4
需要指定 H264规范中的 Main 或者 Baseline 时:
ffmpeg -i input.mp4 -c:v libx264 -profile:v main -pix_fmt yuv420p out.mp4

试用了ffmpeg gl-transitions之后发现ffmpeg4.3以后自带的xfade也是很好用的(这个一定要注意,两个视频的 !帧率必须相同!)

ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v][1:v]xfade=transition=pixelize:offset=2.7s:duration=1s" -c:v libx264 -r 15 -y output.mp4

两张图片合成一张图片

ffmpeg -re -i input1.jpg -re -i input2.jpg  -filter_complex "nullsrc=size=7680x4320 [base];[0:v] setpts=PTS-STARTPTS,scale=3840x2160 [upperleft];[1:v] setpts=PTS-STARTPTS, scale=3840x2160 [upperright]; [base][upperleft] overlay=shortest=1 [tmp1]; [tmp1][upperright] overlay=shortest=1:x=3840" -y output.jpg

视频贴到指定图像上,且视频可以指定缩放宽高

ffmpeg -loop 1 -i input1.jpg -i input2.mp4 -filter_complex "[1] scale=视频缩放宽度:-1 ,[0] overlay=X位置:Y位置:shortest=1,format=yuv420p" -y output.mp4

添加音频,指定视频持续时间(不指定,音频时长大于视频时长,后边都是黑屏)
音频时长可以用:1.图片合成视频时 duration=len(img)/fps 2.使用FFprobe获取视频时间duration

图片合成视频添加声音(必须指定视频时间):
ffmpeg -f image2 -r 帧数 -i %04d.jpg -i 背景音乐  -t 视频时间 -y output.mp4
视频直接添加声音(这个方法不用指定视频时间):
ffmpeg -i 视频 -i 背景音乐 -filter_complex " [1:0] apad " -shortest -y output.mp4

图像平移生成视频

从左到右
ffmpeg -y -i input.jpg -vf "zoompan='1.5':x='if(lte(on,-1),(iw-iw/zoom)/2,x+3)':y='if(lte(on,1),(ih-ih/zoom)/2,y)':d=150"  out.mp4
从右到左
ffmpeg -y -i input.jpg -vf "zoompan='1.5':x='if(lte(on,1),(iw/zoom)/2,x-3)':y='if(lte(on,1),(ih-ih/zoom)/2,y)':d=150"  out.mp4
从上到下
ffmpeg -y -i input.jpg -vf "zoompan='1.5':x='if(lte(on,1),(iw-iw/zoom)/2,x)':y='if(lte(on,-1),(ih-ih/zoom)/2,y+2)':d=150"  out.mp4
从下到上
ffmpeg -y -i input.jpg -vf "zoompan='1.5':x='if(lte(on,1),(iw-iw/zoom)/2,x)':y='if(lte(on,1),(ih/zoom)/2,y-2)':d=150"  out.mp4

从左上到右下
ffmpeg -y -i input.jpg -vf "scale=1920x1080,zoompan='1.2':x='if(lte(on,-1),(iw-iw/zoom)/2,x+2)':y='if(lte(on,-1),(ih-ih/zoom)/2,y+1)':d=50:s=1920x1080"  out.mp4
从右下到左上
ffmpeg -y -i input.jpg -vf "scale=1920x1080,zoompan='1.2':x='if(lte(on,1),(iw/zoom)/2,x-3)':y='if(lte(on,1),(ih-ih/zoom)/2,y-2)':d=50:s=1920x1080"  out.mp4

截取视频片段

-ss 开始时间 -to 结束时间 -i input.mp4
缺点:裁剪时间不准确,帧率会根据原视频进行剪切和拼接其他视频,导致剪切后的视频与其他视频拼接时,时间对应不上
优点:处理速度快,写法简单

trim=start=开始时间:end=结束时间,fps=帧率,setpts=PTS-STARTPTS
缺点:处理速度很慢
优点:解决了上边的缺点
如果视频较大,且视频时长较长,最好还是先将分辨率与帧率转成一致,再进行截取+拼接,处理。

视频画中画

ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[1]scale=iw-60:ih-60[pip];[0][pip]overlay=main_w-overlay_w-30:main_h-overlay_h-30" -y -q:v 1 -max_muxing_queue_size 1024 "out.mp4"

Python 调用ffmpeg方法:

import subprocess
str_cmd = ' -i 视频 -y output.mp4'
subprocess.call('ffmpeg '+str_cmd,shell=True)

Android调用方法:

form ... import FFmpegKit
str_cmd = ' -i 视频 -y output.mp4'
FFmpegKit.execute(str_cmd)

python ffmpeg 处理视频后合成视频(带音频)


import numpy as np
from tqdm import tqdm
import random
import time
import ffmpeg # ffmpeg-python

def get_video_meta_info(video_path):
    ret = {}
    probe = ffmpeg.probe(video_path)
    video_streams = [stream for stream in probe['streams'] if stream['codec_type'] == 'video']
    has_audio = any(stream['codec_type'] == 'audio' for stream in probe['streams'])
    ret['width'] = video_streams[0]['width']
    ret['height'] = video_streams[0]['height']
    ret['fps'] = eval(video_streams[0]['avg_frame_rate'])
    ret['audio'] = ffmpeg.input(video_path).audio if has_audio else None
    ret['nb_frames'] = int(video_streams[0]['nb_frames'])
    return ret

def Writer (audio, out_height, out_width, video_save_path, fps):
    if audio is not None:
        stream_writer = (
            ffmpeg.input('pipe:', format='rawvideo', pix_fmt='bgr24', s=f'{out_width}x{out_height}',
                            framerate=fps).output(audio,video_save_path,
                            pix_fmt='yuv420p',vcodec='libx264',loglevel='error',acodec='copy',r=30)
                            .overwrite_output().run_async(pipe_stdin=True, pipe_stdout=True, cmd='ffmpeg'))
    else:
        stream_writer = (
            ffmpeg.input('pipe:', format='rawvideo', pix_fmt='bgr24', s=f'{out_width}x{out_height}',
                            framerate=fps).output(video_save_path,
                            pix_fmt='yuv420p', vcodec='libx264',loglevel='error',r=30)
                            .overwrite_output().run_async(pipe_stdin=True, pipe_stdout=True, cmd='ffmpeg'))
    return stream_writer


input_vid = '1.mp4'
video_save_path = 'results/'+str(random.randint(0,100))+str(int(time.time()*1000000))+'.mp4'
stream_reader = (ffmpeg.input(input_vid).output('pipe:',format='rawvideo', pix_fmt='bgr24',loglevel='error')
                                        .run_async(pipe_stdin=True, pipe_stdout=True, cmd='ffmpeg'))

meta = get_video_meta_info(input_vid) # 获取视频参数,宽/高/帧率/音频/总帧数
width = meta['width']
height = meta['height']
fps = meta['fps']
audio = meta['audio']
nb_frames = meta['nb_frames']

stream_writer = Writer(audio, height, width, video_save_path, fps)

pbar = tqdm(total=nb_frames, unit='frame', desc='inference')
while True:
    img_bytes = stream_reader.stdout.read(width * height * 3)  # 3 bytes for one pixel
    if not img_bytes: break
    img = np.frombuffer(img_bytes, np.uint8).reshape([height, width, 3])

    print('infer for your image')
    stream_writer.stdin.write(img.astype(np.uint8).tobytes())
    pbar.update(1) # 更新进度条

stream_writer.stdin.close()
stream_writer.wait()

ffmpeg 使用gpu 加速解码

编译:
./configure --pkg-config-flags="--static" --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64 --extra-libs=-lpthread --extra-libs=-lm --enable-gpl --enable-libfdk_aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-nonfree --enable-cuda --enable-cuvid --enable-nvenc --enable-libnpp --enable-openssl --enable-libass --enable-libfdk-aac --enable-libtheora --enable-libxvid --enable-opengl --enable-filter=gltransition --extra-libs='-lGLEW -lglfw -ldl' --enable-pthreads

prefix编译出的ffmpeg位置(可以不选,直接安装到系统默认位置)(注意:如果选择了安装路径可能使用进程守护时会出问题)
openssl网络图片下载,libass添加字幕,pthreads允许使用多线程
extra-cflags和extra-ldflags是cuda路径
--enable-opengl --enable-filter=gltransition --extra-libs='-lGLEW -lglfw -ldl'是gltransition转场,如果想使用GPU转场更换为--extra-libs='-lGLEW -lEGL',需要EGL才能使用GPU。
如果需要使用xfade做转场特效并且使用里面所有的特效,请下载最新的代码并进行编译才可以获得,可以在libavfilter/vf_xfade.c查看
make
sudo make install 
export PATH=$PATH:/usr/local/ffmpeg/bin
export LD_LIBRARY_PATH=/usr/local/ffmpeg/lib:$LD_LIBRARY_PATH 
命令中使用GPU编码:-c:v h264_nvenc
卸载ffmpeg,去编译目录下sudo make uninstall
cpu:libx264   NVIDIA:h264_nvenc    AMD:h264_amf    Intel:h264_qsv

创建画布

-f lavfi -i color=#123000:s=368x640 虚拟color背景368x640幕布做音频背景输入

opencv+ffmpeg

import numpy as np
import random
import time
import cv2
import ffmpeg # ffmpeg-python

camera=cv2.VideoCapture('rtsp://admin:123456789.@192.168.2.43/MPEG-4/ch1/main/av_stream') # 网络摄像头,也可以使用本地0或1
video_size = (int(camera.get(cv2.CAP_PROP_FRAME_WIDTH)),int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT))) # 获取摄像头w,h
fps = camera.get(cv2.CAP_PROP_FPS) # 获取摄像头帧率 !!!!!!!!!!

video_save_path = 'results/'+str(random.randint(0,100))+str(int(time.time()*1000000))+'.mp4'
stream_writer = (
    ffmpeg.input('pipe:', format='rawvideo', pix_fmt='bgr24', s=f'{video_size[0]}x{video_size[1]}',
                    framerate=fps).output(video_save_path,
                    pix_fmt='yuv420p', vcodec='libx264',loglevel='error',r=30)
                    .overwrite_output().run_async(pipe_stdin=True, pipe_stdout=True, cmd='ffmpeg'))

while(True):
    ret,frame=camera.read()
    if not ret: break
    print('infer for your image')
    stream_writer.stdin.write(frame.astype(np.uint8).tobytes())


stream_writer.stdin.close()
stream_writer.wait()

ffmpeg 特效

# 使用裁剪,实现了,上下左右的,拖拽移动
ffmpeg -i in.mp4 -vf crop="in_w/2:in_h/2:(in_w-out_w)/2+((in_w-out_w)/2)*sin(n/10):(in_h-out_h)/2+((in_h-out_h)/2)*sin(n/7)" out.mp4  
# 

ffmpeg 找不到路径或缺少依赖

进入安装目录下 /usr/local/ffmpeg,由于没有配置ffmpeg环境变量,此时执行./ffmpeg会提示各种so链接库找不到。
sudo gedit /etc/ld.so.conf
添加到文件尾行
/usr/local/ffmpeg/lib
执行 sudo ldconfig
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值