mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-11-04 03:27:14 -05:00 
			
		
		
		
	Making subtitle extraction algorithm.
This commit is contained in:
		
							parent
							
								
									5baf78fdde
								
							
						
					
					
						commit
						c4f1214092
					
				@ -8,47 +8,125 @@ extern "C"
 | 
				
			|||||||
	#include <libavutil/dict.h>
 | 
						#include <libavutil/dict.h>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int Init()
 | 
					int Init()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 42;
 | 
						return 42;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ExtractSubtitles(const char* path)
 | 
					void ExtractSubtitles(const char* path, const char* outPath)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	AVFormatContext* formatContext = NULL;
 | 
						AVFormatContext* inputContext = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (avformat_open_input(&formatContext, 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;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (avformat_find_stream_info(formatContext, 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;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (unsigned int i = 0; i < formatContext->nb_streams; i++)
 | 
						for (unsigned int i = 0; i < inputContext->nb_streams; i++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		AVStream* stream = formatContext->streams[i];
 | 
							AVStream* inputStream = inputContext->streams[i];
 | 
				
			||||||
		const AVCodecContext* streamContext = stream->codec;
 | 
							const AVCodecParameters* inputCodecpar = inputStream->codecpar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (streamContext->codec_type == AVMEDIA_TYPE_SUBTITLE)
 | 
							if (inputCodecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			const AVCodec* dec = streamContext->codec;
 | 
								const char* output = outPath;
 | 
				
			||||||
			std::cout << "Stream #" << i << ", stream type: " << streamContext->codec_type << " codec: " << dec->long_name << std::endl;
 | 
								const AVCodec* codec = avcodec_find_decoder(inputCodecpar->codec_id);
 | 
				
			||||||
		}
 | 
								std::cout << "Stream #" << i << ", stream type: " << inputCodecpar->codec_type << " codec: " << codec->name << " long name: " << codec->long_name << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								AVFormatContext* outputContext = NULL;
 | 
				
			||||||
 | 
								if (avformat_alloc_output_context2(&outputContext, NULL, NULL, output) < 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									std::cout << "Error: Couldn't create an output file." << std::endl;
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//const char* outputPath = "subtitle.ass";
 | 
								AVStream* outputStream = avformat_new_stream(outputContext, codec);
 | 
				
			||||||
	//if (avformat_alloc_output_context2(&formatContext, NULL, NULL, outputPath) < 0)
 | 
								if (outputStream == NULL)
 | 
				
			||||||
	//{
 | 
								{
 | 
				
			||||||
	//	std::cout << "Error: Can't create output file at " << outputPath << std::endl;
 | 
									std::cout << "Error: Couldn't create stream." << std::endl;
 | 
				
			||||||
	//	return;
 | 
									avformat_free_context(outputContext);
 | 
				
			||||||
	//}
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
	avformat_close_input(&formatContext);
 | 
					
 | 
				
			||||||
 | 
								AVCodecParameters* outputCodecpar = outputStream->codecpar;
 | 
				
			||||||
 | 
								avcodec_parameters_copy(outputCodecpar, inputCodecpar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//outputStream->disposition = inputStream->disposition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//if (inputStream->nb_side_data)
 | 
				
			||||||
 | 
								//{
 | 
				
			||||||
 | 
								//	for (int i = 0; i < inputStream->nb_side_data; i++)
 | 
				
			||||||
 | 
								//	{
 | 
				
			||||||
 | 
								//		std::cout << "Copying side packet #" << i << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//		AVPacketSideData* sidePkt = &inputStream->side_data[i];
 | 
				
			||||||
 | 
								//		uint8_t* newPkt = av_stream_new_side_data(outputStream, sidePkt->type, sidePkt->size);
 | 
				
			||||||
 | 
								//		if (newPkt == NULL)
 | 
				
			||||||
 | 
								//		{
 | 
				
			||||||
 | 
								//			std::cout << "Error copying side package." << std::endl;
 | 
				
			||||||
 | 
								//			//Should handle return here
 | 
				
			||||||
 | 
								//			return;
 | 
				
			||||||
 | 
								//		}
 | 
				
			||||||
 | 
								//		memcpy(newPkt, sidePkt->data, sidePkt->size);
 | 
				
			||||||
 | 
								//	}
 | 
				
			||||||
 | 
								//}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (avio_open(&outputContext->pb, output, AVIO_FLAG_WRITE) < 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									std::cout << "Error: Couldn't open file at " << output << std::endl;
 | 
				
			||||||
 | 
									avformat_free_context(outputContext);
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (avformat_write_header(outputContext, NULL) < 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									std::cout << "Error: Couldn't write headers to file at " << output << std::endl;
 | 
				
			||||||
 | 
									avformat_free_context(outputContext);
 | 
				
			||||||
 | 
									avio_closep(&outputContext->pb);
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								AVPacket pkt;
 | 
				
			||||||
 | 
								int i = 0;
 | 
				
			||||||
 | 
								while (av_read_frame(inputContext, &pkt) == 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (pkt.stream_index != inputStream->index)
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									std::cout << "Reading packet... " << i << std::endl;
 | 
				
			||||||
 | 
									i++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									pkt.pts = av_rescale_q_rnd(pkt.pts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF);
 | 
				
			||||||
 | 
									pkt.dts = av_rescale_q_rnd(pkt.dts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF);
 | 
				
			||||||
 | 
									pkt.duration = av_rescale_q(pkt.duration, inputStream->time_base, outputStream->time_base);
 | 
				
			||||||
 | 
									pkt.pos = -1;
 | 
				
			||||||
 | 
									pkt.stream_index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (av_interleaved_write_frame(outputContext, &pkt) < 0)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										//Should handle packet copy error;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									av_packet_unref(&pkt);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								av_write_trailer(outputContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								avio_closep(&outputContext->pb);
 | 
				
			||||||
 | 
								avformat_free_context(outputContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								goto end;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					end:
 | 
				
			||||||
 | 
						avformat_close_input(&inputContext);
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -11,4 +11,4 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
extern "C" API int Init();
 | 
					extern "C" API int Init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern "C" API void ExtractSubtitles(const char* path);
 | 
					extern "C" API void ExtractSubtitles(const char* path, const char* outPath);
 | 
				
			||||||
 | 
				
			|||||||
@ -31,12 +31,12 @@ namespace Kyoo.Controllers
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [HttpGet("extract/{showSlug}-s{seasonNumber}e{episodeNumber}")]
 | 
					        [HttpGet("extract/{showSlug}-s{seasonNumber}e{episodeNumber}")]
 | 
				
			||||||
        public IActionResult ExtractSubtitle(string showSlug, long seasonNumber, long episodeNumber)
 | 
					        public string ExtractSubtitle(string showSlug, long seasonNumber, long episodeNumber)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Episode episode = libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber);
 | 
					            Episode episode = libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber);
 | 
				
			||||||
            transcoder.ExtractSubtitles(episode.Path);
 | 
					            transcoder.ExtractSubtitles(episode.Path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return null;
 | 
					            return "Processing...";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
using Kyoo.InternalAPI.TranscoderLink;
 | 
					using Kyoo.InternalAPI.TranscoderLink;
 | 
				
			||||||
using Microsoft.Extensions.Configuration;
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
using System.Diagnostics;
 | 
					using System.Diagnostics;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Kyoo.InternalAPI
 | 
					namespace Kyoo.InternalAPI
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -13,7 +14,9 @@ namespace Kyoo.InternalAPI
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public void ExtractSubtitles(string path)
 | 
					        public void ExtractSubtitles(string path)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            TranscoderAPI.ExtractSubtitles(path);
 | 
					            string output = Path.GetDirectoryName(path);
 | 
				
			||||||
 | 
					            output = Path.Combine(output, "fre\\output.ass");
 | 
				
			||||||
 | 
					            TranscoderAPI.ExtractSubtitles(path, output);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void GetVideo(string path)
 | 
					        public void GetVideo(string path)
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,6 @@ 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);
 | 
					        public extern static void ExtractSubtitles(string path, string outPath);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user