mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Adding subtitle swap fonctionality inside the web app player.
This commit is contained in:
parent
1ce584d087
commit
7cf9a6fe6b
@ -64,7 +64,7 @@
|
||||
<button *ngIf="this.item.audios.length > 0" mat-icon-button data-toggle="tooltip" data-placement="top" title="Select audio track">
|
||||
<mat-icon>music_note</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="this.item.subtitles.length > 0" mat-icon-button data-toggle="tooltip" data-placement="top" title="Select subtitle track">
|
||||
<button *ngIf="this.item.subtitles.length > 0" mat-icon-button [matMenuTriggerFor]="subtitles" data-toggle="tooltip" data-placement="top" title="Select subtitle track">
|
||||
<mat-icon>closed_caption</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button data-toggle="tooltip" data-placement="top" title="Cast">
|
||||
@ -79,6 +79,24 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-menu #subtitles="matMenu">
|
||||
<button mat-menu-item (click)="selectSubtitle(null)">
|
||||
<span>None</span>
|
||||
</button>
|
||||
|
||||
<div *ngFor="let subtitle of this.item.subtitles">
|
||||
<button mat-menu-item *ngIf="subtitle.codec == 'ass'; else elseBlock" (click)="selectSubtitle(subtitle)">
|
||||
<span>{{subtitle.language}}</span>
|
||||
</button>
|
||||
|
||||
<ng-template #elseBlock>
|
||||
<button mat-menu-item disabled>
|
||||
<span>{{subtitle.language}}</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</div>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -18,7 +18,7 @@ namespace Kyoo.InternalAPI
|
||||
|
||||
//Internal HTML read
|
||||
(List<Track> audios, List<Track> 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<Library> GetLibraries();
|
||||
|
@ -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())
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user