aboutsummaryrefslogtreecommitdiffstats
path: root/src/client/players
diff options
context:
space:
mode:
authorRblSb <msrblsb@gmail.com>2021-07-05 17:09:56 +0300
committerRblSb <msrblsb@gmail.com>2021-07-05 17:09:56 +0300
commitcf78d464be214eedcd7909001ece2aa0a216d136 (patch)
tree5801ef0ca01589ed923c961a93b30278df9ea9d3 /src/client/players
parentede45cea8706eb8540e466df9861c2af8ebf9c44 (diff)
vtt/srt subs support
Diffstat (limited to 'src/client/players')
-rw-r--r--src/client/players/Raw.hx42
-rw-r--r--src/client/players/RawSubs.hx139
2 files changed, 160 insertions, 21 deletions
diff --git a/src/client/players/Raw.hx b/src/client/players/Raw.hx
index ea51e97..5889732 100644
--- a/src/client/players/Raw.hx
+++ b/src/client/players/Raw.hx
@@ -54,11 +54,8 @@ class Raw implements IPlayer {
}
titleInput.value = "";
- var subs = "";
- if (JsApi.hasSubtitleSupport()) {
- subs = subsInput.value.trim();
- subsInput.value = "";
- }
+ final subs = subsInput.value.trim();
+ subsInput.value = "";
final video = document.createVideoElement();
video.src = url;
video.onerror = e -> {
@@ -101,24 +98,27 @@ class Raw implements IPlayer {
}
if (video != null) {
video.src = url;
- if (isHls) initHlsSource(video, url);
- restartControlsHider();
- return;
- }
- video = document.createVideoElement();
- video.id = "videoplayer";
- video.src = url;
- restartControlsHider();
- video.oncanplaythrough = player.onCanBePlayed;
- video.onseeking = player.onSetTime;
- video.onplay = e -> {
- playAllowed = true;
- player.onPlay();
+ for (element in video.children) {
+ if (element.nodeName != "TRACK") continue;
+ element.remove();
+ }
+ } else {
+ video = document.createVideoElement();
+ video.id = "videoplayer";
+ video.src = url;
+ video.oncanplaythrough = player.onCanBePlayed;
+ video.onseeking = player.onSetTime;
+ video.onplay = e -> {
+ playAllowed = true;
+ player.onPlay();
+ }
+ video.onpause = player.onPause;
+ video.onratechange = player.onRateChange;
+ playerEl.appendChild(video);
}
- video.onpause = player.onPause;
- video.onratechange = player.onRateChange;
- playerEl.appendChild(video);
if (isHls) initHlsSource(video, url);
+ restartControlsHider();
+ RawSubs.loadSubs(item, video);
}
function restartControlsHider():Void {
diff --git a/src/client/players/RawSubs.hx b/src/client/players/RawSubs.hx
new file mode 100644
index 0000000..4fcf3b6
--- /dev/null
+++ b/src/client/players/RawSubs.hx
@@ -0,0 +1,139 @@
+package client.players;
+
+import Types.VideoItem;
+import haxe.crypto.Base64;
+import haxe.io.Bytes;
+import js.Browser.document;
+import js.Browser.window;
+import js.html.VideoElement;
+
+using StringTools;
+
+private typedef Duration = {
+ h:Int,
+ m:Int,
+ s:Int,
+ ms:Int
+}
+
+class RawSubs {
+ public static function loadSubs(item:VideoItem, video:VideoElement):Void {
+ final ext = PathTools.urlExtension(item.subs);
+ // do not load subs if there is custom plugin
+ if (JsApi.hasSubtitleSupport(ext)) return;
+ final url = '/proxy?url=${encodeURI(item.subs)}';
+
+ switch ext {
+ case "ass":
+ case "srt":
+ parseSrt(video, url);
+ case "vtt":
+ onParsed(video, "VTT subtitles", url);
+ // parseVtt(video, url);
+ }
+ }
+
+ static function parseSrt(video:VideoElement, url:String):Void {
+ window.fetch(url).then(response -> {
+ return response.text();
+ }).then(text -> {
+ final subs:Array<{
+ counter:String,
+ time:String,
+ text:String
+ }> = [];
+ final blocks = text.replace("\r\n", "\n").split("\n\n");
+ for (block in blocks) {
+ final lines = block.split("\n");
+ if (lines.length < 3) continue;
+ final textLines = [
+ for (i in 2...lines.length) lines[i]
+ ];
+ subs.push({
+ counter: lines[0],
+ time: lines[1].replace(",", "."),
+ text: textLines.join("\n")
+ });
+ }
+ var data = "WEBVTT\n\n";
+ for (sub in subs) {
+ data += '${sub.counter}\n';
+ data += '${sub.time}\n';
+ data += '${sub.text}\n\n';
+ }
+ trace(data);
+ final textBase64 = "data:text/plain;base64,";
+ final url = textBase64 + Base64.encode(Bytes.ofString(data));
+ onParsed(video, "SRT subtitles", url);
+ });
+ }
+
+ // function saveSubs() {
+ // final options = [
+ // for (i in 0...subsSelect.options.length)
+ // subsSelect.item(i)
+ // ];
+ // var inputId = (cast el("#id-offset") : InputElement).value;
+ // var id = Std.parseInt(inputId);
+ // if (id == null) id = 1;
+ // final data:Array<String> = options.map(element -> {
+ // final value = element.textContent;
+ // final firstTime = Std.parseFloat(value.split("|")[0]);
+ // final secondTime = Std.parseFloat(value.split("|")[1]);
+ // // 00:00:00,498 --> 00:00:02,827
+ // var time = '$id\n';
+ // time += srvTimeFormat(stringDuration(firstTime));
+ // time += " --> ";
+ // time += srvTimeFormat(stringDuration(secondTime));
+ // time += '\ntext$id\n';
+ // id++;
+ // return time;
+ // });
+ // final data = data.join("\n");
+ // Utils.saveFile("subs.srv", TextPlain, data);
+ // }
+
+ function stringDuration(seconds:Float):Duration {
+ final h = Std.int(seconds / 60 / 60);
+ final m = Std.int(seconds / 60) - h * 60;
+ final s = Std.int(seconds % 60);
+ final ms = Std.int((seconds - Std.int(seconds)) * 1000);
+ return {
+ h: h,
+ m: m,
+ s: s,
+ ms: ms
+ }
+ }
+
+ function srvTimeFormat(time:Duration):String {
+ final h = '${time.h}'.lpad("0", 2);
+ final m = '${time.m}'.lpad("0", 2);
+ final s = '${time.s}'.lpad("0", 2);
+ final ms = '${time.ms}'.rpad("0", 3);
+ return '$h:$m:$s,$ms';
+ }
+
+ static function parseVtt(video:VideoElement, url:String):Void {
+ window.fetch(url).then(response -> response.text()).then(data -> {
+ final textBase64 = "data:text/plain;base64,";
+ final url = textBase64 + Base64.encode(Bytes.ofString(data));
+ onParsed(video, "VTT subtitles", url);
+ });
+ }
+
+ static function onParsed(video:VideoElement, name:String, dataUrl:String) {
+ final trackEl = document.createTrackElement();
+ trackEl.label = name;
+ trackEl.kind = "subtitles";
+ trackEl.src = dataUrl;
+ trackEl.default_ = true;
+ final track = trackEl.track;
+ track.mode = SHOWING;
+ video.appendChild(trackEl);
+ }
+
+ static function encodeURI(data:String):String {
+ return js.Syntax.code("encodeURI({0})", data);
+ }
+}
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage