即上一篇中上传涉及到的 一个视频生成截图的问题,这个很简单,这是上一篇中的代码片段
#region 视频上传,生成默认展示图片(自动剪切) try { string fileSavePath = DateTime.Now.ToString("yyyyMMdd");//当天时间最为文件夹 string fileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");//生成的文件名称 string videoPath = Consts.VIDEOINFOSAVEPATH + fileSavePath + "/"; string gengeratedPicPath = Consts.VIDEOPICTURESAVEPATH + fileSavePath + "/"; Thread.Sleep(100); fileUpLoadVideo = Request.UpLoad(videoPath, 0, gengeratedPicPath, fileName, "480x360"); } catch (Exception ex) { fileUpLoadVideo = new FileUpLoadResult() { Status = false, FileSavePath = null, ErrorMsg = ex.Message }; } #endregion
其中红色部分就是上传和截图的实现,以下脚本是上传:
/// <summary> /// 文件上传 /// </summary> /// <param name="httpRequestBase">request</param> /// <param name="saveFilePath">文件保存路径</param> /// <param name="saveNo">如果是多文件上传,用于指定,上传第几个元素 比如 0 ,1</param> /// <returns></returns> public static FileUpLoadResult UpLoad(this HttpRequestBase httpRequestBase, string saveFilePath, int? saveNo, string generatedPicturePath, string fileName, string generatedPicSize = "480x360") { FileUpLoadResult result = new FileUpLoadResult(); if (httpRequestBase.Files.Count > 0) { if (saveNo != null) { #region 单文件上传 HttpPostedFileBase file = httpRequestBase.Files[int.Parse(saveNo.ToString())]; if (file.ContentLength > 0) { int startIndex = file.FileName.LastIndexOf(".") + 1; string fileExtension = file.FileName.Substring(startIndex, file.FileName.Length - startIndex);//获取文件文件后缀 string path = HttpContext.Current.Server.MapPath(saveFilePath + fileName + "." + fileExtension); //判断文件路径是否存在,否,重新创建 if (!Directory.Exists(HttpContext.Current.Server.MapPath(saveFilePath))) { try { Directory.CreateDirectory(HttpContext.Current.Server.MapPath(saveFilePath)); } catch { } } //file.SaveAs(path); try { Thread.Sleep(30); Stream stream = file.InputStream; byte[] b = new byte[stream.Length];//新建一个字节数组 stream.Read(b, 0, b.Length); // 设置当前流的位置为流的开始 stream.Seek(0, SeekOrigin.Begin); using (FileStream fstream = new FileStream(path, FileMode.Create, FileAccess.Write)) { fstream.Write(b, 0, b.Length); } stream.Close(); } catch { } #region MyRegion //如果是视频,生成截图 if (new string[] { "mp4", "flv" }.Contains(fileExtension)) { result.ShowImagePath = CatchImage.CatchImg(path, generatedPicturePath, fileName, generatedPicSize); if (!string.IsNullOrEmpty(result.ShowImagePath)) { //result.ShowImagePath = generatedPicturePath + title; result.Status = true; result.FileSavePath = new string[] { saveFilePath + fileName + "." + fileExtension }; result.ErrorMsg = ""; } else { try { File.Delete(path); } catch { } result.Status = false; result.FileSavePath = null; result.ErrorMsg = "生成截图失败,视频上传失败!"; } } else { result.Status = true; result.FileSavePath = new string[] { saveFilePath + fileName + "." + fileExtension }; result.ErrorMsg = "图片上传成功"; } #endregion } #endregion } else { #region 文件批量上传 string[] urllist = new string[httpRequestBase.Files.Count]; for (int i = 0; i < httpRequestBase.Files.Count; i++) { HttpPostedFileBase file = httpRequestBase.Files[i]; if (file.ContentLength > 0) { int startIndex = file.FileName.LastIndexOf(".") + 1; string fileExtension = file.FileName.Substring(startIndex, file.FileName.Length - startIndex);//获取文件文件后缀 string title = DateTime.Now.ToString("yyyyMMddHHmmssfff") + "." + fileExtension; string path = HttpContext.Current.Server.MapPath(saveFilePath) + title; //判断文件路径是否存在,否,重新创建 if (!Directory.Exists(HttpContext.Current.Server.MapPath(saveFilePath))) { try { Directory.CreateDirectory(HttpContext.Current.Server.MapPath(saveFilePath)); } catch { } } //file.SaveAs(path); try { Stream stream = file.InputStream; byte[] b = new byte[stream.Length];//新建一个字节数组 stream.Read(b, 0, b.Length); // 设置当前流的位置为流的开始 stream.Seek(0, SeekOrigin.Begin); using (FileStream fstream = new FileStream(path, FileMode.Create, FileAccess.Write)) { fstream.Write(b, 0, b.Length); } stream.Close(); } catch { } urllist[i] = saveFilePath + title; } } #endregion result = new FileUpLoadResult() { Status = true, FileSavePath = urllist, ErrorMsg = "图片上传成功" }; } } else { result = new FileUpLoadResult() { Status = false, FileSavePath = null, ErrorMsg = "请选择上传文件!" }; } return result; }
看一下部分片段(上段代码中的片段):
//如果是视频,生成截图 if (new string[] { "mp4", "flv" }.Contains(fileExtension)) { result.ShowImagePath = CatchImage.CatchImg(path, generatedPicturePath, fileName, generatedPicSize); if (!string.IsNullOrEmpty(result.ShowImagePath)) { //result.ShowImagePath = generatedPicturePath + title; result.Status = true; result.FileSavePath = new string[] { saveFilePath + fileName + "." + fileExtension }; result.ErrorMsg = ""; } else { try { File.Delete(path); } catch { } result.Status = false; result.FileSavePath = null; result.ErrorMsg = "生成截图失败,视频上传失败!"; } } else { result.Status = true; result.FileSavePath = new string[] { saveFilePath + fileName + "." + fileExtension }; result.ErrorMsg = "图片上传成功"; }
这里只是对mp4 flv的格式视频做了判断,直接写死了,里面的生成切图的方法:CatchImage.CatchImg(path, generatedPicturePath, fileName, generatedPicSize);见下面的代码:
/// <summary> /// 图片截取 或转换格式(flv) /// </summary> public class CatchImage { //转换电影 #region //运行FFMpeg的视频解码,(这里是绝对路径) /// <summary> /// 转换文件并保存在指定文件夹下面(这里是绝对路径) /// </summary> /// <param name="fileName">上传视频文件的路径(原文件)</param> /// <param name="playFile">转换后的文件的路径(网络播放文件)</param> /// <param name="imgFile">从视频文件中抓取的图片路径</param> /// <param name="videoWidthAndHeight">视频 高度、宽度 格式: 480x360</param> /// <param name="generatedPictureWidthAndHeight">生成图片的高宽 格式: 480x360</param> /// <returns>成功:返回图片虚拟地址; 失败:返回空字符串</returns> public static string ChangeFilePhy(string fileName, string playFile, string imgFile, string videoWidthAndHeight, string generatedPictureWidthAndHeight) { //取得ffmpeg.exe的路径,路径配置在Web.Config中,如:<add key="ffmpeg" value="E:51aspxffmpeg.exe" /> string ffmpeg = System.Web.HttpContext.Current.Server.MapPath("~/Tools/ffmpeg.exe"); if ((!System.IO.File.Exists(ffmpeg)) || (!System.IO.File.Exists(fileName))) { return ""; } //获得图片和(.flv)文件相对路径/最后存储到数据库的路径,如:/Web/User1/00001.jpg string flv_file = System.IO.Path.ChangeExtension(playFile, ".flv"); //截图的尺寸大小,配置在Web.Config中,如:<add key="CatchFlvImgSize" value="240x180" /> System.Diagnostics.Process FilesProcess = new System.Diagnostics.Process(); FilesProcess.StartInfo.FileName = ffmpeg; FilesProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; FilesProcess.StartInfo.Arguments = " -i " + fileName + " -ab 56 -ar 22050 -b 500 -r 30 -s " + videoWidthAndHeight + " " + flv_file; try { FilesProcess.Start(); while (!FilesProcess.HasExited) { } //截图 //CatchImg(fileName, imgFile, generatedPictureWidthAndHeight); } catch (Exception ex) { //Console.WriteLine(ex.Message); return ex.Message; } return ""; } #endregion //截图程序 public static string CatchImg(string fileName, string imgFile, string imgFileName, string generatedPictureWidthAndHeight) { // string ffmpeg = System.Web.HttpContext.Current.Server.MapPath("~/Tools/ffmpeg.exe"); // if (!Directory.Exists(HttpContext.Current.Server.MapPath(imgFile))) { try { Directory.CreateDirectory(HttpContext.Current.Server.MapPath(imgFile)); } catch { } } string flv_img = imgFile + imgFileName + ".jpg"; string cutImgFullPath = HttpContext.Current.Server.MapPath(flv_img); // System.Diagnostics.ProcessStartInfo ImgstartInfo = new System.Diagnostics.ProcessStartInfo(ffmpeg); ImgstartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; Thread.Sleep(500); // //可用参考指令 ImgstartInfo.Arguments = " -i " + fileName + " -y -f image2 -ss 2 -vframes 1 -s " + generatedPictureWidthAndHeight + " " + cutImgFullPath;//可用指令 //ImgstartInfo.Arguments = ("-i " + fileName + " -y -f image2 -ss 00:00:06 -t 0.001 -s " + generatedPictureWidthAndHeight + " " + flv_img); //return ExeCommand(ToolsPath + " -i " + strFullVideoFile + " -y -f image2 -ss " + StartPoint + " -t 0.001 -s " + CutImgWidth + "x" + CutImgHeight + " " + strFullOutputImg); //ImgstartInfo.Arguments = " -i " + fileName + " -y -f image2 -ss 2 -vframes 1 -s " + generatedPictureWidthAndHeight + " " + flv_img; try { System.Diagnostics.Process.Start(ImgstartInfo); Thread.Sleep(500); } catch (Exception ex) { //Console.WriteLine(ex.Message); return ex.Message; } // if (System.IO.File.Exists(cutImgFullPath)) { return flv_img; } return ""; } }
这是一个完整的类,可以直接拿来使用,包含视频格式转换以及 视频剪切,剪切部分的指令,写法有好多种,目前未注释的指令测试百分百可用,但是使用有一个注意点,细心的 猿类同仁应该看得出来,指令 与指令之间有空格,那么,如此一来,
" -i " + fileName + " -y -f image2 -ss 2 -vframes 1 -s " + generatedPictureWidthAndHeight + " " + cutImgFullPath;//可用
这个命令中的参数,也就是说 加号中间的变量,对应的值不可以出现空格,之语中文可不可以,我已经忘记了,这是好几个月之前搞着玩的东西了。
process调用的工具 ffmpeg,一百度,一大把。