mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Adding stream detections in the Subtitle Extract and adding logic into the c# linker.
This commit is contained in:
parent
40d8575e55
commit
1ced45a763
@ -7,12 +7,15 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
//extern "C" API struct Stream
|
extern "C" struct Stream
|
||||||
//{
|
{
|
||||||
// std::string title;
|
std::string title;
|
||||||
// std::string languageCode;
|
std::string language;
|
||||||
// std::string format;
|
std::string format;
|
||||||
// bool isDefault;
|
bool isDefault;
|
||||||
// bool isForced;
|
bool isForced;
|
||||||
// std::string path;
|
std::string path;
|
||||||
//};
|
|
||||||
|
Stream(std::string title, std::string languageCode, std::string format, bool isDefault, bool isForced, std::string path)
|
||||||
|
: title(title), language(languageCode), format(format), isDefault(isDefault), isForced(isForced), path(path) { }
|
||||||
|
};
|
@ -21,24 +21,25 @@ int Init()
|
|||||||
return 42;
|
return 42;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractSubtitles(const char* path, const char* outPath)
|
int ExtractSubtitles(const char* path, const char* outPath, Stream* streams)
|
||||||
{
|
{
|
||||||
AVFormatContext* inputContext = NULL;
|
AVFormatContext* inputContext = NULL;
|
||||||
|
|
||||||
if (avformat_open_input(&inputContext, path, NULL, NULL))
|
if (avformat_open_input(&inputContext, path, NULL, NULL))
|
||||||
{
|
{
|
||||||
std::cout << "Error: Can't open the file at " << path << std::endl;
|
std::cout << "Error: Can't open the file at " << path << std::endl;
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avformat_find_stream_info(inputContext, NULL) < 0)
|
if (avformat_find_stream_info(inputContext, NULL) < 0)
|
||||||
{
|
{
|
||||||
std::cout << "Error: Could't find streams informations for the file at " << path << std::endl;
|
std::cout << "Error: Could't find streams informations for the file at " << path << std::endl;
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
av_dump_format(inputContext, 0, path, false);
|
av_dump_format(inputContext, 0, path, false);
|
||||||
|
|
||||||
|
std::vector<Stream> subtitleStreams;
|
||||||
const unsigned int outputCount = inputContext->nb_streams;
|
const unsigned int outputCount = inputContext->nb_streams;
|
||||||
AVFormatContext** outputList = new AVFormatContext*[outputCount];
|
AVFormatContext** outputList = new AVFormatContext*[outputCount];
|
||||||
|
|
||||||
@ -53,13 +54,20 @@ void ExtractSubtitles(const char* path, const char* outPath)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Get metadata for file name
|
//Get metadata for file name
|
||||||
const char* language = av_dict_get(inputStream->metadata, "language", NULL, 0)->value;
|
Stream stream("title", //title
|
||||||
|
av_dict_get(inputStream->metadata, "language", NULL, 0)->value, //language
|
||||||
|
"format", //format
|
||||||
|
false, //isDefault
|
||||||
|
false, //isForced
|
||||||
|
"path"); //path
|
||||||
|
|
||||||
std::cout << "Stream #" << i << "(" << language << "), stream type: " << inputCodecpar->codec_type << " codec: " << inputCodecpar->codec_tag << std::endl;
|
subtitleStreams.push_back(stream);
|
||||||
|
|
||||||
|
std::cout << "Stream #" << i << "(" << stream.language << "), stream type: " << inputCodecpar->codec_type << " codec: " << inputCodecpar->codec_tag << std::endl;
|
||||||
|
|
||||||
//Create output folder
|
//Create output folder
|
||||||
std::stringstream outStream;
|
std::stringstream outStream;
|
||||||
outStream << outPath << (char)std::filesystem::path::preferred_separator << language;
|
outStream << outPath << (char)std::filesystem::path::preferred_separator << stream.language;
|
||||||
std::filesystem::create_directory(outStream.str());
|
std::filesystem::create_directory(outStream.str());
|
||||||
|
|
||||||
//Get file name
|
//Get file name
|
||||||
@ -68,7 +76,7 @@ void ExtractSubtitles(const char* path, const char* outPath)
|
|||||||
fileName = fileName.substr(lastSeparator, fileName.find_last_of('.') - lastSeparator);
|
fileName = fileName.substr(lastSeparator, fileName.find_last_of('.') - lastSeparator);
|
||||||
|
|
||||||
//Construct output file name
|
//Construct output file name
|
||||||
outStream << fileName << "." << language;
|
outStream << fileName << "." << stream.language;
|
||||||
outStream << ".ass";
|
outStream << ".ass";
|
||||||
std::string outStr = outStream.str();
|
std::string outStr = outStream.str();
|
||||||
const char* output = outStr.c_str();
|
const char* output = outStr.c_str();
|
||||||
@ -204,4 +212,8 @@ void ExtractSubtitles(const char* path, const char* outPath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete[] outputList;
|
delete[] outputList;
|
||||||
|
|
||||||
|
//std::copy()
|
||||||
|
//streams = subtitleStreams.data(); //SHOULDN'T COPY LIKE THAT, WE OVERRIDE THE POINTER HERE.
|
||||||
|
return subtitleStreams.size();
|
||||||
}
|
}
|
@ -11,4 +11,5 @@
|
|||||||
|
|
||||||
extern "C" API int Init();
|
extern "C" API int Init();
|
||||||
|
|
||||||
extern "C" API void ExtractSubtitles(const char* path, const char* outPath);
|
//Take the path of the file and the path of the output directory. It will return the list of subtitle streams in the streams variable. The int returned is the number of subtitles extracted.
|
||||||
|
extern "C" API int ExtractSubtitles(const char* path, const char* outPath, Stream* streams);
|
||||||
|
@ -8,6 +8,7 @@ using System.Linq;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Stream = Kyoo.Models.Watch.Stream;
|
||||||
|
|
||||||
namespace Kyoo.InternalAPI
|
namespace Kyoo.InternalAPI
|
||||||
{
|
{
|
||||||
@ -16,12 +17,14 @@ namespace Kyoo.InternalAPI
|
|||||||
private readonly IConfiguration config;
|
private readonly IConfiguration config;
|
||||||
private readonly ILibraryManager libraryManager;
|
private readonly ILibraryManager libraryManager;
|
||||||
private readonly IMetadataProvider metadataProvider;
|
private readonly IMetadataProvider metadataProvider;
|
||||||
|
private readonly ITranscoder transcoder;
|
||||||
|
|
||||||
public Crawler(IConfiguration configuration, ILibraryManager libraryManager, IMetadataProvider metadataProvider)
|
public Crawler(IConfiguration configuration, ILibraryManager libraryManager, IMetadataProvider metadataProvider, ITranscoder transcoder)
|
||||||
{
|
{
|
||||||
config = configuration;
|
config = configuration;
|
||||||
this.libraryManager = libraryManager;
|
this.libraryManager = libraryManager;
|
||||||
this.metadataProvider = metadataProvider;
|
this.metadataProvider = metadataProvider;
|
||||||
|
this.transcoder = transcoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
@ -140,7 +143,10 @@ namespace Kyoo.InternalAPI
|
|||||||
Episode episode = await metadataProvider.GetEpisode(showProviderIDs, seasonNumber, episodeNumber, path);
|
Episode episode = await metadataProvider.GetEpisode(showProviderIDs, seasonNumber, episodeNumber, path);
|
||||||
episode.ShowID = showID;
|
episode.ShowID = showID;
|
||||||
episode.SeasonID = seasonID;
|
episode.SeasonID = seasonID;
|
||||||
libraryManager.RegisterEpisode(episode);
|
long episodeID = libraryManager.RegisterEpisode(episode);
|
||||||
|
|
||||||
|
Stream[] streams = transcoder.ExtractSubtitles(episode.Path);
|
||||||
|
//libraryManager.RegisterStreams(episodeID, streams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,10 +205,10 @@ namespace Kyoo.InternalAPI
|
|||||||
{
|
{
|
||||||
Stream stream = Stream.FromReader(reader);
|
Stream stream = Stream.FromReader(reader);
|
||||||
|
|
||||||
if (stream.type == StreamType.Audio)
|
//if (stream.type == StreamType.Audio)
|
||||||
audios.Add(stream);
|
// audios.Add(stream);
|
||||||
else if (stream.type == StreamType.Subtitle)
|
//else if (stream.type == StreamType.Subtitle)
|
||||||
subtitles.Add(stream);
|
// subtitles.Add(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (audios, subtitles);
|
return (audios, subtitles);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
using Kyoo.Models.Watch;
|
||||||
|
|
||||||
namespace Kyoo.InternalAPI
|
namespace Kyoo.InternalAPI
|
||||||
{
|
{
|
||||||
public interface ITranscoder
|
public interface ITranscoder
|
||||||
@ -9,6 +11,6 @@ namespace Kyoo.InternalAPI
|
|||||||
string Transcode(string path);
|
string Transcode(string path);
|
||||||
|
|
||||||
//Extract all subtitles of a video and save them in the subtitles sub-folder.
|
//Extract all subtitles of a video and save them in the subtitles sub-folder.
|
||||||
void ExtractSubtitles(string path);
|
Stream[] ExtractSubtitles(string path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ using Kyoo.InternalAPI.TranscoderLink;
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Stream = Kyoo.Models.Watch.Stream;
|
||||||
|
|
||||||
namespace Kyoo.InternalAPI
|
namespace Kyoo.InternalAPI
|
||||||
{
|
{
|
||||||
@ -12,11 +13,13 @@ namespace Kyoo.InternalAPI
|
|||||||
Debug.WriteLine("&Api INIT: " + TranscoderAPI.Init());
|
Debug.WriteLine("&Api INIT: " + TranscoderAPI.Init());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExtractSubtitles(string path)
|
public Stream[] ExtractSubtitles(string path)
|
||||||
{
|
{
|
||||||
string output = Path.Combine(Path.GetDirectoryName(path), "Subtitles");
|
string output = Path.Combine(Path.GetDirectoryName(path), "Subtitles");
|
||||||
Directory.CreateDirectory(output);
|
Directory.CreateDirectory(output);
|
||||||
TranscoderAPI.ExtractSubtitles(path, output);
|
TranscoderAPI.ExtractSubtitles(path, output, out Stream[] streams);
|
||||||
|
|
||||||
|
return streams;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetVideo(string path)
|
public void GetVideo(string path)
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using System.Runtime.InteropServices;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Kyoo.Models.Watch;
|
||||||
|
|
||||||
namespace Kyoo.InternalAPI.TranscoderLink
|
namespace Kyoo.InternalAPI.TranscoderLink
|
||||||
{
|
{
|
||||||
@ -10,6 +12,25 @@ namespace Kyoo.InternalAPI.TranscoderLink
|
|||||||
public extern static int Init();
|
public extern static int Init();
|
||||||
|
|
||||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||||
public extern static void ExtractSubtitles(string path, string outPath);
|
private extern static int ExtractSubtitles(string path, string outPath, out IntPtr streams);
|
||||||
|
|
||||||
|
public static void ExtractSubtitles(string path, string outPath, out Stream[] streams)
|
||||||
|
{
|
||||||
|
int size = Marshal.SizeOf<Stream>();
|
||||||
|
|
||||||
|
int length = ExtractSubtitles(path, outPath, out IntPtr streamsPtr); //The streamsPtr is always nullptr
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
streams = new Stream[length];
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
streams[i] = Marshal.PtrToStructure<Stream>(streamsPtr);
|
||||||
|
streamsPtr += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
streams = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Kyoo.Models.Watch
|
namespace Kyoo.Models.Watch
|
||||||
{
|
{
|
||||||
@ -7,40 +8,42 @@ namespace Kyoo.Models.Watch
|
|||||||
Audio, Subtitle, Unknow
|
Audio, Subtitle, Unknow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public class Stream
|
public class Stream
|
||||||
{
|
{
|
||||||
[JsonIgnore] public StreamType type;
|
|
||||||
public string Title;
|
public string Title;
|
||||||
public string Language;
|
public string Language;
|
||||||
|
public string Format;
|
||||||
public bool IsDefault;
|
public bool IsDefault;
|
||||||
public bool IsForced;
|
public bool IsForced;
|
||||||
public string Format;
|
|
||||||
|
|
||||||
[JsonIgnore] public bool IsExternal;
|
|
||||||
[JsonIgnore] public string Path;
|
[JsonIgnore] public string Path;
|
||||||
|
|
||||||
public Stream(StreamType type, string title, string language, bool isDefault, bool isForced, string format, bool isExternal, string path)
|
//[JsonIgnore] public StreamType type;
|
||||||
{
|
//[JsonIgnore] public bool IsExternal;
|
||||||
this.type = type;
|
|
||||||
Title = title;
|
//public Stream(StreamType type, string title, string language, bool isDefault, bool isForced, string format, bool isExternal, string path)
|
||||||
Language = language;
|
//{
|
||||||
IsDefault = isDefault;
|
// this.type = type;
|
||||||
IsForced = isForced;
|
// Title = title;
|
||||||
Format = format;
|
// Language = language;
|
||||||
IsExternal = isExternal;
|
// IsDefault = isDefault;
|
||||||
Path = path;
|
// IsForced = isForced;
|
||||||
}
|
// Format = format;
|
||||||
|
// IsExternal = isExternal;
|
||||||
|
// Path = path;
|
||||||
|
//}
|
||||||
|
|
||||||
public static Stream FromReader(System.Data.SQLite.SQLiteDataReader reader)
|
public static Stream FromReader(System.Data.SQLite.SQLiteDataReader reader)
|
||||||
{
|
{
|
||||||
return new Stream(reader["streamType"] as StreamType? ?? StreamType.Unknow,
|
return new Stream();
|
||||||
reader["title"] as string,
|
//return new Stream(reader["streamType"] as StreamType? ?? StreamType.Unknow,
|
||||||
reader["language"] as string,
|
// reader["title"] as string,
|
||||||
reader["isDefault"] as bool? ?? false,
|
// reader["language"] as string,
|
||||||
reader["isForced"] as bool? ?? false,
|
// reader["isDefault"] as bool? ?? false,
|
||||||
reader["codec"] as string,
|
// reader["isForced"] as bool? ?? false,
|
||||||
reader["isExternal"] as bool? ?? false,
|
// reader["codec"] as string,
|
||||||
reader["path"] as string);
|
// reader["isExternal"] as bool? ?? false,
|
||||||
|
// reader["path"] as string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user