利用 FFmpeg 將 MP4 轉成 FLV

最近作一個小項目,要在線播放錄製的 MP4 視頻,想開源的 flash player 或 html 5 能夠播放。可,雖然 MP4 是 H.264 編碼,但就是播放不了。多是封裝方式(PS 方式)不同吧。因爲錄製用的第三方設備,不能修改參數,只能本身使用工具轉碼了。css

FFmpeghtml

網上一搜索,就找到了大名鼎鼎的 FFmpeg ,好像 google 的 youtube 後臺也是用的這個轉碼,國內的不少視頻播放器核心也是這個。有了這個實現起來就很是簡單了。FFmpeg 轉碼時佔用 CPU 很高,能夠到 100%,也不知道該怎麼解決此問題。轉碼只要一條指令就好了:前端

ffmpeg.exe -i source.mp4 -c:v libx264 -crf 24 destination.flv

這是最簡單的設置,更多能夠去官網看詳細的參數,其中 -crf 很重要,是控制轉碼後視頻的質量,質量越高,文件也就越大。git

The range of the quantizer scale is 0-51: where 0 is lossless, 23 is default, and 51 is worst possible. A lower value is a higher quality and a subjectively sane range is 18-28. Consider 18 to be visually lossless or nearly so: it should look the same or nearly the same as the input but it isn't technically lossless.github

官網的解釋(翻譯):瀏覽器

此值的範圍是 0 到 51:0 表示高清無損;23 是默認值(若是沒有指定此參數);51 雖然文件最小,但效果是最差的。less

值越小,質量越高,但文件也越大,建議的值範圍是 18 到 28。而值 18 是視覺上看起來無損或接近無損的,固然不表明是數據(技術上)的轉碼無損。ide

Coding:工具

實現起來也是很簡單,只要使用 Processs 後臺轉碼就行,請看 FfmpegHelper :google

 1 using System;
 2 using System.Configuration;
 3 using System.IO;
 4 // reference https://github.com/LeafDuan/WebPrint/tree/master/WebPrint.Framework
 5 using WebPrint.Framework;
 6 // reference https://github.com/LeafDuan/WebPrint/tree/master/WebPrint.Logging
 7 using WebPrint.Logging;
 8 
 9 namespace WebPrint.CameraServer.Helper
10 {
11     public class FfmpegHelper
12     {
13         private static readonly ILogger Logger = LoggerHelper.GetLogger(typeof (FfmpegHelper));
14 
15         private static string Ffmpeg
16         {
17             get { return ConfigurationManager.AppSettings["ffmepg"]; }
18         }
19 
20         private static string Args
21         {
22             get { return ConfigurationManager.AppSettings["args"]; }
23         }
24 
25         private static string FlvPath
26         {
27             get { return ConfigurationManager.AppSettings["flv"]; }
28         }
29 
30         public static string DecodeMp4ToFlv(string mp4, int timeout = 0)
31         {
32             var ffmpeg = "\"{0}\"".Formatting(Ffmpeg);
33             var flv = Path.Combine(FlvPath, (Path.GetFileNameWithoutExtension(mp4) ?? string.Empty) + ".flv");
34             var args = Args.Formatting("\"{0}\"".Formatting(mp4), "\"{0}\"".Formatting(flv));
35             string output, error;
36             if (timeout <= 0)
37                 timeout = 5*60*1000; // timeout = 5 minutes
38             ProcessHelper.Process(ffmpeg, args, timeout, out output, out error);
39             if (!error.IsNullOrEmpty())
40             {
41                 Logger.Error("{0}{1} : {2}{0}".Formatting(Environment.NewLine, "FFmpeg", error));
42             }
43 
44             return flv;
45         }
46     }
47 }
View Code

卻是其中 Process 的實現須要技巧,尤爲是針對 output、error 和 timeout 的處理。若是不使用 AutoResetEvent ,process 很容易卡死在 error output 上(IO blocked)。其中針對超時,作了一個處理,就是 kill 掉 process ,省得引發資源霸佔和泄露(過多 ffmpeg 進程)。

附:Flash 推薦

能夠轉碼成 html 5 支持的 H.264,也能夠其餘格式,如 flv。爲了兼容 IE6 及以上瀏覽器,只能使用 flash 播放的方式了。使用的是開源的 vcastr22.swf,可能因爲開源,項目如今沒有人維護了。

最後吐槽一句:盼 IE9 如下的版本早日壽終正寢。爲了隨窗口以 16:9 的尺寸自動縮放,兼容 IE六、7 的 css 和 js 是寫得累死了。由於非專業前端,找資料都累死了。

感謝

感謝 @eflay 的解決思路,「經過轉封裝的方式,以複製的效率實現MP4轉FLV」。本人不是很懂這些視頻的編碼,所以沒有想到這麼好的解決方式。

同時也找到了一篇很好的解決這個問題的文章 h264格式的flv和mkv無損轉換成mp4的方法

相關文章
相關標籤/搜索