mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-04-24 22:17:25 -04:00
Merge branch 'master' into usings
This commit is contained in:
commit
ddd5d3aaec
86 changed files with 552 additions and 358 deletions
|
@ -37,7 +37,7 @@ namespace Emby.Naming.AudioBook
|
|||
/// <value>The type.</value>
|
||||
public bool IsDirectory { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <inheritdoc />
|
||||
public int CompareTo(AudioBookFileInfo other)
|
||||
{
|
||||
if (ReferenceEquals(this, other))
|
||||
|
|
|
@ -29,11 +29,7 @@ namespace Emby.Naming.AudioBook
|
|||
// Filter out all extras, otherwise they could cause stacks to not be resolved
|
||||
// See the unit test TestStackedWithTrailer
|
||||
var metadata = audiobookFileInfos
|
||||
.Select(i => new FileSystemMetadata
|
||||
{
|
||||
FullName = i.Path,
|
||||
IsDirectory = i.IsDirectory
|
||||
});
|
||||
.Select(i => new FileSystemMetadata { FullName = i.Path, IsDirectory = i.IsDirectory });
|
||||
|
||||
var stackResult = new StackResolver(_options)
|
||||
.ResolveAudioBooks(metadata);
|
||||
|
@ -42,11 +38,7 @@ namespace Emby.Naming.AudioBook
|
|||
{
|
||||
var stackFiles = stack.Files.Select(i => audioBookResolver.Resolve(i, stack.IsDirectoryStack)).ToList();
|
||||
stackFiles.Sort();
|
||||
var info = new AudioBookInfo
|
||||
{
|
||||
Files = stackFiles,
|
||||
Name = stack.Name
|
||||
};
|
||||
var info = new AudioBookInfo { Files = stackFiles, Name = stack.Name };
|
||||
|
||||
yield return info;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ namespace Emby.Naming.Subtitles
|
|||
IsForced = _options.SubtitleForcedFlags.Any(i => flags.Contains(i, StringComparer.OrdinalIgnoreCase))
|
||||
};
|
||||
|
||||
var parts = flags.Where(i => !_options.SubtitleDefaultFlags.Contains(i, StringComparer.OrdinalIgnoreCase) && !_options.SubtitleForcedFlags.Contains(i, StringComparer.OrdinalIgnoreCase))
|
||||
var parts = flags.Where(i => !_options.SubtitleDefaultFlags.Contains(i, StringComparer.OrdinalIgnoreCase)
|
||||
&& !_options.SubtitleForcedFlags.Contains(i, StringComparer.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
|
||||
// Should have a name, language and file extension
|
||||
|
|
|
@ -18,7 +18,13 @@ namespace Emby.Naming.TV
|
|||
_options = options;
|
||||
}
|
||||
|
||||
public EpisodePathParserResult Parse(string path, bool isDirectory, bool? isNamed = null, bool? isOptimistic = null, bool? supportsAbsoluteNumbers = null, bool fillExtendedInfo = true)
|
||||
public EpisodePathParserResult Parse(
|
||||
string path,
|
||||
bool isDirectory,
|
||||
bool? isNamed = null,
|
||||
bool? isOptimistic = null,
|
||||
bool? supportsAbsoluteNumbers = null,
|
||||
bool fillExtendedInfo = true)
|
||||
{
|
||||
// Added to be able to use regex patterns which require a file extension.
|
||||
// There were no failed tests without this block, but to be safe, we can keep it until
|
||||
|
@ -64,7 +70,7 @@ namespace Emby.Naming.TV
|
|||
{
|
||||
result.SeriesName = result.SeriesName
|
||||
.Trim()
|
||||
.Trim(new[] { '_', '.', '-' })
|
||||
.Trim('_', '.', '-')
|
||||
.Trim();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace Emby.Naming.TV
|
|||
public int? SeasonNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="SeasonPathParserResult"/> is success.
|
||||
/// Gets or sets a value indicating whether this <see cref="SeasonPathParserResult" /> is success.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if success; otherwise, <c>false</c>.</value>
|
||||
public bool Success { get; set; }
|
||||
|
|
|
@ -21,31 +21,24 @@ namespace Emby.Naming.Video
|
|||
|
||||
public IEnumerable<FileStack> ResolveDirectories(IEnumerable<string> files)
|
||||
{
|
||||
return Resolve(files.Select(i => new FileSystemMetadata
|
||||
{
|
||||
FullName = i,
|
||||
IsDirectory = true
|
||||
}));
|
||||
return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = true }));
|
||||
}
|
||||
|
||||
public IEnumerable<FileStack> ResolveFiles(IEnumerable<string> files)
|
||||
{
|
||||
return Resolve(files.Select(i => new FileSystemMetadata
|
||||
{
|
||||
FullName = i,
|
||||
IsDirectory = false
|
||||
}));
|
||||
return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = false }));
|
||||
}
|
||||
|
||||
public IEnumerable<FileStack> ResolveAudioBooks(IEnumerable<FileSystemMetadata> files)
|
||||
{
|
||||
foreach (var directory in files.GroupBy(file => file.IsDirectory ? file.FullName : Path.GetDirectoryName(file.FullName)))
|
||||
var groupedDirectoryFiles = files.GroupBy(file =>
|
||||
file.IsDirectory
|
||||
? file.FullName
|
||||
: Path.GetDirectoryName(file.FullName));
|
||||
|
||||
foreach (var directory in groupedDirectoryFiles)
|
||||
{
|
||||
var stack = new FileStack()
|
||||
{
|
||||
Name = Path.GetFileName(directory.Key),
|
||||
IsDirectoryStack = false
|
||||
};
|
||||
var stack = new FileStack { Name = Path.GetFileName(directory.Key), IsDirectoryStack = false };
|
||||
foreach (var file in directory)
|
||||
{
|
||||
if (file.IsDirectory)
|
||||
|
|
|
@ -77,7 +77,9 @@ namespace Emby.Naming.Video
|
|||
/// Gets the file name without extension.
|
||||
/// </summary>
|
||||
/// <value>The file name without extension.</value>
|
||||
public string FileNameWithoutExtension => !IsDirectory ? System.IO.Path.GetFileNameWithoutExtension(Path) : System.IO.Path.GetFileName(Path);
|
||||
public string FileNameWithoutExtension => !IsDirectory
|
||||
? System.IO.Path.GetFileNameWithoutExtension(Path)
|
||||
: System.IO.Path.GetFileName(Path);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
|
|
|
@ -33,11 +33,7 @@ namespace Emby.Naming.Video
|
|||
// See the unit test TestStackedWithTrailer
|
||||
var nonExtras = videoInfos
|
||||
.Where(i => i.ExtraType == null)
|
||||
.Select(i => new FileSystemMetadata
|
||||
{
|
||||
FullName = i.Path,
|
||||
IsDirectory = i.IsDirectory
|
||||
});
|
||||
.Select(i => new FileSystemMetadata { FullName = i.Path, IsDirectory = i.IsDirectory });
|
||||
|
||||
var stackResult = new StackResolver(_options)
|
||||
.Resolve(nonExtras).ToList();
|
||||
|
@ -57,11 +53,7 @@ namespace Emby.Naming.Video
|
|||
|
||||
info.Year = info.Files[0].Year;
|
||||
|
||||
var extraBaseNames = new List<string>
|
||||
{
|
||||
stack.Name,
|
||||
Path.GetFileNameWithoutExtension(stack.Files[0])
|
||||
};
|
||||
var extraBaseNames = new List<string> { stack.Name, Path.GetFileNameWithoutExtension(stack.Files[0]) };
|
||||
|
||||
var extras = GetExtras(remainingFiles, extraBaseNames);
|
||||
|
||||
|
@ -83,10 +75,7 @@ namespace Emby.Naming.Video
|
|||
|
||||
foreach (var media in standaloneMedia)
|
||||
{
|
||||
var info = new VideoInfo(media.Name)
|
||||
{
|
||||
Files = new List<VideoFileInfo> { media }
|
||||
};
|
||||
var info = new VideoInfo(media.Name) { Files = new List<VideoFileInfo> { media } };
|
||||
|
||||
info.Year = info.Files[0].Year;
|
||||
|
||||
|
@ -222,8 +211,8 @@ namespace Emby.Naming.Video
|
|||
{
|
||||
testFilename = testFilename.Substring(folderName.Length).Trim();
|
||||
return string.IsNullOrEmpty(testFilename)
|
||||
|| testFilename[0] == '-'
|
||||
|| string.IsNullOrWhiteSpace(Regex.Replace(testFilename, @"\[([^]]*)\]", string.Empty));
|
||||
|| testFilename[0] == '-'
|
||||
|| string.IsNullOrWhiteSpace(Regex.Replace(testFilename, @"\[([^]]*)\]", string.Empty));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -239,7 +228,8 @@ namespace Emby.Naming.Video
|
|||
|
||||
return remainingFiles
|
||||
.Where(i => i.ExtraType == null)
|
||||
.Where(i => baseNames.Any(b => i.FileNameWithoutExtension.StartsWith(b, StringComparison.OrdinalIgnoreCase)))
|
||||
.Where(i => baseNames.Any(b =>
|
||||
i.FileNameWithoutExtension.StartsWith(b, StringComparison.OrdinalIgnoreCase)))
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1803,7 +1803,7 @@ namespace Emby.Server.Implementations
|
|||
}
|
||||
|
||||
_userRepository?.Dispose();
|
||||
_displayPreferencesRepository.Dispose();
|
||||
_displayPreferencesRepository?.Dispose();
|
||||
}
|
||||
|
||||
_userRepository = null;
|
||||
|
|
|
@ -9,6 +9,7 @@ using MediaBrowser.Controller.Channels;
|
|||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
||||
namespace Emby.Server.Implementations.Channels
|
||||
{
|
||||
|
@ -18,27 +19,30 @@ namespace Emby.Server.Implementations.Channels
|
|||
private readonly IUserManager _userManager;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
public RefreshChannelsScheduledTask(
|
||||
IChannelManager channelManager,
|
||||
IUserManager userManager,
|
||||
ILogger<RefreshChannelsScheduledTask> logger,
|
||||
ILibraryManager libraryManager)
|
||||
ILibraryManager libraryManager,
|
||||
ILocalizationManager localization)
|
||||
{
|
||||
_channelManager = channelManager;
|
||||
_userManager = userManager;
|
||||
_logger = logger;
|
||||
_libraryManager = libraryManager;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "Refresh Channels";
|
||||
public string Name => _localization.GetLocalizedString("TasksRefreshChannels");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => "Refreshes internet channel information.";
|
||||
public string Description => _localization.GetLocalizedString("TasksRefreshChannelsDescription");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => "Internet Channels";
|
||||
public string Category => _localization.GetLocalizedString("TasksChannelsCategory");
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => ((ChannelManager)_channelManager).Channels.Length == 0;
|
||||
|
|
|
@ -6289,8 +6289,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|||
statement.TryBind("@Codec" + index, attachment.Codec);
|
||||
statement.TryBind("@CodecTag" + index, attachment.CodecTag);
|
||||
statement.TryBind("@Comment" + index, attachment.Comment);
|
||||
statement.TryBind("@FileName" + index, attachment.FileName);
|
||||
statement.TryBind("@MimeType" + index, attachment.MimeType);
|
||||
statement.TryBind("@Filename" + index, attachment.FileName);
|
||||
statement.TryBind("@MIMEType" + index, attachment.MimeType);
|
||||
}
|
||||
|
||||
statement.Reset();
|
||||
|
|
|
@ -29,9 +29,9 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.3" />
|
||||
<PackageReference Include="Mono.Nat" Version="2.0.0" />
|
||||
<PackageReference Include="ServiceStack.Text.Core" Version="5.8.0" />
|
||||
<PackageReference Include="sharpcompress" Version="0.24.0" />
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
"User": "Gebruiker",
|
||||
"TvShows": "TV Programme",
|
||||
"System": "Stelsel",
|
||||
"SubtitlesDownloadedForItem": "Ondertitels afgelaai vir {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Ondertitels het misluk om af te laai van {0} vir {1}",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin Bediener is besig om te laai. Probeer weer in 'n kort tyd.",
|
||||
"ServerNameNeedsToBeRestarted": "{0} moet herbegin word",
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
"Application": "تطبيق",
|
||||
"Artists": "الفنانين",
|
||||
"AuthenticationSucceededWithUserName": "{0} سجل الدخول بنجاح",
|
||||
"Books": "كتب",
|
||||
"Books": "الكتب",
|
||||
"CameraImageUploadedFrom": "صورة كاميرا جديدة تم رفعها من {0}",
|
||||
"Channels": "القنوات",
|
||||
"ChapterNameValue": "فصل {0}",
|
||||
"ChapterNameValue": "الفصل {0}",
|
||||
"Collections": "مجموعات",
|
||||
"DeviceOfflineWithName": "قُطِع الاتصال بـ{0}",
|
||||
"DeviceOnlineWithName": "{0} متصل",
|
||||
|
@ -51,8 +51,8 @@
|
|||
"NotificationOptionAudioPlaybackStopped": "تم إيقاف تشغيل المقطع الصوتي",
|
||||
"NotificationOptionCameraImageUploaded": "تم رفع صورة الكاميرا",
|
||||
"NotificationOptionInstallationFailed": "فشل في التثبيت",
|
||||
"NotificationOptionNewLibraryContent": "أُضِيفَ محتوى جديد",
|
||||
"NotificationOptionPluginError": "فشل في الـPlugin",
|
||||
"NotificationOptionNewLibraryContent": "تم إضافة محتوى جديد",
|
||||
"NotificationOptionPluginError": "فشل في البرنامج المضاف",
|
||||
"NotificationOptionPluginInstalled": "تم تثبيت الملحق",
|
||||
"NotificationOptionPluginUninstalled": "تمت إزالة الملحق",
|
||||
"NotificationOptionPluginUpdateInstalled": "تم تثبيت تحديثات الملحق",
|
||||
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "سيرفر Jellyfin قيد التشغيل . الرجاء المحاولة بعد قليل.",
|
||||
"SubtitleDownloadFailureForItem": "عملية إنزال الترجمة فشلت لـ{0}",
|
||||
"SubtitleDownloadFailureFromForItem": "الترجمات فشلت في التحميل من {0} الى {1}",
|
||||
"SubtitlesDownloadedForItem": "تم تحميل الترجمات الى {0}",
|
||||
"Sync": "مزامنة",
|
||||
"System": "النظام",
|
||||
"TvShows": "البرامج التلفزيونية",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Сървърът зарежда. Моля, опитайте отново след малко.",
|
||||
"SubtitleDownloadFailureForItem": "Неуспешно изтегляне на субтитри за {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Поднадписите за {1} от {0} не можаха да се изтеглят",
|
||||
"SubtitlesDownloadedForItem": "Изтеглени са субтитри за {0}",
|
||||
"Sync": "Синхронизиране",
|
||||
"System": "Система",
|
||||
"TvShows": "Телевизионни сериали",
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
"TvShows": "টিভি শোগুলো",
|
||||
"System": "সিস্টেম",
|
||||
"Sync": "সিংক",
|
||||
"SubtitlesDownloadedForItem": "{0} এর জন্য সাবটাইটেল ডাউনলোড করা হয়েছে",
|
||||
"SubtitleDownloadFailureFromForItem": "{2} থেকে {1} এর জন্য সাবটাইটেল ডাউনলোড ব্যর্থ",
|
||||
"StartupEmbyServerIsLoading": "জেলিফিন সার্ভার লোড হচ্ছে। দয়া করে একটু পরে আবার চেষ্টা করুন।",
|
||||
"Songs": "গানগুলো",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "El Servidor d'Jellyfin està carregant. Si et plau, prova de nou en breus.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Els subtítols no s'han pogut baixar de {0} per {1}",
|
||||
"SubtitlesDownloadedForItem": "Subtítols descarregats per a {0}",
|
||||
"Sync": "Sincronitzar",
|
||||
"System": "System",
|
||||
"TvShows": "Espectacles de TV",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server je spouštěn. Zkuste to prosím v brzké době znovu.",
|
||||
"SubtitleDownloadFailureForItem": "Stahování titulků selhalo pro {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Stažení titulků pro {1} z {0} selhalo",
|
||||
"SubtitlesDownloadedForItem": "Staženy titulky pro {0}",
|
||||
"Sync": "Synchronizace",
|
||||
"System": "Systém",
|
||||
"TvShows": "TV seriály",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server er i gang med at starte op. Prøv venligst igen om lidt.",
|
||||
"SubtitleDownloadFailureForItem": "Fejlet i download af undertekster for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Undertekster kunne ikke downloades fra {0} til {1}",
|
||||
"SubtitlesDownloadedForItem": "Undertekster downloadet for {0}",
|
||||
"Sync": "Synk",
|
||||
"System": "System",
|
||||
"TvShows": "TV serier",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"Albums": "Alben",
|
||||
"AppDeviceValues": "Anw: {0}, Gerät: {1}",
|
||||
"AppDeviceValues": "App: {0}, Gerät: {1}",
|
||||
"Application": "Anwendung",
|
||||
"Artists": "Interpreten",
|
||||
"AuthenticationSucceededWithUserName": "{0} hat sich erfolgreich authentifziert",
|
||||
|
@ -50,7 +50,7 @@
|
|||
"NotificationOptionAudioPlayback": "Audiowiedergabe gestartet",
|
||||
"NotificationOptionAudioPlaybackStopped": "Audiowiedergabe gestoppt",
|
||||
"NotificationOptionCameraImageUploaded": "Foto hochgeladen",
|
||||
"NotificationOptionInstallationFailed": "Fehler bei der Installation",
|
||||
"NotificationOptionInstallationFailed": "Installation fehlgeschlagen",
|
||||
"NotificationOptionNewLibraryContent": "Neuer Inhalt hinzugefügt",
|
||||
"NotificationOptionPluginError": "Plugin-Fehler",
|
||||
"NotificationOptionPluginInstalled": "Plugin installiert",
|
||||
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin-Server startet, bitte versuche es gleich noch einmal.",
|
||||
"SubtitleDownloadFailureForItem": "Download der Untertitel fehlgeschlagen für {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Untertitel von {0} für {1} konnten nicht heruntergeladen werden",
|
||||
"SubtitlesDownloadedForItem": "Untertitel heruntergeladen für {0}",
|
||||
"Sync": "Synchronisation",
|
||||
"System": "System",
|
||||
"TvShows": "TV-Sendungen",
|
||||
|
@ -93,5 +92,27 @@
|
|||
"UserStoppedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} auf {2} beendet",
|
||||
"ValueHasBeenAddedToLibrary": "{0} wurde deiner Bibliothek hinzugefügt",
|
||||
"ValueSpecialEpisodeName": "Extra - {0}",
|
||||
"VersionNumber": "Version {0}"
|
||||
"VersionNumber": "Version {0}",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Durchsucht das Internet nach fehlenden Untertiteln, basierend auf den Meta Einstellungen.",
|
||||
"TaskDownloadMissingSubtitles": "Lade fehlende Untertitel herunter",
|
||||
"TaskRefreshChannelsDescription": "Erneuere Internet Kanal Informationen.",
|
||||
"TaskRefreshChannels": "Erneuere Kanäle",
|
||||
"TaskCleanTranscodeDescription": "Löscht Transkodierdateien welche älter als ein Tag sind.",
|
||||
"TaskCleanTranscode": "Lösche Transkodier Pfad",
|
||||
"TaskUpdatePluginsDescription": "Läd Updates für Plugins herunter, welche dazu eingestellt sind automatisch zu updaten und installiert sie.",
|
||||
"TaskUpdatePlugins": "Update Plugins",
|
||||
"TaskRefreshPeopleDescription": "Erneuert Metadaten für Schausteller und Regisseure in deinen Bibliotheken.",
|
||||
"TaskRefreshPeople": "Erneuere Schausteller",
|
||||
"TaskCleanLogsDescription": "Lösche Log Datein die älter als {0} Tage sind.",
|
||||
"TaskCleanLogs": "Lösche Log Pfad",
|
||||
"TaskRefreshLibraryDescription": "Scanne alle Bibliotheken für hinzugefügte Datein und erneuere Metadaten.",
|
||||
"TaskRefreshLibrary": "Scanne alle Bibliotheken",
|
||||
"TaskRefreshChapterImagesDescription": "Kreiert Vorschaubilder für Videos welche Kapitel haben.",
|
||||
"TaskRefreshChapterImages": "Extrahiert Kapitel-Bilder",
|
||||
"TaskCleanCacheDescription": "Löscht Zwischenspeicherdatein die nicht länger von System gebraucht werden.",
|
||||
"TaskCleanCache": "Leere Cache Pfad",
|
||||
"TasksChannelsCategory": "Internet Kanäle",
|
||||
"TasksApplicationCategory": "Anwendung",
|
||||
"TasksLibraryCategory": "Bibliothek",
|
||||
"TasksMaintenanceCategory": "Wartung"
|
||||
}
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Ο Jellyfin Server φορτώνει. Παρακαλώ δοκιμάστε σε λίγο.",
|
||||
"SubtitleDownloadFailureForItem": "Οι υπότιτλοι απέτυχαν να κατέβουν για {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Αποτυχίες μεταφόρτωσης υποτίτλων από {0} για {1}",
|
||||
"SubtitlesDownloadedForItem": "Οι υπότιτλοι κατέβηκαν για {0}",
|
||||
"Sync": "Συγχρονισμός",
|
||||
"System": "Σύστημα",
|
||||
"TvShows": "Τηλεοπτικές Σειρές",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
|
||||
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
|
||||
"Sync": "Sync",
|
||||
"System": "System",
|
||||
"TvShows": "TV Shows",
|
||||
|
|
|
@ -75,7 +75,6 @@
|
|||
"Songs": "Songs",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.",
|
||||
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
|
||||
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
|
||||
"Sync": "Sync",
|
||||
"System": "System",
|
||||
"TvShows": "TV Shows",
|
||||
|
@ -92,5 +91,27 @@
|
|||
"UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
|
||||
"ValueSpecialEpisodeName": "Special - {0}",
|
||||
"VersionNumber": "Version {0}"
|
||||
"VersionNumber": "Version {0}",
|
||||
"TasksMaintenanceCategory": "Maintenance",
|
||||
"TasksLibraryCategory": "Library",
|
||||
"TasksApplicationCategory": "Application",
|
||||
"TasksChannelsCategory": "Internet Channels",
|
||||
"TaskCleanCache": "Clean Cache Directory",
|
||||
"TaskCleanCacheDescription": "Deletes cache files no longer needed by the system.",
|
||||
"TaskRefreshChapterImages": "Extract Chapter Images",
|
||||
"TaskRefreshChapterImagesDescription": "Creates thumbnails for videos that have chapters.",
|
||||
"TaskRefreshLibrary": "Scan Media Library",
|
||||
"TaskRefreshLibraryDescription": "Scans your media library for new files and refreshes metadata.",
|
||||
"TaskCleanLogs": "Clean Log Directory",
|
||||
"TaskCleanLogsDescription": "Deletes log files that are more than {0} days old.",
|
||||
"TaskRefreshPeople": "Refresh People",
|
||||
"TaskRefreshPeopleDescription": "Updates metadata for actors and directors in your media library.",
|
||||
"TaskUpdatePlugins": "Update Plugins",
|
||||
"TaskUpdatePluginsDescription": "Downloads and installs updates for plugins that are configured to update automatically.",
|
||||
"TaskCleanTranscode": "Clean Transcode Directory",
|
||||
"TaskCleanTranscodeDescription": "Deletes transcode files more than one day old.",
|
||||
"TaskRefreshChannels": "Refresh Channels",
|
||||
"TaskRefreshChannelsDescription": "Refreshes internet channel information.",
|
||||
"TaskDownloadMissingSubtitles": "Download missing subtitles",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Searches the internet for missing subtitles based on metadata configuration."
|
||||
}
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Fallo de descarga de subtítulos desde {0} para {1}",
|
||||
"SubtitlesDownloadedForItem": "Descargar subtítulos para {0}",
|
||||
"Sync": "Sincronizar",
|
||||
"System": "Sistema",
|
||||
"TvShows": "Series de TV",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "El servidor Jellyfin esta cargando. Por favor intente de nuevo dentro de poco.",
|
||||
"SubtitleDownloadFailureForItem": "Falló la descarga de subtítulos para {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Falló la descarga de subtitulos desde {0} para {1}",
|
||||
"SubtitlesDownloadedForItem": "Subtítulos descargados para {0}",
|
||||
"Sync": "Sincronizar",
|
||||
"System": "Sistema",
|
||||
"TvShows": "Programas de TV",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.",
|
||||
"SubtitleDownloadFailureForItem": "Error al descargar subtítulos para {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Fallo de descarga de subtítulos desde {0} para {1}",
|
||||
"SubtitlesDownloadedForItem": "Descargar subtítulos para {0}",
|
||||
"Sync": "Sincronizar",
|
||||
"System": "Sistema",
|
||||
"TvShows": "Programas de televisión",
|
||||
|
@ -93,5 +92,27 @@
|
|||
"UserStoppedPlayingItemWithValues": "{0} ha terminado de reproducir {1} en {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} ha sido añadido a tu biblioteca multimedia",
|
||||
"ValueSpecialEpisodeName": "Especial - {0}",
|
||||
"VersionNumber": "Versión {0}"
|
||||
"VersionNumber": "Versión {0}",
|
||||
"TasksMaintenanceCategory": "Mantenimiento",
|
||||
"TasksLibraryCategory": "Librería",
|
||||
"TasksApplicationCategory": "Aplicación",
|
||||
"TasksChannelsCategory": "Canales de internet",
|
||||
"TaskCleanCache": "Eliminar archivos temporales",
|
||||
"TaskCleanCacheDescription": "Elimina los archivos temporales que ya no son necesarios para el servidor.",
|
||||
"TaskRefreshChapterImages": "Extraer imágenes de los capítulos",
|
||||
"TaskRefreshChapterImagesDescription": "Crea las miniaturas de los vídeos que tengan capítulos.",
|
||||
"TaskRefreshLibrary": "Escanear la biblioteca",
|
||||
"TaskRefreshLibraryDescription": "Añade los archivos que se hayan añadido a la biblioteca y actualiza las etiquetas de los ya presentes.",
|
||||
"TaskCleanLogs": "Limpiar registros",
|
||||
"TaskCleanLogsDescription": "Elimina los archivos de registro que tengan más de {0} días.",
|
||||
"TaskRefreshPeople": "Actualizar personas",
|
||||
"TaskRefreshPeopleDescription": "Actualiza las etiquetas de los intérpretes y directores presentes en tus bibliotecas.",
|
||||
"TaskUpdatePlugins": "Actualizar extensiones",
|
||||
"TaskUpdatePluginsDescription": "Actualiza las extensiones que están configuradas para actualizarse automáticamente.",
|
||||
"TaskCleanTranscode": "Limpiar las transcodificaciones",
|
||||
"TaskCleanTranscodeDescription": "Elimina los archivos temporales de transcodificación anteriores a un día de antigüedad.",
|
||||
"TaskRefreshChannels": "Actualizar canales",
|
||||
"TaskRefreshChannelsDescription": "Actualiza la información de los canales de internet.",
|
||||
"TaskDownloadMissingSubtitles": "Descargar los subtítulos que faltan",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Busca en internet los subtítulos que falten en el contenido de tus bibliotecas, basándose en la configuración de los metadatos."
|
||||
}
|
||||
|
|
|
@ -1,56 +1,56 @@
|
|||
{
|
||||
"Albums": "آلبوم ها",
|
||||
"Albums": "آلبومها",
|
||||
"AppDeviceValues": "برنامه: {0} ، دستگاه: {1}",
|
||||
"Application": "برنامه",
|
||||
"Artists": "هنرمندان",
|
||||
"AuthenticationSucceededWithUserName": "{0} با موفقیت تایید اعتبار شد",
|
||||
"Books": "کتاب ها",
|
||||
"CameraImageUploadedFrom": "یک عکس جدید از دوربین ارسال شده {0}",
|
||||
"Channels": "کانال ها",
|
||||
"ChapterNameValue": "فصل {0}",
|
||||
"Collections": "کلکسیون ها",
|
||||
"Books": "کتابها",
|
||||
"CameraImageUploadedFrom": "یک عکس جدید از دوربین ارسال شده است {0}",
|
||||
"Channels": "کانالها",
|
||||
"ChapterNameValue": "قسمت {0}",
|
||||
"Collections": "مجموعهها",
|
||||
"DeviceOfflineWithName": "ارتباط {0} قطع شد",
|
||||
"DeviceOnlineWithName": "{0} متصل شده",
|
||||
"DeviceOnlineWithName": "{0} متصل شد",
|
||||
"FailedLoginAttemptWithUserName": "تلاش برای ورود از {0} ناموفق بود",
|
||||
"Favorites": "مورد علاقه ها",
|
||||
"Folders": "پوشه ها",
|
||||
"Favorites": "مورد علاقهها",
|
||||
"Folders": "پوشهها",
|
||||
"Genres": "ژانرها",
|
||||
"HeaderAlbumArtists": "هنرمندان آلبوم",
|
||||
"HeaderCameraUploads": "آپلودهای دوربین",
|
||||
"HeaderContinueWatching": "ادامه تماشا",
|
||||
"HeaderFavoriteAlbums": "آلبوم های مورد علاقه",
|
||||
"HeaderFavoriteAlbums": "آلبومهای مورد علاقه",
|
||||
"HeaderFavoriteArtists": "هنرمندان مورد علاقه",
|
||||
"HeaderFavoriteEpisodes": "قسمت های مورد علاقه",
|
||||
"HeaderFavoriteShows": "سریال های مورد علاقه",
|
||||
"HeaderFavoriteSongs": "آهنگ های مورد علاقه",
|
||||
"HeaderFavoriteEpisodes": "قسمتهای مورد علاقه",
|
||||
"HeaderFavoriteShows": "سریالهای مورد علاقه",
|
||||
"HeaderFavoriteSongs": "آهنگهای مورد علاقه",
|
||||
"HeaderLiveTV": "پخش زنده تلویزیون",
|
||||
"HeaderNextUp": "بعدی چیه",
|
||||
"HeaderRecordingGroups": "گروه های ضبط",
|
||||
"HeaderNextUp": "قسمت بعدی",
|
||||
"HeaderRecordingGroups": "گروههای ضبط",
|
||||
"HomeVideos": "ویدیوهای خانگی",
|
||||
"Inherit": "به ارث برده",
|
||||
"ItemAddedWithName": "{0} به کتابخانه افزوده شد",
|
||||
"ItemRemovedWithName": "{0} از کتابخانه حذف شد",
|
||||
"LabelIpAddressValue": "آدرس آی پی: {0}",
|
||||
"LabelRunningTimeValue": "زمان اجرا: {0}",
|
||||
"Latest": "آخرین",
|
||||
"Latest": "جدیدترینها",
|
||||
"MessageApplicationUpdated": "سرور Jellyfin بروزرسانی شد",
|
||||
"MessageApplicationUpdatedTo": "سرور جلیفین آپدیت شده به نسخه {0}",
|
||||
"MessageApplicationUpdatedTo": "سرور Jellyfin به نسخه {0} بروزرسانی شد",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "پکربندی بخش {0} سرور بروزرسانی شد",
|
||||
"MessageServerConfigurationUpdated": "پیکربندی سرور بروزرسانی شد",
|
||||
"MixedContent": "محتوای درهم",
|
||||
"Movies": "فیلم های سینمایی",
|
||||
"MixedContent": "محتوای مخلوط",
|
||||
"Movies": "فیلمها",
|
||||
"Music": "موسیقی",
|
||||
"MusicVideos": "موزیک ویدیوها",
|
||||
"NameInstallFailed": "{0} نصب با مشکل مواجه شده",
|
||||
"NameInstallFailed": "{0} نصب با مشکل مواجه شد",
|
||||
"NameSeasonNumber": "فصل {0}",
|
||||
"NameSeasonUnknown": "فصل های ناشناخته",
|
||||
"NewVersionIsAvailable": "یک نسخه جدید جلیفین برای بروزرسانی آماده میباشد.",
|
||||
"NameSeasonUnknown": "فصل ناشناخته",
|
||||
"NewVersionIsAvailable": "یک نسخه جدید Jellyfin برای بروزرسانی آماده میباشد.",
|
||||
"NotificationOptionApplicationUpdateAvailable": "بروزرسانی برنامه موجود است",
|
||||
"NotificationOptionApplicationUpdateInstalled": "بروزرسانی برنامه نصب شد",
|
||||
"NotificationOptionAudioPlayback": "پخش صدا آغاز شد",
|
||||
"NotificationOptionAudioPlaybackStopped": "پخش صدا متوقف شد",
|
||||
"NotificationOptionCameraImageUploaded": "تصاویر دوربین آپلود شد",
|
||||
"NotificationOptionInstallationFailed": "شکست نصب",
|
||||
"NotificationOptionInstallationFailed": "نصب شکست خورد",
|
||||
"NotificationOptionNewLibraryContent": "محتوای جدید افزوده شد",
|
||||
"NotificationOptionPluginError": "خرابی افزونه",
|
||||
"NotificationOptionPluginInstalled": "افزونه نصب شد",
|
||||
|
@ -58,40 +58,39 @@
|
|||
"NotificationOptionPluginUpdateInstalled": "بروزرسانی افزونه نصب شد",
|
||||
"NotificationOptionServerRestartRequired": "شروع مجدد سرور نیاز است",
|
||||
"NotificationOptionTaskFailed": "شکست وظیفه برنامه ریزی شده",
|
||||
"NotificationOptionUserLockedOut": "کاربر از سیستم خارج شد",
|
||||
"NotificationOptionUserLockedOut": "کاربر قفل شد",
|
||||
"NotificationOptionVideoPlayback": "پخش ویدیو آغاز شد",
|
||||
"NotificationOptionVideoPlaybackStopped": "پخش ویدیو متوقف شد",
|
||||
"Photos": "عکس ها",
|
||||
"Playlists": "لیست های پخش",
|
||||
"Photos": "عکسها",
|
||||
"Playlists": "لیستهای پخش",
|
||||
"Plugin": "افزونه",
|
||||
"PluginInstalledWithName": "{0} نصب شد",
|
||||
"PluginUninstalledWithName": "{0} حذف شد",
|
||||
"PluginUpdatedWithName": "{0} آپدیت شد",
|
||||
"ProviderValue": "ارائه دهنده: {0}",
|
||||
"ScheduledTaskFailedWithName": "{0} ناموفق بود",
|
||||
"ScheduledTaskFailedWithName": "{0} شکست خورد",
|
||||
"ScheduledTaskStartedWithName": "{0} شروع شد",
|
||||
"ServerNameNeedsToBeRestarted": "{0} احتیاج به راه اندازی مجدد",
|
||||
"Shows": "سریال ها",
|
||||
"Songs": "آهنگ ها",
|
||||
"ServerNameNeedsToBeRestarted": "{0} نیاز به راه اندازی مجدد دارد",
|
||||
"Shows": "سریالها",
|
||||
"Songs": "موسیقیها",
|
||||
"StartupEmbyServerIsLoading": "سرور Jellyfin در حال بارگیری است. لطفا کمی بعد دوباره تلاش کنید.",
|
||||
"SubtitleDownloadFailureForItem": "دانلود زیرنویس برای {0} ناموفق بود",
|
||||
"SubtitleDownloadFailureFromForItem": "زیرنویس برای دانلود با مشکل مواجه شده از {0} برای {1}",
|
||||
"SubtitlesDownloadedForItem": "زیرنویس {0} دانلود شد",
|
||||
"Sync": "همگامسازی",
|
||||
"SubtitleDownloadFailureFromForItem": "بارگیری زیرنویس برای {1} از {0} شکست خورد",
|
||||
"Sync": "همگامسازی",
|
||||
"System": "سیستم",
|
||||
"TvShows": "سریال های تلویزیونی",
|
||||
"TvShows": "سریالهای تلویزیونی",
|
||||
"User": "کاربر",
|
||||
"UserCreatedWithName": "کاربر {0} ایجاد شد",
|
||||
"UserDeletedWithName": "کاربر {0} حذف شد",
|
||||
"UserDownloadingItemWithValues": "{0} در حال دانلود است {1}",
|
||||
"UserLockedOutWithName": "کاربر {0} از سیستم خارج شد",
|
||||
"UserDownloadingItemWithValues": "{0} در حال بارگیری {1} میباشد",
|
||||
"UserLockedOutWithName": "کاربر {0} قفل شده است",
|
||||
"UserOfflineFromDevice": "ارتباط {0} از {1} قطع شد",
|
||||
"UserOnlineFromDevice": "{0}از {1} آنلاین میباشد",
|
||||
"UserPasswordChangedWithName": "رمز برای کاربر {0} تغییر یافت",
|
||||
"UserOnlineFromDevice": "{0} از {1} آنلاین میباشد",
|
||||
"UserPasswordChangedWithName": "گذرواژه برای کاربر {0} تغییر کرد",
|
||||
"UserPolicyUpdatedWithName": "سیاست کاربری برای {0} بروزرسانی شد",
|
||||
"UserStartedPlayingItemWithValues": "{0} شروع به پخش {1} کرد",
|
||||
"UserStoppedPlayingItemWithValues": "{0} پخش {1} را متوقف کرد",
|
||||
"ValueHasBeenAddedToLibrary": "{0} اضافه شده به کتابخانه رسانه شما",
|
||||
"ValueSpecialEpisodeName": "ویژه- {0}",
|
||||
"UserStartedPlayingItemWithValues": "{0} در حال پخش {1} بر روی {2} است",
|
||||
"UserStoppedPlayingItemWithValues": "{0} پخش {1} را بر روی {2} به پایان رساند",
|
||||
"ValueHasBeenAddedToLibrary": "{0} به کتابخانهی رسانهی شما افزوده شد",
|
||||
"ValueSpecialEpisodeName": "ویژه - {0}",
|
||||
"VersionNumber": "نسخه {0}"
|
||||
}
|
||||
|
|
|
@ -69,7 +69,6 @@
|
|||
"UserCreatedWithName": "Luotiin käyttäjä {0}",
|
||||
"TvShows": "TV-Ohjelmat",
|
||||
"Sync": "Synkronoi",
|
||||
"SubtitlesDownloadedForItem": "Tekstitys ladattu {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Tekstityksen lataaminen epäonnistui {0} - {1}",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin palvelin latautuu. Kokeile hetken kuluttua uudelleen.",
|
||||
"Songs": "Kappaleet",
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
"TvShows": "Pelikula",
|
||||
"System": "Sistema",
|
||||
"Sync": "Pag-sync",
|
||||
"SubtitlesDownloadedForItem": "Naidownload na ang subtitles {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Hindi naidownload ang subtitles {0} para sa {1}",
|
||||
"StartupEmbyServerIsLoading": "Nagloload ang Jellyfin Server. Sandaling maghintay.",
|
||||
"Songs": "Kanta",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Le serveur Jellyfin est en cours de chargement. Veuillez réessayer dans quelques instants.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Échec du téléchargement des sous-titres depuis {0} pour {1}",
|
||||
"SubtitlesDownloadedForItem": "Les sous-titres de {0} ont été téléchargés",
|
||||
"Sync": "Synchroniser",
|
||||
"System": "Système",
|
||||
"TvShows": "Séries Télé",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Le serveur Jellyfin est en cours de chargement. Veuillez réessayer dans quelques instants.",
|
||||
"SubtitleDownloadFailureForItem": "Le téléchargement des sous-titres pour {0} a échoué.",
|
||||
"SubtitleDownloadFailureFromForItem": "Échec du téléchargement des sous-titres depuis {0} pour {1}",
|
||||
"SubtitlesDownloadedForItem": "Les sous-titres de {0} ont été téléchargés",
|
||||
"Sync": "Synchroniser",
|
||||
"System": "Système",
|
||||
"TvShows": "Séries Télé",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server ladt. Bitte grad noeinisch probiere.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Ondertetle vo {0} för {1} hend ned chönne abeglade wärde",
|
||||
"SubtitlesDownloadedForItem": "Ondertetle abeglade för {0}",
|
||||
"Sync": "Synchronisation",
|
||||
"System": "System",
|
||||
"TvShows": "Färnsehserie",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "שרת Jellyfin בהליכי טעינה. אנא נסה שנית בעוד זמן קצר.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
|
||||
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
|
||||
"Sync": "סנכרן",
|
||||
"System": "System",
|
||||
"TvShows": "סדרות טלוויזיה",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server se učitava. Pokušajte ponovo kasnije.",
|
||||
"SubtitleDownloadFailureForItem": "Titlovi prijevoda nisu preuzeti za {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
|
||||
"SubtitlesDownloadedForItem": "Titlovi prijevoda preuzeti za {0}",
|
||||
"Sync": "Sink.",
|
||||
"System": "Sistem",
|
||||
"TvShows": "TV Shows",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "A Jellyfin Szerver betöltődik. Kérlek, próbáld újra hamarosan.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Nem sikerült a felirat letöltése innen: {0} ehhez: {1}",
|
||||
"SubtitlesDownloadedForItem": "Letöltött feliratok a következőhöz: {0}",
|
||||
"Sync": "Szinkronizál",
|
||||
"System": "Rendszer",
|
||||
"TvShows": "TV műsorok",
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
"User": "Pengguna",
|
||||
"System": "Sistem",
|
||||
"Sync": "Sinkron",
|
||||
"SubtitlesDownloadedForItem": "Talop telah diunduh untuk {0}",
|
||||
"Shows": "Tayangan",
|
||||
"ServerNameNeedsToBeRestarted": "{0} perlu dimuat ulang",
|
||||
"ScheduledTaskStartedWithName": "{0} dimulai",
|
||||
|
|
|
@ -86,7 +86,6 @@
|
|||
"UserOfflineFromDevice": "{0} hefur aftengst frá {1}",
|
||||
"UserLockedOutWithName": "Notanda {0} hefur verið hindraður aðgangur",
|
||||
"UserDownloadingItemWithValues": "{0} Hleður niður {1}",
|
||||
"SubtitlesDownloadedForItem": "Skjátextum halað niður fyrir {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Tókst ekki að hala niður skjátextum frá {0} til {1}",
|
||||
"ProviderValue": "Veitandi: {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Stilling {0} hefur verið uppfærð á netþjón",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin server si sta avviando. Per favore riprova più tardi.",
|
||||
"SubtitleDownloadFailureForItem": "Impossibile scaricare i sottotitoli per {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Impossibile scaricare i sottotitoli da {0} per {1}",
|
||||
"SubtitlesDownloadedForItem": "Sottotitoli scaricati per {0}",
|
||||
"Sync": "Sincronizza",
|
||||
"System": "Sistema",
|
||||
"TvShows": "Serie TV",
|
||||
|
|
|
@ -75,7 +75,6 @@
|
|||
"Songs": "曲",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin Server は現在読み込み中です。しばらくしてからもう一度お試しください。",
|
||||
"SubtitleDownloadFailureFromForItem": "{0} から {1}の字幕のダウンロードに失敗しました",
|
||||
"SubtitlesDownloadedForItem": "{0} の字幕がダウンロードされました",
|
||||
"Sync": "同期",
|
||||
"System": "システム",
|
||||
"TvShows": "テレビ番組",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server júktelýde. Áreketti kóp uzamaı qaıtalańyz.",
|
||||
"SubtitleDownloadFailureForItem": "Субтитрлер {0} үшін жүктеліп алынуы сәтсіз",
|
||||
"SubtitleDownloadFailureFromForItem": "{1} úshin sýbtıtrlerdi {0} kózinen júktep alý sátsiz",
|
||||
"SubtitlesDownloadedForItem": "{0} úshin sýbtıtrler júktelip alyndy",
|
||||
"Sync": "Úndestirý",
|
||||
"System": "Júıe",
|
||||
"TvShows": "TD-kórsetimder",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin 서버를 불러오고 있습니다. 잠시 후에 다시 시도하십시오.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "{0}에서 {1} 자막 다운로드에 실패했습니다",
|
||||
"SubtitlesDownloadedForItem": "{0} 자막 다운로드 완료",
|
||||
"Sync": "동기화",
|
||||
"System": "시스템",
|
||||
"TvShows": "TV 쇼",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server kraunasi. Netrukus pabandykite dar kartą.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "{1} subtitrai buvo nesėkmingai parsiųsti iš {0}",
|
||||
"SubtitlesDownloadedForItem": "{0} subtitrai parsiųsti",
|
||||
"Sync": "Sinchronizuoti",
|
||||
"System": "System",
|
||||
"TvShows": "TV Serialai",
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
"TvShows": "TV Raidījumi",
|
||||
"Sync": "Sinhronizācija",
|
||||
"System": "Sistēma",
|
||||
"SubtitlesDownloadedForItem": "Subtitri lejupielādēti priekš {0}",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin Serveris lādējas. Lūdzu mēģiniet vēlreiz pēc brīža.",
|
||||
"Songs": "Dziesmas",
|
||||
"Shows": "Raidījumi",
|
||||
|
|
|
@ -86,7 +86,6 @@
|
|||
"TvShows": "ТВ Серии",
|
||||
"System": "Систем",
|
||||
"Sync": "Синхронизација",
|
||||
"SubtitlesDownloadedForItem": "Спуштање превод за {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Преводот неуспешно се спушти од {0} за {1}",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin Server се пушта. Ве молиме причекајте.",
|
||||
"Songs": "Песни",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
|
||||
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
|
||||
"Sync": "Sync",
|
||||
"System": "Sistem",
|
||||
"TvShows": "TV Shows",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server laster. Prøv igjen snart.",
|
||||
"SubtitleDownloadFailureForItem": "En feil oppstå under nedlasting av undertekster for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Kunne ikke laste ned undertekster fra {0} for {1}",
|
||||
"SubtitlesDownloadedForItem": "Undertekster lastet ned for {0}",
|
||||
"Sync": "Synkroniser",
|
||||
"System": "System",
|
||||
"TvShows": "TV-serier",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server is aan het laden, probeer het later opnieuw.",
|
||||
"SubtitleDownloadFailureForItem": "Downloaden van ondertiteling voor {0} is mislukt",
|
||||
"SubtitleDownloadFailureFromForItem": "Ondertitels konden niet gedownload worden van {0} voor {1}",
|
||||
"SubtitlesDownloadedForItem": "Ondertiteling voor {0} is gedownload",
|
||||
"Sync": "Synchronisatie",
|
||||
"System": "Systeem",
|
||||
"TvShows": "TV-series",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Trwa wczytywanie serwera Jellyfin. Spróbuj ponownie za chwilę.",
|
||||
"SubtitleDownloadFailureForItem": "Pobieranie napisów dla {0} zakończone niepowodzeniem",
|
||||
"SubtitleDownloadFailureFromForItem": "Nieudane pobieranie napisów z {0} dla {1}",
|
||||
"SubtitlesDownloadedForItem": "Pobrano napisy dla {0}",
|
||||
"Sync": "Synchronizacja",
|
||||
"System": "System",
|
||||
"TvShows": "Seriale",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "O Servidor Jellyfin está carregando. Por favor, tente novamente mais tarde.",
|
||||
"SubtitleDownloadFailureForItem": "Download de legendas falhou para {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Houve um problema ao baixar as legendas de {0} para {1}",
|
||||
"SubtitlesDownloadedForItem": "Legendas baixadas para {0}",
|
||||
"Sync": "Sincronizar",
|
||||
"System": "Sistema",
|
||||
"TvShows": "Séries",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "O servidor Jellyfin está a iniciar. Tente novamente mais tarde.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas a partir de {0} para {1}",
|
||||
"SubtitlesDownloadedForItem": "Transferidas legendas para {0}",
|
||||
"Sync": "Sincronização",
|
||||
"System": "Sistema",
|
||||
"TvShows": "Programas TV",
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
"User": "Utilizador",
|
||||
"TvShows": "Séries",
|
||||
"System": "Sistema",
|
||||
"SubtitlesDownloadedForItem": "Legendas transferidas para {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas de {0} para {1}",
|
||||
"StartupEmbyServerIsLoading": "O servidor Jellyfin está a iniciar. Tente novamente dentro de momentos.",
|
||||
"ServerNameNeedsToBeRestarted": "{0} necessita ser reiniciado",
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
"TvShows": "Spectacole TV",
|
||||
"System": "Sistem",
|
||||
"Sync": "Sincronizare",
|
||||
"SubtitlesDownloadedForItem": "Subtitrari descarcate pentru {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Subtitrările nu au putut fi descărcate de la {0} pentru {1}",
|
||||
"StartupEmbyServerIsLoading": "Se încarcă serverul Jellyfin. Încercați din nou în scurt timp.",
|
||||
"Songs": "Melodii",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server загружается. Повторите попытку в ближайшее время.",
|
||||
"SubtitleDownloadFailureForItem": "Субтитры к {0} не удалось загрузить",
|
||||
"SubtitleDownloadFailureFromForItem": "Субтитры к {1} не удалось загрузить с {0}",
|
||||
"SubtitlesDownloadedForItem": "Субтитры к {0} загружены",
|
||||
"Sync": "Синхро",
|
||||
"System": "Система",
|
||||
"TvShows": "ТВ",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server sa spúšťa. Prosím, skúste to o chvíľu znova.",
|
||||
"SubtitleDownloadFailureForItem": "Sťahovanie titulkov pre {0} zlyhalo",
|
||||
"SubtitleDownloadFailureFromForItem": "Sťahovanie titulkov z {0} pre {1} zlyhalo",
|
||||
"SubtitlesDownloadedForItem": "Titulky pre {0} stiahnuté",
|
||||
"Sync": "Synchronizácia",
|
||||
"System": "Systém",
|
||||
"TvShows": "TV seriály",
|
||||
|
@ -93,5 +92,27 @@
|
|||
"UserStoppedPlayingItemWithValues": "{0} ukončil prehrávanie {1} na {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} bol pridané do vašej knižnice médií",
|
||||
"ValueSpecialEpisodeName": "Špeciál - {0}",
|
||||
"VersionNumber": "Verzia {0}"
|
||||
"VersionNumber": "Verzia {0}",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Vyhľadá na internete chýbajúce titulky podľa toho, ako sú nakonfigurované metadáta.",
|
||||
"TaskDownloadMissingSubtitles": "Stiahnuť chýbajúce titulky",
|
||||
"TaskRefreshChannelsDescription": "Obnoví informácie o internetových kanáloch.",
|
||||
"TaskRefreshChannels": "Obnoviť kanály",
|
||||
"TaskCleanTranscodeDescription": "Vymaže súbory transkódovania, ktoré sú staršie ako jeden deň.",
|
||||
"TaskCleanTranscode": "Vyčistiť priečinok pre transkódovanie",
|
||||
"TaskUpdatePluginsDescription": "Stiahne a nainštaluje aktualizácie pre zásuvné moduly, ktoré sú nastavené tak, aby sa aktualizovali automaticky.",
|
||||
"TaskUpdatePlugins": "Aktualizovať zásuvné moduly",
|
||||
"TaskRefreshPeopleDescription": "Aktualizuje metadáta pre hercov a režisérov vo vašej mediálnej knižnici.",
|
||||
"TaskRefreshPeople": "Obnoviť osoby",
|
||||
"TaskCleanLogsDescription": "Vymaže log súbory, ktoré su staršie ako {0} deň/dni/dní.",
|
||||
"TaskCleanLogs": "Vyčistiť priečinok s logmi",
|
||||
"TaskRefreshLibraryDescription": "Hľadá vo vašej mediálnej knižnici nové súbory a obnovuje metadáta.",
|
||||
"TaskRefreshLibrary": "Prehľadávať knižnicu medií",
|
||||
"TaskRefreshChapterImagesDescription": "Vytvorí náhľady pre videá, ktoré majú kapitoly.",
|
||||
"TaskRefreshChapterImages": "Extrahovať obrázky kapitol",
|
||||
"TaskCleanCacheDescription": "Vymaže cache súbory, ktoré nie sú už potrebné pre systém.",
|
||||
"TaskCleanCache": "Vyčistiť Cache priečinok",
|
||||
"TasksChannelsCategory": "Internetové kanály",
|
||||
"TasksApplicationCategory": "Aplikácia",
|
||||
"TasksLibraryCategory": "Knižnica",
|
||||
"TasksMaintenanceCategory": "Údržba"
|
||||
}
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server se nalaga. Poskusi ponovno kasneje.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Neuspešen prenos podnapisov iz {0} za {1}",
|
||||
"SubtitlesDownloadedForItem": "Podnapisi preneseni za {0}",
|
||||
"Sync": "Sinhroniziraj",
|
||||
"System": "System",
|
||||
"TvShows": "TV serije",
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
"TvShows": "ТВ серије",
|
||||
"System": "Систем",
|
||||
"Sync": "Усклади",
|
||||
"SubtitlesDownloadedForItem": "Титлови преузети за {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Неуспело преузимање титлова за {1} са {0}",
|
||||
"StartupEmbyServerIsLoading": "Џелифин сервер се подиже. Покушајте поново убрзо.",
|
||||
"Songs": "Песме",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Server arbetar. Pröva igen snart.",
|
||||
"SubtitleDownloadFailureForItem": "Nerladdning av undertexter för {0} misslyckades",
|
||||
"SubtitleDownloadFailureFromForItem": "Undertexter kunde inte laddas ner från {0} för {1}",
|
||||
"SubtitlesDownloadedForItem": "Undertexter har laddats ner till {0}",
|
||||
"Sync": "Synk",
|
||||
"System": "System",
|
||||
"TvShows": "TV-serier",
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin Sunucusu yükleniyor. Lütfen kısa süre sonra tekrar deneyin.",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "{1} için alt yazılar {0} 'dan indirilemedi",
|
||||
"SubtitlesDownloadedForItem": "{0} için altyazılar indirildi",
|
||||
"Sync": "Eşitle",
|
||||
"System": "Sistem",
|
||||
"TvShows": "Diziler",
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"AppDeviceValues": "应用: {0}, 设备: {1}",
|
||||
"Application": "应用程序",
|
||||
"Artists": "艺术家",
|
||||
"AuthenticationSucceededWithUserName": "{0} 验证成功",
|
||||
"AuthenticationSucceededWithUserName": "成功验证{0} ",
|
||||
"Books": "书籍",
|
||||
"CameraImageUploadedFrom": "新的相机图像已从 {0} 上传",
|
||||
"Channels": "频道",
|
||||
"ChapterNameValue": "第 {0} 章",
|
||||
"ChapterNameValue": "第 {0} 集",
|
||||
"Collections": "合集",
|
||||
"DeviceOfflineWithName": "{0} 已断开",
|
||||
"DeviceOnlineWithName": "{0} 已连接",
|
||||
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin 服务器加载中。请稍后再试。",
|
||||
"SubtitleDownloadFailureForItem": "为 {0} 下载字幕失败",
|
||||
"SubtitleDownloadFailureFromForItem": "无法从 {0} 下载 {1} 的字幕",
|
||||
"SubtitlesDownloadedForItem": "已为 {0} 下载了字幕",
|
||||
"Sync": "同步",
|
||||
"System": "系统",
|
||||
"TvShows": "电视剧",
|
||||
|
@ -93,5 +92,27 @@
|
|||
"UserStoppedPlayingItemWithValues": "{0} 已在 {2} 上停止播放 {1}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} 已添加至您的媒体库中",
|
||||
"ValueSpecialEpisodeName": "特典 - {0}",
|
||||
"VersionNumber": "版本 {0}"
|
||||
"VersionNumber": "版本 {0}",
|
||||
"TaskUpdatePluginsDescription": "为已设置为自动更新的插件下载和安装更新。",
|
||||
"TaskRefreshPeople": "刷新人员",
|
||||
"TasksChannelsCategory": "互联网频道",
|
||||
"TasksLibraryCategory": "媒体库",
|
||||
"TaskDownloadMissingSubtitlesDescription": "根据元数据设置在互联网上搜索缺少的字幕。",
|
||||
"TaskDownloadMissingSubtitles": "下载缺少的字幕",
|
||||
"TaskRefreshChannelsDescription": "刷新互联网频道信息。",
|
||||
"TaskRefreshChannels": "刷新频道",
|
||||
"TaskCleanTranscodeDescription": "删除存在超过 1 天的转码文件。",
|
||||
"TaskCleanTranscode": "清理转码目录",
|
||||
"TaskUpdatePlugins": "更新插件",
|
||||
"TaskRefreshPeopleDescription": "更新媒体库中演员和导演的元数据。",
|
||||
"TaskCleanLogsDescription": "删除存在超过 {0} 天的的日志文件。",
|
||||
"TaskCleanLogs": "清理日志目录",
|
||||
"TaskRefreshLibraryDescription": "扫描你的媒体库以获取新文件并刷新元数据。",
|
||||
"TaskRefreshLibrary": "扫描媒体库",
|
||||
"TaskRefreshChapterImagesDescription": "为包含剧集的视频提取缩略图。",
|
||||
"TaskRefreshChapterImages": "提取剧集图片",
|
||||
"TaskCleanCacheDescription": "删除系统不再需要的缓存文件。",
|
||||
"TaskCleanCache": "清理缓存目录",
|
||||
"TasksApplicationCategory": "应用程序",
|
||||
"TasksMaintenanceCategory": "维护"
|
||||
}
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
"StartupEmbyServerIsLoading": "Jellyfin 伺服器載入中,請稍後再試。",
|
||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "無法從 {0} 下載 {1} 的字幕",
|
||||
"SubtitlesDownloadedForItem": "已為 {0} 下載了字幕",
|
||||
"Sync": "同步",
|
||||
"System": "System",
|
||||
"TvShows": "電視節目",
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
"Shows": "節目",
|
||||
"Songs": "歌曲",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin Server正在啟動,請稍後再試一次。",
|
||||
"SubtitlesDownloadedForItem": "已為 {0} 下載字幕",
|
||||
"Sync": "同步",
|
||||
"System": "系統",
|
||||
"TvShows": "電視節目",
|
||||
|
|
|
@ -15,6 +15,7 @@ using MediaBrowser.Model.Entities;
|
|||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
||||
namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
|
@ -39,11 +40,19 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
|
||||
private readonly IEncodingManager _encodingManager;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChapterImagesTask" /> class.
|
||||
/// </summary>
|
||||
public ChapterImagesTask(ILoggerFactory loggerFactory, ILibraryManager libraryManager, IItemRepository itemRepo, IApplicationPaths appPaths, IEncodingManager encodingManager, IFileSystem fileSystem)
|
||||
public ChapterImagesTask(
|
||||
ILoggerFactory loggerFactory,
|
||||
ILibraryManager libraryManager,
|
||||
IItemRepository itemRepo,
|
||||
IApplicationPaths appPaths,
|
||||
IEncodingManager encodingManager,
|
||||
IFileSystem fileSystem,
|
||||
ILocalizationManager localization)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger(GetType().Name);
|
||||
_libraryManager = libraryManager;
|
||||
|
@ -51,6 +60,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
_appPaths = appPaths;
|
||||
_encodingManager = encodingManager;
|
||||
_fileSystem = fileSystem;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -159,11 +169,11 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
}
|
||||
}
|
||||
|
||||
public string Name => "Extract Chapter Images";
|
||||
public string Name => _localization.GetLocalizedString("TaskRefreshChapterImages");
|
||||
|
||||
public string Description => "Creates thumbnails for videos that have chapters.";
|
||||
public string Description => _localization.GetLocalizedString("TaskRefreshChapterImagesDescription");
|
||||
|
||||
public string Category => "Library";
|
||||
public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
|
||||
|
||||
public string Key => "RefreshChapterImages";
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ using MediaBrowser.Common.Configuration;
|
|||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
||||
namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
{
|
||||
|
@ -25,6 +26,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
private readonly ILogger _logger;
|
||||
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
|
||||
|
@ -32,11 +34,13 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
public DeleteCacheFileTask(
|
||||
IApplicationPaths appPaths,
|
||||
ILogger<DeleteCacheFileTask> logger,
|
||||
IFileSystem fileSystem)
|
||||
IFileSystem fileSystem,
|
||||
ILocalizationManager localization)
|
||||
{
|
||||
ApplicationPaths = appPaths;
|
||||
_logger = logger;
|
||||
_fileSystem = fileSystem;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -161,11 +165,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
}
|
||||
}
|
||||
|
||||
public string Name => "Clean Cache Directory";
|
||||
public string Name => _localization.GetLocalizedString("TaskCleanCache");
|
||||
|
||||
public string Description => "Deletes cache files no longer needed by the system.";
|
||||
public string Description => _localization.GetLocalizedString("TaskCleanCacheDescription");
|
||||
|
||||
public string Category => "Maintenance";
|
||||
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
||||
|
||||
public string Key => "DeleteCacheFiles";
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
|||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
||||
namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
{
|
||||
|
@ -21,15 +22,17 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
private IConfigurationManager ConfigurationManager { get; set; }
|
||||
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DeleteLogFileTask" /> class.
|
||||
/// </summary>
|
||||
/// <param name="configurationManager">The configuration manager.</param>
|
||||
public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem)
|
||||
public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization)
|
||||
{
|
||||
ConfigurationManager = configurationManager;
|
||||
_fileSystem = fileSystem;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -79,11 +82,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public string Name => "Clean Log Directory";
|
||||
public string Name => _localization.GetLocalizedString("TaskCleanLogs");
|
||||
|
||||
public string Description => string.Format("Deletes log files that are more than {0} days old.", ConfigurationManager.CommonConfiguration.LogFileRetentionDays);
|
||||
public string Description => string.Format(_localization.GetLocalizedString("TaskCleanLogsDescription"), ConfigurationManager.CommonConfiguration.LogFileRetentionDays);
|
||||
|
||||
public string Category => "Maintenance";
|
||||
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
||||
|
||||
public string Key => "CleanLogFiles";
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ using MediaBrowser.Common.Configuration;
|
|||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
||||
namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
{
|
||||
|
@ -19,6 +20,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
private readonly ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DeleteTranscodeFileTask" /> class.
|
||||
|
@ -26,11 +28,13 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
public DeleteTranscodeFileTask(
|
||||
ILogger<DeleteTranscodeFileTask> logger,
|
||||
IFileSystem fileSystem,
|
||||
IConfigurationManager configurationManager)
|
||||
IConfigurationManager configurationManager,
|
||||
ILocalizationManager localization)
|
||||
{
|
||||
_logger = logger;
|
||||
_fileSystem = fileSystem;
|
||||
_configurationManager = configurationManager;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -128,11 +132,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
}
|
||||
}
|
||||
|
||||
public string Name => "Clean Transcode Directory";
|
||||
public string Name => _localization.GetLocalizedString("TaskCleanTranscode");
|
||||
|
||||
public string Description => "Deletes transcode files more than one day old.";
|
||||
public string Description => _localization.GetLocalizedString("TaskCleanTranscodeDescription");
|
||||
|
||||
public string Category => "Maintenance";
|
||||
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
||||
|
||||
public string Key => "DeleteTranscodeFiles";
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
|||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
||||
namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
|
@ -19,16 +20,18 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PeopleValidationTask" /> class.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="appHost">The server application host</param>
|
||||
public PeopleValidationTask(ILibraryManager libraryManager, IServerApplicationHost appHost)
|
||||
public PeopleValidationTask(ILibraryManager libraryManager, IServerApplicationHost appHost, ILocalizationManager localization)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_appHost = appHost;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -57,11 +60,11 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
return _libraryManager.ValidatePeople(cancellationToken, progress);
|
||||
}
|
||||
|
||||
public string Name => "Refresh People";
|
||||
public string Name => _localization.GetLocalizedString("TaskRefreshPeople");
|
||||
|
||||
public string Description => "Updates metadata for actors and directors in your media library.";
|
||||
public string Description => _localization.GetLocalizedString("TaskRefreshPeopleDescription");
|
||||
|
||||
public string Category => "Library";
|
||||
public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
|
||||
|
||||
public string Key => "RefreshPeople";
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ using MediaBrowser.Common.Updates;
|
|||
using MediaBrowser.Model.Net;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
||||
namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
|
@ -22,11 +23,13 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
private readonly ILogger _logger;
|
||||
|
||||
private readonly IInstallationManager _installationManager;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
public PluginUpdateTask(ILogger<PluginUpdateTask> logger, IInstallationManager installationManager)
|
||||
public PluginUpdateTask(ILogger<PluginUpdateTask> logger, IInstallationManager installationManager, ILocalizationManager localization)
|
||||
{
|
||||
_logger = logger;
|
||||
_installationManager = installationManager;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -96,13 +99,13 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "Update Plugins";
|
||||
public string Name => _localization.GetLocalizedString("TaskUpdatePlugins");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => "Downloads and installs updates for plugins that are configured to update automatically.";
|
||||
public string Description => _localization.GetLocalizedString("TaskUpdatePluginsDescription");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => "Application";
|
||||
public string Category => _localization.GetLocalizedString("TasksApplicationCategory");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => "PluginUpdates";
|
||||
|
|
|
@ -6,6 +6,7 @@ using Emby.Server.Implementations.Library;
|
|||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
||||
namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
|
@ -19,15 +20,17 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
/// </summary>
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RefreshMediaLibraryTask" /> class.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
public RefreshMediaLibraryTask(ILibraryManager libraryManager, IServerConfigurationManager config)
|
||||
public RefreshMediaLibraryTask(ILibraryManager libraryManager, IServerConfigurationManager config, ILocalizationManager localization)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_config = config;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -58,11 +61,11 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken);
|
||||
}
|
||||
|
||||
public string Name => "Scan Media Library";
|
||||
public string Name => _localization.GetLocalizedString("TaskRefreshLibrary");
|
||||
|
||||
public string Description => "Scans your media library for new files and refreshes metadata.";
|
||||
public string Description => _localization.GetLocalizedString("TaskRefreshLibraryDescription");
|
||||
|
||||
public string Category => "Library";
|
||||
public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
|
||||
|
||||
public string Key => "RefreshLibrary";
|
||||
|
||||
|
|
|
@ -1401,6 +1401,16 @@ namespace Emby.Server.Implementations.Session
|
|||
user = _userManager.GetUserByName(request.Username);
|
||||
}
|
||||
|
||||
if (enforcePassword)
|
||||
{
|
||||
user = await _userManager.AuthenticateUser(
|
||||
request.Username,
|
||||
request.Password,
|
||||
request.PasswordSha1,
|
||||
request.RemoteEndPoint,
|
||||
true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
AuthenticationFailed?.Invoke(this, new GenericEventArgs<AuthenticationRequest>(request));
|
||||
|
@ -1413,16 +1423,6 @@ namespace Emby.Server.Implementations.Session
|
|||
throw new SecurityException("User is not allowed access from this device.");
|
||||
}
|
||||
|
||||
if (enforcePassword)
|
||||
{
|
||||
user = await _userManager.AuthenticateUser(
|
||||
request.Username,
|
||||
request.Password,
|
||||
request.PasswordSha1,
|
||||
request.RemoteEndPoint,
|
||||
true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var token = GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName);
|
||||
|
||||
var session = LogSessionActivity(
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="SkiaSharp" Version="1.68.1" />
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="1.68.1" />
|
||||
<PackageReference Include="Jellyfin.SkiaSharp.NativeAssets.LinuxArm" Version="1.68.0" />
|
||||
<PackageReference Include="Jellyfin.SkiaSharp.NativeAssets.LinuxArm" Version="1.68.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.7.82" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
|
||||
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
|
||||
|
|
|
@ -927,61 +927,69 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
}
|
||||
else
|
||||
{
|
||||
var gopArg = string.Empty;
|
||||
var keyFrameArg = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
" -force_key_frames:0 \"expr:gte(t,{0}+n_forced*{1})\"",
|
||||
GetStartNumber(state) * state.SegmentLength,
|
||||
state.SegmentLength);
|
||||
if (state.TargetFramerate.HasValue)
|
||||
|
||||
var framerate = state.VideoStream?.RealFrameRate;
|
||||
|
||||
if (framerate != null && framerate.HasValue)
|
||||
{
|
||||
// This is to make sure keyframe interval is limited to our segment,
|
||||
// as forcing keyframes is not enough.
|
||||
// Example: we encoded half of desired length, then codec detected
|
||||
// scene cut and inserted a keyframe; next forced keyframe would
|
||||
// be created outside of segment, which breaks seeking.
|
||||
keyFrameArg += string.Format(
|
||||
// be created outside of segment, which breaks seeking
|
||||
// -sc_threshold 0 is used to prevent the hardware encoder from post processing to break the set keyframe
|
||||
gopArg = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
" -g {0} -keyint_min {0}",
|
||||
(int)(state.SegmentLength * state.TargetFramerate)
|
||||
" -g {0} -keyint_min {0} -sc_threshold 0",
|
||||
Math.Ceiling(state.SegmentLength * framerate.Value)
|
||||
);
|
||||
}
|
||||
|
||||
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
|
||||
|
||||
args += " " + EncodingHelper.GetVideoQualityParam(state, codec, encodingOptions, GetDefaultEncoderPreset());
|
||||
|
||||
// Unable to force key frames to h264_qsv transcode
|
||||
if (string.Equals(codec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
||||
// Unable to force key frames using these hw encoders, set key frames by GOP
|
||||
if (string.Equals(codec, "h264_qsv", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(codec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(codec, "h264_amf", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Logger.LogInformation("Bug Workaround: Disabling force_key_frames for h264_qsv");
|
||||
args += " " + gopArg;
|
||||
}
|
||||
else
|
||||
{
|
||||
args += " " + keyFrameArg;
|
||||
args += " " + keyFrameArg + gopArg;
|
||||
}
|
||||
|
||||
//args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0";
|
||||
|
||||
// Add resolution params, if specified
|
||||
if (!hasGraphicalSubs)
|
||||
{
|
||||
args += EncodingHelper.GetOutputSizeParam(state, encodingOptions, codec, true);
|
||||
}
|
||||
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
|
||||
|
||||
// This is for internal graphical subs
|
||||
// This is for graphical subs
|
||||
if (hasGraphicalSubs)
|
||||
{
|
||||
args += EncodingHelper.GetGraphicalSubtitleParam(state, encodingOptions, codec);
|
||||
}
|
||||
// Add resolution params, if specified
|
||||
else
|
||||
{
|
||||
args += EncodingHelper.GetOutputSizeParam(state, encodingOptions, codec);
|
||||
}
|
||||
|
||||
// -start_at_zero is necessary to use with -ss when seeking,
|
||||
// otherwise the target position cannot be determined.
|
||||
if (!(state.SubtitleStream != null && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream))
|
||||
{
|
||||
args += " -start_at_zero";
|
||||
}
|
||||
|
||||
//args += " -flags -global_header";
|
||||
}
|
||||
|
||||
if (args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
|
||||
{
|
||||
args += " -copyts";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(state.OutputVideoSync))
|
||||
{
|
||||
args += " -vsync " + state.OutputVideoSync;
|
||||
|
@ -1025,7 +1033,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
}
|
||||
|
||||
return string.Format(
|
||||
"{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f hls -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {6} -individual_header_trailer 0 -hls_segment_type {7} -start_number {8} -hls_segment_filename \"{9}\" -hls_playlist_type vod -hls_list_size 0 -y \"{10}\"",
|
||||
"{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -copyts -avoid_negative_ts disabled -f hls -max_delay 5000000 -hls_time {6} -individual_header_trailer 0 -hls_segment_type {7} -start_number {8} -hls_segment_filename \"{9}\" -hls_playlist_type vod -hls_list_size 0 -y \"{10}\"",
|
||||
inputModifier,
|
||||
EncodingHelper.GetInputArgument(state, encodingOptions),
|
||||
threads,
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -460,16 +460,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
if (state.IsVideoRequest
|
||||
&& string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
|
||||
var hwOutputFormat = "vaapi";
|
||||
|
||||
if (hasGraphicalSubs)
|
||||
{
|
||||
hwOutputFormat = "yuv420p";
|
||||
}
|
||||
|
||||
arg.Append("-hwaccel vaapi -hwaccel_output_format ")
|
||||
.Append(hwOutputFormat)
|
||||
arg.Append("-hwaccel vaapi -hwaccel_output_format vaapi")
|
||||
.Append(" -vaapi_device ")
|
||||
.Append(encodingOptions.VaapiDevice)
|
||||
.Append(' ');
|
||||
|
@ -480,20 +471,26 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
{
|
||||
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions);
|
||||
var outputVideoCodec = GetVideoEncoder(state, encodingOptions);
|
||||
|
||||
var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
|
||||
|
||||
if (encodingOptions.EnableHardwareEncoding && outputVideoCodec.Contains("qsv", StringComparison.OrdinalIgnoreCase))
|
||||
if (!hasTextSubs)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(videoDecoder) && videoDecoder.Contains("qsv", StringComparison.OrdinalIgnoreCase))
|
||||
// While using QSV encoder
|
||||
if ((outputVideoCodec ?? string.Empty).IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
arg.Append("-hwaccel qsv ");
|
||||
}
|
||||
else
|
||||
{
|
||||
arg.Append("-init_hw_device qsv=hw -filter_hw_device hw ");
|
||||
// While using QSV decoder
|
||||
if ((videoDecoder ?? string.Empty).IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
arg.Append("-hwaccel qsv ");
|
||||
}
|
||||
// While using SW decoder
|
||||
else
|
||||
{
|
||||
arg.Append("-init_hw_device qsv=hw -filter_hw_device hw ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arg.Append(videoDecoder + " ");
|
||||
}
|
||||
|
||||
arg.Append("-i ")
|
||||
|
@ -503,17 +500,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
&& state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode
|
||||
&& state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)
|
||||
{
|
||||
if (state.VideoStream != null && state.VideoStream.Width.HasValue)
|
||||
{
|
||||
// This is hacky but not sure how to get the exact subtitle resolution
|
||||
int height = Convert.ToInt32(state.VideoStream.Width.Value / 16.0 * 9.0);
|
||||
|
||||
arg.Append(" -canvas_size ")
|
||||
.Append(state.VideoStream.Width.Value.ToString(CultureInfo.InvariantCulture))
|
||||
.Append(':')
|
||||
.Append(height.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
var subtitlePath = state.SubtitleStream.Path;
|
||||
|
||||
if (string.Equals(Path.GetExtension(subtitlePath), ".sub", StringComparison.OrdinalIgnoreCase))
|
||||
|
@ -1546,9 +1532,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the internal graphical subtitle param.
|
||||
/// Gets the graphical subtitle param.
|
||||
/// </summary>
|
||||
public string GetGraphicalSubtitleParam(EncodingJobInfo state, EncodingOptions options, string outputVideoCodec)
|
||||
public string GetGraphicalSubtitleParam(
|
||||
EncodingJobInfo state,
|
||||
EncodingOptions options,
|
||||
string outputVideoCodec)
|
||||
{
|
||||
var outputSizeParam = string.Empty;
|
||||
|
||||
|
@ -1562,54 +1551,77 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
{
|
||||
outputSizeParam = GetOutputSizeParam(state, options, outputVideoCodec).TrimEnd('"');
|
||||
|
||||
if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||
var index = outputSizeParam.IndexOf("hwdownload", StringComparison.OrdinalIgnoreCase);
|
||||
if (index != -1)
|
||||
{
|
||||
var index = outputSizeParam.IndexOf("format", StringComparison.OrdinalIgnoreCase);
|
||||
if (index != -1)
|
||||
{
|
||||
outputSizeParam = "," + outputSizeParam.Substring(index);
|
||||
}
|
||||
outputSizeParam = "," + outputSizeParam.Substring(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase);
|
||||
index = outputSizeParam.IndexOf("format", StringComparison.OrdinalIgnoreCase);
|
||||
if (index != -1)
|
||||
{
|
||||
outputSizeParam = "," + outputSizeParam.Substring(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
|
||||
&& outputSizeParam.Length == 0)
|
||||
{
|
||||
outputSizeParam = ",format=nv12|vaapi,hwupload";
|
||||
|
||||
// Add parameters to use VAAPI with burn-in subttiles (GH issue #642)
|
||||
if (state.SubtitleStream != null
|
||||
&& state.SubtitleStream.IsTextSubtitleStream
|
||||
&& state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode)
|
||||
{
|
||||
outputSizeParam += ",hwmap=mode=read+write+direct";
|
||||
else
|
||||
{
|
||||
index = outputSizeParam.IndexOf("yadif", StringComparison.OrdinalIgnoreCase);
|
||||
if (index != -1)
|
||||
{
|
||||
outputSizeParam = "," + outputSizeParam.Substring(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase);
|
||||
if (index != -1)
|
||||
{
|
||||
outputSizeParam = "," + outputSizeParam.Substring(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var videoSizeParam = string.Empty;
|
||||
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options);
|
||||
|
||||
// Setup subtitle scaling
|
||||
if (state.VideoStream != null && state.VideoStream.Width.HasValue && state.VideoStream.Height.HasValue)
|
||||
{
|
||||
// force_original_aspect_ratio=decrease
|
||||
// Enable decreasing output video width or height if necessary to keep the original aspect ratio
|
||||
videoSizeParam = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale={0}:{1}",
|
||||
"scale={0}:{1}:force_original_aspect_ratio=decrease",
|
||||
state.VideoStream.Width.Value,
|
||||
state.VideoStream.Height.Value);
|
||||
|
||||
//For QSV, feed it into hardware encoder now
|
||||
// For QSV, feed it into hardware encoder now
|
||||
if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
videoSizeParam += ",hwupload=extra_hw_frames=64";
|
||||
}
|
||||
|
||||
// For VAAPI and CUVID decoder
|
||||
// these encoders cannot automatically adjust the size of graphical subtitles to fit the output video,
|
||||
// thus needs to be manually adjusted.
|
||||
if (string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)
|
||||
|| (videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
var videoStream = state.VideoStream;
|
||||
var inputWidth = videoStream?.Width;
|
||||
var inputHeight = videoStream?.Height;
|
||||
var (width, height) = GetFixedOutputSize(inputWidth, inputHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight);
|
||||
|
||||
if (width.HasValue && height.HasValue)
|
||||
{
|
||||
videoSizeParam = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale={0}:{1}:force_original_aspect_ratio=decrease",
|
||||
width.Value,
|
||||
height.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mapPrefix = state.SubtitleStream.IsExternal ?
|
||||
|
@ -1620,12 +1632,34 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
? 0
|
||||
: state.SubtitleStream.Index;
|
||||
|
||||
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options);
|
||||
|
||||
// Setup default filtergraph utilizing FFMpeg overlay() and FFMpeg scale() (see the return of this function for index reference)
|
||||
var retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\"";
|
||||
|
||||
if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
||||
// When the input may or may not be hardware VAAPI decodable
|
||||
if (string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && options.EnableHardwareEncoding)
|
||||
{
|
||||
/*
|
||||
[base]: HW scaling video to OutputSize
|
||||
[sub]: SW scaling subtitle to FixedOutputSize
|
||||
[base][sub]: SW overlay
|
||||
*/
|
||||
outputSizeParam = outputSizeParam.TrimStart(',');
|
||||
retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3},hwdownload[base];[base][sub]overlay,format=nv12,hwupload\"";
|
||||
}
|
||||
|
||||
// If we're hardware VAAPI decoding and software encoding, download frames from the decoder first
|
||||
else if (string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && !options.EnableHardwareEncoding)
|
||||
{
|
||||
/*
|
||||
[base]: SW scaling video to OutputSize
|
||||
[sub]: SW scaling subtitle to FixedOutputSize
|
||||
[base][sub]: SW overlay
|
||||
*/
|
||||
outputSizeParam = outputSizeParam.TrimStart(',');
|
||||
retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\"";
|
||||
}
|
||||
|
||||
else if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
/*
|
||||
QSV in FFMpeg can now setup hardware overlay for transcodes.
|
||||
|
@ -1689,7 +1723,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
return (Convert.ToInt32(outputWidth), Convert.ToInt32(outputHeight));
|
||||
}
|
||||
|
||||
public List<string> GetScalingFilters(int? videoWidth,
|
||||
public List<string> GetScalingFilters(EncodingJobInfo state,
|
||||
int? videoWidth,
|
||||
int? videoHeight,
|
||||
Video3DFormat? threedFormat,
|
||||
string videoDecoder,
|
||||
|
@ -1708,7 +1743,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
requestedMaxWidth,
|
||||
requestedMaxHeight);
|
||||
|
||||
if ((string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) || string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
||||
var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
|
||||
|
||||
if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) || (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) && !hasTextSubs)
|
||||
&& width.HasValue
|
||||
&& height.HasValue)
|
||||
{
|
||||
|
@ -1738,7 +1775,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
filters.Add(string.Format(CultureInfo.InvariantCulture, "scale_{0}=format=nv12", vaapi_or_qsv));
|
||||
}
|
||||
}
|
||||
else if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1
|
||||
else if ((videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1
|
||||
&& width.HasValue
|
||||
&& height.HasValue)
|
||||
{
|
||||
|
@ -1942,8 +1979,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
public string GetOutputSizeParam(
|
||||
EncodingJobInfo state,
|
||||
EncodingOptions options,
|
||||
string outputVideoCodec,
|
||||
bool allowTimeStampCopy = true)
|
||||
string outputVideoCodec)
|
||||
{
|
||||
// http://sonnati.wordpress.com/2012/10/19/ffmpeg-the-swiss-army-knife-of-internet-streaming-part-vi/
|
||||
|
||||
|
@ -1952,42 +1988,57 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
var videoStream = state.VideoStream;
|
||||
var filters = new List<string>();
|
||||
|
||||
// If we're hardware VAAPI decoding and software encoding, download frames from the decoder first
|
||||
var hwType = options.HardwareAccelerationType ?? string.Empty;
|
||||
if (string.Equals(hwType, "vaapi", StringComparison.OrdinalIgnoreCase) && !options.EnableHardwareEncoding)
|
||||
{
|
||||
filters.Add("hwdownload");
|
||||
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options);
|
||||
var inputWidth = videoStream?.Width;
|
||||
var inputHeight = videoStream?.Height;
|
||||
var threeDFormat = state.MediaSource.Video3DFormat;
|
||||
|
||||
// If transcoding from 10 bit, transform colour spaces too
|
||||
if (!string.IsNullOrEmpty(videoStream.PixelFormat)
|
||||
&& videoStream.PixelFormat.IndexOf("p10", StringComparison.OrdinalIgnoreCase) != -1
|
||||
&& string.Equals(outputVideoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
filters.Add("format=p010le");
|
||||
filters.Add("format=nv12");
|
||||
}
|
||||
else
|
||||
{
|
||||
filters.Add("format=nv12");
|
||||
}
|
||||
}
|
||||
var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
|
||||
|
||||
if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||
// When the input may or may not be hardware VAAPI decodable
|
||||
if (string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && options.EnableHardwareEncoding)
|
||||
{
|
||||
filters.Add("format=nv12|vaapi");
|
||||
filters.Add("hwupload");
|
||||
}
|
||||
|
||||
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options);
|
||||
|
||||
// If we are software decoding, and hardware encoding
|
||||
if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)
|
||||
&& (string.IsNullOrEmpty(videoDecoder) || !videoDecoder.Contains("qsv", StringComparison.OrdinalIgnoreCase)))
|
||||
// When the input may or may not be hardware QSV decodable
|
||||
else if (string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase) && options.EnableHardwareEncoding)
|
||||
{
|
||||
filters.Add("format=nv12|qsv");
|
||||
filters.Add("hwupload=extra_hw_frames=64");
|
||||
if (!hasTextSubs)
|
||||
{
|
||||
filters.Add("format=nv12|qsv");
|
||||
filters.Add("hwupload=extra_hw_frames=64");
|
||||
}
|
||||
}
|
||||
|
||||
// If we're hardware VAAPI decoding and software encoding, download frames from the decoder first
|
||||
|
||||
else if (string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && !options.EnableHardwareEncoding)
|
||||
{
|
||||
var codec = videoStream.Codec.ToLowerInvariant();
|
||||
var pixelFormat = videoStream.PixelFormat.ToLowerInvariant();
|
||||
|
||||
// Assert 10-bit hardware VAAPI decodable
|
||||
if ((pixelFormat ?? string.Empty).IndexOf("p10", StringComparison.OrdinalIgnoreCase) != -1
|
||||
&& (string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
filters.Add("hwdownload");
|
||||
filters.Add("format=p010le");
|
||||
filters.Add("format=nv12");
|
||||
}
|
||||
|
||||
// Assert 8-bit hardware VAAPI decodable
|
||||
else if ((pixelFormat ?? string.Empty).IndexOf("p10", StringComparison.OrdinalIgnoreCase) == -1)
|
||||
{
|
||||
filters.Add("hwdownload");
|
||||
filters.Add("format=nv12");
|
||||
}
|
||||
}
|
||||
|
||||
// Add hardware deinterlace filter before scaling filter
|
||||
if (state.DeInterlace("h264", true))
|
||||
{
|
||||
if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||
|
@ -1996,17 +2047,23 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
}
|
||||
else if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
filters.Add(string.Format(CultureInfo.InvariantCulture, "deinterlace_qsv"));
|
||||
if (!hasTextSubs)
|
||||
{
|
||||
filters.Add(string.Format(CultureInfo.InvariantCulture, "deinterlace_qsv"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((state.DeInterlace("h264", true) || state.DeInterlace("h265", true) || state.DeInterlace("hevc", true))
|
||||
&& !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||
// Add software deinterlace filter before scaling filter
|
||||
if (((state.DeInterlace("h264", true) || state.DeInterlace("h265", true) || state.DeInterlace("hevc", true))
|
||||
&& !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
|
||||
&& !string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
||||
|| (hasTextSubs && state.DeInterlace("h264", true) && string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
var inputFramerate = videoStream?.RealFrameRate;
|
||||
|
||||
// If it is already 60fps then it will create an output framerate that is much too high for roku and others to handle
|
||||
if (string.Equals(options.DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase) && (inputFramerate ?? 60) <= 30)
|
||||
if (string.Equals(options.DeinterlaceMethod, "yadif_bob", StringComparison.OrdinalIgnoreCase) && (inputFramerate ?? 60) <= 30)
|
||||
{
|
||||
filters.Add("yadif=1:-1:0");
|
||||
}
|
||||
|
@ -2016,11 +2073,21 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
}
|
||||
}
|
||||
|
||||
var inputWidth = videoStream?.Width;
|
||||
var inputHeight = videoStream?.Height;
|
||||
var threeDFormat = state.MediaSource.Video3DFormat;
|
||||
// Add scaling filter: scale_*=format=nv12 or scale_*=w=*:h=*:format=nv12 or scale=expr
|
||||
filters.AddRange(GetScalingFilters(state, inputWidth, inputHeight, threeDFormat, videoDecoder, outputVideoCodec, request.Width, request.Height, request.MaxWidth, request.MaxHeight));
|
||||
|
||||
filters.AddRange(GetScalingFilters(inputWidth, inputHeight, threeDFormat, videoDecoder, outputVideoCodec, request.Width, request.Height, request.MaxWidth, request.MaxHeight));
|
||||
// Add parameters to use VAAPI with burn-in text subttiles (GH issue #642)
|
||||
if (string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && options.EnableHardwareEncoding)
|
||||
{
|
||||
if (state.SubtitleStream != null
|
||||
&& state.SubtitleStream.IsTextSubtitleStream
|
||||
&& state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode)
|
||||
{
|
||||
// Test passed on Intel and AMD gfx
|
||||
filters.Add("hwmap=mode=read+write");
|
||||
filters.Add("format=nv12");
|
||||
}
|
||||
}
|
||||
|
||||
var output = string.Empty;
|
||||
|
||||
|
@ -2038,11 +2105,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
{
|
||||
filters.Add("hwmap");
|
||||
}
|
||||
|
||||
if (allowTimeStampCopy)
|
||||
{
|
||||
output += " -copyts";
|
||||
}
|
||||
}
|
||||
|
||||
if (filters.Count > 0)
|
||||
|
@ -2219,7 +2281,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
{
|
||||
inputModifier += " " + videoDecoder;
|
||||
|
||||
if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
if ((videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
var videoStream = state.VideoStream;
|
||||
var inputWidth = videoStream?.Width;
|
||||
|
@ -2228,7 +2290,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
|
||||
var (width, height) = GetFixedOutputSize(inputWidth, inputHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight);
|
||||
|
||||
if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1
|
||||
if ((videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1
|
||||
&& width.HasValue
|
||||
&& height.HasValue)
|
||||
{
|
||||
|
@ -2526,6 +2588,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
case "h264":
|
||||
if (_mediaEncoder.SupportsDecoder("h264_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
// cuvid decoder does not support 10-bit input
|
||||
if ((videoStream.BitDepth ?? 8) > 8)
|
||||
{
|
||||
encodingOptions.HardwareDecodingCodecs = Array.Empty<string>();
|
||||
return null;
|
||||
}
|
||||
return "-c:v h264_cuvid ";
|
||||
}
|
||||
break;
|
||||
|
@ -2773,14 +2841,27 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
|
||||
|
||||
var hasCopyTs = false;
|
||||
|
||||
// Add resolution params, if specified
|
||||
if (!hasGraphicalSubs)
|
||||
{
|
||||
var outputSizeParam = GetOutputSizeParam(state, encodingOptions, videoCodec);
|
||||
|
||||
args += outputSizeParam;
|
||||
|
||||
hasCopyTs = outputSizeParam.IndexOf("copyts", StringComparison.OrdinalIgnoreCase) != -1;
|
||||
}
|
||||
|
||||
// This is for graphical subs
|
||||
if (hasGraphicalSubs)
|
||||
{
|
||||
var graphicalSubtitleParam = GetGraphicalSubtitleParam(state, encodingOptions, videoCodec);
|
||||
|
||||
args += graphicalSubtitleParam;
|
||||
|
||||
hasCopyTs = graphicalSubtitleParam.IndexOf("copyts", StringComparison.OrdinalIgnoreCase) != -1;
|
||||
}
|
||||
|
||||
if (state.RunTimeTicks.HasValue && state.BaseRequest.CopyTimestamps)
|
||||
{
|
||||
if (!hasCopyTs)
|
||||
|
@ -2788,13 +2869,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
args += " -copyts";
|
||||
}
|
||||
|
||||
args += " -avoid_negative_ts disabled -start_at_zero";
|
||||
}
|
||||
args += " -avoid_negative_ts disabled";
|
||||
|
||||
// This is for internal graphical subs
|
||||
if (hasGraphicalSubs)
|
||||
{
|
||||
args += GetGraphicalSubtitleParam(state, encodingOptions, videoCodec);
|
||||
if (!(state.SubtitleStream != null && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream))
|
||||
{
|
||||
args += " -start_at_zero";
|
||||
}
|
||||
}
|
||||
|
||||
var qualityParam = GetVideoQualityParam(state, videoCodec, encodingOptions, defaultPreset);
|
||||
|
@ -2900,6 +2980,5 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
string.Empty,
|
||||
string.Empty).Trim();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,9 +183,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||
|
||||
private async Task<Stream> GetSubtitleStream(string path, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken)
|
||||
{
|
||||
using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false))
|
||||
if (requiresCharset)
|
||||
{
|
||||
if (requiresCharset)
|
||||
using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
var result = CharsetDetector.DetectFromStream(stream).Detected;
|
||||
stream.Position = 0;
|
||||
|
@ -200,9 +200,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||
return new MemoryStream(Encoding.UTF8.GetBytes(text));
|
||||
}
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
return File.OpenRead(path);
|
||||
}
|
||||
|
||||
private async Task<SubtitleInfo> GetReadableFile(
|
||||
|
@ -731,6 +731,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||
{
|
||||
var charset = CharsetDetector.DetectFromStream(stream).Detected?.EncodingName;
|
||||
|
||||
// UTF16 is automatically converted to UTF8 by FFmpeg, do not specify a character encoding
|
||||
if ((path.EndsWith(".ass") || path.EndsWith(".ssa"))
|
||||
&& (string.Equals(charset, "utf-16le", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(charset, "utf-16be", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
charset = "";
|
||||
}
|
||||
|
||||
_logger.LogDebug("charset {0} detected for {Path}", charset ?? "null", path);
|
||||
|
||||
return charset;
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace MediaBrowser.Model.Configuration
|
|||
VaapiDevice = "/dev/dri/renderD128";
|
||||
H264Crf = 23;
|
||||
H265Crf = 28;
|
||||
DeinterlaceMethod = "yadif";
|
||||
EnableHardwareEncoding = true;
|
||||
EnableSubtitleExtraction = true;
|
||||
HardwareDecodingCodecs = new string[] { "h264", "vc1" };
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace MediaBrowser.Model.Entities
|
|||
/// </summary>
|
||||
/// <value>The image path.</value>
|
||||
public string ImagePath { get; set; }
|
||||
|
||||
public DateTime ImageDateModified { get; set; }
|
||||
|
||||
public string ImageTag { get; set; }
|
||||
|
|
|
@ -22,6 +22,11 @@ namespace MediaBrowser.Model.Extensions
|
|||
return str;
|
||||
}
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
char[] a = str.ToCharArray();
|
||||
a[0] = char.ToUpperInvariant(a[0]);
|
||||
return new string(a);
|
||||
#else
|
||||
return string.Create(
|
||||
str.Length,
|
||||
str,
|
||||
|
@ -33,6 +38,7 @@ namespace MediaBrowser.Model.Extensions
|
|||
chars[i] = buf[i];
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Authors>Jellyfin Contributors</Authors>
|
||||
|
@ -8,7 +8,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release' ">true</TreatWarningsAsErrors>
|
||||
|
@ -16,7 +16,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.3" />
|
||||
<PackageReference Include="System.Globalization" Version="4.3.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.3" />
|
||||
<PackageReference Include="OptimizedPriorityQueue" Version="4.2.0" />
|
||||
<PackageReference Include="PlaylistsNET" Version="1.0.4" />
|
||||
<PackageReference Include="TvDbSharper" Version="3.0.1" />
|
||||
|
|
|
@ -14,6 +14,7 @@ using MediaBrowser.Model.Providers;
|
|||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
||||
namespace MediaBrowser.Providers.MediaInfo
|
||||
{
|
||||
|
@ -25,6 +26,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
private readonly IMediaSourceManager _mediaSourceManager;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IJsonSerializer _json;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
public SubtitleScheduledTask(
|
||||
ILibraryManager libraryManager,
|
||||
|
@ -32,7 +34,8 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
IServerConfigurationManager config,
|
||||
ISubtitleManager subtitleManager,
|
||||
ILogger<SubtitleScheduledTask> logger,
|
||||
IMediaSourceManager mediaSourceManager)
|
||||
IMediaSourceManager mediaSourceManager,
|
||||
ILocalizationManager localization)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_config = config;
|
||||
|
@ -40,6 +43,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
_logger = logger;
|
||||
_mediaSourceManager = mediaSourceManager;
|
||||
_json = json;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
private SubtitleOptions GetOptions()
|
||||
|
@ -204,11 +208,11 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
};
|
||||
}
|
||||
|
||||
public string Name => "Download missing subtitles";
|
||||
public string Name => _localization.GetLocalizedString("TaskDownloadMissingSubtitles");
|
||||
|
||||
public string Description => "Searches the internet for missing subtitles based on metadata configuration.";
|
||||
public string Description => _localization.GetLocalizedString("TaskDownloadMissingSubtitlesDescription");
|
||||
|
||||
public string Category => "Library";
|
||||
public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
|
||||
|
||||
public string Key => "DownloadSubtitles";
|
||||
|
||||
|
|
|
@ -32,7 +32,11 @@ namespace MediaBrowser.Providers.Plugins.MusicBrainz
|
|||
{
|
||||
if (value < Plugin.DefaultRateLimit && _server == Plugin.DefaultServer)
|
||||
{
|
||||
RateLimit = Plugin.DefaultRateLimit;
|
||||
_rateLimit = Plugin.DefaultRateLimit;
|
||||
}
|
||||
else
|
||||
{
|
||||
_rateLimit = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -344,7 +344,11 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
|||
series.ProductionYear = date.Year;
|
||||
}
|
||||
|
||||
series.RunTimeTicks = TimeSpan.FromMinutes(Convert.ToDouble(tvdbSeries.Runtime)).Ticks;
|
||||
if (!string.IsNullOrEmpty(tvdbSeries.Runtime) && double.TryParse(tvdbSeries.Runtime, out double runtime))
|
||||
{
|
||||
series.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks;
|
||||
}
|
||||
|
||||
foreach (var genre in tvdbSeries.Genre)
|
||||
{
|
||||
series.AddGenre(genre);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<PackageReference Include="AutoFixture" Version="4.11.0" />
|
||||
<PackageReference Include="AutoFixture.AutoMoq" Version="4.11.0" />
|
||||
<PackageReference Include="AutoFixture.Xunit2" Version="4.11.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue