zoukankan      html  css  js  c++  java
  • 利用 FFmpeg 将 MP4 转成 FLV

    最近做一个小项目,要在线播放录制的 MP4 视频,想开源的 flash player 或 html 5 可以播放。可,虽然 MP4 是 H.264 编码,但就是播放不了。可能是封装方式(PS 方式)不一样吧。由于录制用的第三方设备,不能修改参数,只能自己使用工具转码了。

    FFmpeg

    网上一搜索,就找到了大名鼎鼎的 FFmpeg ,好像 google 的 youtube 后台也是用的这个转码,国内的很多视频播放器核心也是这个。有了这个实现起来就非常简单了。FFmpeg 转码时占用 CPU 很高,可以到 100%,也不知道该怎么解决此问题。转码只要一条指令就行了:

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

    这是最简单的设置,更多可以去官网看详细的参数,其中 -crf 很重要,是控制转码后视频的质量,质量越高,文件也就越大。

    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.

    官网的解释(翻译):

    此值的范围是 0 到 51:0 表示高清无损;23 是默认值(如果没有指定此参数);51 虽然文件最小,但效果是最差的。

    值越小,质量越高,但文件也越大,建议的值范围是 18 到 28。而值 18 是视觉上看起来无损或接近无损的,当然不代表是数据(技术上)的转码无损。

    Coding:

    实现起来也是很简单,只要使用 Processs 后台转码就行,请看 FfmpegHelper :

     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 的尺寸自动缩放,兼容 IE6、7 的 css 和 js 是写得累死了。因为非专业前端,找资料都累死了。

    感谢

    感谢 @eflay 的解决思路,“通过转封装的方式,以复制的效率实现MP4转FLV”。本人不是很懂这些视频的编码,因此没有想到这么好的解决方式。

    同时也找到了一篇很好的解决这个问题的文章 h264格式的flv和mkv无损转换成mp4的方法

  • 相关阅读:
    ELM学习
    《进化》从孤胆极客到高效团队
    《人件》《PeopleWare》 【美】Tom DeMarco TimothyLister 著 肖然 张逸 滕云 译
    《进化》从孤胆极客到高效团队---Notes1
    大数据第一部分LInux学习Note1
    C#Windows窗体初学
    C#初学笔记(Windows编程的基本概念)
    C#学习2017-9-26(读取文本文件和读取二进制文件)Notes9
    C#学习2017-9-26Notes8(文件和流,FileStream类)
    C#学习笔记Notes8(接口,接口实现,程序集,命名空间,using)
  • 原文地址:https://www.cnblogs.com/ranmofang/p/4390712.html
Copyright © 2011-2022 走看看