FFmpegValidator.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using MediaBrowser.Common.Configuration;
  2. using MediaBrowser.Model.Logging;
  3. using System;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Collections.Generic;
  7. using CommonIO;
  8. namespace MediaBrowser.Server.Startup.Common.FFMpeg
  9. {
  10. public class FFmpegValidator
  11. {
  12. private readonly ILogger _logger;
  13. private readonly IApplicationPaths _appPaths;
  14. private readonly IFileSystem _fileSystem;
  15. public FFmpegValidator(ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem)
  16. {
  17. _logger = logger;
  18. _appPaths = appPaths;
  19. _fileSystem = fileSystem;
  20. }
  21. public Tuple<List<string>,List<string>> Validate(FFMpegInfo info)
  22. {
  23. _logger.Info("FFMpeg: {0}", info.EncoderPath);
  24. _logger.Info("FFProbe: {0}", info.ProbePath);
  25. var decoders = GetDecoders(info.EncoderPath);
  26. var encoders = GetEncoders(info.EncoderPath);
  27. return new Tuple<List<string>, List<string>>(decoders, encoders);
  28. }
  29. private List<string> GetDecoders(string ffmpegPath)
  30. {
  31. string output = string.Empty;
  32. try
  33. {
  34. output = GetFFMpegOutput(ffmpegPath, "-decoders");
  35. }
  36. catch
  37. {
  38. }
  39. //_logger.Debug("ffmpeg decoder query result: {0}", output ?? string.Empty);
  40. var found = new List<string>();
  41. var required = new[]
  42. {
  43. "h264_qsv",
  44. "mpeg2_qsv",
  45. "vc1_qsv"
  46. };
  47. foreach (var codec in required)
  48. {
  49. var srch = " " + codec + " ";
  50. if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) == -1)
  51. {
  52. _logger.Warn("ffmpeg is missing decoder " + codec);
  53. }
  54. else
  55. {
  56. found.Add(codec);
  57. }
  58. }
  59. return found;
  60. }
  61. private List<string> GetEncoders(string ffmpegPath)
  62. {
  63. string output = null;
  64. try
  65. {
  66. output = GetFFMpegOutput(ffmpegPath, "-encoders");
  67. }
  68. catch
  69. {
  70. }
  71. //_logger.Debug("ffmpeg encoder query result: {0}", output ?? string.Empty);
  72. var found = new List<string>();
  73. var required = new[]
  74. {
  75. "libx264",
  76. "libx265",
  77. "mpeg4",
  78. "msmpeg4",
  79. //"libvpx",
  80. //"libvpx-vp9",
  81. "aac",
  82. "libmp3lame",
  83. "libopus",
  84. //"libvorbis",
  85. "srt"
  86. };
  87. foreach (var codec in required)
  88. {
  89. var srch = " " + codec + " ";
  90. if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) == -1)
  91. {
  92. _logger.Warn("ffmpeg is missing encoder " + codec);
  93. }
  94. else
  95. {
  96. found.Add(codec);
  97. }
  98. }
  99. return found;
  100. }
  101. private string GetFFMpegOutput(string path, string arguments)
  102. {
  103. var process = new Process
  104. {
  105. StartInfo = new ProcessStartInfo
  106. {
  107. CreateNoWindow = true,
  108. UseShellExecute = false,
  109. FileName = path,
  110. Arguments = arguments,
  111. WindowStyle = ProcessWindowStyle.Hidden,
  112. ErrorDialog = false,
  113. RedirectStandardOutput = true,
  114. RedirectStandardError = true
  115. }
  116. };
  117. using (process)
  118. {
  119. process.Start();
  120. try
  121. {
  122. process.BeginErrorReadLine();
  123. using (var reader = new StreamReader(process.StandardOutput.BaseStream))
  124. {
  125. return reader.ReadToEnd();
  126. }
  127. }
  128. catch
  129. {
  130. // Hate having to do this
  131. try
  132. {
  133. process.Kill();
  134. }
  135. catch (Exception ex1)
  136. {
  137. _logger.ErrorException("Error killing ffmpeg", ex1);
  138. }
  139. throw;
  140. }
  141. }
  142. }
  143. }
  144. }