Merge pull request #7529 from Shadowghost/strm-ffprobe-external-fix
(cherry picked from commit 60affd096595d68728506149d0ffce6e84b6b015) Signed-off-by: crobibero <cody@robibe.ro>
This commit is contained in:
parent
5e593cf29c
commit
efcdab116f
|
@ -5763,7 +5763,7 @@ AND Type = @InternalPersonType)");
|
||||||
{
|
{
|
||||||
var itemIdBlob = id.ToByteArray();
|
var itemIdBlob = id.ToByteArray();
|
||||||
|
|
||||||
// First delete chapters
|
// Delete existing mediastreams
|
||||||
db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob);
|
db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob);
|
||||||
|
|
||||||
InsertMediaStreams(itemIdBlob, streams, db);
|
InsertMediaStreams(itemIdBlob, streams, db);
|
||||||
|
@ -5867,10 +5867,10 @@ AND Type = @InternalPersonType)");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the chapter.
|
/// Gets the media stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader">The reader.</param>
|
/// <param name="reader">The reader.</param>
|
||||||
/// <returns>ChapterInfo.</returns>
|
/// <returns>MediaStream.</returns>
|
||||||
private MediaStream GetMediaStream(IReadOnlyList<ResultSetValue> reader)
|
private MediaStream GetMediaStream(IReadOnlyList<ResultSetValue> reader)
|
||||||
{
|
{
|
||||||
var item = new MediaStream
|
var item = new MediaStream
|
||||||
|
|
|
@ -151,7 +151,11 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
var mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user);
|
var mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user);
|
||||||
|
|
||||||
if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Audio || i.Type == MediaStreamType.Video))
|
// If file is strm or main media stream is missing, force a metadata refresh with remote probing
|
||||||
|
if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder
|
||||||
|
&& (item.Path.EndsWith(".strm", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| (item.MediaType == MediaType.Video && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Video))
|
||||||
|
|| (item.MediaType == MediaType.Audio && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Audio))))
|
||||||
{
|
{
|
||||||
await item.RefreshMetadata(
|
await item.RefreshMetadata(
|
||||||
new MetadataRefreshOptions(_directoryService)
|
new MetadataRefreshOptions(_directoryService)
|
||||||
|
|
|
@ -2215,13 +2215,13 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
return state.IsInputVideo ? "-sn" : string.Empty;
|
return state.IsInputVideo ? "-sn" : string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have media info, but we don't know the stream indexes
|
// We have media info, but we don't know the stream index
|
||||||
if (state.VideoStream != null && state.VideoStream.Index == -1)
|
if (state.VideoStream != null && state.VideoStream.Index == -1)
|
||||||
{
|
{
|
||||||
return "-sn";
|
return "-sn";
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have media info, but we don't know the stream indexes
|
// We have media info, but we don't know the stream index
|
||||||
if (state.AudioStream != null && state.AudioStream.Index == -1)
|
if (state.AudioStream != null && state.AudioStream.Index == -1)
|
||||||
{
|
{
|
||||||
return state.IsInputVideo ? "-sn" : string.Empty;
|
return state.IsInputVideo ? "-sn" : string.Empty;
|
||||||
|
@ -2231,10 +2231,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
if (state.VideoStream != null)
|
if (state.VideoStream != null)
|
||||||
{
|
{
|
||||||
|
int videoStreamIndex = FindIndex(state.MediaSource.MediaStreams, state.VideoStream);
|
||||||
|
|
||||||
args += string.Format(
|
args += string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"-map 0:{0}",
|
"-map 0:{0}",
|
||||||
state.VideoStream.Index);
|
videoStreamIndex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2244,24 +2246,24 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
if (state.AudioStream != null)
|
if (state.AudioStream != null)
|
||||||
{
|
{
|
||||||
|
int audioStreamIndex = FindIndex(state.MediaSource.MediaStreams, state.AudioStream);
|
||||||
if (state.AudioStream.IsExternal)
|
if (state.AudioStream.IsExternal)
|
||||||
{
|
{
|
||||||
bool hasExternalGraphicsSubs = state.SubtitleStream != null && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream;
|
bool hasExternalGraphicsSubs = state.SubtitleStream != null && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream;
|
||||||
int externalAudioMapIndex = hasExternalGraphicsSubs ? 2 : 1;
|
int externalAudioMapIndex = hasExternalGraphicsSubs ? 2 : 1;
|
||||||
int externalAudioStream = state.MediaSource.MediaStreams.Where(i => i.Path == state.AudioStream.Path).ToList().IndexOf(state.AudioStream);
|
|
||||||
|
|
||||||
args += string.Format(
|
args += string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
" -map {0}:{1}",
|
" -map {0}:{1}",
|
||||||
externalAudioMapIndex,
|
externalAudioMapIndex,
|
||||||
externalAudioStream);
|
audioStreamIndex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
args += string.Format(
|
args += string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
" -map 0:{0}",
|
" -map 0:{0}",
|
||||||
state.AudioStream.Index);
|
audioStreamIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2276,14 +2278,21 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
}
|
}
|
||||||
else if (subtitleMethod == SubtitleDeliveryMethod.Embed)
|
else if (subtitleMethod == SubtitleDeliveryMethod.Embed)
|
||||||
{
|
{
|
||||||
|
int subtitleStreamIndex = FindIndex(state.MediaSource.MediaStreams, state.SubtitleStream);
|
||||||
|
|
||||||
args += string.Format(
|
args += string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
" -map 0:{0}",
|
" -map 0:{0}",
|
||||||
state.SubtitleStream.Index);
|
subtitleStreamIndex);
|
||||||
}
|
}
|
||||||
else if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)
|
else if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)
|
||||||
{
|
{
|
||||||
args += " -map 1:0 -sn";
|
int externalSubtitleStreamIndex = FindIndex(state.MediaSource.MediaStreams, state.SubtitleStream);
|
||||||
|
|
||||||
|
args += string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
" -map 1:{0} -sn",
|
||||||
|
externalSubtitleStreamIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
|
@ -4129,9 +4138,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
string.Join(',', overlayFilters));
|
string.Join(',', overlayFilters));
|
||||||
|
|
||||||
var mapPrefix = Convert.ToInt32(state.SubtitleStream.IsExternal);
|
var mapPrefix = Convert.ToInt32(state.SubtitleStream.IsExternal);
|
||||||
var subtitleStreamIndex = state.SubtitleStream.IsExternal
|
var subtitleStreamIndex = FindIndex(state.MediaSource.MediaStreams, state.SubtitleStream);
|
||||||
? 0
|
var videoStreamIndex = FindIndex(state.MediaSource.MediaStreams, state.VideoStream);
|
||||||
: state.SubtitleStream.Index;
|
|
||||||
|
|
||||||
if (hasSubs)
|
if (hasSubs)
|
||||||
{
|
{
|
||||||
|
@ -4152,7 +4160,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
filterStr,
|
filterStr,
|
||||||
mapPrefix,
|
mapPrefix,
|
||||||
subtitleStreamIndex,
|
subtitleStreamIndex,
|
||||||
state.VideoStream.Index,
|
videoStreamIndex,
|
||||||
mainStr,
|
mainStr,
|
||||||
subStr,
|
subStr,
|
||||||
overlayStr);
|
overlayStr);
|
||||||
|
@ -5389,6 +5397,28 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
string.Empty).Trim();
|
string.Empty).Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int FindIndex(IReadOnlyList<MediaStream> mediaStreams, MediaStream streamToFind)
|
||||||
|
{
|
||||||
|
var index = 0;
|
||||||
|
var length = mediaStreams.Count;
|
||||||
|
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
var currentMediaStream = mediaStreams[i];
|
||||||
|
if (currentMediaStream == streamToFind)
|
||||||
|
{
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(currentMediaStream.Path, streamToFind.Path, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool IsCopyCodec(string codec)
|
public static bool IsCopyCodec(string codec)
|
||||||
{
|
{
|
||||||
return string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase);
|
return string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
|
@ -141,6 +141,13 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
string GetInputArgument(string inputFile, MediaSourceInfo mediaSource);
|
string GetInputArgument(string inputFile, MediaSourceInfo mediaSource);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the input argument for an external subtitle file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputFile">The input file.</param>
|
||||||
|
/// <returns>System.String.</returns>
|
||||||
|
string GetExternalSubtitleInputArgument(string inputFile);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the time parameter.
|
/// Gets the time parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -411,6 +411,19 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
return EncodingUtils.GetInputArgument(prefix, inputFile, mediaSource.Protocol);
|
return EncodingUtils.GetInputArgument(prefix, inputFile, mediaSource.Protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the input argument for an external subtitle file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputFile">The input file.</param>
|
||||||
|
/// <returns>System.String.</returns>
|
||||||
|
/// <exception cref="ArgumentException">Unrecognized InputType.</exception>
|
||||||
|
public string GetExternalSubtitleInputArgument(string inputFile)
|
||||||
|
{
|
||||||
|
const string Prefix = "file";
|
||||||
|
|
||||||
|
return EncodingUtils.GetInputArgument(Prefix, inputFile, MediaProtocol.File);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the media info internal.
|
/// Gets the media info internal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -195,7 +195,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
MediaStream subtitleStream,
|
MediaStream subtitleStream,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!subtitleStream.IsExternal)
|
if (!subtitleStream.IsExternal || subtitleStream.Path.EndsWith(".mks", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
string outputFormat;
|
string outputFormat;
|
||||||
string outputCodec;
|
string outputCodec;
|
||||||
|
@ -224,7 +224,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
// Extract
|
// Extract
|
||||||
var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, "." + outputFormat);
|
var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, "." + outputFormat);
|
||||||
|
|
||||||
await ExtractTextSubtitle(mediaSource, subtitleStream.Index, outputCodec, outputPath, cancellationToken)
|
await ExtractTextSubtitle(mediaSource, subtitleStream, outputCodec, outputPath, cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
return new SubtitleInfo(outputPath, MediaProtocol.File, outputFormat, false);
|
return new SubtitleInfo(outputPath, MediaProtocol.File, outputFormat, false);
|
||||||
|
@ -494,7 +494,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
/// Extracts the text subtitle.
|
/// Extracts the text subtitle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mediaSource">The mediaSource.</param>
|
/// <param name="mediaSource">The mediaSource.</param>
|
||||||
/// <param name="subtitleStreamIndex">Index of the subtitle stream.</param>
|
/// <param name="subtitleStream">The subtitle stream.</param>
|
||||||
/// <param name="outputCodec">The output codec.</param>
|
/// <param name="outputCodec">The output codec.</param>
|
||||||
/// <param name="outputPath">The output path.</param>
|
/// <param name="outputPath">The output path.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
@ -502,7 +502,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
/// <exception cref="ArgumentException">Must use inputPath list overload.</exception>
|
/// <exception cref="ArgumentException">Must use inputPath list overload.</exception>
|
||||||
private async Task ExtractTextSubtitle(
|
private async Task ExtractTextSubtitle(
|
||||||
MediaSourceInfo mediaSource,
|
MediaSourceInfo mediaSource,
|
||||||
int subtitleStreamIndex,
|
MediaStream subtitleStream,
|
||||||
string outputCodec,
|
string outputCodec,
|
||||||
string outputPath,
|
string outputPath,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
|
@ -511,12 +511,21 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
|
|
||||||
await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var subtitleStreamIndex = EncodingHelper.FindIndex(mediaSource.MediaStreams, subtitleStream);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!File.Exists(outputPath))
|
if (!File.Exists(outputPath))
|
||||||
{
|
{
|
||||||
|
var args = _mediaEncoder.GetInputArgument(mediaSource.Path, mediaSource);
|
||||||
|
|
||||||
|
if (subtitleStream.IsExternal)
|
||||||
|
{
|
||||||
|
args = _mediaEncoder.GetExternalSubtitleInputArgument(subtitleStream.Path);
|
||||||
|
}
|
||||||
|
|
||||||
await ExtractTextSubtitleInternal(
|
await ExtractTextSubtitleInternal(
|
||||||
_mediaEncoder.GetInputArgument(mediaSource.Path, mediaSource),
|
args,
|
||||||
subtitleStreamIndex,
|
subtitleStreamIndex,
|
||||||
outputCodec,
|
outputCodec,
|
||||||
outputPath,
|
outputPath,
|
||||||
|
|
|
@ -173,16 +173,30 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
IReadOnlyList<MediaAttachment> mediaAttachments;
|
IReadOnlyList<MediaAttachment> mediaAttachments;
|
||||||
ChapterInfo[] chapters;
|
ChapterInfo[] chapters;
|
||||||
|
|
||||||
|
mediaStreams = new List<MediaStream>();
|
||||||
|
|
||||||
|
// Add external streams before adding the streams from the file to preserve stream IDs on remote videos
|
||||||
|
await AddExternalSubtitlesAsync(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await AddExternalAudioAsync(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var startIndex = mediaStreams.Count == 0 ? 0 : (mediaStreams.Max(i => i.Index) + 1);
|
||||||
|
|
||||||
if (mediaInfo != null)
|
if (mediaInfo != null)
|
||||||
{
|
{
|
||||||
mediaStreams = mediaInfo.MediaStreams.ToList();
|
foreach (var mediaStream in mediaInfo.MediaStreams)
|
||||||
|
{
|
||||||
|
mediaStream.Index = startIndex++;
|
||||||
|
mediaStreams.Add(mediaStream);
|
||||||
|
}
|
||||||
|
|
||||||
mediaAttachments = mediaInfo.MediaAttachments;
|
mediaAttachments = mediaInfo.MediaAttachments;
|
||||||
|
|
||||||
video.TotalBitrate = mediaInfo.Bitrate;
|
video.TotalBitrate = mediaInfo.Bitrate;
|
||||||
// video.FormatName = (mediaInfo.Container ?? string.Empty)
|
// video.FormatName = (mediaInfo.Container ?? string.Empty)
|
||||||
// .Replace("matroska", "mkv", StringComparison.OrdinalIgnoreCase);
|
// .Replace("matroska", "mkv", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
// For dvd's this may not always be accurate, so don't set the runtime if the item already has one
|
// For DVDs this may not always be accurate, so don't set the runtime if the item already has one
|
||||||
var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0;
|
var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0;
|
||||||
|
|
||||||
if (needToSetRuntime)
|
if (needToSetRuntime)
|
||||||
|
@ -213,15 +227,20 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mediaStreams = new List<MediaStream>();
|
var currentMediaStreams = video.GetMediaStreams();
|
||||||
|
foreach (var mediaStream in currentMediaStreams)
|
||||||
|
{
|
||||||
|
if (!mediaStream.IsExternal)
|
||||||
|
{
|
||||||
|
mediaStream.Index = startIndex++;
|
||||||
|
mediaStreams.Add(mediaStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mediaAttachments = Array.Empty<MediaAttachment>();
|
mediaAttachments = Array.Empty<MediaAttachment>();
|
||||||
chapters = Array.Empty<ChapterInfo>();
|
chapters = Array.Empty<ChapterInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
await AddExternalSubtitlesAsync(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
await AddExternalAudioAsync(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var libraryOptions = _libraryManager.GetLibraryOptions(video);
|
var libraryOptions = _libraryManager.GetLibraryOptions(video);
|
||||||
|
|
||||||
if (mediaInfo != null)
|
if (mediaInfo != null)
|
||||||
|
@ -254,7 +273,11 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle);
|
video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle);
|
||||||
|
|
||||||
_itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken);
|
_itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken);
|
||||||
|
|
||||||
|
if (mediaAttachments.Any())
|
||||||
|
{
|
||||||
_itemRepo.SaveMediaAttachments(video.Id, mediaAttachments, cancellationToken);
|
_itemRepo.SaveMediaAttachments(video.Id, mediaAttachments, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh ||
|
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh ||
|
||||||
options.MetadataRefreshMode == MetadataRefreshMode.Default)
|
options.MetadataRefreshMode == MetadataRefreshMode.Default)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user