VidConverter.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. using SkiaSharp;
  2. using DICOM = Dicom;
  3. using Dicom.Imaging;
  4. using Vinno.IUS.Common.Media.FFmpeg;
  5. using System.Diagnostics;
  6. namespace VidProcessService.Utilities
  7. {
  8. public class VidConverter
  9. {
  10. private static string _ffmpegPath;
  11. private string _tempfolder;
  12. public VidConverter(string tempfolder)
  13. {
  14. if (!Directory.Exists(tempfolder))
  15. {
  16. Directory.CreateDirectory(tempfolder);
  17. }
  18. _tempfolder = tempfolder;
  19. _ffmpegPath = GetFFmpegPath();
  20. }
  21. public long DicomToVid(string filePath, string targetPath)
  22. {
  23. var dicomFile = DICOM.DicomFile.Open(filePath);
  24. var dataset = dicomFile.Dataset;
  25. var dicomImage = new DicomImage(dataset);
  26. using (var vidFile = new VidFile(targetPath))
  27. {
  28. vidFile.AddExtendedData(dataset);
  29. vidFile.AddProbe(dataset);
  30. vidFile.AddImages(dicomImage);
  31. }
  32. if (File.Exists(targetPath))
  33. {
  34. FileInfo fileInfo = new FileInfo(targetPath);
  35. return fileInfo.Length;
  36. }
  37. return 0;
  38. }
  39. public long ImageToVid(string filePath, string targetPath)
  40. {
  41. FileStream fileStream =
  42. new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
  43. // 读取文件的 byte[]
  44. byte[] bytes = new byte[fileStream.Length];
  45. fileStream.Read(bytes, 0, bytes.Length);
  46. fileStream.Close();
  47. using (var vidFile = new VidFile(targetPath))
  48. {
  49. using (MemoryStream ms = new MemoryStream(bytes))
  50. {
  51. var skiaBitmap = SKBitmap.Decode(ms);
  52. vidFile.AddProbe(1);
  53. vidFile.AddImages(skiaBitmap.Width, skiaBitmap.Height, bytes);
  54. }
  55. }
  56. if (File.Exists(targetPath))
  57. {
  58. FileInfo fileInfo = new FileInfo(targetPath);
  59. return fileInfo.Length;
  60. }
  61. return 0;
  62. }
  63. /// <summary>
  64. /// Mp4 to vid
  65. /// </summary>
  66. /// <param name="filePath"></param>
  67. /// <param name="targetPath"></param>
  68. /// <returns></returns>
  69. public long Mp4ToVid(string filePath, string targetPath)
  70. {
  71. var imageTempPathList = new List<string>();
  72. string id = Guid.NewGuid().ToString();
  73. var targetImageDirectory = Path.Combine(_tempfolder, id);
  74. if (!Directory.Exists(targetImageDirectory))
  75. {
  76. Directory.CreateDirectory(targetImageDirectory);
  77. }
  78. ConvertImages(filePath, targetImageDirectory);//Mp4 to images
  79. //生成Vid
  80. ImagesToVid(targetImageDirectory, targetPath);//images to vid
  81. if (File.Exists(targetPath))
  82. {
  83. FileInfo fileInfo = new FileInfo(targetPath);
  84. return fileInfo.Length;
  85. }
  86. return 0;
  87. }
  88. private void ImagesToVid(string targetImageDirectory, string targetPath)
  89. {
  90. var filePaths = Directory.GetFiles(targetImageDirectory, "*.jpg");
  91. using (var vidFile = new VidFile(targetPath))
  92. {
  93. foreach (var item in filePaths)
  94. {
  95. FileStream fileStream =
  96. new FileStream(item, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
  97. // 读取文件的 byte[]
  98. byte[] bytes = new byte[fileStream.Length];
  99. fileStream.Read(bytes, 0, bytes.Length);
  100. fileStream.Close();
  101. using (MemoryStream ms = new MemoryStream(bytes))
  102. {
  103. var skiaBitmap = SKBitmap.Decode(ms);
  104. vidFile.AddProbe(1);
  105. vidFile.AddImages(skiaBitmap.Width, skiaBitmap.Height, bytes);
  106. }
  107. }
  108. }
  109. if (Directory.Exists(targetImageDirectory))//清除images文件夹
  110. {
  111. Directory.Delete(targetImageDirectory, true);
  112. }
  113. }
  114. private void ConvertImages(string sourcePath, string desfolderPath)
  115. {
  116. //TODO 需要计算帧率大小
  117. //var argument = "-i " + sourcePath + " -y -vframes 1 -f mjpeg " + desfolderPath+"\\output%d.jpg";
  118. // var argument = "-i " + sourcePath + " -vf fps=15 -vsync vfr " + desfolderPath+"\\output%d.jpg";
  119. var argument = "-i " + sourcePath + " " + Path.Combine(desfolderPath, "output%d.jpg");
  120. var log = new FFmpegLog();
  121. log.WriteArgs(argument);
  122. Process process;
  123. StartFFmpeg(out process, argument, log);
  124. process.WaitForExit();
  125. }
  126. private static void StartFFmpeg(out Process process, string arguments, FFmpegLog logItem = null)
  127. {
  128. process = new Process
  129. {
  130. StartInfo =
  131. {
  132. FileName = _ffmpegPath,
  133. Arguments = arguments,
  134. UseShellExecute = false,
  135. Verb = "runas",
  136. CreateNoWindow = true,
  137. RedirectStandardError = true,
  138. RedirectStandardInput = true
  139. },
  140. EnableRaisingEvents = true
  141. };
  142. if (logItem != null)
  143. {
  144. process.ErrorDataReceived += (s, e) => { };
  145. }
  146. process.Start();
  147. process.BeginErrorReadLine();
  148. }
  149. /// <summary>
  150. /// 获取 FFmpeg exe 路径
  151. /// </summary>
  152. /// <returns></returns>
  153. private string GetFFmpegPath()
  154. {
  155. switch (Environment.OSVersion.Platform)
  156. {
  157. case PlatformID.Win32S:
  158. throw new NotSupportedException($"Not supported OS {Environment.OSVersion.Platform}");
  159. case PlatformID.Win32Windows:
  160. throw new NotSupportedException($"Not supported OS {Environment.OSVersion.Platform}");
  161. case PlatformID.Win32NT:
  162. return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Packages", "ffmpeg.exe");
  163. break;
  164. case PlatformID.WinCE:
  165. throw new NotSupportedException($"Not supported OS {Environment.OSVersion.Platform}");
  166. case PlatformID.Unix:
  167. return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Packages", "ffmpeg");
  168. break;
  169. case PlatformID.Xbox:
  170. throw new NotSupportedException($"Not supported OS {Environment.OSVersion.Platform}");
  171. case PlatformID.MacOSX:
  172. return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Packages", "ffmpeg");
  173. break;
  174. default:
  175. throw new NotSupportedException($"Not supported OS {Environment.OSVersion.Platform}");
  176. }
  177. }
  178. }
  179. }