mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 18:08:53 -07:00
Merge pull request #3086 from redSpoutnik/api-upload-subtitle
Add Post subtitle in API
This commit is contained in:
commit
96dcd9c87e
@ -11,6 +11,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Api.Attributes;
|
||||
using Jellyfin.Api.Constants;
|
||||
using Jellyfin.Api.Models.SubtitleDtos;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
@ -319,6 +320,33 @@ namespace Jellyfin.Api.Controllers
|
||||
return File(Encoding.UTF8.GetBytes(builder.ToString()), MimeTypes.GetMimeType("playlist.m3u8"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload an external subtitle file.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item the subtitle belongs to.</param>
|
||||
/// <param name="body">The request body.</param>
|
||||
/// <response code="204">Subtitle uploaded.</response>
|
||||
/// <returns>A <see cref="NoContentResult"/>.</returns>
|
||||
[HttpPost("Videos/{itemId}/Subtitles")]
|
||||
public async Task<ActionResult> UploadSubtitle(
|
||||
[FromRoute, Required] Guid itemId,
|
||||
[FromBody, Required] UploadSubtitleDto body)
|
||||
{
|
||||
var video = (Video)_libraryManager.GetItemById(itemId);
|
||||
var data = Convert.FromBase64String(body.Data);
|
||||
await using var memoryStream = new MemoryStream(data);
|
||||
await _subtitleManager.UploadSubtitle(
|
||||
video,
|
||||
new SubtitleResponse
|
||||
{
|
||||
Format = body.Format,
|
||||
Language = body.Language,
|
||||
IsForced = body.IsForced,
|
||||
Stream = memoryStream
|
||||
}).ConfigureAwait(false);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a subtitle in the specified format.
|
||||
/// </summary>
|
||||
|
34
Jellyfin.Api/Models/SubtitleDtos/UploadSubtitleDto.cs
Normal file
34
Jellyfin.Api/Models/SubtitleDtos/UploadSubtitleDto.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Jellyfin.Api.Models.SubtitleDtos
|
||||
{
|
||||
/// <summary>
|
||||
/// Upload subtitles dto.
|
||||
/// </summary>
|
||||
public class UploadSubtitleDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the subtitle language.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Language { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the subtitle format.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Format { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the subtitle is forced.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool IsForced { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the subtitle data.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Data { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
@ -52,6 +53,14 @@ namespace MediaBrowser.Controller.Subtitles
|
||||
/// </summary>
|
||||
Task DownloadSubtitles(Video video, LibraryOptions libraryOptions, string subtitleId, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Upload new subtitle.
|
||||
/// </summary>
|
||||
/// <param name="video">The video the subtitle belongs to.</param>
|
||||
/// <param name="response">The subtitle response.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task UploadSubtitle(Video video, SubtitleResponse response);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the remote subtitles.
|
||||
/// </summary>
|
||||
|
@ -150,37 +150,11 @@ namespace MediaBrowser.Providers.Subtitles
|
||||
var parts = subtitleId.Split(new[] { '_' }, 2);
|
||||
var provider = GetProvider(parts[0]);
|
||||
|
||||
var saveInMediaFolder = libraryOptions.SaveSubtitlesWithMedia;
|
||||
|
||||
try
|
||||
{
|
||||
var response = await GetRemoteSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
using (var stream = response.Stream)
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||
memoryStream.Position = 0;
|
||||
|
||||
var savePaths = new List<string>();
|
||||
var saveFileName = Path.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLowerInvariant();
|
||||
|
||||
if (response.IsForced)
|
||||
{
|
||||
saveFileName += ".forced";
|
||||
}
|
||||
|
||||
saveFileName += "." + response.Format.ToLowerInvariant();
|
||||
|
||||
if (saveInMediaFolder)
|
||||
{
|
||||
savePaths.Add(Path.Combine(video.ContainingFolderPath, saveFileName));
|
||||
}
|
||||
|
||||
savePaths.Add(Path.Combine(video.GetInternalMetadataPath(), saveFileName));
|
||||
|
||||
await TrySaveToFiles(memoryStream, savePaths).ConfigureAwait(false);
|
||||
}
|
||||
await TrySaveSubtitle(video, libraryOptions, response).ConfigureAwait(false);
|
||||
}
|
||||
catch (RateLimitExceededException)
|
||||
{
|
||||
@ -199,6 +173,47 @@ namespace MediaBrowser.Providers.Subtitles
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task UploadSubtitle(Video video, SubtitleResponse response)
|
||||
{
|
||||
var libraryOptions = BaseItem.LibraryManager.GetLibraryOptions(video);
|
||||
return TrySaveSubtitle(video, libraryOptions, response);
|
||||
}
|
||||
|
||||
private async Task TrySaveSubtitle(
|
||||
Video video,
|
||||
LibraryOptions libraryOptions,
|
||||
SubtitleResponse response)
|
||||
{
|
||||
var saveInMediaFolder = libraryOptions.SaveSubtitlesWithMedia;
|
||||
|
||||
using (var stream = response.Stream)
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||
memoryStream.Position = 0;
|
||||
|
||||
var savePaths = new List<string>();
|
||||
var saveFileName = Path.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLowerInvariant();
|
||||
|
||||
if (response.IsForced)
|
||||
{
|
||||
saveFileName += ".forced";
|
||||
}
|
||||
|
||||
saveFileName += "." + response.Format.ToLowerInvariant();
|
||||
|
||||
if (saveInMediaFolder)
|
||||
{
|
||||
savePaths.Add(Path.Combine(video.ContainingFolderPath, saveFileName));
|
||||
}
|
||||
|
||||
savePaths.Add(Path.Combine(video.GetInternalMetadataPath(), saveFileName));
|
||||
|
||||
await TrySaveToFiles(memoryStream, savePaths).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task TrySaveToFiles(Stream stream, List<string> savePaths)
|
||||
{
|
||||
Exception exceptionToThrow = null;
|
||||
|
Loading…
Reference in New Issue
Block a user