mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-03-13 13:46:24 +00:00
beginning remote subtitle downloading
This commit is contained in:
@@ -31,11 +31,11 @@ using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Controller.Resolvers;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Controller.Subtitles;
|
||||
using MediaBrowser.Controller.Themes;
|
||||
using MediaBrowser.Dlna;
|
||||
using MediaBrowser.Dlna.Eventing;
|
||||
using MediaBrowser.Dlna.Main;
|
||||
using MediaBrowser.Dlna.PlayTo;
|
||||
using MediaBrowser.Dlna.Server;
|
||||
using MediaBrowser.MediaEncoding.BdInfo;
|
||||
using MediaBrowser.MediaEncoding.Encoder;
|
||||
@@ -44,6 +44,7 @@ using MediaBrowser.Model.MediaInfo;
|
||||
using MediaBrowser.Model.System;
|
||||
using MediaBrowser.Model.Updates;
|
||||
using MediaBrowser.Providers.Manager;
|
||||
using MediaBrowser.Providers.Subtitles;
|
||||
using MediaBrowser.Server.Implementations;
|
||||
using MediaBrowser.Server.Implementations.Channels;
|
||||
using MediaBrowser.Server.Implementations.Collections;
|
||||
@@ -193,6 +194,7 @@ namespace MediaBrowser.ServerApplication
|
||||
private IProviderRepository ProviderRepository { get; set; }
|
||||
|
||||
private INotificationManager NotificationManager { get; set; }
|
||||
private ISubtitleManager SubtitleManager { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ApplicationHost"/> class.
|
||||
@@ -531,6 +533,9 @@ namespace MediaBrowser.ServerApplication
|
||||
NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager);
|
||||
RegisterSingleInstance(NotificationManager);
|
||||
|
||||
SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor);
|
||||
RegisterSingleInstance(SubtitleManager);
|
||||
|
||||
var displayPreferencesTask = Task.Run(async () => await ConfigureDisplayPreferencesRepositories().ConfigureAwait(false));
|
||||
var itemsTask = Task.Run(async () => await ConfigureItemRepositories().ConfigureAwait(false));
|
||||
var userdataTask = Task.Run(async () => await ConfigureUserDataRepositories().ConfigureAwait(false));
|
||||
@@ -566,7 +571,7 @@ namespace MediaBrowser.ServerApplication
|
||||
{
|
||||
var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager).GetFFMpegInfo(progress).ConfigureAwait(false);
|
||||
|
||||
MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ApplicationPaths, JsonSerializer, info.Path, info.ProbePath, info.Version, FileSystemManager);
|
||||
MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ApplicationPaths, JsonSerializer, info.EncoderPath, info.ProbePath, info.Version, FileSystemManager);
|
||||
RegisterSingleInstance(MediaEncoder);
|
||||
}
|
||||
|
||||
@@ -710,6 +715,8 @@ namespace MediaBrowser.ServerApplication
|
||||
|
||||
LiveTvManager.AddParts(GetExports<ILiveTvService>());
|
||||
|
||||
SubtitleManager.AddParts(GetExports<ISubtitleProvider>());
|
||||
|
||||
SessionManager.AddParts(GetExports<ISessionControllerFactory>());
|
||||
|
||||
ChannelManager.AddParts(GetExports<IChannel>(), GetExports<IChannelFactory>());
|
||||
|
||||
@@ -4,6 +4,8 @@ using Mono.Unix.Native;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
#endif
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
{
|
||||
@@ -32,7 +34,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
switch (arg)
|
||||
{
|
||||
case "Version":
|
||||
return "20140304";
|
||||
return "20140506";
|
||||
case "FFMpegFilename":
|
||||
return "ffmpeg.exe";
|
||||
case "FFProbeFilename":
|
||||
@@ -42,7 +44,6 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
}
|
||||
break;
|
||||
|
||||
#if __MonoCS__
|
||||
case PlatformID.Unix:
|
||||
if (PlatformDetection.IsMac)
|
||||
{
|
||||
@@ -69,7 +70,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
switch (arg)
|
||||
{
|
||||
case "Version":
|
||||
return "20140304";
|
||||
return "20140506";
|
||||
case "FFMpegFilename":
|
||||
return "ffmpeg";
|
||||
case "FFProbeFilename":
|
||||
@@ -85,7 +86,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
switch (arg)
|
||||
{
|
||||
case "Version":
|
||||
return "20140304";
|
||||
return "20140505";
|
||||
case "FFMpegFilename":
|
||||
return "ffmpeg";
|
||||
case "FFProbeFilename":
|
||||
@@ -98,7 +99,6 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
}
|
||||
// Unsupported Unix platform
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -106,18 +106,17 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
private static string[] GetDownloadUrls()
|
||||
{
|
||||
var pid = Environment.OSVersion.Platform;
|
||||
|
||||
|
||||
switch (pid)
|
||||
{
|
||||
case PlatformID.Win32NT:
|
||||
return new[]
|
||||
{
|
||||
"http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20140304-git-f34cceb-win32-static.7z",
|
||||
"https://www.dropbox.com/s/6brdetuzbld93jk/ffmpeg-20140304-git-f34cceb-win32-static.7z?dl=1"
|
||||
"http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20140506-git-2baf1c8-win32-static.7z",
|
||||
"https://www.dropbox.com/s/lxlzxs0r83iatsv/ffmpeg-20140506-git-2baf1c8-win32-static.7z?dl=1"
|
||||
};
|
||||
|
||||
#if __MonoCS__
|
||||
case PlatformID.Unix:
|
||||
|
||||
case PlatformID.Unix:
|
||||
if (PlatformDetection.IsMac && PlatformDetection.IsX86_64)
|
||||
{
|
||||
return new[]
|
||||
@@ -132,8 +131,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
"http://ffmpeg.gusari.org/static/32bit/ffmpeg.static.32bit.2014-03-04.tar.gz",
|
||||
"https://www.dropbox.com/s/0l76mcauqqkta31/ffmpeg.static.32bit.2014-03-04.tar.gz?dl=1"
|
||||
"http://ffmpeg.gusari.org/static/32bit/ffmpeg.static.32bit.latest.tar.gz",
|
||||
"https://www.dropbox.com/s/k9s02pv5to6slfb/ffmpeg.static.32bit.2014-05-06.tar.gz?dl=1"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -141,22 +140,20 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
"http://ffmpeg.gusari.org/static/64bit/ffmpeg.static.64bit.2014-03-04.tar.gz",
|
||||
"https://www.dropbox.com/s/9wlxz440mdejuqe/ffmpeg.static.64bit.2014-03-04.tar.gz?dl=1"
|
||||
"http://ffmpeg.gusari.org/static/64bit/ffmpeg.static.64bit.latest.tar.gz",
|
||||
"https://www.dropbox.com/s/onuregwghywnzjo/ffmpeg.static.64bit.2014-05-05.tar.gz?dl=1"
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//No Unix version available
|
||||
return new string[] {};
|
||||
#endif
|
||||
return new string[] { };
|
||||
}
|
||||
return new string[] {};
|
||||
return new string[] { };
|
||||
}
|
||||
}
|
||||
|
||||
#if __MonoCS__
|
||||
public static class PlatformDetection
|
||||
{
|
||||
public readonly static bool IsWindows;
|
||||
@@ -166,34 +163,52 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
public readonly static bool IsX86_64;
|
||||
public readonly static bool IsArm;
|
||||
|
||||
static PlatformDetection ()
|
||||
static PlatformDetection()
|
||||
{
|
||||
IsWindows = Path.DirectorySeparatorChar == '\\';
|
||||
|
||||
//Don't call uname on windows
|
||||
if (!IsWindows)
|
||||
{
|
||||
Utsname uname;
|
||||
var callResult = Syscall.uname(out uname);
|
||||
if (callResult == 0)
|
||||
{
|
||||
IsMac = uname.sysname == "Darwin";
|
||||
IsLinux = !IsMac && uname.sysname == "Linux";
|
||||
var uname = GetUnixName();
|
||||
|
||||
Regex archX86 = new Regex("(i|I)[3-6]86");
|
||||
IsX86 = archX86.IsMatch(uname.machine);
|
||||
IsX86_64 = !IsX86 && uname.machine == "x86_64";
|
||||
IsArm = !IsX86 && !IsX86 && uname.machine.StartsWith("arm");
|
||||
}
|
||||
IsMac = uname.sysname == "Darwin";
|
||||
IsLinux = uname.sysname == "Linux";
|
||||
|
||||
var archX86 = new Regex("(i|I)[3-6]86");
|
||||
IsX86 = archX86.IsMatch(uname.machine);
|
||||
IsX86_64 = !IsX86 && uname.machine == "x86_64";
|
||||
IsArm = !IsX86 && !IsX86_64 && uname.machine.StartsWith("arm");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (System.Environment.Is64BitOperatingSystem)
|
||||
if (Environment.Is64BitOperatingSystem)
|
||||
IsX86_64 = true;
|
||||
else
|
||||
IsX86 = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static Uname GetUnixName()
|
||||
{
|
||||
var uname = new Uname();
|
||||
|
||||
#if __MonoCS__
|
||||
Utsname uname;
|
||||
var callResult = Syscall.uname(out uname);
|
||||
if (callResult == 0)
|
||||
{
|
||||
uname.sysname= uname.sysname;
|
||||
uname.machine= uname.machine;
|
||||
}
|
||||
#endif
|
||||
return uname;
|
||||
}
|
||||
}
|
||||
|
||||
public class Uname
|
||||
{
|
||||
public string sysname = string.Empty;
|
||||
public string machine = string.Empty;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -42,63 +42,86 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
|
||||
public async Task<FFMpegInfo> GetFFMpegInfo(IProgress<double> progress)
|
||||
{
|
||||
var versionedDirectoryPath = Path.Combine(GetMediaToolsPath(true), FFMpegDownloadInfo.Version);
|
||||
var rootEncoderPath = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg");
|
||||
var versionedDirectoryPath = Path.Combine(rootEncoderPath, FFMpegDownloadInfo.Version);
|
||||
|
||||
var info = new FFMpegInfo
|
||||
{
|
||||
ProbePath = Path.Combine(versionedDirectoryPath, FFMpegDownloadInfo.FFProbeFilename),
|
||||
Path = Path.Combine(versionedDirectoryPath, FFMpegDownloadInfo.FFMpegFilename),
|
||||
EncoderPath = Path.Combine(versionedDirectoryPath, FFMpegDownloadInfo.FFMpegFilename),
|
||||
Version = FFMpegDownloadInfo.Version
|
||||
};
|
||||
|
||||
Directory.CreateDirectory(versionedDirectoryPath);
|
||||
|
||||
var tasks = new List<Task>();
|
||||
|
||||
double ffmpegPercent = 0;
|
||||
double fontPercent = 0;
|
||||
var syncLock = new object();
|
||||
|
||||
if (!File.Exists(info.ProbePath) || !File.Exists(info.Path))
|
||||
if (!File.Exists(info.ProbePath) || !File.Exists(info.EncoderPath))
|
||||
{
|
||||
var ffmpegProgress = new ActionableProgress<double>();
|
||||
ffmpegProgress.RegisterAction(p =>
|
||||
// ffmpeg not present. See if there's an older version we can start with
|
||||
var existingVersion = GetExistingVersion(info, rootEncoderPath);
|
||||
|
||||
// No older version. Need to download and block until complete
|
||||
if (existingVersion == null)
|
||||
{
|
||||
ffmpegPercent = p;
|
||||
|
||||
lock (syncLock)
|
||||
{
|
||||
progress.Report((ffmpegPercent / 2) + (fontPercent / 2));
|
||||
}
|
||||
});
|
||||
|
||||
tasks.Add(DownloadFFMpeg(info, ffmpegProgress));
|
||||
}
|
||||
else
|
||||
{
|
||||
ffmpegPercent = 100;
|
||||
progress.Report(50);
|
||||
}
|
||||
|
||||
var fontProgress = new ActionableProgress<double>();
|
||||
fontProgress.RegisterAction(p =>
|
||||
{
|
||||
fontPercent = p;
|
||||
|
||||
lock (syncLock)
|
||||
{
|
||||
progress.Report((ffmpegPercent / 2) + (fontPercent / 2));
|
||||
await DownloadFFMpeg(versionedDirectoryPath, progress).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
else
|
||||
{
|
||||
// Older version found.
|
||||
// Start with that. Download new version in the background.
|
||||
var newPath = versionedDirectoryPath;
|
||||
Task.Run(() => DownloadFFMpegInBackground(newPath));
|
||||
|
||||
tasks.Add(DownloadFonts(versionedDirectoryPath, fontProgress));
|
||||
info = existingVersion;
|
||||
versionedDirectoryPath = Path.GetDirectoryName(info.EncoderPath);
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
await DownloadFonts(versionedDirectoryPath).ConfigureAwait(false);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private async Task DownloadFFMpeg(FFMpegInfo info, IProgress<double> progress)
|
||||
private FFMpegInfo GetExistingVersion(FFMpegInfo info, string rootEncoderPath)
|
||||
{
|
||||
var encoderFilename = Path.GetFileName(info.EncoderPath);
|
||||
var probeFilename = Path.GetFileName(info.ProbePath);
|
||||
|
||||
foreach (var directory in Directory.EnumerateDirectories(rootEncoderPath, "*", SearchOption.TopDirectoryOnly)
|
||||
.ToList())
|
||||
{
|
||||
var allFiles = Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories).ToList();
|
||||
|
||||
var encoder = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), encoderFilename, StringComparison.OrdinalIgnoreCase));
|
||||
var probe = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), probeFilename, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(encoder) &&
|
||||
!string.IsNullOrWhiteSpace(probe))
|
||||
{
|
||||
return new FFMpegInfo
|
||||
{
|
||||
EncoderPath = encoder,
|
||||
ProbePath = probe,
|
||||
Version = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(probe))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async void DownloadFFMpegInBackground(string directory)
|
||||
{
|
||||
try
|
||||
{
|
||||
await DownloadFFMpeg(directory, new Progress<double>()).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error downloading ffmpeg", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadFFMpeg(string directory, IProgress<double> progress)
|
||||
{
|
||||
foreach (var url in FFMpegDownloadInfo.FfMpegUrls)
|
||||
{
|
||||
@@ -114,7 +137,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
ExtractFFMpeg(tempFile, Path.GetDirectoryName(info.Path));
|
||||
ExtractFFMpeg(tempFile, directory);
|
||||
return;
|
||||
}
|
||||
catch (HttpException ex)
|
||||
@@ -132,7 +155,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
|
||||
private void ExtractFFMpeg(string tempFile, string targetFolder)
|
||||
{
|
||||
_logger.Debug("Extracting ffmpeg from {0}", tempFile);
|
||||
_logger.Info("Extracting ffmpeg from {0}", tempFile);
|
||||
|
||||
var tempFolder = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString());
|
||||
|
||||
@@ -171,6 +194,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
|
||||
private void ExtractArchive(string archivePath, string targetPath)
|
||||
{
|
||||
_logger.Info("Extracting {0} to {1}", archivePath, targetPath);
|
||||
|
||||
if (string.Equals(FFMpegDownloadInfo.ArchiveType, "7z", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_zipClient.ExtractAllFrom7z(archivePath, targetPath, true);
|
||||
@@ -182,6 +207,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
}
|
||||
private void Extract7zArchive(string archivePath, string targetPath)
|
||||
{
|
||||
_logger.Info("Extracting {0} to {1}", archivePath, targetPath);
|
||||
|
||||
_zipClient.ExtractAllFrom7z(archivePath, targetPath, true);
|
||||
}
|
||||
|
||||
@@ -201,7 +228,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
/// Extracts the fonts.
|
||||
/// </summary>
|
||||
/// <param name="targetPath">The target path.</param>
|
||||
private async Task DownloadFonts(string targetPath, IProgress<double> progress)
|
||||
/// <returns>Task.</returns>
|
||||
private async Task DownloadFonts(string targetPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -213,12 +241,19 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
|
||||
var fontFile = Path.Combine(fontsDirectory, fontFilename);
|
||||
|
||||
if (!File.Exists(fontFile))
|
||||
if (File.Exists(fontFile))
|
||||
{
|
||||
await DownloadFontFile(fontsDirectory, fontFilename, progress).ConfigureAwait(false);
|
||||
await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Kick this off, but no need to wait on it
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await DownloadFontFile(fontsDirectory, fontFilename, new Progress<double>()).ConfigureAwait(false);
|
||||
await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
|
||||
await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
@@ -230,8 +265,6 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
// Don't let the server crash because of this
|
||||
_logger.ErrorException("Error writing ffmpeg font files", ex);
|
||||
}
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -325,19 +358,5 @@ namespace MediaBrowser.ServerApplication.FFMpeg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media tools path.
|
||||
/// </summary>
|
||||
/// <param name="create">if set to <c>true</c> [create].</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private string GetMediaToolsPath(bool create)
|
||||
{
|
||||
var path = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg");
|
||||
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/// Gets or sets the path.
|
||||
/// </summary>
|
||||
/// <value>The path.</value>
|
||||
public string Path { get; set; }
|
||||
public string EncoderPath { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the probe path.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user