mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-06-03 13:44:22 -04:00
add extracting attachments from external subs
This commit is contained in:
parent
c512e783b3
commit
6904edf68c
@ -13,6 +13,7 @@ using Jellyfin.Api.Models.StreamingDtos;
|
|||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
@ -530,6 +531,15 @@ namespace Jellyfin.Api.Helpers
|
|||||||
{
|
{
|
||||||
var attachmentPath = Path.Combine(_appPaths.CachePath, "attachments", state.MediaSource.Id);
|
var attachmentPath = Path.Combine(_appPaths.CachePath, "attachments", state.MediaSource.Id);
|
||||||
await _attachmentExtractor.ExtractAllAttachments(state.MediaPath, state.MediaSource, attachmentPath, CancellationToken.None).ConfigureAwait(false);
|
await _attachmentExtractor.ExtractAllAttachments(state.MediaPath, state.MediaSource, attachmentPath, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (state.SubtitleStream.IsExternal)
|
||||||
|
{
|
||||||
|
string subtitlePath = state.SubtitleStream.Path;
|
||||||
|
string subtitlePathArgument = string.Format(CultureInfo.InvariantCulture, "file:\"{0}\"", subtitlePath.Replace("\"", "\\\"", StringComparison.Ordinal));
|
||||||
|
string subtitleId = subtitlePath.GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
await _attachmentExtractor.ExtractAllAttachmentsExternal(subtitlePathArgument, subtitleId, attachmentPath, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var process = new Process
|
var process = new Process
|
||||||
|
@ -23,5 +23,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
MediaSourceInfo mediaSource,
|
MediaSourceInfo mediaSource,
|
||||||
string outputPath,
|
string outputPath,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
Task ExtractAllAttachmentsExternal(
|
||||||
|
string inputArgument,
|
||||||
|
string id,
|
||||||
|
string outputPath,
|
||||||
|
CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,29 +89,63 @@ namespace MediaBrowser.MediaEncoding.Attachments
|
|||||||
string outputPath,
|
string outputPath,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var semaphore = _semaphoreLocks.GetOrAdd(outputPath, key => new SemaphoreSlim(1, 1));
|
if (!Directory.Exists(outputPath))
|
||||||
|
|
||||||
await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(outputPath))
|
var semaphore = _semaphoreLocks.GetOrAdd(outputPath, key => new SemaphoreSlim(1, 1));
|
||||||
|
|
||||||
|
await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await ExtractAllAttachmentsInternal(
|
await ExtractAllAttachmentsInternal(
|
||||||
_mediaEncoder.GetInputArgument(inputFile, mediaSource),
|
_mediaEncoder.GetInputArgument(inputFile, mediaSource),
|
||||||
outputPath,
|
outputPath,
|
||||||
|
false,
|
||||||
cancellationToken).ConfigureAwait(false);
|
cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally
|
}
|
||||||
|
|
||||||
|
public async Task ExtractAllAttachmentsExternal(
|
||||||
|
string inputArgument,
|
||||||
|
string id,
|
||||||
|
string outputPath,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (!File.Exists(Path.Join(outputPath, id)))
|
||||||
{
|
{
|
||||||
semaphore.Release();
|
var semaphore = _semaphoreLocks.GetOrAdd(outputPath, key => new SemaphoreSlim(1, 1));
|
||||||
|
|
||||||
|
await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await ExtractAllAttachmentsInternal(
|
||||||
|
inputArgument,
|
||||||
|
outputPath,
|
||||||
|
true,
|
||||||
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (Directory.Exists(outputPath))
|
||||||
|
{
|
||||||
|
File.Create(Path.Join(outputPath, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
semaphore.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ExtractAllAttachmentsInternal(
|
private async Task ExtractAllAttachmentsInternal(
|
||||||
string inputPath,
|
string inputPath,
|
||||||
string outputPath,
|
string outputPath,
|
||||||
|
bool isExternal,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(inputPath))
|
if (string.IsNullOrEmpty(inputPath))
|
||||||
@ -124,11 +158,14 @@ namespace MediaBrowser.MediaEncoding.Attachments
|
|||||||
throw new ArgumentNullException(nameof(outputPath));
|
throw new ArgumentNullException(nameof(outputPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
Directory.CreateDirectory(outputPath);
|
if (!Directory.Exists(outputPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(outputPath);
|
||||||
|
}
|
||||||
|
|
||||||
var processArgs = string.Format(
|
var processArgs = string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"-dump_attachment:t \"\" -i {0} -t 0 -f null null",
|
"-dump_attachment:t \"\" -y -i {0} -t 0 -f null null",
|
||||||
inputPath);
|
inputPath);
|
||||||
|
|
||||||
int exitCode;
|
int exitCode;
|
||||||
@ -174,19 +211,24 @@ namespace MediaBrowser.MediaEncoding.Attachments
|
|||||||
|
|
||||||
if (exitCode != 0)
|
if (exitCode != 0)
|
||||||
{
|
{
|
||||||
failed = true;
|
if (isExternal && exitCode == 1)
|
||||||
|
|
||||||
_logger.LogWarning("Deleting extracted attachments {Path} due to failure: {ExitCode}", outputPath, exitCode);
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (Directory.Exists(outputPath))
|
// ffmpeg returns exitCode 1 because there is no video or audio stream
|
||||||
|
// this can be ignored
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
failed = true;
|
||||||
|
|
||||||
|
_logger.LogWarning("Deleting extracted attachments {Path} due to failure: {ExitCode}", outputPath, exitCode);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Directory.Delete(outputPath);
|
Directory.Delete(outputPath);
|
||||||
}
|
}
|
||||||
}
|
catch (IOException ex)
|
||||||
catch (IOException ex)
|
{
|
||||||
{
|
_logger.LogError(ex, "Error deleting extracted attachments {Path}", outputPath);
|
||||||
_logger.LogError(ex, "Error deleting extracted attachments {Path}", outputPath);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!Directory.Exists(outputPath))
|
else if (!Directory.Exists(outputPath))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user