aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/client.js108
-rw-r--r--src/client/players/RawSubs.hx151
2 files changed, 212 insertions, 47 deletions
diff --git a/res/client.js b/res/client.js
index acc335f..11b6094 100644
--- a/res/client.js
+++ b/res/client.js
@@ -407,6 +407,25 @@ StringTools.rtrim = function(s) {
StringTools.trim = function(s) {
return StringTools.ltrim(StringTools.rtrim(s));
};
+StringTools.lpad = function(s,c,l) {
+ if(c.length <= 0) {
+ return s;
+ }
+ var buf_b = "";
+ l -= s.length;
+ while(buf_b.length < l) buf_b += c == null ? "null" : "" + c;
+ buf_b += s == null ? "null" : "" + s;
+ return buf_b;
+};
+StringTools.rpad = function(s,c,l) {
+ if(c.length <= 0) {
+ return s;
+ }
+ var buf_b = "";
+ buf_b = "" + (s == null ? "null" : "" + s);
+ while(buf_b.length < l) buf_b += c == null ? "null" : "" + c;
+ return buf_b;
+};
StringTools.replace = function(s,sub,by) {
return s.split(sub).join(by);
};
@@ -2701,9 +2720,10 @@ client_players_RawSubs.loadSubs = function(item,video) {
if(client_JsApi.hasSubtitleSupport(ext)) {
return;
}
- var url = "/proxy?url=" + client_players_RawSubs.encodeURI(item.subs);
+ var url = "/proxy?url=" + encodeURI(item.subs);
switch(ext) {
case "ass":
+ client_players_RawSubs.parseAss(video,url);
break;
case "srt":
client_players_RawSubs.parseSrt(video,url);
@@ -2740,11 +2760,91 @@ client_players_RawSubs.parseSrt = function(video,url) {
data += "" + sub.time + "\n";
data += "" + sub.text + "\n\n";
}
- haxe_Log.trace(data,{ fileName : "src/client/players/RawSubs.hx", lineNumber : 64, className : "client.players.RawSubs", methodName : "parseSrt"});
var url = "data:text/plain;base64," + haxe_crypto_Base64.encode(haxe_io_Bytes.ofString(data));
client_players_RawSubs.onParsed(video,"SRT subtitles",url);
});
};
+client_players_RawSubs.parseAss = function(video,url) {
+ window.fetch(url).then(function(response) {
+ return response.text();
+ }).then(function(text) {
+ var subs = [];
+ var lines = StringTools.replace(text,"\r\n","\n").split("\n");
+ var matchFormat = new EReg("^Format:","");
+ var matchDialogue = new EReg("^Dialogue:","");
+ var blockTags_r = new RegExp("\\{\\\\[^}]*\\}","g".split("u").join(""));
+ var tags_r = new RegExp("\\\\[^ ]+","g".split("u").join(""));
+ var drawingMode = new EReg("\\\\p[124]","");
+ var eventStart = false;
+ var formatFound = false;
+ var ids_h = Object.create(null);
+ var subsCounter = 1;
+ var _g = 0;
+ while(_g < lines.length) {
+ var line = StringTools.trim(lines[_g++]);
+ if(!eventStart) {
+ eventStart = StringTools.startsWith(line,"[Events]");
+ continue;
+ }
+ if(!formatFound) {
+ formatFound = matchFormat.match(line);
+ if(!formatFound) {
+ continue;
+ }
+ var list = line.replace(matchFormat.r,"").split(",");
+ var _g1 = 0;
+ var _g2 = list.length;
+ while(_g1 < _g2) {
+ var i = _g1++;
+ ids_h[StringTools.trim(list[i])] = i;
+ }
+ ids_h["_length"] = list.length;
+ }
+ if(!matchDialogue.match(line)) {
+ continue;
+ }
+ var list1 = line.replace(matchDialogue.r,"").split(",");
+ while(list1.length > ids_h["_length"]) {
+ var el = list1.pop();
+ list1[list1.length - 1] += el;
+ }
+ var result = new Array(list1.length);
+ var _g3 = 0;
+ var _g11 = list1.length;
+ while(_g3 < _g11) {
+ var i1 = _g3++;
+ result[i1] = StringTools.trim(list1[i1]);
+ }
+ list1 = result;
+ var text = result[ids_h["Text"]];
+ if(drawingMode.match(text)) {
+ text = "";
+ }
+ text = text.replace(blockTags_r,"");
+ text = text.replace(tags_r,"");
+ subs.push({ counter : subsCounter, start : client_players_RawSubs.convertAssTime(result[ids_h["Start"]]), end : client_players_RawSubs.convertAssTime(result[ids_h["End"]]), text : text});
+ ++subsCounter;
+ }
+ var data = "WEBVTT\n\n";
+ var _g = 0;
+ while(_g < subs.length) {
+ var sub = subs[_g];
+ ++_g;
+ data += "" + sub.counter + "\n";
+ data += "" + sub.start + " --> " + sub.end + "\n";
+ data += "" + sub.text + "\n\n";
+ }
+ var url = "data:text/plain;base64," + haxe_crypto_Base64.encode(haxe_io_Bytes.ofString(data));
+ client_players_RawSubs.onParsed(video,"ASS subtitles",url);
+ });
+};
+client_players_RawSubs.convertAssTime = function(time) {
+ if(!client_players_RawSubs.assTimeStamp.match(time)) {
+ return "" + StringTools.lpad("" + 0,"0",2) + ":" + StringTools.lpad("" + 0,"0",2) + ":" + StringTools.lpad("" + 0,"0",2) + "." + HxOverrides.substr(StringTools.rpad("" + 0,"0",3),0,3);
+ }
+ var time = { h : Std.parseInt(client_players_RawSubs.assTimeStamp.matched(1)), m : Std.parseInt(client_players_RawSubs.assTimeStamp.matched(2)), s : Std.parseInt(client_players_RawSubs.assTimeStamp.matched(3)), ms : Std.parseInt(client_players_RawSubs.assTimeStamp.matched(4))};
+ return "" + StringTools.lpad("" + time.h,"0",2) + ":" + StringTools.lpad("" + time.m,"0",2) + ":" + StringTools.lpad("" + time.s,"0",2) + "." + HxOverrides.substr(StringTools.rpad("" + time.ms,"0",3),0,3);
+};
client_players_RawSubs.onParsed = function(video,name,dataUrl) {
var trackEl = window.document.createElement("track");
trackEl.label = name;
@@ -2754,9 +2854,6 @@ client_players_RawSubs.onParsed = function(video,name,dataUrl) {
trackEl.track.mode = "showing";
video.appendChild(trackEl);
};
-client_players_RawSubs.encodeURI = function(data) {
- return encodeURI(data);
-};
var client_players_Youtube = function(main,player) {
this.matchSeconds = new EReg("([0-9]+)S","");
this.matchMinutes = new EReg("([0-9]+)M","");
@@ -3783,6 +3880,7 @@ client_JsApi.videoChange = [];
client_JsApi.videoRemove = [];
client_JsApi.onceListeners = [];
client_Settings.isSupported = false;
+client_players_RawSubs.assTimeStamp = new EReg("([0-9]+):([0-9][0-9]):([0-9][0-9]).([0-9][0-9])","");
haxe_crypto_Base64.CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
haxe_crypto_Base64.BYTES = haxe_io_Bytes.ofString(haxe_crypto_Base64.CHARS);
js_youtube_Youtube.isLoadedAPI = false;
diff --git a/src/client/players/RawSubs.hx b/src/client/players/RawSubs.hx
index 4fcf3b6..cf37baa 100644
--- a/src/client/players/RawSubs.hx
+++ b/src/client/players/RawSubs.hx
@@ -25,6 +25,7 @@ class RawSubs {
switch ext {
case "ass":
+ parseAss(video, url);
case "srt":
parseSrt(video, url);
case "vtt":
@@ -61,57 +62,102 @@ class RawSubs {
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);
- // }
+ static function parseAss(video:VideoElement, url:String):Void {
+ window.fetch(url).then(response -> {
+ return response.text();
+ }).then(text -> {
+ final subs:Array<{
+ counter:Int,
+ start:String,
+ end:String,
+ text:String,
+ }> = [];
+ final lines = text.replace("\r\n", "\n").split("\n");
+ final matchFormat = ~/^Format:/;
+ final matchDialogue = ~/^Dialogue:/;
+ final blockTags = ~/\{\\[^}]*\}/g;
+ final tags = ~/\\[^ ]+/g;
+ final drawingMode = ~/\\p[124]/;
+ var eventStart = false;
+ var formatFound = false;
+ final ids:Map<String, Int> = [];
+ var subsCounter = 1;
+ for (rawLine in lines) {
+ final line = rawLine.trim();
+ if (!eventStart) {
+ eventStart = line.startsWith("[Events]");
+ continue;
+ }
- 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 {
+ if (!formatFound) {
+ formatFound = matchFormat.match(line);
+ if (!formatFound) continue;
+ final list = matchFormat.replace(line, "").split(",");
+ for (i in 0...list.length) {
+ ids[list[i].trim()] = i;
+ }
+ ids["_length"] = list.length;
+ }
+
+ if (!matchDialogue.match(line)) continue;
+ var list = matchDialogue.replace(line, "").split(",");
+ while (list.length > ids["_length"]) {
+ final el = list.pop();
+ list[list.length - 1] += el;
+ }
+ list = list.map((e) -> e.trim());
+ var text = list[ids["Text"]];
+ if (drawingMode.match(text)) text = "";
+ text = blockTags.replace(text, "");
+ text = tags.replace(text, "");
+ subs.push({
+ counter: subsCounter,
+ start: convertAssTime(list[ids["Start"]]),
+ end: convertAssTime(list[ids["End"]]),
+ text: text,
+ });
+ subsCounter++;
+ }
+
+ var data = "WEBVTT\n\n";
+ for (sub in subs) {
+ data += '${sub.counter}\n';
+ data += '${sub.start} --> ${sub.end}\n';
+ data += '${sub.text}\n\n';
+ }
+ final textBase64 = "data:text/plain;base64,";
+ final url = textBase64 + Base64.encode(Bytes.ofString(data));
+ onParsed(video, "ASS subtitles", url);
+ });
+ }
+
+ static final assTimeStamp = ~/([0-9]+):([0-9][0-9]):([0-9][0-9]).([0-9][0-9])/;
+
+ static function convertAssTime(time:String):String {
+ if (!assTimeStamp.match(time)) {
+ return toVttTime({
+ h: 0,
+ m: 0,
+ s: 0,
+ ms: 0,
+ });
+ }
+ final h = Std.parseInt(assTimeStamp.matched(1));
+ final m = Std.parseInt(assTimeStamp.matched(2));
+ final s = Std.parseInt(assTimeStamp.matched(3));
+ final ms = Std.parseInt(assTimeStamp.matched(4));
+ return toVttTime({
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';
+ ms: ms,
+ });
}
static function parseVtt(video:VideoElement, url:String):Void {
@@ -133,7 +179,28 @@ class RawSubs {
video.appendChild(trackEl);
}
- static function encodeURI(data:String):String {
+ static inline function encodeURI(data:String):String {
return js.Syntax.code("encodeURI({0})", data);
}
+
+ static inline function toVttTime(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).substr(0, 3);
+ return '$h:$m:$s.$ms';
+ }
+
+ static inline function secondsToDuration(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
+ }
+ }
}
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage