使用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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章