jellyfin/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs

204 lines
7 KiB
C#
Raw Normal View History

#pragma warning disable CS1591
using System;
2014-05-16 21:16:29 +02:00
using System.Collections.Generic;
using System.IO;
using System.Linq;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
2016-10-24 04:45:23 +02:00
using MediaBrowser.Model.Globalization;
2014-05-16 21:16:29 +02:00
namespace MediaBrowser.Providers.MediaInfo
{
public class SubtitleResolver
{
private readonly ILocalizationManager _localization;
2019-02-24 15:47:59 +01:00
private static readonly HashSet<string> SubtitleExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
".srt",
".ssa",
".ass",
".sub",
".smi",
".sami",
".vtt"
};
public SubtitleResolver(ILocalizationManager localization)
2014-05-16 21:16:29 +02:00
{
_localization = localization;
}
public List<MediaStream> GetExternalSubtitleStreams(
Video video,
2020-04-11 15:37:24 +02:00
int startIndex,
IDirectoryService directoryService,
bool clearCache)
2014-05-16 21:16:29 +02:00
{
var streams = new List<MediaStream>();
2018-09-12 19:26:21 +02:00
if (!video.IsFileProtocol)
{
return streams;
}
AddExternalSubtitleStreams(streams, video.ContainingFolderPath, video.Path, startIndex, directoryService, clearCache);
startIndex += streams.Count;
2019-02-24 15:47:59 +01:00
string folder = video.GetInternalMetadataPath();
if (!Directory.Exists(folder))
{
return streams;
}
try
{
2019-02-24 15:47:59 +01:00
AddExternalSubtitleStreams(streams, folder, video.Path, startIndex, directoryService, clearCache);
}
catch (IOException)
{
}
return streams;
}
2020-09-07 13:20:39 +02:00
public List<string> GetExternalSubtitleFiles(
Video video,
IDirectoryService directoryService,
bool clearCache)
{
var list = new List<string>();
2018-09-12 19:26:21 +02:00
if (!video.IsFileProtocol)
{
return list;
}
var streams = GetExternalSubtitleStreams(video, 0, directoryService, clearCache);
foreach (var stream in streams)
{
list.Add(stream.Path);
}
return list;
}
2020-09-07 13:20:39 +02:00
private void AddExternalSubtitleStreams(
List<MediaStream> streams,
string folder,
string videoPath,
int startIndex,
IDirectoryService directoryService,
bool clearCache)
2018-09-12 19:26:21 +02:00
{
var files = directoryService.GetFilePaths(folder, clearCache).OrderBy(i => i).ToArray();
AddExternalSubtitleStreams(streams, videoPath, startIndex, files);
}
2020-09-07 13:20:39 +02:00
public void AddExternalSubtitleStreams(
List<MediaStream> streams,
2018-09-12 19:26:21 +02:00
string videoPath,
int startIndex,
string[] files)
{
var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(videoPath);
videoFileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(videoFileNameWithoutExtension);
2014-05-16 21:16:29 +02:00
2017-03-29 08:26:48 +02:00
foreach (var fullName in files)
2014-05-16 21:16:29 +02:00
{
var extension = Path.GetExtension(fullName);
2019-02-24 15:47:59 +01:00
if (!SubtitleExtensions.Contains(extension))
{
continue;
}
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
fileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(fileNameWithoutExtension);
2014-05-16 21:16:29 +02:00
if (!string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase) &&
!fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
{
continue;
}
2019-01-27 12:03:43 +01:00
var codec = Path.GetExtension(fullName).ToLowerInvariant().TrimStart('.');
2014-05-16 21:16:29 +02:00
2016-11-08 19:44:23 +01:00
if (string.Equals(codec, "txt", StringComparison.OrdinalIgnoreCase))
{
codec = "srt";
}
2014-05-16 21:16:29 +02: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 21:16:29 +02:00
// Support xbmc naming conventions - 300.spanish.srt
var language = fileNameWithoutExtension
.Replace(".forced", string.Empty, StringComparison.OrdinalIgnoreCase)
.Replace(".foreign", string.Empty, StringComparison.OrdinalIgnoreCase)
2018-09-12 19:26:21 +02:00
.Replace(".default", string.Empty, StringComparison.OrdinalIgnoreCase)
2014-05-16 21:16:29 +02:00
.Split('.')
.LastOrDefault();
// Try to translate to three character code
// Be flexible and check against both the full and three character versions
2018-09-12 19:26:21 +02:00
var culture = _localization.FindLanguageInfo(language);
2014-05-16 21:16:29 +02: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 21:16:29 +02:00
});
}
}
}
private string NormalizeFilenameForSubtitleComparison(string filename)
{
// Try to account for sloppy file naming
2020-09-07 13:20:39 +02:00
filename = filename.Replace("_", string.Empty, StringComparison.Ordinal);
filename = filename.Replace(" ", string.Empty, StringComparison.Ordinal);
2016-07-21 04:55:35 +02:00
// can't normalize this due to languages such as pt-br
2020-06-14 11:11:11 +02:00
// filename = filename.Replace("-", string.Empty);
2016-07-21 04:55:35 +02:00
2020-06-14 11:11:11 +02:00
// filename = filename.Replace(".", string.Empty);
return filename;
}
2014-05-16 21:16:29 +02:00
}
}