1、FFmpeg下载
1)Windows 64位
下载地址:https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20190107-e9564f7-win64-static.zip
2)Windows 32位
下载地址:https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20190107-e9564f7-win32-static.zip
3)MacOS 64位
下载地址:https://ffmpeg.zeranoe.com/builds/macos64/static/ffmpeg-20190107-e9564f7-macos64-static.zip
2、Linux下安装
其它系统中下载下来可以直接使用,Linux下需要安装一下,具体步骤如下,
安装依赖包:
yum install libtheora-devel libvorbis-devel
FFmpeg编译安装:
由于系统不同,会导致依赖也不尽相同,需根据报错信息逐渐安装依赖
wgethttp://ffmpeg.org/releases/ffmpeg-3.3.2.tar.bz2
tar jxvf ffmpeg-3.3.2.tar.bz2
cd ffmpeg-3.3.2
# 如下是个人需要的编译参数,可以根据实际情况增减
./configure --prefix=/usr/local/ffmpeg \
--enable-shared \
--enable-libfdk-aac \
--enable-gpl \
--enable-nonfree \
--enable-postproc \
--enable-avfilter \
--enable-pthreads \
--enable-libmp3lame \
--enable-libtheora \
--enable-libvorbis \
--enable-libx264 \
--enable-libxvid \
--enable-decoder=libx264 \
--enable-encoder=libx264
安装FFmpeg
make && make install
安装后,查看版本
./bin/ffmpeg -version
3、使用FFmpeg转换代码
1)读取视频文件和输出帧Jpeg图片(不涉及管道或内存/文件流)
string str_MyProg = "C:/FFmpeg/bin/ffmpeg.exe"; string VideoPath = "C:/someFolder/test_vid.mp4"; string save_folder = "C:/someOutputFolder/"; //#设置参数以直接输出图像序列(帧) string str_CommandArgs = "-i " + VideoPath + " -vf fps=25/1 " + save_folder + "n_%03d.jpg"; //the n_%03d replaces "n++" count System.Diagnostics.ProcessStartInfo cmd_StartInfo = new System.Diagnostics.ProcessStartInfo(str_MyProg, str_CommandArgs); cmd_StartInfo.RedirectStandardError = false; //set false cmd_StartInfo.RedirectStandardOutput = false; //set false cmd_StartInfo.UseShellExecute = true; //set true cmd_StartInfo.CreateNoWindow = true; //don't need the black window //创建一个进程,分配它的ProcessStartInfo并启动它 System.Diagnostics.Process cmd = new System.Diagnostics.Process(); cmd.StartInfo = cmd_StartInfo; cmd.Start();
2)管道方法
using System; using System.IO; using System.Net; using System.Drawing; using System.Diagnostics; using System.Collections.Generic; namespace FFmpeg_Vid_to_JPEG //replace with your own project "namespace" { class Program { public static void Main(string[] args) { ExtractFrames(); } public static void ExtractFrames() { string FFmpegPath = "C:/FFmpeg/bin/ffmpeg.exe"; string VideoPath = "C:/someFolder/test_vid.mp4"; //# FFmpeg 使用命令参数 string str_myCommandArgs = "-i " + VideoPath + " -f image2pipe -c:v mjpeg -q:v 2 -vf fps=25/1 pipe:1"; //# 保存图片路径 string save_folder = "C:/someOutputFolder/"; string save_filename = ""; MemoryStream mStream = new MemoryStream(); //创建一次,循环相同的每帧 bool got_current_JPG_End = false; //标记开始提取流中的图像字节 int pos_in_Buffer = 0; //缓冲区中的pos(在检查Jpeg开始/结束字节时) int this_jpeg_len = 0; // 保存单个jpeg图像字节以保存…长度正确,避免裁切效果 int pos_jpeg_start = 0; int pos_jpeg_end = 0; //在整个流中标记一个图像的开始/结束pos int jpeg_count = 0; //导出Jpeg文件的计数(替换“n++”计数) int frames_expected_Total = 0; //停止前要获得的帧数 //# 使用输入视频的宽度x高度作为缓冲区大小 //eg: size 921600 = 1280 W x 720H int BufferSize = 921600; byte[] buffer = new byte[BufferSize + 1]; // 创建一个进程,分配它的ProcessStartInfo并启动它 ProcessStartInfo cmd_StartInfo = new ProcessStartInfo(FFmpegPath, str_myCommandArgs); cmd_StartInfo.RedirectStandardError = true; cmd_StartInfo.RedirectStandardOutput = true; //设置为true将进程stdout重定向到进程。StandardOutput StreamReader cmd_StartInfo.UseShellExecute = false; cmd_StartInfo.CreateNoWindow = true; //不创建黑窗口 Process cmd = new System.Diagnostics.Process(); cmd.StartInfo = cmd_StartInfo; cmd.Start(); if (cmd.Start()) { //# holds FFmpeg output bytes stream... var ffmpeg_Output = cmd.StandardOutput.BaseStream; //replaces: fStream = cmd.StandardOutput.BaseStream as FileStream; cmd.BeginErrorReadLine(); //# 开始接收FFmpeg输出字节流 //# 获取(读取)流中的前两个字节,因此可以检查jpeg的SOI (xFF xD8) //#每个“读取”自动前进读取“数量”… ffmpeg_Output.Read(buffer, 0, 1); ffmpeg_Output.Read(buffer, 1, 1); pos_in_Buffer = this_jpeg_len = 2; //更新读取的pos //# 首先我们知道jpeg的SOI总是处于缓冲pos:[0]和[1] pos_jpeg_start = 0; got_current_JPG_End = false; //# testing amount... Duration 4.88 sec, FPS 25 --> (25 x 4.88) = 122 frames frames_expected_Total = 122; //122; //number of Jpegs to get before stopping. while(true) { //# 对于管道视频,您必须手动退出流 if ( jpeg_count == (frames_expected_Total + 1) ) { cmd.Close(); cmd.Dispose(); //退出进程 break; //如果获取到所需的帧jpeg数,则退出 } //#否则正常读取 ffmpeg_Output.Read(buffer, pos_in_Buffer, 1); this_jpeg_len +=1; //add 1 to expected jpeg bytes length //#查找JPEG start (SOI是字节0xFF 0xD8) if ( (buffer[pos_in_Buffer] == 0xD8) && (buffer[pos_in_Buffer-1] == 0xFF) ) { if (got_current_JPG_End == true) { pos_jpeg_start = (pos_in_Buffer-1); got_current_JPG_End = false; } } //# 查找JPEG结束符(EOI是字节0xFF 0xD9),然后保存文件 if ( (buffer[pos_in_Buffer] == 0xD9) && (buffer[pos_in_Buffer-1] == 0xFF) ) { if (got_current_JPG_End == false) { pos_jpeg_end = pos_in_Buffer; got_current_JPG_End = true; //# 更新保存的文件名 save_filename = save_folder + "n_" + (jpeg_count).ToString() + ".jpg"; try { //# 如果Jpeg保存文件夹不存在,则创建它。 if ( !Directory.Exists( save_folder ) ) { Directory.CreateDirectory( save_folder ); } } catch (Exception) { //# 处理任何文件夹创建错误在这里。 } mStream.Write(buffer, pos_jpeg_start, this_jpeg_len); // //# 保存到磁盘 File.WriteAllBytes(@save_filename, mStream.ToArray()); //recycle MemoryStream, avoids creating multiple = new MemoryStream(); mStream.SetLength(0); mStream.Position = 0; //# 下一个pic重置 jpeg_count +=1; this_jpeg_len=0; pos_in_Buffer = -1; //使其在递增部分变为0 pos } } pos_in_Buffer += 1; //增量以在stdOut流中存储下一个字节 } //# end While } else { // 这里的处理程序代码用于“进程未运行”的情况 } } //end ExtractFrame function } //end class } //end program