From 7cf9a6fe6b76bff4bab1803d75f06a437a8731a8 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Tue, 17 Sep 2019 02:39:26 +0200 Subject: [PATCH] Adding subtitle swap fonctionality inside the web app player. --- .../src/app/player/player.component.html | 20 ++++++++++- .../src/app/player/player.component.ts | 36 ++++++++++++++++--- Kyoo/ClientApp/src/models/watch-item.ts | 8 ++--- Kyoo/Controllers/SubtitleController.cs | 19 ++++++++-- .../LibraryManager/ILibraryManager.cs | 2 +- .../LibraryManager/LibraryManager.cs | 17 ++++----- Kyoo/Models/Track.cs | 3 +- 7 files changed, 83 insertions(+), 22 deletions(-) diff --git a/Kyoo/ClientApp/src/app/player/player.component.html b/Kyoo/ClientApp/src/app/player/player.component.html index 21c4b91a..b469d3b0 100644 --- a/Kyoo/ClientApp/src/app/player/player.component.html +++ b/Kyoo/ClientApp/src/app/player/player.component.html @@ -64,7 +64,7 @@ - + +
+ + + + + +
+ diff --git a/Kyoo/ClientApp/src/app/player/player.component.ts b/Kyoo/ClientApp/src/app/player/player.component.ts index 9cd771b5..c588dfa3 100644 --- a/Kyoo/ClientApp/src/app/player/player.component.ts +++ b/Kyoo/ClientApp/src/app/player/player.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; -import { WatchItem } from "../../models/watch-item"; +import { WatchItem, Track } from "../../models/watch-item"; import { ActivatedRoute } from "@angular/router"; import { DomSanitizer, Title } from "@angular/platform-browser"; import { Location } from "@angular/common"; @@ -20,6 +20,7 @@ export class PlayerComponent implements OnInit volume: number = 100; seeking: boolean = false; videoHider; + selectedSubtitle: Track; hours: number; minutes: number = 0; @@ -100,7 +101,6 @@ export class PlayerComponent implements OnInit let progressBar: HTMLElement = document.getElementById("progress-bar") as HTMLElement; $(progressBar).click((event) => { - console.log("Duration: " + this.player.duration); event.preventDefault(); let time: number = this.getTimeFromSeekbar(progressBar, event.pageX); this.player.currentTime = time; @@ -182,8 +182,6 @@ export class PlayerComponent implements OnInit }); $('[data-toggle="tooltip"]').tooltip({ trigger: "hover" }); - - SubtitleManager.add(this.player, "/api/subtitle/" + this.item.link + "-fre.ass", true); } getTimeFromSeekbar(progressBar: HTMLElement, pageX: number) @@ -281,6 +279,36 @@ export class PlayerComponent implements OnInit } } + selectSubtitle(subtitle: Track) + { + this.selectedSubtitle = subtitle; + + if (subtitle == null) + { + SubtitleManager.remove(this.player); + } + else + { + if (subtitle.codec == "ass") + SubtitleManager.add(this.player, this.getSubtitleLink(subtitle), true); + } + } + + getSubtitleLink(subtitle: Track): string + { + let link: string = "/api/subtitle/" + this.item.link + "-" + subtitle.language; + + if (subtitle.isForced) + link += "-forced"; + + //The extension is not necesarry but we add this because it allow the user to quickly download the file in the good format if he wants. + if (subtitle.codec == "ass") + link += ".ass"; + else if (subtitle.codec == "subrip") + link += ".srt" + + return link; + } getThumb(url: string) { diff --git a/Kyoo/ClientApp/src/models/watch-item.ts b/Kyoo/ClientApp/src/models/watch-item.ts index c6ff6a6d..03ab046c 100644 --- a/Kyoo/ClientApp/src/models/watch-item.ts +++ b/Kyoo/ClientApp/src/models/watch-item.ts @@ -15,15 +15,15 @@ export interface WatchItem previousEpisode: string; nextEpisode: Episode; - audio: Stream[]; - subtitles: Stream[]; + audio: Track[]; + subtitles: Track[]; } -export interface Stream +export interface Track { title: string; language: string; isDefault: boolean; isForced: boolean; - format: string; + codec: string; } diff --git a/Kyoo/Controllers/SubtitleController.cs b/Kyoo/Controllers/SubtitleController.cs index 547aeecc..9f0b04cc 100644 --- a/Kyoo/Controllers/SubtitleController.cs +++ b/Kyoo/Controllers/SubtitleController.cs @@ -18,10 +18,23 @@ namespace Kyoo.Controllers this.transcoder = transcoder; } - [HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}-{languageTag}.{format?}")] - public IActionResult GetSubtitle(string showSlug, long seasonNumber, long episodeNumber, string languageTag, string format) + [HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}-{languageTag}.{codec?}")] + public IActionResult GetSubtitle(string showSlug, long seasonNumber, long episodeNumber, string languageTag, string codec) { - Track subtitle = libraryManager.GetSubtitle(showSlug, seasonNumber, episodeNumber, languageTag); + Track subtitle = libraryManager.GetSubtitle(showSlug, seasonNumber, episodeNumber, languageTag, false); + + if (subtitle == null) + return NotFound(); + + //Should use appropriate mime type here + return PhysicalFile(subtitle.Path, "text/x-ssa"); + } + + //This one is never called. + [HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}-{languageTag}-{disposition}.{codec?}")] //Disposition can't be tagged as optional because there is a parametter after him. + public IActionResult GetForcedSubtitle(string showSlug, long seasonNumber, long episodeNumber, string languageTag, string disposition, string codec) + { + Track subtitle = libraryManager.GetSubtitle(showSlug, seasonNumber, episodeNumber, languageTag, disposition == "forced"); if (subtitle == null) return NotFound(); diff --git a/Kyoo/InternalAPI/LibraryManager/ILibraryManager.cs b/Kyoo/InternalAPI/LibraryManager/ILibraryManager.cs index ec748ece..e8f4d933 100644 --- a/Kyoo/InternalAPI/LibraryManager/ILibraryManager.cs +++ b/Kyoo/InternalAPI/LibraryManager/ILibraryManager.cs @@ -18,7 +18,7 @@ namespace Kyoo.InternalAPI //Internal HTML read (List audios, List subtitles) GetStreams(long episodeID); - Track GetSubtitle(string showSlug, long seasonNumber, long episodeNumber, string languageTag); + Track GetSubtitle(string showSlug, long seasonNumber, long episodeNumber, string languageTag, bool forced); //Public read IEnumerable GetLibraries(); diff --git a/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs b/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs index 4cbf51ae..6b81df26 100644 --- a/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs +++ b/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs @@ -73,7 +73,7 @@ namespace Kyoo.InternalAPI CREATE TABLE tracks( id INTEGER PRIMARY KEY UNIQUE, episodeID INTEGER, - streamType TEXT, + streamType INTEGER, title TEXT, language TEXT, codec TEXT, @@ -203,21 +203,21 @@ namespace Kyoo.InternalAPI while (reader.Read()) { - Track stream = Track.FromReader(reader); + Track track = Track.FromReader(reader); - if (stream.type == StreamType.Audio) - audios.Add(stream); - else if (stream.type == StreamType.Subtitle) - subtitles.Add(stream); + if (track.type == StreamType.Audio) + audios.Add(track); + else if (track.type == StreamType.Subtitle) + subtitles.Add(track); } return (audios, subtitles); } } - public Track GetSubtitle(string showSlug, long seasonNumber, long episodeNumber, string languageTag) + public Track GetSubtitle(string showSlug, long seasonNumber, long episodeNumber, string languageTag, bool forced) { - string query = "SELECT tracks.* FROM tracks JOIN episodes ON tracks.episodeID = episodes.id JOIN shows ON episodes.showID = shows.id WHERE shows.slug = $showSlug AND episodes.seasonNumber = $seasonNumber AND episodes.episodeNumber = $episodeNumber AND tracks.language = $languageTag;"; + string query = "SELECT tracks.* FROM tracks JOIN episodes ON tracks.episodeID = episodes.id JOIN shows ON episodes.showID = shows.id WHERE shows.slug = $showSlug AND episodes.seasonNumber = $seasonNumber AND episodes.episodeNumber = $episodeNumber AND tracks.language = $languageTag AND tracks.isForced = $forced;"; using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection)) { @@ -225,6 +225,7 @@ namespace Kyoo.InternalAPI cmd.Parameters.AddWithValue("$seasonNumber", seasonNumber); cmd.Parameters.AddWithValue("$episodeNumber", episodeNumber); cmd.Parameters.AddWithValue("$languageTag", languageTag); + cmd.Parameters.AddWithValue("$forced", forced); SQLiteDataReader reader = cmd.ExecuteReader(); if (reader.Read()) diff --git a/Kyoo/Models/Track.cs b/Kyoo/Models/Track.cs index e3f74cf0..a5ccbe40 100644 --- a/Kyoo/Models/Track.cs +++ b/Kyoo/Models/Track.cs @@ -1,5 +1,6 @@ using Kyoo.Models.Watch; using Newtonsoft.Json; +using System; using System.Runtime.InteropServices; namespace Kyoo.Models @@ -44,7 +45,7 @@ namespace Kyoo.Models public static Track FromReader(System.Data.SQLite.SQLiteDataReader reader) { - return new Track(reader["streamType"] as StreamType? ?? StreamType.Unknow, + return new Track((StreamType)Enum.ToObject(typeof(StreamType), reader["streamType"]), reader["title"] as string, reader["language"] as string, reader["isDefault"] as bool? ?? false,