mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-31 14:33:54 -04: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 System.Threading.Tasks;
|
||||||
using Jellyfin.Api.Attributes;
|
using Jellyfin.Api.Attributes;
|
||||||
using Jellyfin.Api.Constants;
|
using Jellyfin.Api.Constants;
|
||||||
|
using Jellyfin.Api.Models.SubtitleDtos;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
@ -319,6 +320,33 @@ namespace Jellyfin.Api.Controllers
|
|||||||
return File(Encoding.UTF8.GetBytes(builder.ToString()), MimeTypes.GetMimeType("playlist.m3u8"));
|
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>
|
/// <summary>
|
||||||
/// Encodes a subtitle in the specified format.
|
/// Encodes a subtitle in the specified format.
|
||||||
/// </summary>
|
/// </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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
@ -52,6 +53,14 @@ namespace MediaBrowser.Controller.Subtitles
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Task DownloadSubtitles(Video video, LibraryOptions libraryOptions, string subtitleId, CancellationToken cancellationToken);
|
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>
|
/// <summary>
|
||||||
/// Gets the remote subtitles.
|
/// Gets the remote subtitles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -150,12 +150,43 @@ namespace MediaBrowser.Providers.Subtitles
|
|||||||
var parts = subtitleId.Split(new[] { '_' }, 2);
|
var parts = subtitleId.Split(new[] { '_' }, 2);
|
||||||
var provider = GetProvider(parts[0]);
|
var provider = GetProvider(parts[0]);
|
||||||
|
|
||||||
var saveInMediaFolder = libraryOptions.SaveSubtitlesWithMedia;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = await GetRemoteSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
|
var response = await GetRemoteSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await TrySaveSubtitle(video, libraryOptions, response).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (RateLimitExceededException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SubtitleDownloadFailure?.Invoke(this, new SubtitleDownloadFailureEventArgs
|
||||||
|
{
|
||||||
|
Item = video,
|
||||||
|
Exception = ex,
|
||||||
|
Provider = provider.Name
|
||||||
|
});
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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 stream = response.Stream)
|
||||||
using (var memoryStream = new MemoryStream())
|
using (var memoryStream = new MemoryStream())
|
||||||
{
|
{
|
||||||
@ -182,22 +213,6 @@ namespace MediaBrowser.Providers.Subtitles
|
|||||||
await TrySaveToFiles(memoryStream, savePaths).ConfigureAwait(false);
|
await TrySaveToFiles(memoryStream, savePaths).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (RateLimitExceededException)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
SubtitleDownloadFailure?.Invoke(this, new SubtitleDownloadFailureEventArgs
|
|
||||||
{
|
|
||||||
Item = video,
|
|
||||||
Exception = ex,
|
|
||||||
Provider = provider.Name
|
|
||||||
});
|
|
||||||
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task TrySaveToFiles(Stream stream, List<string> savePaths)
|
private async Task TrySaveToFiles(Stream stream, List<string> savePaths)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user