Creating a Transmux function and cleaning up the Transcoder code.

This commit is contained in:
Zoe Roux 2019-09-25 01:06:37 +02:00
parent 6534ea2e99
commit 3c47c88767
12 changed files with 409 additions and 117 deletions

View File

@ -21,33 +21,178 @@ int Init()
return 42; return 42;
} }
Stream* ExtractSubtitles(const char* path, const char* outPath, int* streamCount)
{
AVFormatContext* inputContext = NULL;
if (avformat_open_input(&inputContext, path, NULL, NULL)) #pragma region InternalProcess
int open_input_context(AVFormatContext **inputContext, const char *path)
{
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 0; return 1;
} }
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 0; return 1;
} }
av_dump_format(inputContext, 0, path, false); av_dump_format(*inputContext, 0, path, false);
return 0;
}
std::vector<Stream>* subtitleStreams = new std::vector<Stream>(); AVStream* copy_stream_to_output(AVFormatContext *outputContext, AVStream *inputStream)
{
AVStream *outputStream = avformat_new_stream(outputContext, NULL);
if (outputStream == NULL)
{
std::cout << "Error: Couldn't create stream." << std::endl;
return NULL;
}
if (avcodec_parameters_copy(outputStream->codecpar, inputStream->codecpar) < 0)
{
std::cout << "Error: Couldn't copy parameters to the output file." << std::endl;
return NULL;
}
outputStream->codecpar->codec_tag = 0;
avformat_transfer_internal_stream_timing_info(outputContext->oformat, outputStream, inputStream, AVTimebaseSource::AVFMT_TBCF_AUTO);
outputStream->time_base = av_add_q(av_stream_get_codec_timebase(outputStream), AVRational{ 0, 1 });
outputStream->duration = av_rescale_q(inputStream->duration, inputStream->time_base, outputStream->time_base);
outputStream->disposition = inputStream->disposition;
av_dict_copy(&outputStream->metadata, inputStream->metadata, NULL);
//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);
// }
//}
return outputStream;
}
int open_output_file_for_write(AVFormatContext *outputContext, const char* outputPath)
{
if (!(outputContext->flags & AVFMT_NOFILE))
{
if (avio_open(&outputContext->pb, outputPath, AVIO_FLAG_WRITE) < 0)
{
std::cout << "Error: Couldn't open file at " << outputPath << std::endl;
return 1;
}
}
else
std::cout << "Output flag set to AVFMT_NOFILE." << std::endl;
if (avformat_write_header(outputContext, NULL) < 0)
{
std::cout << "Error: Couldn't write headers to file at " << outputPath << std::endl;
return 1;
}
return 0;
}
void process_packet(AVPacket pkt, AVStream* inputStream, AVStream* outputStream)
{
pkt.pts = av_rescale_q_rnd(pkt.pts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
pkt.dts = av_rescale_q_rnd(pkt.dts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
pkt.duration = av_rescale_q(pkt.duration, inputStream->time_base, outputStream->time_base);
pkt.pos = -1;
}
#pragma endregion
//Should add goto end;
int Transmux(const char *path, const char *outPath)
{
AVFormatContext *inputContext = NULL;
int ret = 0;
if (open_input_context(&inputContext, path) != 0)
return 1;
AVFormatContext *outputContext = NULL;
if (avformat_alloc_output_context2(&outputContext, NULL, NULL, outPath) < 0)
{
std::cout << "Error: Couldn't create an output file." << std::endl;
return 1;
}
for (unsigned int i = 0; i < inputContext->nb_streams; i++)
{
AVStream *stream = inputContext->streams[i];
if(stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) //Should support multi-audio on a good format.
if (copy_stream_to_output(outputContext, stream) == NULL)
return 1;
}
av_dump_format(outputContext, 0, outPath, true);
if (open_output_file_for_write(outputContext, outPath) != 0)
return 1;
AVPacket pkt;
while (av_read_frame(inputContext, &pkt) == 0)
{
if (pkt.stream_index >= outputContext->nb_streams)
continue;
AVStream *inputStream = inputContext->streams[pkt.stream_index];
AVStream *outputStream = outputContext->streams[pkt.stream_index];
process_packet(pkt, inputStream, outputStream);
if (av_interleaved_write_frame(outputContext, &pkt) < 0)
std::cout << "Error while writing a packet to the output file." << std::endl;
av_packet_unref(&pkt);
}
avformat_close_input(&inputContext);
av_write_trailer(outputContext);
if (outputContext && !(outputContext->flags & AVFMT_NOFILE))
avio_closep(&outputContext->pb);
avformat_free_context(outputContext);
return ret;
}
Stream *ExtractSubtitles(const char *path, const char *outPath, int *streamCount)
{
AVFormatContext *inputContext = NULL;
if (open_input_context(&inputContext, path) != 0)
return 0;
std::vector<Stream> *subtitleStreams = new std::vector<Stream>();
const unsigned int outputCount = inputContext->nb_streams; const unsigned int outputCount = inputContext->nb_streams;
AVFormatContext** outputList = new AVFormatContext*[outputCount]; AVFormatContext **outputList = new AVFormatContext*[outputCount];
//Initialize output and set headers. //Initialize output and set headers.
for (unsigned int i = 0; i < inputContext->nb_streams; i++) for (unsigned int i = 0; i < inputContext->nb_streams; i++)
{ {
AVStream* inputStream = inputContext->streams[i]; AVStream *inputStream = inputContext->streams[i];
const AVCodecParameters* inputCodecpar = inputStream->codecpar; const AVCodecParameters *inputCodecpar = inputStream->codecpar;
if (inputCodecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) if (inputCodecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
outputList[i] = NULL; outputList[i] = NULL;
@ -62,7 +207,7 @@ Stream* ExtractSubtitles(const char* path, const char* outPath, int* streamCount
NULL); //Path builder references NULL); //Path builder references
//Create the language subfolder //Create the language subfolder
std::stringstream outStream /*= new std::stringstream()*/; std::stringstream outStream;
outStream << outPath << (char)std::filesystem::path::preferred_separator << stream.language; outStream << outPath << (char)std::filesystem::path::preferred_separator << stream.language;
std::filesystem::create_directory(outStream.str()); std::filesystem::create_directory(outStream.str());
@ -90,7 +235,7 @@ Stream* ExtractSubtitles(const char* path, const char* outPath, int* streamCount
subtitleStreams->push_back(stream); subtitleStreams->push_back(stream);
std::cout << "Stream #" << i << "(" << stream.language << "), stream type: " << inputCodecpar->codec_type << " codec: " << stream.codec << std::endl; std::cout << "Stream #" << i << "(" << stream.language << "), stream type: " << inputCodecpar->codec_type << " codec: " << stream.codec << std::endl;
AVFormatContext* outputContext = NULL; AVFormatContext *outputContext = NULL;
if (avformat_alloc_output_context2(&outputContext, NULL, NULL, stream.path) < 0) if (avformat_alloc_output_context2(&outputContext, NULL, NULL, stream.path) < 0)
{ {
std::cout << "Error: Couldn't create an output file." << std::endl; std::cout << "Error: Couldn't create an output file." << std::endl;
@ -99,63 +244,14 @@ Stream* ExtractSubtitles(const char* path, const char* outPath, int* streamCount
av_dict_copy(&outputContext->metadata, inputContext->metadata, NULL); av_dict_copy(&outputContext->metadata, inputContext->metadata, NULL);
AVStream* outputStream = avformat_new_stream(outputContext, NULL); AVStream* outputStream = copy_stream_to_output(outputContext, inputStream);
if (outputStream == NULL) if (outputStream == NULL)
{
std::cout << "Error: Couldn't create stream." << std::endl;
goto end; goto end;
}
if (avcodec_parameters_copy(outputStream->codecpar, inputCodecpar) < 0)
{
std::cout << "Error: Couldn't copy parameters to the output file." << std::endl;
goto end;
}
outputStream->codecpar->codec_tag = 0;
avformat_transfer_internal_stream_timing_info(outputContext->oformat, outputStream, inputStream, AVTimebaseSource::AVFMT_TBCF_AUTO);
outputStream->time_base = av_add_q(av_stream_get_codec_timebase(outputStream), AVRational { 0, 1 });
outputStream->duration = av_rescale_q(inputStream->duration, inputStream->time_base, outputStream->time_base);
outputStream->disposition = inputStream->disposition;
av_dict_copy(&outputStream->metadata, inputStream->metadata, NULL);
//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);
// }
//}
av_dump_format(outputContext, 0, stream.path, true); av_dump_format(outputContext, 0, stream.path, true);
if (!(outputContext->flags & AVFMT_NOFILE)) if (open_output_file_for_write(outputContext, stream.path) != 0)
{
if (avio_open(&outputContext->pb, stream.path, AVIO_FLAG_WRITE) < 0)
{
std::cout << "Error: Couldn't open file at " << stream.path << std::endl;
goto end;
}
}
else
std::cout << "Output flag set to AVFMT_NOFILE." << std::endl;
if (avformat_write_header(outputContext, NULL) < 0)
{
std::cout << "Error: Couldn't write headers to file at " << stream.path << std::endl;
goto end; goto end;
}
outputList[i] = outputContext; outputList[i] = outputContext;
@ -179,22 +275,18 @@ Stream* ExtractSubtitles(const char* path, const char* outPath, int* streamCount
if (pkt.stream_index >= outputCount) if (pkt.stream_index >= outputCount)
continue; continue;
AVFormatContext* outputContext = outputList[pkt.stream_index]; AVFormatContext *outputContext = outputList[pkt.stream_index];
if(outputContext == nullptr) if(outputContext == nullptr)
{ {
av_packet_unref(&pkt); av_packet_unref(&pkt);
continue; continue;
} }
AVStream* inputStream = inputContext->streams[pkt.stream_index]; AVStream *inputStream = inputContext->streams[pkt.stream_index];
AVStream* outputStream = outputContext->streams[0]; AVStream *outputStream = outputContext->streams[0];
pkt.stream_index = 0; pkt.stream_index = 0;
process_packet(pkt, inputStream, outputStream);
pkt.pts = av_rescale_q_rnd(pkt.pts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
pkt.dts = av_rescale_q_rnd(pkt.dts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
pkt.duration = av_rescale_q(pkt.duration, inputStream->time_base, outputStream->time_base);
pkt.pos = -1;
if (av_interleaved_write_frame(outputContext, &pkt) < 0) if (av_interleaved_write_frame(outputContext, &pkt) < 0)
{ {
@ -208,7 +300,7 @@ Stream* ExtractSubtitles(const char* path, const char* outPath, int* streamCount
for (unsigned int i = 0; i < outputCount; i++) for (unsigned int i = 0; i < outputCount; i++)
{ {
AVFormatContext* outputContext = outputList[i]; AVFormatContext *outputContext = outputList[i];
if (outputContext == NULL) if (outputContext == NULL)
continue; continue;

View File

@ -13,3 +13,5 @@ extern "C" API int Init();
//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. //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 Stream* ExtractSubtitles(const char* path, const char* outPath, int* streamsCount); extern "C" API Stream* ExtractSubtitles(const char* path, const char* outPath, int* streamsCount);
extern "C" API int Transmux(const char* path, const char* outPath);

View File

@ -32,7 +32,8 @@
"scripts": [ "scripts": [
"./node_modules/jquery/dist/jquery.min.js", "./node_modules/jquery/dist/jquery.min.js",
"./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js", "./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
"./src/libraries/subtitles.js" "./src/libraries/subtitles.js",
"./node_modules/video.js/dist/video.min.js"
] ]
}, },
"configurations": { "configurations": {

View File

@ -1134,6 +1134,21 @@
"integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==",
"dev": true "dev": true
}, },
"@babel/runtime": {
"version": "7.6.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz",
"integrity": "sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==",
"requires": {
"regenerator-runtime": "^0.13.2"
},
"dependencies": {
"regenerator-runtime": {
"version": "0.13.3",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
"integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw=="
}
}
},
"@babel/template": { "@babel/template": {
"version": "7.4.4", "version": "7.4.4",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz",
@ -1349,6 +1364,20 @@
} }
} }
}, },
"@videojs/http-streaming": {
"version": "1.10.6",
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-1.10.6.tgz",
"integrity": "sha512-uPBuunHnxWeFRYxRX0j6h1IIWv3+QKvSkZGmW9TvqxWBqeNGSrQymR6tm1nVjQ2HhMVxVphQTUhUTTPDVWqmQg==",
"requires": {
"aes-decrypter": "3.0.0",
"global": "^4.3.0",
"m3u8-parser": "4.4.0",
"mpd-parser": "0.8.1",
"mux.js": "5.2.1",
"url-toolkit": "^2.1.3",
"video.js": "^6.8.0 || ^7.0.0"
}
},
"@webassemblyjs/ast": { "@webassemblyjs/ast": {
"version": "1.8.5", "version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
@ -1575,6 +1604,16 @@
"integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==",
"dev": true "dev": true
}, },
"aes-decrypter": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.0.0.tgz",
"integrity": "sha1-eEihwUW5/b9Xrj4rWxvHzwZEqPs=",
"requires": {
"commander": "^2.9.0",
"global": "^4.3.2",
"pkcs7": "^1.0.2"
}
},
"after": { "after": {
"version": "0.8.2", "version": "0.8.2",
"resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
@ -2791,8 +2830,7 @@
"commander": { "commander": {
"version": "2.20.0", "version": "2.20.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ=="
"dev": true
}, },
"commondir": { "commondir": {
"version": "1.0.1", "version": "1.0.1",
@ -3203,7 +3241,6 @@
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
"dev": true,
"requires": { "requires": {
"object-keys": "^1.0.12" "object-keys": "^1.0.12"
} }
@ -3415,6 +3452,11 @@
"void-elements": "^2.0.0" "void-elements": "^2.0.0"
} }
}, },
"dom-walk": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
"integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg="
},
"domain-browser": { "domain-browser": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
@ -3631,7 +3673,6 @@
"version": "1.13.0", "version": "1.13.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
"integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
"dev": true,
"requires": { "requires": {
"es-to-primitive": "^1.2.0", "es-to-primitive": "^1.2.0",
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
@ -3645,7 +3686,6 @@
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
"integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
"dev": true,
"requires": { "requires": {
"is-callable": "^1.1.4", "is-callable": "^1.1.4",
"is-date-object": "^1.0.1", "is-date-object": "^1.0.1",
@ -4130,6 +4170,14 @@
} }
} }
}, },
"for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"requires": {
"is-callable": "^1.1.3"
}
},
"for-in": { "for-in": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@ -4250,8 +4298,7 @@
"function-bind": { "function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
"dev": true
}, },
"genfun": { "genfun": {
"version": "5.0.0", "version": "5.0.0",
@ -4324,6 +4371,22 @@
} }
} }
}, },
"global": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz",
"integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=",
"requires": {
"min-document": "^2.19.0",
"process": "~0.5.1"
},
"dependencies": {
"process": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz",
"integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8="
}
}
},
"globals": { "globals": {
"version": "9.18.0", "version": "9.18.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
@ -4409,7 +4472,6 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"requires": { "requires": {
"function-bind": "^1.1.1" "function-bind": "^1.1.1"
} }
@ -4455,8 +4517,7 @@
"has-symbols": { "has-symbols": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
"dev": true
}, },
"has-value": { "has-value": {
"version": "1.0.0", "version": "1.0.0",
@ -4803,6 +4864,11 @@
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
"dev": true "dev": true
}, },
"individual": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/individual/-/individual-2.0.0.tgz",
"integrity": "sha1-gzsJfa0jKU52EXqY+zjg2a1hu5c="
},
"infer-owner": { "infer-owner": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
@ -4956,8 +5022,7 @@
"is-callable": { "is-callable": {
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
"dev": true
}, },
"is-data-descriptor": { "is-data-descriptor": {
"version": "0.1.4", "version": "0.1.4",
@ -4982,8 +5047,7 @@
"is-date-object": { "is-date-object": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
"dev": true
}, },
"is-descriptor": { "is-descriptor": {
"version": "0.1.6", "version": "0.1.6",
@ -5037,6 +5101,11 @@
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true "dev": true
}, },
"is-function": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz",
"integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU="
},
"is-glob": { "is-glob": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
@ -5101,7 +5170,6 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
"dev": true,
"requires": { "requires": {
"has": "^1.0.1" "has": "^1.0.1"
} }
@ -5116,7 +5184,6 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
"integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
"dev": true,
"requires": { "requires": {
"has-symbols": "^1.0.0" "has-symbols": "^1.0.0"
} }
@ -6312,6 +6379,11 @@
"source-map-support": "^0.5.5" "source-map-support": "^0.5.5"
} }
}, },
"keycode": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz",
"integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ="
},
"killable": { "killable": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@ -6488,6 +6560,14 @@
"yallist": "^3.0.2" "yallist": "^3.0.2"
} }
}, },
"m3u8-parser": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.4.0.tgz",
"integrity": "sha512-iH2AygTFILtato+XAgnoPYzLHM4R3DjATj7Ozbk7EHdB2XoLF2oyOUguM7Kc4UVHbQHHL/QPaw98r7PbWzG0gg==",
"requires": {
"global": "^4.3.2"
}
},
"magic-string": { "magic-string": {
"version": "0.25.3", "version": "0.25.3",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz",
@ -6787,6 +6867,14 @@
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true "dev": true
}, },
"min-document": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
"integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=",
"requires": {
"dom-walk": "^0.1.0"
}
},
"mini-css-extract-plugin": { "mini-css-extract-plugin": {
"version": "0.8.0", "version": "0.8.0",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz",
@ -6933,6 +7021,15 @@
"run-queue": "^1.0.3" "run-queue": "^1.0.3"
} }
}, },
"mpd-parser": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.8.1.tgz",
"integrity": "sha512-WBTJ1bKk8OLUIxBh6s1ju1e2yz/5CzhPbgi6P3F3kJHKhGy1Z+ElvEnuzEbtC/dnbRcJtMXazE3f93N5LLdp9Q==",
"requires": {
"global": "^4.3.2",
"url-toolkit": "^2.1.1"
}
},
"ms": { "ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@ -6961,6 +7058,11 @@
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
"dev": true "dev": true
}, },
"mux.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.2.1.tgz",
"integrity": "sha512-1t2payD3Y8izfZRq7tfUQlhL2fKzjeLr9v1/2qNCTkEQnd9Abtn1JgzsBgGZubEXh6lM5L8B0iLGoWQiukjtbQ=="
},
"nan": { "nan": {
"version": "2.14.0", "version": "2.14.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
@ -7270,8 +7372,7 @@
"object-keys": { "object-keys": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
"dev": true
}, },
"object-visit": { "object-visit": {
"version": "1.0.1", "version": "1.0.1",
@ -7586,6 +7687,15 @@
"safe-buffer": "^5.1.1" "safe-buffer": "^5.1.1"
} }
}, },
"parse-headers": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.2.tgz",
"integrity": "sha512-/LypJhzFmyBIDYP9aDVgeyEb5sQfbfY5mnDq4hVhlQ69js87wXfmEI5V3xI6vvXasqebp0oCytYFLxsBVfCzSg==",
"requires": {
"for-each": "^0.3.3",
"string.prototype.trim": "^1.1.2"
}
},
"parse-json": { "parse-json": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
@ -7743,6 +7853,11 @@
"pinkie": "^2.0.0" "pinkie": "^2.0.0"
} }
}, },
"pkcs7": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.2.tgz",
"integrity": "sha1-ttulJ1KMKUK/wSLOLa/NteWQdOc="
},
"pkg-dir": { "pkg-dir": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
@ -8557,6 +8672,14 @@
"aproba": "^1.1.1" "aproba": "^1.1.1"
} }
}, },
"rust-result": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/rust-result/-/rust-result-1.0.0.tgz",
"integrity": "sha1-NMdbLm3Dn+WHXlveyFteD5FTb3I=",
"requires": {
"individual": "^2.0.0"
}
},
"rxjs": { "rxjs": {
"version": "6.4.0", "version": "6.4.0",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
@ -8571,6 +8694,14 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true "dev": true
}, },
"safe-json-parse": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-4.0.0.tgz",
"integrity": "sha1-fA9XjPzNEtM6ccDgVBPi7KFx6qw=",
"requires": {
"rust-result": "^1.0.0"
}
},
"safe-regex": { "safe-regex": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
@ -9579,6 +9710,16 @@
} }
} }
}, },
"string.prototype.trim": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz",
"integrity": "sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.13.0",
"function-bind": "^1.1.1"
}
},
"string_decoder": { "string_decoder": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@ -10172,6 +10313,11 @@
"requires-port": "^1.0.0" "requires-port": "^1.0.0"
} }
}, },
"url-toolkit": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.1.6.tgz",
"integrity": "sha512-UaZ2+50am4HwrV2crR/JAf63Q4VvPYphe63WGeoJxeu8gmOm0qxPt+KsukfakPNrX9aymGNEkkaoICwn+OuvBw=="
},
"use": { "use": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
@ -10286,6 +10432,34 @@
"extsprintf": "^1.2.0" "extsprintf": "^1.2.0"
} }
}, },
"video.js": {
"version": "7.6.5",
"resolved": "https://registry.npmjs.org/video.js/-/video.js-7.6.5.tgz",
"integrity": "sha512-r0kC9SNJhXz9th/wwbRaLVOIZTvXkF+rhFq9/FWU+e+EJClwClRCgP8STGmfrPHDXrfWiJwH9YY21JZK61vGGQ==",
"requires": {
"@babel/runtime": "^7.4.5",
"@videojs/http-streaming": "1.10.6",
"global": "4.3.2",
"keycode": "^2.2.0",
"safe-json-parse": "4.0.0",
"videojs-font": "3.2.0",
"videojs-vtt.js": "^0.14.1",
"xhr": "2.4.0"
}
},
"videojs-font": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-3.2.0.tgz",
"integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA=="
},
"videojs-vtt.js": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.14.1.tgz",
"integrity": "sha512-YxOiywx6N9t3J5nqsE5WN2Sw4CSqVe3zV+AZm2T4syOc2buNJaD6ZoexSdeszx2sHLU/RRo2r4BJAXFDQ7Qo2Q==",
"requires": {
"global": "^4.3.1"
}
},
"vm-browserify": { "vm-browserify": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz",
@ -11994,6 +12168,17 @@
"ultron": "~1.1.0" "ultron": "~1.1.0"
} }
}, },
"xhr": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/xhr/-/xhr-2.4.0.tgz",
"integrity": "sha1-4W5mpF+GmGHu76tBbV7/ci3ECZM=",
"requires": {
"global": "~4.3.0",
"is-function": "^1.0.1",
"parse-headers": "^2.0.0",
"xtend": "^4.0.0"
}
},
"xml2js": { "xml2js": {
"version": "0.4.19", "version": "0.4.19",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
@ -12027,8 +12212,7 @@
"xtend": { "xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
"dev": true
}, },
"y18n": { "y18n": {
"version": "4.0.0", "version": "4.0.0",

View File

@ -27,6 +27,7 @@
"popper.js": "^1.15.0", "popper.js": "^1.15.0",
"rxjs": "~6.4.0", "rxjs": "~6.4.0",
"tslib": "^1.10.0", "tslib": "^1.10.0",
"video.js": "^7.6.5",
"zone.js": "~0.9.1" "zone.js": "~0.9.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,10 +1,8 @@
<div id="root"> <div id="root">
<div class="player"> <div class="player">
<video id="player" poster="backdrop/{{this.item.showSlug}}" autoplay muted (click)="tooglePlayback()"> <video id="player" poster="backdrop/{{this.item.showSlug}}" autoplay muted (click)="tooglePlayback()" class="video-js">
<source src="/api/video/{{this.item.link}}" /> <source src="/api/video/{{this.item.link}}" />
<source src="/api/video/{{this.item.link}}/stream" type="video/mp4" /> <source src="/api/video/transmux/{{this.item.link}}" type="video/mp4" />
<!--<track src="/api/subtitle/clannad-s1e1.eng.vtt" lang="English" srclang="en" default/>-->
</video> </video>
</div> </div>

View File

@ -1,10 +1,8 @@
import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { WatchItem, Track } from "../../models/watch-item";
import { ActivatedRoute, Router } from "@angular/router";
import { DomSanitizer, Title } from "@angular/platform-browser";
import { Location } from "@angular/common";
import { MatSliderChange } from "@angular/material/slider";
import { MatSnackBar } from "@angular/material/snack-bar"; import { MatSnackBar } from "@angular/material/snack-bar";
import { DomSanitizer, Title } from "@angular/platform-browser";
import { ActivatedRoute, Router } from "@angular/router";
import { Track, WatchItem } from "../../models/watch-item";
declare var SubtitleManager: any; declare var SubtitleManager: any;

View File

@ -22,35 +22,38 @@ namespace Kyoo.Controllers
{ {
WatchItem episode = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber); WatchItem episode = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
if (System.IO.File.Exists(episode.Path)) if (episode != null && System.IO.File.Exists(episode.Path))
return PhysicalFile(episode.Path, "video/x-matroska", true); return PhysicalFile(episode.Path, "video/x-matroska", true);
else else
return NotFound(); return NotFound();
} }
[HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}/stream")] [HttpGet("transmux/{showSlug}-s{seasonNumber}e{episodeNumber}")]
public IActionResult Stream(string showSlug, long seasonNumber, long episodeNumber) public IActionResult Transmux(string showSlug, long seasonNumber, long episodeNumber)
{ {
WatchItem episode = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber); WatchItem episode = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
if (System.IO.File.Exists(episode.Path)) if (episode != null && System.IO.File.Exists(episode.Path))
{ {
string path = transcoder.Stream(episode.Path); string path = transcoder.Transmux(episode);
return PhysicalFile(path, "video/mp4", true); if (path != null)
return PhysicalFile(path, "video/mp4", true);
else
return StatusCode(500);
} }
else else
return NotFound(); return NotFound();
} }
[HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}/transcode")] [HttpGet("transcode/{showSlug}-s{seasonNumber}e{episodeNumber}")]
public IActionResult Transcode(string showSlug, long seasonNumber, long episodeNumber) public IActionResult Transcode(string showSlug, long seasonNumber, long episodeNumber)
{ {
WatchItem episode = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber); WatchItem episode = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
if (System.IO.File.Exists(episode.Path)) if (episode != null && System.IO.File.Exists(episode.Path))
{ {
string path = transcoder.Transcode(episode.Path); string path = transcoder.Transcode(episode.Path);
return PhysicalFile(path, "video/mp4", true); return PhysicalFile(path, "video/mp4", true); //Should use mpeg dash
} }
else else
return NotFound(); return NotFound();

View File

@ -6,7 +6,7 @@ namespace Kyoo.InternalAPI
public interface ITranscoder public interface ITranscoder
{ {
//Should transcode to a mp4 container (same video/audio format if possible, no subtitles). //Should transcode to a mp4 container (same video/audio format if possible, no subtitles).
string Stream(string path); string Transmux(WatchItem episode);
//Should transcode to a mp4 container with a h264 video format and a AAC audio format, no subtitles. //Should transcode to a mp4 container with a h264 video format and a AAC audio format, no subtitles.
string Transcode(string path); string Transcode(string path);

View File

@ -10,8 +10,12 @@ namespace Kyoo.InternalAPI
{ {
public class Transcoder : ITranscoder public class Transcoder : ITranscoder
{ {
private readonly string tempPath;
public Transcoder(IConfiguration config) public Transcoder(IConfiguration config)
{ {
tempPath = config.GetValue<string>("tempPath");
Debug.WriteLine("&Api INIT: " + TranscoderAPI.Init()); Debug.WriteLine("&Api INIT: " + TranscoderAPI.Init());
} }
@ -29,9 +33,14 @@ namespace Kyoo.InternalAPI
Debug.WriteLine("&Getting video..."); Debug.WriteLine("&Getting video...");
} }
public string Stream(string path) public string Transmux(WatchItem episode)
{ {
return @"D:\Videos\Anohana\AnoHana S01E01.mp4"; string temp = Path.Combine(tempPath, episode.Link + ".mp4");
Debug.WriteLine("&Transmuxing " + episode.Link + " at " + episode.Path + ", outputPath: " + temp);
if (File.Exists(temp) || TranscoderAPI.Transmux(episode.Path, temp) == 0)
return temp;
else
return null;
} }
public string Transcode(string path) public string Transcode(string path)

View File

@ -12,6 +12,9 @@ namespace Kyoo.InternalAPI.TranscoderLink
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
public extern static int Init(); public extern static int Init();
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
public extern static int Transmux(string path, string outPath);
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
private extern static IntPtr ExtractSubtitles(string path, string outPath, out int streams); private extern static IntPtr ExtractSubtitles(string path, string outPath, out int streams);

View File

@ -1,5 +1,6 @@
{ {
"databasePath": "C://Projects/database.db", "databasePath": "C://Projects/database.db",
"tempPath": "C:\\Projects",
"peoplePath": "D://Videos/People", "peoplePath": "D://Videos/People",
"plugins": "C:\\Projects\\Kyoo\\Debug", "plugins": "C:\\Projects\\Kyoo\\Debug",
"providerPlugins": "C://Projects/Plugins/Providers", "providerPlugins": "C://Projects/Plugins/Providers",