Review comments
Address review comments from JustAMan, Bond-009 and cvium.
This commit is contained in:
parent
20775116f7
commit
ed69e690b8
|
@ -791,7 +791,17 @@ namespace Emby.Server.Implementations
|
||||||
ChapterManager = new ChapterManager(LibraryManager, LoggerFactory, ServerConfigurationManager, ItemRepository);
|
ChapterManager = new ChapterManager(LibraryManager, LoggerFactory, ServerConfigurationManager, ItemRepository);
|
||||||
serviceCollection.AddSingleton(ChapterManager);
|
serviceCollection.AddSingleton(ChapterManager);
|
||||||
|
|
||||||
MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder(LoggerFactory, JsonSerializer, StartupOptions.FFmpegPath, StartupOptions.FFprobePath, ServerConfigurationManager, FileSystemManager, () => SubtitleEncoder, () => MediaSourceManager, ProcessFactory, 5000);
|
MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder(
|
||||||
|
LoggerFactory,
|
||||||
|
JsonSerializer,
|
||||||
|
StartupOptions.FFmpegPath,
|
||||||
|
StartupOptions.FFprobePath,
|
||||||
|
ServerConfigurationManager,
|
||||||
|
FileSystemManager,
|
||||||
|
() => SubtitleEncoder,
|
||||||
|
() => MediaSourceManager,
|
||||||
|
ProcessFactory,
|
||||||
|
5000);
|
||||||
serviceCollection.AddSingleton(MediaEncoder);
|
serviceCollection.AddSingleton(MediaEncoder);
|
||||||
|
|
||||||
EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager);
|
EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager);
|
||||||
|
@ -908,27 +918,6 @@ namespace Emby.Server.Implementations
|
||||||
return new ImageProcessor(LoggerFactory, ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => LibraryManager, () => MediaEncoder);
|
return new ImageProcessor(LoggerFactory, ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => LibraryManager, () => MediaEncoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Registers the media encoder.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Task.</returns>
|
|
||||||
private void RegisterMediaEncoder(IAssemblyInfo assemblyInfo)
|
|
||||||
{
|
|
||||||
MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder(
|
|
||||||
LoggerFactory,
|
|
||||||
JsonSerializer,
|
|
||||||
StartupOptions.FFmpegPath,
|
|
||||||
StartupOptions.FFprobePath,
|
|
||||||
ServerConfigurationManager,
|
|
||||||
FileSystemManager,
|
|
||||||
() => SubtitleEncoder,
|
|
||||||
() => MediaSourceManager,
|
|
||||||
ProcessFactory,
|
|
||||||
5000);
|
|
||||||
|
|
||||||
RegisterSingleInstance(MediaEncoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user repository.
|
/// Gets the user repository.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1404,7 +1393,7 @@ namespace Emby.Server.Implementations
|
||||||
ServerName = FriendlyName,
|
ServerName = FriendlyName,
|
||||||
LocalAddress = localAddress,
|
LocalAddress = localAddress,
|
||||||
SupportsLibraryMonitor = true,
|
SupportsLibraryMonitor = true,
|
||||||
EncoderLocationType = MediaEncoder.EncoderLocationType,
|
EncoderLocation = MediaEncoder.EncoderLocation,
|
||||||
SystemArchitecture = EnvironmentInfo.SystemArchitecture,
|
SystemArchitecture = EnvironmentInfo.SystemArchitecture,
|
||||||
SystemUpdateLevel = SystemUpdateLevel,
|
SystemUpdateLevel = SystemUpdateLevel,
|
||||||
PackageName = StartupOptions.PackageName
|
PackageName = StartupOptions.PackageName
|
||||||
|
|
|
@ -6,6 +6,7 @@ using MediaBrowser.Model.Dlna;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
|
using MediaBrowser.Model.System;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.MediaEncoding
|
namespace MediaBrowser.Controller.MediaEncoding
|
||||||
{
|
{
|
||||||
|
@ -14,7 +15,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMediaEncoder : ITranscoderSupport
|
public interface IMediaEncoder : ITranscoderSupport
|
||||||
{
|
{
|
||||||
string EncoderLocationType { get; }
|
FFmpegLocation EncoderLocation { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the encoder path.
|
/// Gets the encoder path.
|
||||||
|
|
|
@ -48,6 +48,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(output))
|
if (string.IsNullOrWhiteSpace(output))
|
||||||
{
|
{
|
||||||
|
if (logOutput)
|
||||||
|
{
|
||||||
|
_logger.LogError("FFmpeg validation: The process returned no result");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +59,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
if (output.IndexOf("Libav developers", StringComparison.OrdinalIgnoreCase) != -1)
|
if (output.IndexOf("Libav developers", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
{
|
{
|
||||||
|
if (logOutput)
|
||||||
|
{
|
||||||
|
_logger.LogError("FFmpeg validation: avconv instead of ffmpeg is not supported");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
@ -18,6 +19,7 @@ using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
|
using MediaBrowser.Model.System;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.MediaEncoding.Encoder
|
namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
@ -34,17 +36,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
public string EncoderPath => FFmpegPath;
|
public string EncoderPath => FFmpegPath;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// External: path supplied via command line
|
/// The location of the discovered FFmpeg tool.
|
||||||
/// Custom: coming from UI or config/encoding.xml file
|
|
||||||
/// System: FFmpeg found in system $PATH
|
|
||||||
/// null: No FFmpeg found
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string EncoderLocationType { get; private set; }
|
public FFmpegLocation EncoderLocation { get; private set; }
|
||||||
|
|
||||||
|
private FFmpegLocation ProbeLocation;
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
private string FFmpegPath { get; set; }
|
private string FFmpegPath;
|
||||||
private string FFprobePath { get; set; }
|
private string FFprobePath;
|
||||||
protected readonly IServerConfigurationManager ConfigurationManager;
|
protected readonly IServerConfigurationManager ConfigurationManager;
|
||||||
protected readonly IFileSystem FileSystem;
|
protected readonly IFileSystem FileSystem;
|
||||||
protected readonly Func<ISubtitleEncoder> SubtitleEncoder;
|
protected readonly Func<ISubtitleEncoder> SubtitleEncoder;
|
||||||
|
@ -54,6 +55,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
private readonly string StartupOptionFFmpegPath;
|
private readonly string StartupOptionFFmpegPath;
|
||||||
private readonly string StartupOptionFFprobePath;
|
private readonly string StartupOptionFFprobePath;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enum to identify the two types of FF utilities of interest.
|
||||||
|
/// </summary>
|
||||||
|
private enum FFtype { Mpeg, Probe };
|
||||||
|
|
||||||
private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1);
|
||||||
private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
|
private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
|
||||||
|
|
||||||
|
@ -82,48 +88,24 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Run at startup or if the user removes a Custom path from transcode page.
|
/// Run at startup or if the user removes a Custom path from transcode page.
|
||||||
/// Sets global variables FFmpegPath and EncoderLocationType.
|
/// Sets global variables FFmpegPath.
|
||||||
/// If startup options --ffprobe is given then FFprobePath is set too.
|
/// Precedence is: Config > CLI > $PATH
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
// 1) If given, use the --ffmpeg CLI switch
|
// 1) Custom path stored in config/encoding xml file under tag <EncoderAppPathCustom> takes precedence
|
||||||
if (ValidatePathFFmpeg("From CLI Switch", StartupOptionFFmpegPath))
|
if (!ValidatePath(FFtype.Mpeg, ConfigurationManager.GetConfiguration<EncodingOptions>("encoding").EncoderAppPathCustom, FFmpegLocation.Custom))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("FFmpeg: Using path from command line switch --ffmpeg");
|
// 2) Check if the --ffmpeg CLI switch has been given
|
||||||
EncoderLocationType = "External";
|
if (!ValidatePath(FFtype.Mpeg, StartupOptionFFmpegPath, FFmpegLocation.SetByArgument))
|
||||||
}
|
{
|
||||||
|
// 3) Search system $PATH environment variable for valid FFmpeg
|
||||||
// 2) Try Custom path stroed in config/encoding xml file under tag <EncoderAppPathCustom>
|
if (!ValidatePath(FFtype.Mpeg, ExistsOnSystemPath("ffmpeg"), FFmpegLocation.System))
|
||||||
else if (ValidatePathFFmpeg("From Config File", ConfigurationManager.GetConfiguration<EncodingOptions>("encoding").EncoderAppPathCustom))
|
{
|
||||||
{
|
EncoderLocation = FFmpegLocation.NotFound;
|
||||||
_logger.LogInformation("FFmpeg: Using path from config/encoding.xml file");
|
FFmpegPath = null;
|
||||||
EncoderLocationType = "Custom";
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3) Search system $PATH environment variable for valid FFmpeg
|
|
||||||
else if (ValidatePathFFmpeg("From $PATH", ExistsOnSystemPath("ffmpeg")))
|
|
||||||
{
|
|
||||||
_logger.LogInformation("FFmpeg: Using system $PATH for FFmpeg");
|
|
||||||
EncoderLocationType = "System";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.LogError("FFmpeg: No suitable executable found");
|
|
||||||
FFmpegPath = null;
|
|
||||||
EncoderLocationType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If given, use the --ffprobe CLI switch
|
|
||||||
if (ValidatePathFFprobe("CLI Switch", StartupOptionFFprobePath))
|
|
||||||
{
|
|
||||||
_logger.LogInformation("FFprobe: Using path from command line switch --ffprobe");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// FFprobe path from command line is no good, so set to null and let ReInit() try
|
|
||||||
// and set using the FFmpeg path.
|
|
||||||
FFprobePath = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReInit();
|
ReInit();
|
||||||
|
@ -136,27 +118,27 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void ReInit()
|
private void ReInit()
|
||||||
{
|
{
|
||||||
// Write the FFmpeg path to the config/encoding.xml file so it appears in UI
|
// Write the FFmpeg path to the config/encoding.xml file as <EncoderAppPath> so it appears in UI
|
||||||
var config = ConfigurationManager.GetConfiguration<EncodingOptions>("encoding");
|
var config = ConfigurationManager.GetConfiguration<EncodingOptions>("encoding");
|
||||||
config.EncoderAppPath = FFmpegPath ?? string.Empty;
|
config.EncoderAppPath = FFmpegPath ?? string.Empty;
|
||||||
ConfigurationManager.SaveConfiguration("encoding", config);
|
ConfigurationManager.SaveConfiguration("encoding", config);
|
||||||
|
|
||||||
|
// Clear probe settings in case probe validation fails
|
||||||
|
ProbeLocation = FFmpegLocation.NotFound;
|
||||||
|
FFprobePath = null;
|
||||||
|
|
||||||
// Only if mpeg path is set, try and set path to probe
|
// Only if mpeg path is set, try and set path to probe
|
||||||
if (FFmpegPath != null)
|
if (FFmpegPath != null)
|
||||||
{
|
{
|
||||||
// Probe would be null here if no valid --ffprobe path was given
|
if (EncoderLocation == FFmpegLocation.Custom || StartupOptionFFprobePath == null)
|
||||||
// at startup, or we're performing ReInit following mpeg path update from UI
|
|
||||||
if (FFprobePath == null)
|
|
||||||
{
|
{
|
||||||
// Use the mpeg path to create a probe path
|
// If mpeg was read from config, or CLI switch not given, try and set probe from mpeg path
|
||||||
if (ValidatePathFFprobe("Copied from FFmpeg:", GetProbePathFromEncoderPath(FFmpegPath)))
|
ValidatePath(FFtype.Probe, GetProbePathFromEncoderPath(FFmpegPath), EncoderLocation);
|
||||||
{
|
}
|
||||||
_logger.LogInformation("FFprobe: Using FFprobe in same folders as FFmpeg");
|
else
|
||||||
}
|
{
|
||||||
else
|
// Else try and set probe path from CLI switch
|
||||||
{
|
ValidatePath(FFtype.Probe, StartupOptionFFmpegPath, FFmpegLocation.SetByArgument);
|
||||||
_logger.LogError("FFprobe: No suitable executable found");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interrogate to understand what coders it supports
|
// Interrogate to understand what coders it supports
|
||||||
|
@ -183,108 +165,95 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Unexpected pathType value");
|
throw new ArgumentException("Unexpected pathType value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
|
{
|
||||||
|
// User had cleared the custom path in UI. Clear the Custom config
|
||||||
|
// setting and perform full Init to reinspect any CLI switches and system $PATH
|
||||||
|
var config = ConfigurationManager.GetConfiguration<EncodingOptions>("encoding");
|
||||||
|
config.EncoderAppPathCustom = string.Empty;
|
||||||
|
ConfigurationManager.SaveConfiguration("encoding", config);
|
||||||
|
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
else if (!File.Exists(path) && !Directory.Exists(path))
|
||||||
|
{
|
||||||
|
// Given path is neither file or folder
|
||||||
|
throw new ResourceNotFoundException();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(path))
|
// Supplied path could be either file path or folder path.
|
||||||
|
// Resolve down to file path and validate
|
||||||
|
if (!ValidatePath(FFtype.Mpeg, GetEncoderPath(path), FFmpegLocation.Custom))
|
||||||
{
|
{
|
||||||
// User had cleared the cutom path in UI. Clear the Custom config
|
throw new ResourceNotFoundException("Failed validation checks.");
|
||||||
// setting and peform full Init to relook any CLI switches and system $PATH
|
|
||||||
var config = ConfigurationManager.GetConfiguration<EncodingOptions>("encoding");
|
|
||||||
config.EncoderAppPathCustom = string.Empty;
|
|
||||||
ConfigurationManager.SaveConfiguration("encoding", config);
|
|
||||||
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
else if (!File.Exists(path) && !Directory.Exists(path))
|
|
||||||
{
|
|
||||||
// Given path is neither file or folder
|
|
||||||
throw new ResourceNotFoundException();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Supplied path could be either file path or folder path.
|
// Write the validated mpeg path to the xml as <EncoderAppPathCustom>
|
||||||
// Resolve down to file path and validate
|
// This ensures its not lost on new startup
|
||||||
path = GetEncoderPath(path);
|
var config = ConfigurationManager.GetConfiguration<EncodingOptions>("encoding");
|
||||||
|
config.EncoderAppPathCustom = FFmpegPath;
|
||||||
|
ConfigurationManager.SaveConfiguration("encoding", config);
|
||||||
|
|
||||||
if (path == null)
|
ReInit();
|
||||||
{
|
|
||||||
throw new ResourceNotFoundException("FFmpeg not found");
|
|
||||||
}
|
|
||||||
else if (!ValidatePathFFmpeg("New From UI", path))
|
|
||||||
{
|
|
||||||
throw new ResourceNotFoundException("Failed validation checks. Version 4.0 or greater is required");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EncoderLocationType = "Custom";
|
|
||||||
|
|
||||||
// Write the validated mpeg path to the xml as <EncoderAppPathCustom>
|
|
||||||
// This ensures its not lost on new startup
|
|
||||||
var config = ConfigurationManager.GetConfiguration<EncodingOptions>("encoding");
|
|
||||||
config.EncoderAppPathCustom = FFmpegPath;
|
|
||||||
ConfigurationManager.SaveConfiguration("encoding", config);
|
|
||||||
|
|
||||||
FFprobePath = null; // Clear probe path so it gets relooked in ReInit()
|
|
||||||
|
|
||||||
ReInit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ValidatePath(string type, string path)
|
/// <summary>
|
||||||
|
/// Validates the supplied FQPN to ensure it is a FFxxx utility.
|
||||||
|
/// If checks pass, global variable FFmpegPath (or FFprobePath) and
|
||||||
|
/// EncoderLocation (or ProbeLocation) are updated.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">Either mpeg or probe</param>
|
||||||
|
/// <param name="path">FQPN to test</param>
|
||||||
|
/// <param name="location">Location (External, Custom, System) of tool</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private bool ValidatePath(FFtype type, string path, FFmpegLocation location)
|
||||||
{
|
{
|
||||||
|
bool rc = false;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(path))
|
if (!string.IsNullOrEmpty(path))
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
{
|
{
|
||||||
var valid = new EncoderValidator(_logger, _processFactory).ValidateVersion(path, true);
|
rc = new EncoderValidator(_logger, _processFactory).ValidateVersion(path, false);
|
||||||
|
|
||||||
if (valid == true)
|
// Only update the global variables if the checks passed
|
||||||
|
if (rc)
|
||||||
{
|
{
|
||||||
return true;
|
if (type == FFtype.Mpeg)
|
||||||
|
{
|
||||||
|
FFmpegPath = path;
|
||||||
|
EncoderLocation = location;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FFprobePath = path;
|
||||||
|
ProbeLocation = location;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("{0}: Failed validation checks. Version 4.0 or greater is required: {1}", type, path);
|
_logger.LogError("{0}: {1}: Failed version check: {2}", type.ToString(), location.ToString(), path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError("{0}: File not found: {1}", type, path);
|
_logger.LogError("{0}: {1}: File not found: {2}", type.ToString(), location.ToString(), path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return rc;
|
||||||
}
|
|
||||||
|
|
||||||
private bool ValidatePathFFmpeg(string comment, string path)
|
|
||||||
{
|
|
||||||
if (ValidatePath("FFmpeg: " + comment, path) == true)
|
|
||||||
{
|
|
||||||
FFmpegPath = path;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ValidatePathFFprobe(string comment, string path)
|
|
||||||
{
|
|
||||||
if (ValidatePath("FFprobe: " + comment, path) == true)
|
|
||||||
{
|
|
||||||
FFprobePath = path;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetEncoderPath(string path)
|
private string GetEncoderPath(string path)
|
||||||
{
|
{
|
||||||
if (Directory.Exists(path))
|
if (Directory.Exists(path))
|
||||||
{
|
{
|
||||||
return GetEncoderPathFromDirectory(path);
|
return GetEncoderPathFromDirectory(path, "ffmpeg");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
|
@ -295,7 +264,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetEncoderPathFromDirectory(string path)
|
private string GetEncoderPathFromDirectory(string path, string filename)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -303,7 +272,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
var excludeExtensions = new[] { ".c" };
|
var excludeExtensions = new[] { ".c" };
|
||||||
|
|
||||||
return files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty));
|
return files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), filename, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty));
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
@ -314,8 +284,15 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
private string GetProbePathFromEncoderPath(string appPath)
|
private string GetProbePathFromEncoderPath(string appPath)
|
||||||
{
|
{
|
||||||
return FileSystem.GetFilePaths(Path.GetDirectoryName(appPath))
|
if (!string.IsNullOrEmpty(appPath))
|
||||||
.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase));
|
{
|
||||||
|
string pattern = @"[^\/\\]+?(\.[^\/\\\n.]+)?$";
|
||||||
|
string substitution = @"ffprobe$1";
|
||||||
|
|
||||||
|
return Regex.Replace(appPath, pattern, substitution);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -323,15 +300,15 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fileName"></param>
|
/// <param name="fileName"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private string ExistsOnSystemPath(string fileName)
|
private string ExistsOnSystemPath(string filename)
|
||||||
{
|
{
|
||||||
var values = Environment.GetEnvironmentVariable("PATH");
|
var values = Environment.GetEnvironmentVariable("PATH");
|
||||||
|
|
||||||
foreach (var path in values.Split(Path.PathSeparator))
|
foreach (var path in values.Split(Path.PathSeparator))
|
||||||
{
|
{
|
||||||
var candidatePath = GetEncoderPathFromDirectory(path);
|
var candidatePath = GetEncoderPathFromDirectory(path, filename);
|
||||||
|
|
||||||
if (ValidatePath("Found on PATH", candidatePath))
|
if (!string.IsNullOrEmpty(candidatePath))
|
||||||
{
|
{
|
||||||
return candidatePath;
|
return candidatePath;
|
||||||
}
|
}
|
||||||
|
@ -341,8 +318,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
private void LogPaths()
|
private void LogPaths()
|
||||||
{
|
{
|
||||||
_logger.LogInformation("FFMpeg: {0}", FFmpegPath ?? "not found");
|
_logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation.ToString(), FFmpegPath ?? string.Empty);
|
||||||
_logger.LogInformation("FFProbe: {0}", FFprobePath ?? "not found");
|
_logger.LogInformation("FFprobe: {0}: {1}", ProbeLocation.ToString(), FFprobePath ?? string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<string> _encoders = new List<string>();
|
private List<string> _encoders = new List<string>();
|
||||||
|
|
|
@ -4,6 +4,21 @@ using MediaBrowser.Model.Updates;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.System
|
namespace MediaBrowser.Model.System
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enum describing the location of the FFmpeg tool.
|
||||||
|
/// </summary>
|
||||||
|
public enum FFmpegLocation
|
||||||
|
{
|
||||||
|
/// <summary>No path to FFmpeg found.</summary>
|
||||||
|
NotFound,
|
||||||
|
/// <summary>Path supplied via command line using switch --ffmpeg.</summary>
|
||||||
|
SetByArgument,
|
||||||
|
/// <summary>User has supplied path via Transcoding UI page.</summary>
|
||||||
|
Custom,
|
||||||
|
/// <summary>FFmpeg tool found on system $PATH.</summary>
|
||||||
|
System
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class SystemInfo
|
/// Class SystemInfo
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -122,7 +137,7 @@ namespace MediaBrowser.Model.System
|
||||||
/// <value><c>true</c> if this instance has update available; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if this instance has update available; otherwise, <c>false</c>.</value>
|
||||||
public bool HasUpdateAvailable { get; set; }
|
public bool HasUpdateAvailable { get; set; }
|
||||||
|
|
||||||
public string EncoderLocationType { get; set; }
|
public FFmpegLocation EncoderLocation { get; set; }
|
||||||
|
|
||||||
public Architecture SystemArchitecture { get; set; }
|
public Architecture SystemArchitecture { get; set; }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user