mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-23 15:30:34 -04:00
Merge pull request #4 from AnonymusRaccoon/dev
Reworking the transmuxer to use HLS (it is really fast now).
This commit is contained in:
commit
3f284fad42
@ -18,6 +18,7 @@ int transmux(const char *path, const char *out_path, float *playable_duration)
|
||||
int *stream_map;
|
||||
int stream_count;
|
||||
int ret = 0;
|
||||
std::string seg_path = ((std::string)out_path).substr(0, strrchr(out_path, '/') - out_path).append("/segments/");
|
||||
|
||||
*playable_duration = 0;
|
||||
if (open_input_context(&in_ctx, path) != 0)
|
||||
@ -54,10 +55,10 @@ int transmux(const char *path, const char *out_path, float *playable_duration)
|
||||
}
|
||||
|
||||
av_dump_format(out_ctx, 0, out_path, true);
|
||||
|
||||
std::filesystem::create_directory(((std::string)out_path).substr(0, strrchr(out_path, '/') - out_path).append("/dash/"));
|
||||
av_dict_set(&options, "init_seg_name", "dash/init-stream$RepresentationID$.m4s", 0);
|
||||
av_dict_set(&options, "media_seg_name", "dash/chunk-stream$RepresentationID$-$Number%05d$.m4s", 0);
|
||||
std::filesystem::create_directory(seg_path);
|
||||
av_dict_set(&options, "hls_segment_filename", seg_path.append("%v-%03d.ts").c_str(), 0);
|
||||
av_dict_set(&options, "hls_base_url", "segment/", 0);
|
||||
av_dict_set(&options, "hls_list_size", "0", 0);
|
||||
av_dict_set(&options, "streaming", "1", 0);
|
||||
|
||||
if (open_output_file_for_write(out_ctx, out_path, &options) != 0)
|
||||
|
@ -32,7 +32,7 @@
|
||||
"scripts": [
|
||||
"./node_modules/jquery/dist/jquery.min.js",
|
||||
"./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
|
||||
"./node_modules/dashjs/dist/dash.all.min.js",
|
||||
"./node_modules/hls.js/dist/hls.js",
|
||||
"./src/libraries/subtitles.js"
|
||||
]
|
||||
},
|
||||
|
60
Kyoo/ClientApp/package-lock.json
generated
60
Kyoo/ClientApp/package-lock.json
generated
@ -1270,6 +1270,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/hls.js": {
|
||||
"version": "0.12.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/hls.js/-/hls.js-0.12.5.tgz",
|
||||
"integrity": "sha512-UWNROsxKxW1yASacUZzvjGZwS1xGp1gN3Yyd6XWMpqr8HLiYepVWZLxsyfPNsgSJrQ1oyz03tV7y4dS5nlSOaw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/jasmine": {
|
||||
"version": "3.3.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.3.16.tgz",
|
||||
@ -2754,11 +2760,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codem-isoboxer": {
|
||||
"version": "0.3.6",
|
||||
"resolved": "https://registry.npmjs.org/codem-isoboxer/-/codem-isoboxer-0.3.6.tgz",
|
||||
"integrity": "sha512-LuO8/7LW6XuR5ERn1yavXAfodGRhuY2yP60JTZIw5yNYMCE5lUVbk3NFUCJxjnphQH+Xemp5hOGb1LgUXm00Xw=="
|
||||
},
|
||||
"collection-visit": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
|
||||
@ -3146,16 +3147,6 @@
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"dashjs": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dashjs/-/dashjs-3.0.0.tgz",
|
||||
"integrity": "sha512-XyVkjeHB4mqzf/Y7ARQ1IqbRBaee0osAulwCFV5ZNZ734wea8LbSC/23zKI32BulW7Kk6f7I6onW1WDMHRgz7Q==",
|
||||
"requires": {
|
||||
"codem-isoboxer": "0.3.6",
|
||||
"fast-deep-equal": "2.0.1",
|
||||
"imsc": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"date-format": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz",
|
||||
@ -3999,7 +3990,8 @@
|
||||
"fast-deep-equal": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
|
||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
|
||||
"dev": true
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.0.0",
|
||||
@ -4555,6 +4547,22 @@
|
||||
"minimalistic-assert": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"hls.js": {
|
||||
"version": "0.12.4",
|
||||
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-0.12.4.tgz",
|
||||
"integrity": "sha512-e8OPxQ60dBVsdkv4atdxR21KzC1mgwspM41qpozpj3Uv1Fz4CaeQy3FWoaV2O+QKKbNRvV5hW+/LipCWdrwnMQ==",
|
||||
"requires": {
|
||||
"eventemitter3": "3.1.0",
|
||||
"url-toolkit": "^2.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"eventemitter3": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
|
||||
"integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"hmac-drbg": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||
@ -4816,21 +4824,6 @@
|
||||
"resolve-cwd": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"imsc": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/imsc/-/imsc-1.1.0.tgz",
|
||||
"integrity": "sha512-z2aUE3X00O39fCgkLHEVbfKG/D9cBrmsbf4NjP7K1gQb06YBjgljq5nZD72HYMFG2lRJI7QY7v+JVxg6o6I/Jg==",
|
||||
"requires": {
|
||||
"sax": "1.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"sax": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
|
||||
"integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
|
||||
}
|
||||
}
|
||||
},
|
||||
"imurmurhash": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||
@ -10220,6 +10213,11 @@
|
||||
"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": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||
|
@ -22,9 +22,9 @@
|
||||
"@angular/platform-browser-dynamic": "~8.2.0",
|
||||
"@angular/router": "~8.2.0",
|
||||
"bootstrap": "^4.3.1",
|
||||
"dashjs": "^3.0.0",
|
||||
"detect-browser": "^4.8.0",
|
||||
"hammerjs": "^2.0.8",
|
||||
"hls.js": "^0.12.4",
|
||||
"jquery": "^3.4.1",
|
||||
"popper.js": "^1.15.0",
|
||||
"zone.js": "~0.9.1"
|
||||
@ -35,6 +35,7 @@
|
||||
"@angular/compiler-cli": "~8.2.0",
|
||||
"@angular/language-service": "~8.2.0",
|
||||
"@types/bootstrap": "^4.3.1",
|
||||
"@types/hls.js": "^0.12.5",
|
||||
"@types/jasmine": "~3.3.8",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/jquery": "^3.3.31",
|
||||
|
@ -4,7 +4,7 @@ import { DomSanitizer, Title } from "@angular/platform-browser";
|
||||
import { ActivatedRoute, Event, NavigationCancel, NavigationEnd, NavigationStart, Router } from "@angular/router";
|
||||
import { Track, WatchItem } from "../../models/watch-item";
|
||||
import { Location } from "@angular/common";
|
||||
import { MediaPlayer } from "dashjs";
|
||||
import * as Hls from "hls.js"
|
||||
import { getPlaybackMethod, method } from "../../videoSupport/playbackMethodDetector";
|
||||
|
||||
declare var SubtitleManager: any;
|
||||
@ -43,8 +43,7 @@ export class PlayerComponent implements OnInit
|
||||
playMethod: method;
|
||||
|
||||
private player: HTMLVideoElement;
|
||||
private dashPlayer: dashjs.MediaPlayerClass = MediaPlayer().create();
|
||||
private dashPlayerInitialized: boolean = false;
|
||||
private hlsPlayer: Hls = new Hls();
|
||||
private thumb: HTMLElement;
|
||||
private progress: HTMLElement;
|
||||
private buffered: HTMLElement;
|
||||
@ -381,22 +380,27 @@ export class PlayerComponent implements OnInit
|
||||
|
||||
selectPlayMethod()
|
||||
{
|
||||
if (this.dashPlayerInitialized)
|
||||
this.dashPlayer.reset();
|
||||
if (this.playMethod == method.direct)
|
||||
{
|
||||
this.player.src = "/video/" + this.item.link;
|
||||
this.dashPlayerInitialized = false;
|
||||
}
|
||||
else if (this.playMethod == method.transmux)
|
||||
{
|
||||
this.dashPlayer.initialize(this.player, "/video/transmux/" + this.item.link + "/", true);
|
||||
this.dashPlayerInitialized = true;
|
||||
this.hlsPlayer.loadSource("/video/transmux/" + this.item.link + "/");
|
||||
this.hlsPlayer.attachMedia(this.player);
|
||||
this.hlsPlayer.on(Hls.Events.MANIFEST_LOADED, () =>
|
||||
{
|
||||
this.player.play();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dashPlayer.initialize(this.player, "/video/transcode/" + this.item.link + "/", true);
|
||||
this.dashPlayerInitialized = true;
|
||||
this.hlsPlayer.loadSource("/video/transcode/" + this.item.link + "/");
|
||||
this.hlsPlayer.attachMedia(this.player);
|
||||
this.hlsPlayer.on(Hls.Events.MANIFEST_LOADED, () =>
|
||||
{
|
||||
this.player.play();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ namespace Kyoo.Controllers
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("transmux/{showSlug}-s{seasonNumber}e{episodeNumber}/")]
|
||||
[HttpGet("transmux/{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public async Task<IActionResult> Transmux(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
WatchItem episode = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
|
||||
@ -42,7 +42,7 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
string path = await transcoder.Transmux(episode);
|
||||
if (path != null)
|
||||
return PhysicalFile(path, "application/dash+xml", true);
|
||||
return PhysicalFile(path, "application/x-mpegURL ", true);
|
||||
else
|
||||
return StatusCode(500);
|
||||
}
|
||||
@ -50,13 +50,13 @@ namespace Kyoo.Controllers
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("transmux/{episodeLink}/dash/{chunk}")]
|
||||
[HttpGet("transmux/{episodeLink}/segment/{chunk}")]
|
||||
public IActionResult GetTransmuxedChunk(string episodeLink, string chunk)
|
||||
{
|
||||
string path = Path.Combine(transmuxPath, episodeLink);
|
||||
path = Path.Combine(path, "dash" + Path.DirectorySeparatorChar + chunk);
|
||||
path = Path.Combine(path, "segments" + Path.DirectorySeparatorChar + chunk);
|
||||
|
||||
return PhysicalFile(path, "video/iso.segment");
|
||||
return PhysicalFile(path, "video/MP2T");
|
||||
}
|
||||
|
||||
[HttpGet("transcode/{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
|
@ -43,7 +43,7 @@ namespace Kyoo.InternalAPI
|
||||
public async Task<string> Transmux(WatchItem episode)
|
||||
{
|
||||
string folder = Path.Combine(transmuxPath, episode.Link);
|
||||
string manifest = Path.Combine(folder, episode.Link + ".mpd");
|
||||
string manifest = Path.Combine(folder, episode.Link + ".m3u8");
|
||||
float playableDuration = 0;
|
||||
bool transmuxFailed = false;
|
||||
|
||||
|
@ -58,7 +58,7 @@ namespace Kyoo
|
||||
ctx.Response.Headers.Remove("X-Powered-By");
|
||||
ctx.Response.Headers.Remove("Server");
|
||||
ctx.Response.Headers.Add("Feature-Policy", "autoplay 'self'; fullscreen");
|
||||
ctx.Response.Headers.Add("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'");
|
||||
ctx.Response.Headers.Add("Content-Security-Policy", "default-src 'self' data: blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:; style-src 'self' 'unsafe-inline'");
|
||||
ctx.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
|
||||
ctx.Response.Headers.Add("Referrer-Policy", "no-referrer");
|
||||
ctx.Response.Headers.Add("Access-Control-Allow-Origin", "null");
|
||||
|
Loading…
x
Reference in New Issue
Block a user