使用ffmpeg制作时光影集

目前QQ、剪影等都有照片制作成视频的功能。研究一段时间,始终不得要点。目前能实现的方式有h5动感影集、webv格式视频以及传统的ffmpeg进行照片合成剪辑。H5动感影集没办法导出成视频、webv对于视频的编辑依托于js。因此最终选择了利用ffmpeg来实现。由于语言使用的是C#,所以只能利用windows命令来调用。如果使用nodejs,可以使用封装好的方法fluent-ffmpeg。
对于ffmpeg的各类命令,可以在网上搜索出来。但是大都是满足某一场景,最好还是自己研究参数。进入ffmpeg的官网,里面对每一个属性都有说明和示例。http://ffmpeg.org/ffmpeg-all.html
本示例实现的是多张照片合成一个视频。照片实现的效果有渐入渐出、放大、移动、模糊处理,视频可以添加背景音乐。整体思路是,读取某一文件夹中的所有照片,逐个加入ffmpeg动效参数,然后拼接成一个长的命令字符串,使用Process命令行调用ffmpeg执行该命令。
具体效果如下:
核心代码如下:

     public static string GetCommand(string[] files)
{
    //string[] files = Directory.GetFiles("d:/yb/ffmpeg/pic/", "*.jpg");
    StringBuilder sbFile = new StringBuilder();
    StringBuilder sbFilter = new StringBuilder();
    StringBuilder sbConcat = new StringBuilder();
    int w = 540;
    int h = 720;
    int second = 4;
    for (int i = 0; i < files.Length; i++)
    {
        sbFile.Append(string.Format("-i {0} ", files[i]));
        Image img = Image.FromFile(files[i]);
        int th = img.Height * w / img.Width;
        int offset = (second - 1) * i;
        string fade = string.Empty;
        if (offset > 0)
        {
            fade = string.Format(",fade =in:d = 1:alpha = 1,setpts = PTS - STARTPTS + {0} / TB", offset);
        }

        // 如果是宽图片,则需要添加模糊背景,采用横向滚动的方式
        if (th < h * 0.8)
        {
            sbFilter.Append(string.Format(" [{0}]zoompan=d={1}:s={2}x{3}, boxblur=10{4}[bg{5}];", i, second * 25, w, h, fade, i));
            sbFilter.Append(string.Format("[{0}]zoompan=z='{1}':x='if(lte(on,-1),(iw-iw/zoom)/2,x+{2})':d={3}:s={4}x{5}{6}[v{7}];", i, 1.5, (1.5 - 1) * w / ((second+1) * 25), second * 25, w, th, fade, i));
            if (i > 0)
            {
                sbConcat.Append(string.Format("[c{0}][bg{1}]overlay[cc{2}];", i - 1, i, i));
                sbConcat.Append(string.Format("[cc{0}][v{1}]overlay=y=(H-h)/2[c{2}];", i, i, i));
            }
            else
            {
                sbConcat.Append(string.Format("[bg0][v0]overlay=y=(H-h)/2[c0];"));
            }
        }
        else
        {
            //长图,假设比例合适
            //sbFilter.Append(string.Format(" [{0}]zoompan=d={1}, boxblur=10{2}[bg{3}];", i, second * 25, fade, i));
            //sbFilter.Append(string.Format("[{0}]zoompan=z='{1}':x='if(lte(on,-1),(iw-iw/zoom)/2,x+{2})':d={3}:s={5}x{6}{7}[v{8}];", i, 1.3, (1.3 - 1) * w / (second + 1), second * 25, w, th, fade, i));
            string[] effects = { "z='min(max(zoom,pzoom)+0.0015,1.5)'", "z='if(lte(zoom,1.0),1.5,max(1.001,zoom-0.0015))':y='ih*(1-max(zoom,pzoom))'", "z='1.5':x='if(lte(on,-1),(iw-iw/zoom)/2,x+1.25)'", "z='1.5':y='if(lte(on,-1),(ih-ih/zoom)/2,y+1.25)'" };
           // Random rn = new Random();
            string effect = effects[i%4];
            sbFilter.Append(string.Format(" [{0}] zoompan =d = {1}:{2}:s={3}x{4}{5}[{6}];", i, 125, effect, w, h, fade, i == 0 ? "c0" : "v" + i));
            if (i > 0)
            {
                sbConcat.Append(string.Format("[c{0}][v{1}]overlay[c{2}];", i - 1, i, i));
            }
        }
    }
    sbFile.Append("-i d:/yb/ffmpeg/music/02.mp3 ");
    string concat = sbConcat.ToString();
    concat = concat.Substring(0, concat.LastIndexOf('['));
    string result = string.Format("-y {0} -filter_complex \"{1} {2}, format=yuv420p[v]\"  -map \"[v]\"  -map {3}:a -shortest -movflags +faststart {4}", sbFile.ToString(), sbFilter.ToString(), concat, files.Length, "d:/yb/ffmpeg/video/" + DateTime.Now.ToString("HHmmss") + ".mp4");
    return result;
}

重点参数解释:
模糊化效果
string.Format(" [{0}]zoompan=d={1}:s={2}x{3}, boxblur=10{4}[bg{5}];", i, second * 25, w, h, fade, i)
[0]:代表操作第一个图片;
[bg0]:代表将[0]第一个图片做成的视频命名为bg0;
zoompan:主要使用该属性来实现效果,d为总帧数,默认的fps为25帧,如果要设置一个5s的效果,那么d就可以设置为125;当然如果为了提高流畅度,可以这样设置一个5s的效果zoompan=d=300:fps=60; s代表第一个照片输出的尺寸,固定尺寸后可以放大再 进行移动。以上的命令字符串代表让第n个照片boxblue模糊后作为底层;
sbFilter.Append(string.Format(" [{0}]zoompan=d={1}:s={2}x{3}, boxblur=10{4}[bg{5}];", i, second * 25, w, h, fade, i));
sbFilter.Append(string.Format("[{0}]zoompan=z=’{1}’:x=‘if(lte(on,-1),(iw-iw/zoom)/2,x+{2})’:d={3}:s={4}x{5}{6}[v{7}];", i, 1.5, (1.5 - 1) * w / ((second+1) * 25), second * 25, w, th, fade, i));
let:小于等于;gte:大于等于。
将图片首先以背景模糊输出,然后在同一时间段覆盖上图片动效。效果如下:
在这里插入图片描述
sbConcat.Append(string.Format("[c{0}][bg{1}]overlay[cc{2}];", i - 1, i, i));
sbConcat.Append(string.Format("[cc{0}][v{1}]overlay=y=(H-h)/2[c{2}];", i, i, i));
合并视频,此处采用的是overlay覆盖合并,concat是顺序合并。将c0视频覆盖在bg0视频上,合并后的视频命名为cc0;将cc0视频合并到v0视频上,位置是垂直居中;
fade = string.Format(",fade =in:d = 1:alpha = 1,setpts = PTS - STARTPTS + {0} / TB", offset);
fade是渐入渐出的控制;in/out渐入/减出;d=1为渐变时间持续1s;setpts 是为了让第一个视频渐出的时间和第二个视频渐入的时间进行重叠,不至于突然变黑很突兀。setpts = PTS - STARTPTS + {0} / TB,offset是第二个视频渐入的时间,比如两个5s的视频,该值应该这是为4,在第4秒进行渐入;
代码可在此处下载https://download.csdn.net/download/wuwo333/12500865

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值