From 69c9d1179eb17bca1e81b61c4de27edb80101f95 Mon Sep 17 00:00:00 2001 From: Danny Michel Date: Tue, 21 Jun 2022 10:19:19 +0100 Subject: [PATCH 1/4] Github files --- .github/CODEOWNERS | 6 +- .github/renovate.json | 2 +- .github/workflows/automation.yml | 4 +- .github/workflows/commands.yml | 4 +- .github/workflows/repo-stale.yaml | 2 +- .gitignore | 1 + README.md | 191 ++++-------------------------- 7 files changed, 34 insertions(+), 176 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e1900d5833..2e39990b6f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,4 @@ # Joshua must review all changes to deployment and build.sh -.ci/* @joshuaboniface -deployment/* @joshuaboniface -build.sh @joshuaboniface +.ci/* @dannymichel +deployment/* @dannymichel +build.sh @dannymichel diff --git a/.github/renovate.json b/.github/renovate.json index 5ca683876a..736a972f56 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,6 +1,6 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "github>jellyfin/.github//renovate-presets/dotnet" + "github>vesoapp/.github//renovate-presets/dotnet" ] } diff --git a/.github/workflows/automation.yml b/.github/workflows/automation.yml index 4b5571c774..d23601d563 100644 --- a/.github/workflows/automation.yml +++ b/.github/workflows/automation.yml @@ -12,7 +12,7 @@ jobs: label: name: Labeling runs-on: ubuntu-latest - if: ${{ github.repository == 'jellyfin/jellyfin' }} + if: ${{ github.repository == 'vesoapp/veso' }} steps: - name: Apply label uses: eps1lon/actions-label-merge-conflict@fd1f295ee7443d13745804bc49fe158e240f6c6e # tag=v2.1.0 @@ -24,7 +24,7 @@ jobs: project: name: Project board runs-on: ubuntu-latest - if: ${{ github.repository == 'jellyfin/jellyfin' }} + if: ${{ github.repository == 'vesoapp/veso' }} steps: - name: Remove from 'Current Release' project uses: alex-page/github-project-automation-plus@7ffb872c64bd809d23563a130a0a97d01dfa8f43 # v0.8.3 diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml index c0b365b02f..1c320d098b 100644 --- a/.github/workflows/commands.yml +++ b/.github/workflows/commands.yml @@ -13,7 +13,7 @@ permissions: {} jobs: rebase: name: Rebase - if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '@jellyfin-bot rebase') && github.event.comment.author_association == 'MEMBER' + if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '@veso-bot rebase') && github.event.comment.author_association == 'MEMBER' runs-on: ubuntu-latest steps: - name: Notify as seen @@ -39,7 +39,7 @@ jobs: contents: read name: Check Backport - if: ${{ ( github.event.issue.pull_request && contains(github.event.comment.body, '@jellyfin-bot check backport') ) || github.event.label.name == 'stable backport' || contains(github.event.pull_request.labels.*.name, 'stable backport' ) }} + if: ${{ ( github.event.issue.pull_request && contains(github.event.comment.body, '@veso-bot check backport') ) || github.event.label.name == 'stable backport' || contains(github.event.pull_request.labels.*.name, 'stable backport' ) }} runs-on: ubuntu-latest steps: - name: Notify as seen diff --git a/.github/workflows/repo-stale.yaml b/.github/workflows/repo-stale.yaml index 7f6fcffed5..a9895cd233 100644 --- a/.github/workflows/repo-stale.yaml +++ b/.github/workflows/repo-stale.yaml @@ -10,7 +10,7 @@ permissions: jobs: stale: runs-on: ubuntu-latest - if: ${{ contains(github.repository, 'jellyfin/') }} + if: ${{ contains(github.repository, 'vesoapp/') }} steps: - uses: actions/stale@6f05e4244c9a0b2ed3401882b05d701dd0a7289b # v7 with: diff --git a/.gitignore b/.gitignore index d5a0367bff..7a4c6353db 100644 --- a/.gitignore +++ b/.gitignore @@ -277,3 +277,4 @@ apiclient/generated # Omnisharp crash logs mono_crash.*.json +.DS_Store diff --git a/README.md b/README.md index 2362741b47..d225e241e2 100644 --- a/README.md +++ b/README.md @@ -1,176 +1,33 @@ -

