jellyfin-server/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs

163 lines
6.5 KiB
C#
Raw Normal View History

2015-01-17 20:12:02 +00:00
using MediaBrowser.Model.Extensions;
2014-05-16 19:16:29 +00:00
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
2016-10-25 19:02:04 +00:00
using MediaBrowser.Model.IO;
2016-10-24 02:45:23 +00:00
using MediaBrowser.Model.Globalization;
2014-05-16 19:16:29 +00:00
namespace MediaBrowser.Providers.MediaInfo
{
public class SubtitleResolver
{
private readonly ILocalizationManager _localization;
2014-07-26 17:30:15 +00:00
private readonly IFileSystem _fileSystem;
2014-05-16 19:16:29 +00:00
2014-07-26 17:30:15 +00:00
public SubtitleResolver(ILocalizationManager localization, IFileSystem fileSystem)
2014-05-16 19:16:29 +00:00
{
_localization = localization;
2014-07-26 17:30:15 +00:00
_fileSystem = fileSystem;
2014-05-16 19:16:29 +00:00
}
public IEnumerable<MediaStream> GetExternalSubtitleStreams(Video video,
int startIndex,
IDirectoryService directoryService,
bool clearCache)
{
2014-07-26 17:30:15 +00:00
var files = GetSubtitleFiles(video, directoryService, _fileSystem, clearCache);
2014-05-16 19:16:29 +00:00
var streams = new List<MediaStream>();
2014-07-26 17:30:15 +00:00
var videoFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(video.Path);
videoFileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(videoFileNameWithoutExtension);
2014-05-16 19:16:29 +00:00
2017-03-29 06:26:48 +00:00
foreach (var fullName in files)
2014-05-16 19:16:29 +00:00
{
2017-03-29 06:26:48 +00:00
var fileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(fullName);
fileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(fileNameWithoutExtension);
2014-05-16 19:16:29 +00:00
var codec = Path.GetExtension(fullName).ToLower().TrimStart('.');
2016-11-08 18:44:23 +00:00
if (string.Equals(codec, "txt", StringComparison.OrdinalIgnoreCase))
{
codec = "srt";
}
2014-05-16 19:16:29 +00:00
// If the subtitle file matches the video file name
if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{
streams.Add(new MediaStream
{
Index = startIndex++,
Type = MediaStreamType.Subtitle,
IsExternal = true,
Path = fullName,
Codec = codec
});
}
else if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
{
var isForced = fullName.IndexOf(".forced.", StringComparison.OrdinalIgnoreCase) != -1 ||
fullName.IndexOf(".foreign.", StringComparison.OrdinalIgnoreCase) != -1;
var isDefault = fullName.IndexOf(".default.", StringComparison.OrdinalIgnoreCase) != -1;
2014-05-16 19:16:29 +00:00
// Support xbmc naming conventions - 300.spanish.srt
var language = fileNameWithoutExtension
.Replace(".forced", string.Empty, StringComparison.OrdinalIgnoreCase)
.Replace(".foreign", string.Empty, StringComparison.OrdinalIgnoreCase)
.Split('.')
.LastOrDefault();
// Try to translate to three character code
// Be flexible and check against both the full and three character versions
var culture = _localization.GetCultures()
2016-11-08 18:44:23 +00:00
.FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) ||
string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) ||
string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) ||
2016-07-21 02:55:35 +00:00
string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase));
2014-05-16 19:16:29 +00:00
if (culture != null)
{
language = culture.ThreeLetterISOLanguageName;
}
streams.Add(new MediaStream
{
Index = startIndex++,
Type = MediaStreamType.Subtitle,
IsExternal = true,
Path = fullName,
Codec = codec,
Language = language,
IsForced = isForced,
IsDefault = isDefault
2014-05-16 19:16:29 +00:00
});
}
}
return streams;
}
private string NormalizeFilenameForSubtitleComparison(string filename)
{
// Try to account for sloppy file naming
filename = filename.Replace("_", string.Empty);
filename = filename.Replace(" ", string.Empty);
2016-07-21 02:55:35 +00:00
// can't normalize this due to languages such as pt-br
//filename = filename.Replace("-", string.Empty);
//filename = filename.Replace(".", string.Empty);
return filename;
}
2014-05-16 19:16:29 +00:00
private static IEnumerable<string> SubtitleExtensions
{
get
{
2017-02-05 20:44:08 +00:00
return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami" };
2014-05-16 19:16:29 +00:00
}
}
2017-03-29 06:26:48 +00:00
public static IEnumerable<string> GetSubtitleFiles(Video video, IDirectoryService directoryService, IFileSystem fileSystem, bool clearCache)
2014-05-16 19:16:29 +00:00
{
var containingPath = video.ContainingFolderPath;
if (string.IsNullOrEmpty(containingPath))
{
throw new ArgumentException(string.Format("Cannot search for items that don't have a path: {0} {1}", video.Name, video.Id));
}
2017-03-29 06:26:48 +00:00
var files = directoryService.GetFilePaths(containingPath, clearCache);
2014-05-16 19:16:29 +00:00
2014-07-26 17:30:15 +00:00
var videoFileNameWithoutExtension = fileSystem.GetFileNameWithoutExtension(video.Path);
2014-05-16 19:16:29 +00:00
return files.Where(i =>
{
2017-03-29 06:26:48 +00:00
var extension = Path.GetExtension(i);
if (SubtitleExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
2014-05-16 19:16:29 +00:00
{
2014-07-26 17:30:15 +00:00
var fileNameWithoutExtension = fileSystem.GetFileNameWithoutExtension(i);
2014-05-16 19:16:29 +00:00
if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
});
}
}
}