aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.MediaEncoding/Encoder
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.MediaEncoding/Encoder')
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs113
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs385
2 files changed, 236 insertions, 262 deletions
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
index 262772959..3eed891cb 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
-using System.Globalization;
+using System.Collections.ObjectModel;
using System.Linq;
using System.Text.RegularExpressions;
using MediaBrowser.Model.Diagnostics;
@@ -19,7 +19,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
_processFactory = processFactory;
}
- public (IEnumerable<string> decoders, IEnumerable<string> encoders) Validate(string encoderPath)
+ public (IEnumerable<string> decoders, IEnumerable<string> encoders) GetAvailableCoders(string encoderPath)
{
_logger.LogInformation("Validating media encoder at {EncoderPath}", encoderPath);
@@ -48,6 +48,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (string.IsNullOrWhiteSpace(output))
{
+ if (logOutput)
+ {
+ _logger.LogError("FFmpeg validation: The process returned no result");
+ }
return false;
}
@@ -55,21 +59,114 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (output.IndexOf("Libav developers", StringComparison.OrdinalIgnoreCase) != -1)
{
+ if (logOutput)
+ {
+ _logger.LogError("FFmpeg validation: avconv instead of ffmpeg is not supported");
+ }
return false;
}
- output = " " + output + " ";
+ // The min and max FFmpeg versions required to run jellyfin successfully
+ var minRequired = new Version(4, 0);
+ var maxRequired = new Version(4, 0);
+
+ // Work out what the version under test is
+ var underTest = GetFFmpegVersion(output);
- for (var i = 2013; i <= 2015; i++)
+ if (logOutput)
{
- var yearString = i.ToString(CultureInfo.InvariantCulture);
- if (output.IndexOf(" " + yearString + " ", StringComparison.OrdinalIgnoreCase) != -1)
+ _logger.LogInformation("FFmpeg validation: Found ffmpeg version {0}", underTest != null ? underTest.ToString() : "unknown");
+
+ if (underTest == null) // Version is unknown
{
- return false;
+ if (minRequired.Equals(maxRequired))
+ {
+ _logger.LogWarning("FFmpeg validation: We recommend ffmpeg version {0}", minRequired.ToString());
+ }
+ else
+ {
+ _logger.LogWarning("FFmpeg validation: We recommend a minimum of {0} and maximum of {1}", minRequired.ToString(), maxRequired.ToString());
+ }
}
+ else if (underTest.CompareTo(minRequired) < 0) // Version is below what we recommend
+ {
+ _logger.LogWarning("FFmpeg validation: The minimum recommended ffmpeg version is {0}", minRequired.ToString());
+ }
+ else if (underTest.CompareTo(maxRequired) > 0) // Version is above what we recommend
+ {
+ _logger.LogWarning("FFmpeg validation: The maximum recommended ffmpeg version is {0}", maxRequired.ToString());
+ }
+ else // Version is ok
+ {
+ _logger.LogInformation("FFmpeg validation: Found suitable ffmpeg version");
+ }
+ }
+
+ // underTest shall be null if versions is unknown
+ return (underTest == null) ? false : (underTest.CompareTo(minRequired) >= 0 && underTest.CompareTo(maxRequired) <= 0);
+ }
+
+ /// <summary>
+ /// Using the output from "ffmpeg -version" work out the FFmpeg version.
+ /// For pre-built binaries the first line should contain a string like "ffmpeg version x.y", which is easy
+ /// to parse. If this is not available, then we try to match known library versions to FFmpeg versions.
+ /// If that fails then we use one of the main libraries to determine if it's new/older than the latest
+ /// we have stored.
+ /// </summary>
+ /// <param name="output"></param>
+ /// <returns></returns>
+ static private Version GetFFmpegVersion(string output)
+ {
+ // For pre-built binaries the FFmpeg version should be mentioned at the very start of the output
+ var match = Regex.Match(output, @"ffmpeg version (\d+\.\d+)");
+
+ if (match.Success)
+ {
+ return new Version(match.Groups[1].Value);
+ }
+ else
+ {
+ // Try and use the individual library versions to determine a FFmpeg version
+ // This lookup table is to be maintained with the following command line:
+ // $ ./ffmpeg.exe -version | perl -ne ' print "$1=$2.$3," if /^(lib\w+)\s+(\d+)\.\s*(\d+)/'
+ var lut = new ReadOnlyDictionary<Version, string>
+ (new Dictionary<Version, string>
+ {
+ { new Version("4.1"), "libavutil=56.22,libavcodec=58.35,libavformat=58.20,libavdevice=58.5,libavfilter=7.40,libswscale=5.3,libswresample=3.3,libpostproc=55.3," },
+ { new Version("4.0"), "libavutil=56.14,libavcodec=58.18,libavformat=58.12,libavdevice=58.3,libavfilter=7.16,libswscale=5.1,libswresample=3.1,libpostproc=55.1," },
+ { new Version("3.4"), "libavutil=55.78,libavcodec=57.107,libavformat=57.83,libavdevice=57.10,libavfilter=6.107,libswscale=4.8,libswresample=2.9,libpostproc=54.7," },
+ { new Version("3.3"), "libavutil=55.58,libavcodec=57.89,libavformat=57.71,libavdevice=57.6,libavfilter=6.82,libswscale=4.6,libswresample=2.7,libpostproc=54.5," },
+ { new Version("3.2"), "libavutil=55.34,libavcodec=57.64,libavformat=57.56,libavdevice=57.1,libavfilter=6.65,libswscale=4.2,libswresample=2.3,libpostproc=54.1," },
+ { new Version("2.8"), "libavutil=54.31,libavcodec=56.60,libavformat=56.40,libavdevice=56.4,libavfilter=5.40,libswscale=3.1,libswresample=1.2,libpostproc=53.3," }
+ });
+
+ // Create a reduced version string and lookup key from dictionary
+ var reducedVersion = GetVersionString(output);
+
+ // Try to lookup the string and return Key, otherwise if not found returns null
+ return lut.FirstOrDefault(x => x.Value == reducedVersion).Key;
+ }
+ }
+
+ /// <summary>
+ /// Grabs the library names and major.minor version numbers from the 'ffmpeg -version' output
+ /// and condenses them on to one line. Output format is "name1=major.minor,name2=major.minor,etc."
+ /// </summary>
+ /// <param name="output"></param>
+ /// <returns></returns>
+ static private string GetVersionString(string output)
+ {
+ string pattern = @"((?<name>lib\w+)\s+(?<major>\d+)\.\s*(?<minor>\d+))";
+ RegexOptions options = RegexOptions.Multiline;
+
+ string rc = null;
+
+ foreach (Match m in Regex.Matches(output, pattern, options))
+ {
+ rc += string.Concat(m.Groups["name"], '=', m.Groups["major"], '.', m.Groups["minor"], ',');
}
- return true;
+ return rc;
}
private static readonly string[] requiredDecoders = new[]
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index d922f1068..292457788 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -3,17 +3,14 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Controller.Session;
using MediaBrowser.MediaEncoding.Probing;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Diagnostics;
@@ -22,6 +19,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.System;
using Microsoft.Extensions.Logging;
namespace MediaBrowser.MediaEncoding.Encoder
@@ -32,340 +30,223 @@ namespace MediaBrowser.MediaEncoding.Encoder
public class MediaEncoder : IMediaEncoder, IDisposable
{
/// <summary>
- /// The _logger
- /// </summary>
- private readonly ILogger _logger;
-
- /// <summary>
- /// Gets the json serializer.
+ /// Gets the encoder path.
/// </summary>
- /// <value>The json serializer.</value>
- private readonly IJsonSerializer _jsonSerializer;
+ /// <value>The encoder path.</value>
+ public string EncoderPath => FFmpegPath;
/// <summary>
- /// The _thumbnail resource pool
+ /// The location of the discovered FFmpeg tool.
/// </summary>
- private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1);
-
- public string FFMpegPath { get; private set; }
-
- public string FFProbePath { get; private set; }
+ public FFmpegLocation EncoderLocation { get; private set; }
+ private readonly ILogger _logger;
+ private readonly IJsonSerializer _jsonSerializer;
+ private string FFmpegPath;
+ private string FFprobePath;
protected readonly IServerConfigurationManager ConfigurationManager;
protected readonly IFileSystem FileSystem;
- protected readonly ILiveTvManager LiveTvManager;
- protected readonly IIsoManager IsoManager;
- protected readonly ILibraryManager LibraryManager;
- protected readonly IChannelManager ChannelManager;
- protected readonly ISessionManager SessionManager;
protected readonly Func<ISubtitleEncoder> SubtitleEncoder;
protected readonly Func<IMediaSourceManager> MediaSourceManager;
- private readonly IHttpClient _httpClient;
- private readonly IZipClient _zipClient;
private readonly IProcessFactory _processFactory;
+ private readonly int DefaultImageExtractionTimeoutMs;
+ private readonly string StartupOptionFFmpegPath;
+ private readonly string StartupOptionFFprobePath;
+ private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1);
private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
- private readonly bool _hasExternalEncoder;
- private readonly string _originalFFMpegPath;
- private readonly string _originalFFProbePath;
- private readonly int DefaultImageExtractionTimeoutMs;
public MediaEncoder(
ILoggerFactory loggerFactory,
IJsonSerializer jsonSerializer,
- string ffMpegPath,
- string ffProbePath,
- bool hasExternalEncoder,
+ string startupOptionsFFmpegPath,
+ string startupOptionsFFprobePath,
IServerConfigurationManager configurationManager,
IFileSystem fileSystem,
- ILiveTvManager liveTvManager,
- IIsoManager isoManager,
- ILibraryManager libraryManager,
- IChannelManager channelManager,
- ISessionManager sessionManager,
Func<ISubtitleEncoder> subtitleEncoder,
Func<IMediaSourceManager> mediaSourceManager,
- IHttpClient httpClient,
- IZipClient zipClient,
IProcessFactory processFactory,
int defaultImageExtractionTimeoutMs)
{
_logger = loggerFactory.CreateLogger(nameof(MediaEncoder));
_jsonSerializer = jsonSerializer;
+ StartupOptionFFmpegPath = startupOptionsFFmpegPath;
+ StartupOptionFFprobePath = startupOptionsFFprobePath;
ConfigurationManager = configurationManager;
FileSystem = fileSystem;
- LiveTvManager = liveTvManager;
- IsoManager = isoManager;
- LibraryManager = libraryManager;
- ChannelManager = channelManager;
- SessionManager = sessionManager;
SubtitleEncoder = subtitleEncoder;
- MediaSourceManager = mediaSourceManager;
- _httpClient = httpClient;
- _zipClient = zipClient;
_processFactory = processFactory;
DefaultImageExtractionTimeoutMs = defaultImageExtractionTimeoutMs;
- FFProbePath = ffProbePath;
- FFMpegPath = ffMpegPath;
- _originalFFProbePath = ffProbePath;
- _originalFFMpegPath = ffMpegPath;
- _hasExternalEncoder = hasExternalEncoder;
}
- public string EncoderLocationType
+ /// <summary>
+ /// Run at startup or if the user removes a Custom path from transcode page.
+ /// Sets global variables FFmpegPath.
+ /// Precedence is: Config > CLI > $PATH
+ /// </summary>
+ public void SetFFmpegPath()
{
- get
+ // ToDo - Finalise removal of the --ffprobe switch
+ if (!string.IsNullOrEmpty(StartupOptionFFprobePath))
{
- if (_hasExternalEncoder)
- {
- return "External";
- }
-
- if (string.IsNullOrWhiteSpace(FFMpegPath))
- {
- return null;
- }
-
- if (IsSystemInstalledPath(FFMpegPath))
- {
- return "System";
- }
-
- return "Custom";
+ _logger.LogWarning("--ffprobe switch is deprecated and shall be removed in the next release");
}
- }
- private bool IsSystemInstalledPath(string path)
- {
- if (path.IndexOf("/", StringComparison.Ordinal) == -1 && path.IndexOf("\\", StringComparison.Ordinal) == -1)
+ // 1) Custom path stored in config/encoding xml file under tag <EncoderAppPath> takes precedence
+ if (!ValidatePath(ConfigurationManager.GetConfiguration<EncodingOptions>("encoding").EncoderAppPath, FFmpegLocation.Custom))
{
- return true;
+ // 2) Check if the --ffmpeg CLI switch has been given
+ if (!ValidatePath(StartupOptionFFmpegPath, FFmpegLocation.SetByArgument))
+ {
+ // 3) Search system $PATH environment variable for valid FFmpeg
+ if (!ValidatePath(ExistsOnSystemPath("ffmpeg"), FFmpegLocation.System))
+ {
+ EncoderLocation = FFmpegLocation.NotFound;
+ FFmpegPath = null;
+ }
+ }
}
- return false;
- }
-
- public void Init()
- {
- InitPaths();
+ // Write the FFmpeg path to the config/encoding.xml file as <EncoderAppPathDisplay> so it appears in UI
+ var config = ConfigurationManager.GetConfiguration<EncodingOptions>("encoding");
+ config.EncoderAppPathDisplay = FFmpegPath ?? string.Empty;
+ ConfigurationManager.SaveConfiguration("encoding", config);
- if (!string.IsNullOrWhiteSpace(FFMpegPath))
+ // Only if mpeg path is set, try and set path to probe
+ if (FFmpegPath != null)
{
- var result = new EncoderValidator(_logger, _processFactory).Validate(FFMpegPath);
+ // Determine a probe path from the mpeg path
+ FFprobePath = Regex.Replace(FFmpegPath, @"[^\/\\]+?(\.[^\/\\\n.]+)?$", @"ffprobe$1");
+
+ // Interrogate to understand what coders are supported
+ var result = new EncoderValidator(_logger, _processFactory).GetAvailableCoders(FFmpegPath);
SetAvailableDecoders(result.decoders);
SetAvailableEncoders(result.encoders);
}
- }
-
- private void InitPaths()
- {
- ConfigureEncoderPaths();
-
- if (_hasExternalEncoder)
- {
- LogPaths();
- return;
- }
-
- // If the path was passed in, save it into config now.
- var encodingOptions = GetEncodingOptions();
- var appPath = encodingOptions.EncoderAppPath;
-
- var valueToSave = FFMpegPath;
-
- if (!string.IsNullOrWhiteSpace(valueToSave))
- {
- // if using system variable, don't save this.
- if (IsSystemInstalledPath(valueToSave) || _hasExternalEncoder)
- {
- valueToSave = null;
- }
- }
- if (!string.Equals(valueToSave, appPath, StringComparison.Ordinal))
- {
- encodingOptions.EncoderAppPath = valueToSave;
- ConfigurationManager.SaveConfiguration("encoding", encodingOptions);
- }
+ _logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation.ToString(), FFmpegPath ?? string.Empty);
}
+ /// <summary>
+ /// Triggered from the Settings > Transcoding UI page when users submits Custom FFmpeg path to use.
+ /// Only write the new path to xml if it exists. Do not perform validation checks on ffmpeg here.
+ /// </summary>
+ /// <param name="path"></param>
+ /// <param name="pathType"></param>
public void UpdateEncoderPath(string path, string pathType)
{
- if (_hasExternalEncoder)
- {
- return;
- }
+ string newPath;
_logger.LogInformation("Attempting to update encoder path to {0}. pathType: {1}", path ?? string.Empty, pathType ?? string.Empty);
- Tuple<string, string> newPaths;
-
- if (string.Equals(pathType, "system", StringComparison.OrdinalIgnoreCase))
- {
- path = "ffmpeg";
-
- newPaths = TestForInstalledVersions();
- }
- else if (string.Equals(pathType, "custom", StringComparison.OrdinalIgnoreCase))
+ if (!string.Equals(pathType, "custom", StringComparison.OrdinalIgnoreCase))
{
- if (string.IsNullOrWhiteSpace(path))
- {
- throw new ArgumentNullException(nameof(path));
- }
-
- if (!File.Exists(path) && !Directory.Exists(path))
- {
- throw new ResourceNotFoundException();
- }
- newPaths = GetEncoderPaths(path);
+ throw new ArgumentException("Unexpected pathType value");
}
- else
+ else if (string.IsNullOrWhiteSpace(path))
{
- throw new ArgumentException("Unexpected pathType value");
+ // User had cleared the custom path in UI
+ newPath = string.Empty;
}
-
- if (string.IsNullOrWhiteSpace(newPaths.Item1))
+ else if (File.Exists(path))
{
- throw new ResourceNotFoundException("ffmpeg not found");
+ newPath = path;
}
- if (string.IsNullOrWhiteSpace(newPaths.Item2))
+ else if (Directory.Exists(path))
{
- throw new ResourceNotFoundException("ffprobe not found");
+ // Given path is directory, so resolve down to filename
+ newPath = GetEncoderPathFromDirectory(path, "ffmpeg");
}
-
- path = newPaths.Item1;
-
- if (!ValidateVersion(path, true))
+ else
{
- throw new ResourceNotFoundException("ffmpeg version 3.0 or greater is required.");
+ throw new ResourceNotFoundException();
}
- var config = GetEncodingOptions();
- config.EncoderAppPath = path;
+ // Write the new ffmpeg path to the xml as <EncoderAppPath>
+ // This ensures its not lost on next startup
+ var config = ConfigurationManager.GetConfiguration<EncodingOptions>("encoding");
+ config.EncoderAppPath = newPath;
ConfigurationManager.SaveConfiguration("encoding", config);
- Init();
+ // Trigger SetFFmpegPath so we validate the new path and setup probe path
+ SetFFmpegPath();
}
- private bool ValidateVersion(string path, bool logOutput)
- {
- return new EncoderValidator(_logger, _processFactory).ValidateVersion(path, logOutput);
- }
-
- private void ConfigureEncoderPaths()
+ /// <summary>
+ /// Validates the supplied FQPN to ensure it is a ffmpeg utility.
+ /// If checks pass, global variable FFmpegPath and EncoderLocation are updated.
+ /// </summary>
+ /// <param name="path">FQPN to test</param>
+ /// <param name="location">Location (External, Custom, System) of tool</param>
+ /// <returns></returns>
+ private bool ValidatePath(string path, FFmpegLocation location)
{
- if (_hasExternalEncoder)
- {
- return;
- }
-
- var appPath = GetEncodingOptions().EncoderAppPath;
+ bool rc = false;
- if (string.IsNullOrWhiteSpace(appPath))
+ if (!string.IsNullOrEmpty(path))
{
- appPath = Path.Combine(ConfigurationManager.ApplicationPaths.ProgramDataPath, "ffmpeg");
- }
-
- var newPaths = GetEncoderPaths(appPath);
- if (string.IsNullOrWhiteSpace(newPaths.Item1) || string.IsNullOrWhiteSpace(newPaths.Item2) || IsSystemInstalledPath(appPath))
- {
- newPaths = TestForInstalledVersions();
- }
-
- if (!string.IsNullOrWhiteSpace(newPaths.Item1) && !string.IsNullOrWhiteSpace(newPaths.Item2))
- {
- FFMpegPath = newPaths.Item1;
- FFProbePath = newPaths.Item2;
- }
+ if (File.Exists(path))
+ {
+ rc = new EncoderValidator(_logger, _processFactory).ValidateVersion(path, true);
- LogPaths();
- }
+ if (!rc)
+ {
+ _logger.LogWarning("FFmpeg: {0}: Failed version check: {1}", location.ToString(), path);
+ }
- private Tuple<string, string> GetEncoderPaths(string configuredPath)
- {
- var appPath = configuredPath;
+ // ToDo - Enable the ffmpeg validator. At the moment any version can be used.
+ rc = true;
- if (!string.IsNullOrWhiteSpace(appPath))
- {
- if (Directory.Exists(appPath))
- {
- return GetPathsFromDirectory(appPath);
+ FFmpegPath = path;
+ EncoderLocation = location;
}
-
- if (File.Exists(appPath))
+ else
{
- return new Tuple<string, string>(appPath, GetProbePathFromEncoderPath(appPath));
+ _logger.LogWarning("FFmpeg: {0}: File not found: {1}", location.ToString(), path);
}
}
- return new Tuple<string, string>(null, null);
+ return rc;
}
- private Tuple<string, string> TestForInstalledVersions()
+ private string GetEncoderPathFromDirectory(string path, string filename)
{
- string encoderPath = null;
- string probePath = null;
-
- if (_hasExternalEncoder && ValidateVersion(_originalFFMpegPath, true))
+ try
{
- encoderPath = _originalFFMpegPath;
- probePath = _originalFFProbePath;
- }
+ var files = FileSystem.GetFilePaths(path);
- if (string.IsNullOrWhiteSpace(encoderPath))
+ var excludeExtensions = new[] { ".c" };
+
+ return files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), filename, StringComparison.OrdinalIgnoreCase)
+ && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty));
+ }
+ catch (Exception)
{
- if (ValidateVersion("ffmpeg", true) && ValidateVersion("ffprobe", false))
- {
- encoderPath = "ffmpeg";
- probePath = "ffprobe";
- }
+ // Trap all exceptions, like DirNotExists, and return null
+ return null;
}
-
- return new Tuple<string, string>(encoderPath, probePath);
}
- private Tuple<string, string> GetPathsFromDirectory(string path)
+ /// <summary>
+ /// Search the system $PATH environment variable looking for given filename.
+ /// </summary>
+ /// <param name="fileName"></param>
+ /// <returns></returns>
+ private string ExistsOnSystemPath(string filename)
{
- // Since we can't predict the file extension, first try directly within the folder
- // If that doesn't pan out, then do a recursive search
- var files = FileSystem.GetFilePaths(path);
-
- var excludeExtensions = new[] { ".c" };
+ var values = Environment.GetEnvironmentVariable("PATH");
- var ffmpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty));
- var ffprobePath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty));
-
- if (string.IsNullOrWhiteSpace(ffmpegPath) || !File.Exists(ffmpegPath))
+ foreach (var path in values.Split(Path.PathSeparator))
{
- files = FileSystem.GetFilePaths(path, true);
-
- ffmpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty));
+ var candidatePath = GetEncoderPathFromDirectory(path, filename);
- if (!string.IsNullOrWhiteSpace(ffmpegPath))
+ if (!string.IsNullOrEmpty(candidatePath))
{
- ffprobePath = GetProbePathFromEncoderPath(ffmpegPath);
+ return candidatePath;
}
}
-
- return new Tuple<string, string>(ffmpegPath, ffprobePath);
- }
-
- private string GetProbePathFromEncoderPath(string appPath)
- {
- return FileSystem.GetFilePaths(Path.GetDirectoryName(appPath))
- .FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase));
- }
-
- private void LogPaths()
- {
- _logger.LogInformation("FFMpeg: {0}", FFMpegPath ?? "not found");
- _logger.LogInformation("FFProbe: {0}", FFProbePath ?? "not found");
- }
-
- private EncodingOptions GetEncodingOptions()
- {
- return ConfigurationManager.GetConfiguration<EncodingOptions>("encoding");
+ return null;
}
private List<string> _encoders = new List<string>();
@@ -413,12 +294,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
/// <summary>
- /// Gets the encoder path.
- /// </summary>
- /// <value>The encoder path.</value>
- public string EncoderPath => FFMpegPath;
-
- /// <summary>
/// Gets the media info.
/// </summary>
/// <param name="request">The request.</param>
@@ -489,7 +364,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
// Must consume both or ffmpeg may hang due to deadlocks. See comments below.
RedirectStandardOutput = true,
- FileName = FFProbePath,
+ FileName = FFprobePath,
Arguments = string.Format(args, probeSizeArgument, inputPath).Trim(),
IsHidden = true,
@@ -691,10 +566,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
CreateNoWindow = true,
UseShellExecute = false,
- FileName = FFMpegPath,
+ FileName = FFmpegPath,
Arguments = args,
IsHidden = true,
- ErrorDialog = false
+ ErrorDialog = false,
+ EnableRaisingEvents = true
});
_logger.LogDebug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
@@ -813,10 +689,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
CreateNoWindow = true,
UseShellExecute = false,
- FileName = FFMpegPath,
+ FileName = FFmpegPath,
Arguments = args,
IsHidden = true,
- ErrorDialog = false
+ ErrorDialog = false,
+ EnableRaisingEvents = true
});
_logger.LogInformation(process.StartInfo.FileName + " " + process.StartInfo.Arguments);