Jellyfin

+

Veso

The Free Software Media System

- ---- +

A Jellyfin Fork with Fixes and Usability in Mind

-Logo Banner -
-
- -GPL 2.0 License - - -Current Release - - -Translation Status - - -Azure Builds - - -Docker Pull Count - -
- -Donate - - -Submit Feature Requests - - -Chat on Matrix - - -Join our Subreddit - - -Release RSS Feed - - -Master Commits RSS Feed - +Logo Banner

---- - -Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media. It is an alternative to the proprietary Emby and Plex, to provide media from a dedicated server to end-user devices via multiple apps. Jellyfin is descended from Emby's 3.5.2 release and ported to the .NET Core framework to enable full cross-platform support. There are no strings attached, no premium licenses or features, and no hidden agendas: just a team who want to build something better and work together to achieve it. We welcome anyone who is interested in joining us in our quest! - -For further details, please see [our documentation page](https://jellyfin.org/docs/). To receive the latest updates, get help with Jellyfin, and join the community, please visit [one of our communication channels](https://jellyfin.org/docs/general/getting-help). For more information about the project, please see our [about page](https://jellyfin.org/docs/general/about). - -Want to get started?
-Check out our downloads page or our installation guide, then see our quick start guide. You can also build from source.
- -Something not working right?
-Open an Issue on GitHub.
- -Want to contribute?
-Check out our contributing choose-your-own-adventure to see where you can help, then see our contributing guide and our community standards.
- -New idea or improvement?
-Check out our feature request hub.
- -Don't see Jellyfin in your language?
-Check out our Weblate instance to help translate Jellyfin and its subprojects.
- - -Detailed Translation Status - - ---- - -## Jellyfin Server - -This repository contains the code for Jellyfin's backend server. Note that this is only one of many projects under the Jellyfin GitHub [organization](https://github.com/jellyfin/) on GitHub. If you want to contribute, you can start by checking out our [documentation](https://jellyfin.org/docs/general/contributing/index.html) to see what to work on. - -## Server Development - -These instructions will help you get set up with a local development environment in order to contribute to this repository. Before you start, please be sure to completely read our [guidelines on development contributions](https://jellyfin.org/docs/general/contributing/development.html). Note that this project is supported on all major operating systems except FreeBSD, which is still incompatible. +### docker-compose -### Prerequisites - -Before the project can be built, you must first install the [.NET 7.0 SDK](https://dotnet.microsoft.com/download/dotnet) on your system. - -Instructions to run this project from the command line are included here, but you will also need to install an IDE if you want to debug the server while it is running. Any IDE that supports .NET 6 development will work, but two options are recent versions of [Visual Studio](https://visualstudio.microsoft.com/downloads/) (at least 2022) and [Visual Studio Code](https://code.visualstudio.com/Download). - -[ffmpeg](https://github.com/jellyfin/jellyfin-ffmpeg) will also need to be installed. - -### Cloning the Repository - -After dependencies are installed you will need to clone a local copy of this repository. If you just want to run the server from source you can clone this repository directly, but if you are intending to contribute code changes to the project, you should [set up your own fork](https://jellyfin.org/docs/general/contributing/development.html#set-up-your-copy-of-the-repo) of the repository. The following example shows how you can clone the repository directly over HTTPS. - -```bash -git clone https://github.com/jellyfin/jellyfin.git ``` +version: '3.7' +services: + veso: + container_name: veso + environment: + - TZ=America/New_York + user: 1000:1000 + volumes: + - '/dev/dri:/dev/dri' + - '/path/to/config:/config' + - '/path/to/cache:/cache' + - '/path/to/media:/media' + ports: + - 8096:8096 + - 8920:8920 + devices: + - /dev/dri:/dev/dri + restart: unless-stopped + image: vesotv/veso:latest -### Installing the Web Client - -The server is configured to host the static files required for the [web client](https://github.com/jellyfin/jellyfin-web) in addition to serving the backend by default. Before you can run the server, you will need to get a copy of the web client since they are not included in this repository directly. - -Note that it is also possible to [host the web client separately](#hosting-the-web-client-separately) from the web server with some additional configuration, in which case you can skip this step. - -There are three options to get the files for the web client. - -1. Download one of the finished builds from the [Azure DevOps pipeline](https://dev.azure.com/jellyfin-project/jellyfin/_build?definitionId=27). You can download the build for a specific release by looking at the [branches tab](https://dev.azure.com/jellyfin-project/jellyfin/_build?definitionId=27&_a=summary&repositoryFilter=6&view=branches) of the pipelines page. -2. Build them from source following the instructions on the [jellyfin-web repository](https://github.com/jellyfin/jellyfin-web) -3. Get the pre-built files from an existing installation of the server. For example, with a Windows server installation the client files are located at `C:\Program Files\Jellyfin\Server\jellyfin-web` - -### Running The Server - -The following instructions will help you get the project up and running via the command line, or your preferred IDE. - -#### Running With Visual Studio - -To run the project with Visual Studio you can open the Solution (`.sln`) file and then press `F5` to run the server. - -#### Running With Visual Studio Code - -To run the project with Visual Studio Code you will first need to open the repository directory with Visual Studio Code using the `Open Folder...` option. - -Second, you need to [install the recommended extensions for the workspace](https://code.visualstudio.com/docs/editor/extension-gallery#_recommended-extensions). Note that extension recommendations are classified as either "Workspace Recommendations" or "Other Recommendations", but only the "Workspace Recommendations" are required. - -After the required extensions are installed, you can run the server by pressing `F5`. - -#### Running From The Command Line - -To run the server from the command line you can use the `dotnet run` command. The example below shows how to do this if you have cloned the repository into a directory named `jellyfin` (the default directory name) and should work on all operating systems. - -```bash -cd jellyfin # Move into the repository directory -dotnet run --project Jellyfin.Server --webdir /absolute/path/to/jellyfin-web/dist # Run the server startup project -``` - -A second option is to build the project and then run the resulting executable file directly. When running the executable directly you can easily add command line options. Add the `--help` flag to list details on all the supported command line options. - -1. Build the project - -```bash -dotnet build # Build the project -cd Jellyfin.Server/bin/Debug/net7.0 # Change into the build output directory ``` - -2. Execute the build output. On Linux, Mac, etc. use `./jellyfin` and on Windows use `jellyfin.exe`. - -### Running The Tests - -This repository also includes unit tests that are used to validate functionality as part of a CI pipeline on Azure. There are several ways to run these tests. - -1. Run tests from the command line using `dotnet test` -2. Run tests in Visual Studio using the [Test Explorer](https://docs.microsoft.com/en-us/visualstudio/test/run-unit-tests-with-test-explorer) -3. Run individual tests in Visual Studio Code using the associated [CodeLens annotation](https://github.com/OmniSharp/omnisharp-vscode/wiki/How-to-run-and-debug-unit-tests) - -### Advanced Configuration - -The following sections describe some more advanced scenarios for running the server from source that build upon the standard instructions above. - -#### Hosting The Web Client Separately - -It is not necessary to host the frontend web client as part of the backend server. Hosting these two components separately may be useful for frontend developers who would prefer to host the client in a separate webpack development server for a tighter development loop. See the [jellyfin-web](https://github.com/jellyfin/jellyfin-web#getting-started) repo for instructions on how to do this. - -To instruct the server not to host the web content, there is a `nowebclient` configuration flag that must be set. This can specified using the command line -switch `--nowebclient` or the environment variable `JELLYFIN_NOWEBCONTENT=true`. - -Since this is a common scenario, there is also a separate launch profile defined for Visual Studio called `Jellyfin.Server (nowebcontent)` that can be selected from the 'Start Debugging' dropdown in the main toolbar. - -**NOTE:** The setup wizard can not be run if the web client is hosted separately. - ---- -

