Subrip to WebVTT on the fly transcoder finished.

This commit is contained in:
Zoe Roux 2019-09-19 12:24:08 +02:00
parent 8fc703ff15
commit f67293d065
6 changed files with 131 additions and 8 deletions

View File

@ -20,7 +20,7 @@
<div class="controller container-fluid" id="controller">
<div class="img d-none d-sm-block">
<img src="thumb/{{this.item.showSlug}}" />
<img src="poster/{{this.item.showSlug}}" />
</div>
<div class="content">
<h3>S{{this.item.seasonNumber}}:E{{this.item.episodeNumber}} - {{this.item.title}}</h3>

View File

@ -207,7 +207,6 @@ export class PlayerComponent implements OnInit
$(window).keydown((e) =>
{
console.log(e.keyCode);
switch (e.keyCode)
{
case 32: //space
@ -313,6 +312,7 @@ export class PlayerComponent implements OnInit
this.title.setTitle("Kyoo");
$(document).unbind();
$(window).unbind();
$('[data-toggle="tooltip"]').hide();
}

View File

@ -2,7 +2,12 @@
using Kyoo.Models;
using Kyoo.Models.Watch;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace Kyoo.Controllers
{
@ -19,8 +24,8 @@ namespace Kyoo.Controllers
this.transcoder = transcoder;
}
[HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}.{identifier}.{codec?}")]
public IActionResult GetSubtitle(string showSlug, int seasonNumber, int episodeNumber, string identifier, string codec)
[HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}.{identifier}.{extension?}")]
public IActionResult GetSubtitle(string showSlug, int seasonNumber, int episodeNumber, string identifier, string extension)
{
string languageTag = identifier.Substring(0, 3);
bool forced = identifier.Length > 3 && identifier.Substring(4) == "forced";
@ -30,10 +35,16 @@ namespace Kyoo.Controllers
if (subtitle == null)
return NotFound();
string mime = "text/vtt";
if (subtitle.Codec == "subrip" && extension == "vtt") //The request wants a WebVTT from a Subrip subtitle, convert it on the fly and send it.
{
return new ConvertSubripToVtt(subtitle.Path);
}
string mime;
if (subtitle.Codec == "ass")
mime = "text/x-ssa";
else if (subtitle.Codec == "subrip")
else
mime = "application/x-subrip";
//Should use appropriate mime type here
@ -44,9 +55,87 @@ namespace Kyoo.Controllers
public string ExtractSubtitle(string showSlug, long seasonNumber, long episodeNumber)
{
Episode episode = libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber);
transcoder.ExtractSubtitles(episode.Path);
libraryManager.ClearSubtitles(episode.id);
return "Processing...";
Track[] tracks = transcoder.ExtractSubtitles(episode.Path);
foreach (Track track in tracks)
{
track.episodeID = episode.id;
libraryManager.RegisterTrack(track);
}
return "Done. " + tracks.Length + " track(s) extracted.";
}
[HttpGet("extract/{showSlug}")]
public string ExtractSubtitle(string showSlug)
{
List<Episode> episodes = libraryManager.GetEpisodes(showSlug);
foreach (Episode episode in episodes)
{
libraryManager.ClearSubtitles(episode.id);
Track[] tracks = transcoder.ExtractSubtitles(episode.Path);
foreach (Track track in tracks)
{
track.episodeID = episode.id;
libraryManager.RegisterTrack(track);
}
}
return "Done.";
}
}
public class ConvertSubripToVtt : IActionResult
{
private string path;
private string lastLine = "";
public ConvertSubripToVtt(string subtitlePath)
{
path = subtitlePath;
}
public async Task ExecuteResultAsync(ActionContext context)
{
context.HttpContext.Response.StatusCode = 200;
//HttpContext.Response.Headers.Add("Content-Disposition", "attachement");
context.HttpContext.Response.Headers.Add("Content-Type", "text/vtt");
using (StreamWriter writer = new StreamWriter(context.HttpContext.Response.Body))
{
await writer.WriteLineAsync("WEBVTT");
await writer.WriteLineAsync("");
await writer.WriteLineAsync("");
string line;
using (StreamReader reader = new StreamReader(path))
{
while ((line = await reader.ReadLineAsync()) != null)
{
string processedLine = ConvertLine(line);
if(processedLine != null)
await writer.WriteLineAsync(processedLine);
lastLine = processedLine;
}
}
}
await context.HttpContext.Response.Body.FlushAsync();
}
public string ConvertLine(string line)
{
if (lastLine == "")
line = null;
if (lastLine == null) //The line is a timecode only if the last line is an index line and we already set it to null.
line = line.Replace(',', '.'); //This is never called.
return line;
}
}
}

View File

@ -24,6 +24,7 @@ namespace Kyoo.InternalAPI
IEnumerable<Library> GetLibraries();
Show GetShowBySlug(string slug);
Season GetSeason(string showSlug, long seasonNumber);
List<Episode> GetEpisodes(string showSlug);
List<Episode> GetEpisodes(string showSlug, long seasonNumber);
Episode GetEpisode(string showSlug, long seasonNumber, long episodeNumber);
WatchItem GetWatchItem(string showSlug, long seasonNumber, long episodeNumber, bool complete = true);
@ -48,5 +49,7 @@ namespace Kyoo.InternalAPI
long GetOrCreateStudio(Studio studio);
void RegisterShowPeople(long showID, List<People> actors);
void ClearSubtitles(long episodeID);
}
}

View File

@ -318,6 +318,24 @@ namespace Kyoo.InternalAPI
}
}
public List<Episode> GetEpisodes(string showSlug)
{
string query = "SELECT * FROM episodes JOIN shows ON shows.id = episodes.showID WHERE shows.slug = $showSlug ORDER BY episodeNumber;";
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
cmd.Parameters.AddWithValue("$showSlug", showSlug);
SQLiteDataReader reader = cmd.ExecuteReader();
List<Episode> episodes = new List<Episode>();
while (reader.Read())
episodes.Add(Episode.FromReader(reader).SetThumb(showSlug));
return episodes;
}
}
public List<Episode> GetEpisodes(string showSlug, long seasonNumber)
{
string query = "SELECT * FROM episodes JOIN shows ON shows.id = episodes.showID WHERE shows.slug = $showSlug AND episodes.seasonNumber = $seasonNumber ORDER BY episodeNumber;";
@ -735,6 +753,17 @@ namespace Kyoo.InternalAPI
}
}
}
public void ClearSubtitles(long episodeID)
{
string query = "DELETE FROM tracks WHERE episodeID = $episodeID;";
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
{
cmd.Parameters.AddWithValue("$episodeID", episodeID);
cmd.ExecuteNonQuery();
}
}
#endregion
}
}

View File

@ -1,8 +1,10 @@
using Kyoo.InternalAPI.TranscoderLink;
using Kyoo.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
namespace Kyoo.InternalAPI
{