-This project is supported by: -
-
-DigitalOcean -   -JetBrains logo -

+Join us on discord https://discord.gg/Ce4PmFcX7Y From d11435a75f59737cb446887e2c762188f5c37fbf Mon Sep 17 00:00:00 2001 From: Danny Michel Date: Tue, 21 Jun 2022 10:19:19 +0100 Subject: [PATCH 2/4] Dockerfile --- Dockerfile | 4 ++-- Dockerfile.arm | 4 ++-- Dockerfile.arm64 | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index e51d285e12..8c73a97fe7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,8 +7,8 @@ ARG DOTNET_VERSION=7.0 FROM node:lts-alpine as web-builder ARG JELLYFIN_WEB_VERSION=master RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-sdk automake libtool make gcc musl-dev nasm python3 \ - && curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ - && cd jellyfin-web-* \ + && curl -L https://github.com/vesoapp/veso-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ + && cd veso-web-* \ && npm ci --no-audit --unsafe-perm \ && npm run build:production \ && mv dist /dist diff --git a/Dockerfile.arm b/Dockerfile.arm index 46a3e9b998..9188b5fcad 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -8,8 +8,8 @@ ARG DOTNET_VERSION=7.0 FROM node:lts-alpine as web-builder ARG JELLYFIN_WEB_VERSION=master RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-sdk automake libtool make gcc musl-dev nasm python3 \ - && curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ - && cd jellyfin-web-* \ + && curl -L https://github.com/vesoapp/veso-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ + && cd veso-web-* \ && npm ci --no-audit --unsafe-perm \ && npm run build:production \ && mv dist /dist diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index 4f9d5e1fdc..86173b1d1a 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -8,8 +8,8 @@ ARG DOTNET_VERSION=7.0 FROM node:lts-alpine as web-builder ARG JELLYFIN_WEB_VERSION=master RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-sdk automake libtool make gcc musl-dev nasm python3 \ - && curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ - && cd jellyfin-web-* \ + && curl -L https://github.com/vesoapp/veso-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ + && cd veso-web-* \ && npm ci --no-audit --unsafe-perm \ && npm run build:production \ && mv dist /dist From 8202ded245fe029de3b49168ffded3a988cdd77f Mon Sep 17 00:00:00 2001 From: Danny Michel Date: Mon, 1 Aug 2022 23:19:19 +0100 Subject: [PATCH 3/4] Revert "Backport pull request #8087 from jellyfin/release-10.8.z" This reverts commit 38eefbbafa381ea2d87efaa3328c5e273b902732. --- .../ApplicationHost.cs | 3 +- .../Subtitles/AssParser.cs | 19 +++++ .../Subtitles/ISubtitleParser.cs | 12 +-- .../Subtitles/SrtParser.cs | 19 +++++ .../Subtitles/SsaParser.cs | 19 +++++ .../Subtitles/SubtitleEditParser.cs | 83 +++---------------- .../Subtitles/SubtitleEncoder.cs | 45 ++++++++-- .../Subtitles/AssParserTests.cs | 2 +- .../Subtitles/SrtParserTests.cs | 4 +- .../Subtitles/SsaParserTests.cs | 6 +- 10 files changed, 118 insertions(+), 94 deletions(-) create mode 100644 MediaBrowser.MediaEncoding/Subtitles/AssParser.cs create mode 100644 MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs create mode 100644 MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 080c448299..cae808a893 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -597,8 +597,7 @@ protected virtual void RegisterServices(IServiceCollection serviceCollection) serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs new file mode 100644 index 0000000000..08ee5c72e5 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Logging; +using Nikse.SubtitleEdit.Core.SubtitleFormats; + +namespace MediaBrowser.MediaEncoding.Subtitles +{ + /// + /// Advanced SubStation Alpha subtitle parser. + /// + public class AssParser : SubtitleEditParser + { + /// + /// Initializes a new instance of the class. + /// + /// The logger. + public AssParser(ILogger logger) : base(logger) + { + } + } +} diff --git a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs index bd13437fb6..c0023ebf24 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System.IO; +using System.Threading; using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.Subtitles @@ -11,15 +12,8 @@ public interface ISubtitleParser /// Parses the specified stream. /// /// The stream. - /// The file extension. + /// The cancellation token. /// SubtitleTrackInfo. - SubtitleTrackInfo Parse(Stream stream, string fileExtension); - - /// - /// Determines whether the file extension is supported by the parser. - /// - /// The file extension. - /// A value indicating whether the file extension is supported. - bool SupportsFileExtension(string fileExtension); + SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs new file mode 100644 index 0000000000..78d54ca51f --- /dev/null +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Logging; +using Nikse.SubtitleEdit.Core.SubtitleFormats; + +namespace MediaBrowser.MediaEncoding.Subtitles +{ + /// + /// SubRip subtitle parser. + /// + public class SrtParser : SubtitleEditParser + { + /// + /// Initializes a new instance of the class. + /// + /// The logger. + public SrtParser(ILogger logger) : base(logger) + { + } + } +} diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs new file mode 100644 index 0000000000..17c2ae40e0 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Logging; +using Nikse.SubtitleEdit.Core.SubtitleFormats; + +namespace MediaBrowser.MediaEncoding.Subtitles +{ + /// + /// SubStation Alpha subtitle parser. + /// + public class SsaParser : SubtitleEditParser + { + /// + /// Initializes a new instance of the class. + /// + /// The logger. + public SsaParser(ILogger logger) : base(logger) + { + } + } +} diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index 0d4489517e..52c1b64677 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Threading; using Jellyfin.Extensions; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core.Common; +using ILogger = Microsoft.Extensions.Logging.ILogger; using SubtitleFormat = Nikse.SubtitleEdit.Core.SubtitleFormats.SubtitleFormat; namespace MediaBrowser.MediaEncoding.Subtitles @@ -14,57 +14,31 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// /// SubStation Alpha subtitle parser. /// - public class SubtitleEditParser : ISubtitleParser + /// The . + public abstract class SubtitleEditParser : ISubtitleParser + where T : SubtitleFormat, new() { - private readonly ILogger _logger; - private readonly Dictionary _subtitleFormats; + private readonly ILogger _logger; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The logger. - public SubtitleEditParser(ILogger logger) + protected SubtitleEditParser(ILogger logger) { _logger = logger; - _subtitleFormats = GetSubtitleFormats() - .Where(subtitleFormat => !string.IsNullOrEmpty(subtitleFormat.Extension)) - .GroupBy(subtitleFormat => subtitleFormat.Extension.TrimStart('.'), StringComparer.OrdinalIgnoreCase) - .ToDictionary(g => g.Key, g => g.ToArray(), StringComparer.OrdinalIgnoreCase); } /// - public SubtitleTrackInfo Parse(Stream stream, string fileExtension) + public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken) { var subtitle = new Subtitle(); + var subRip = new T(); var lines = stream.ReadAllLines().ToList(); - - if (!_subtitleFormats.TryGetValue(fileExtension, out var subtitleFormats)) - { - throw new ArgumentException($"Unsupported file extension: {fileExtension}", nameof(fileExtension)); - } - - foreach (var subtitleFormat in subtitleFormats) + subRip.LoadSubtitle(subtitle, lines, "untitled"); + if (subRip.ErrorCount > 0) { - _logger.LogDebug( - "Trying to parse '{FileExtension}' subtitle using the {SubtitleFormatParser} format parser", - fileExtension, - subtitleFormat.Name); - subtitleFormat.LoadSubtitle(subtitle, lines, fileExtension); - if (subtitleFormat.ErrorCount == 0) - { - break; - } - - _logger.LogError( - "{ErrorCount} errors encountered while parsing '{FileExtension}' subtitle using the {SubtitleFormatParser} format parser", - subtitleFormat.ErrorCount, - fileExtension, - subtitleFormat.Name); - } - - if (subtitle.Paragraphs.Count == 0) - { - throw new ArgumentException("Unsupported format: " + fileExtension); + _logger.LogError("{ErrorCount} errors encountered while parsing subtitle", subRip.ErrorCount); } var trackInfo = new SubtitleTrackInfo(); @@ -83,36 +57,5 @@ public SubtitleTrackInfo Parse(Stream stream, string fileExtension) trackInfo.TrackEvents = trackEvents; return trackInfo; } - - /// - public bool SupportsFileExtension(string fileExtension) - => _subtitleFormats.ContainsKey(fileExtension); - - private IEnumerable GetSubtitleFormats() - { - var subtitleFormats = new List(); - var assembly = typeof(SubtitleFormat).Assembly; - - foreach (var type in assembly.GetTypes()) - { - if (!type.IsSubclassOf(typeof(SubtitleFormat)) || type.IsAbstract) - { - continue; - } - - try - { - // It shouldn't be null, but the exception is caught if it is - var subtitleFormat = (SubtitleFormat)Activator.CreateInstance(type, true)!; - subtitleFormats.Add(subtitleFormat); - } - catch (Exception ex) - { - _logger.LogWarning(ex, "Failed to create instance of the subtitle format {SubtitleFormatType}", type.Name); - } - } - - return subtitleFormats; - } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 90bc491322..9e43b91299 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -35,7 +35,6 @@ public sealed class SubtitleEncoder : ISubtitleEncoder private readonly IMediaEncoder _mediaEncoder; private readonly IHttpClientFactory _httpClientFactory; private readonly IMediaSourceManager _mediaSourceManager; - private readonly ISubtitleParser _subtitleParser; /// /// The _semaphoreLocks. @@ -49,8 +48,7 @@ public SubtitleEncoder( IFileSystem fileSystem, IMediaEncoder mediaEncoder, IHttpClientFactory httpClientFactory, - IMediaSourceManager mediaSourceManager, - ISubtitleParser subtitleParser) + IMediaSourceManager mediaSourceManager) { _logger = logger; _appPaths = appPaths; @@ -58,7 +56,6 @@ public SubtitleEncoder( _mediaEncoder = mediaEncoder; _httpClientFactory = httpClientFactory; _mediaSourceManager = mediaSourceManager; - _subtitleParser = subtitleParser; } private string SubtitleCachePath => Path.Combine(_appPaths.DataPath, "subtitles"); @@ -76,7 +73,8 @@ private Stream ConvertSubtitles( try { - var trackInfo = _subtitleParser.Parse(stream, inputFormat); + var reader = GetReader(inputFormat); + var trackInfo = reader.Parse(stream, cancellationToken); FilterEvents(trackInfo, startTimeTicks, endTimeTicks, preserveOriginalTimestamps); @@ -238,8 +236,7 @@ await ExtractTextSubtitle(mediaSource, subtitleStream, outputCodec, outputPath, var currentFormat = (Path.GetExtension(subtitleStream.Path) ?? subtitleStream.Codec) .TrimStart('.'); - // Fallback to ffmpeg conversion - if (!_subtitleParser.SupportsFileExtension(currentFormat)) + if (!TryGetReader(currentFormat, out _)) { // Convert var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, ".srt"); @@ -265,6 +262,40 @@ await ExtractTextSubtitle(mediaSource, subtitleStream, outputCodec, outputPath, }; } + private bool TryGetReader(string format, [NotNullWhen(true)] out ISubtitleParser? value) + { + if (string.Equals(format, SubtitleFormat.SRT, StringComparison.OrdinalIgnoreCase)) + { + value = new SrtParser(_logger); + return true; + } + + if (string.Equals(format, SubtitleFormat.SSA, StringComparison.OrdinalIgnoreCase)) + { + value = new SsaParser(_logger); + return true; + } + + if (string.Equals(format, SubtitleFormat.ASS, StringComparison.OrdinalIgnoreCase)) + { + value = new AssParser(_logger); + return true; + } + + value = null; + return false; + } + + private ISubtitleParser GetReader(string format) + { + if (TryGetReader(format, out var reader)) + { + return reader; + } + + throw new ArgumentException("Unsupported format: " + format); + } + private bool TryGetWriter(string format, [NotNullWhen(true)] out ISubtitleWriter? value) { ArgumentException.ThrowIfNullOrEmpty(format); diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs index fe0d7fc90f..6d90929e1f 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs @@ -14,7 +14,7 @@ public void Parse_Valid_Success() { using (var stream = File.OpenRead("Test Data/example.ass")) { - var parsed = new SubtitleEditParser(new NullLogger()).Parse(stream, "ass"); + var parsed = new AssParser(new NullLogger()).Parse(stream, CancellationToken.None); Assert.Single(parsed.TrackEvents); var trackEvent = parsed.TrackEvents[0]; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs index 2aebee5562..a1e9414461 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs @@ -14,7 +14,7 @@ public void Parse_Valid_Success() { using (var stream = File.OpenRead("Test Data/example.srt")) { - var parsed = new SubtitleEditParser(new NullLogger()).Parse(stream, "srt"); + var parsed = new SrtParser(new NullLogger()).Parse(stream, CancellationToken.None); Assert.Equal(2, parsed.TrackEvents.Count); var trackEvent1 = parsed.TrackEvents[0]; @@ -36,7 +36,7 @@ public void Parse_EmptyNewlineBetweenText_Success() { using (var stream = File.OpenRead("Test Data/example2.srt")) { - var parsed = new SubtitleEditParser(new NullLogger()).Parse(stream, "srt"); + var parsed = new SrtParser(new NullLogger()).Parse(stream, CancellationToken.None); Assert.Equal(2, parsed.TrackEvents.Count); var trackEvent1 = parsed.TrackEvents[0]; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs index 6abf2d26cb..e5451d4621 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs @@ -12,7 +12,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests { public class SsaParserTests { - private readonly SubtitleEditParser _parser = new SubtitleEditParser(new NullLogger()); + private readonly SsaParser _parser = new SsaParser(new NullLogger()); [Theory] [MemberData(nameof(Parse_MultipleDialogues_TestData))] @@ -20,7 +20,7 @@ public void Parse_MultipleDialogues_Success(string ssa, IReadOnlyList Date: Mon, 17 Apr 2023 11:41:48 +0000 Subject: [PATCH 4/4] chore(deps): update actions/checkout digest to 8e5e7e5 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/commands.yml | 4 ++-- .github/workflows/openapi.yml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d5dcb785c1..bf0da51d28 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -20,7 +20,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 - name: Setup .NET uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # tag=v3 with: diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml index 1c320d098b..99d1db88b7 100644 --- a/.github/workflows/commands.yml +++ b/.github/workflows/commands.yml @@ -24,7 +24,7 @@ jobs: reactions: '+1' - name: Checkout the latest code - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 with: token: ${{ secrets.JF_BOT_TOKEN }} fetch-depth: 0 @@ -51,7 +51,7 @@ jobs: reactions: eyes - name: Checkout the latest code - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 with: token: ${{ secrets.JF_BOT_TOKEN }} fetch-depth: 0 diff --git a/.github/workflows/openapi.yml b/.github/workflows/openapi.yml index a67ce90d22..0f8221b767 100644 --- a/.github/workflows/openapi.yml +++ b/.github/workflows/openapi.yml @@ -14,7 +14,7 @@ jobs: permissions: read-all steps: - name: Checkout repository - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 with: ref: ${{ github.event.pull_request.head.sha }} repository: ${{ github.event.pull_request.head.repo.full_name }} @@ -39,7 +39,7 @@ jobs: permissions: read-all steps: - name: Checkout repository - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 with: ref: ${{ github.event.pull_request.head.sha }} repository: ${{ github.event.pull_request.head.repo.full_name }}