aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRblSb <msrblsb@gmail.com>2024-01-01 07:31:02 +0300
committerRblSb <msrblsb@gmail.com>2024-01-01 07:31:02 +0300
commitc9b920cea600b5fbe84ad7ab0b279275243faacb (patch)
treefada67761c471fc461402135a8688e7961d08de7 /src
parent0d1fd0f960a64252638eb94f079c0e7747792b95 (diff)
Flashback time per item, improve webm/webp support
Diffstat (limited to 'src')
-rw-r--r--src/Types.hx6
-rw-r--r--src/VideoList.hx4
-rw-r--r--src/client/Main.hx6
-rw-r--r--src/client/Player.hx19
-rw-r--r--src/server/HttpServer.hx7
-rw-r--r--src/server/Main.hx79
6 files changed, 89 insertions, 32 deletions
diff --git a/src/Types.hx b/src/Types.hx
index fe0e6b2..4ef233b 100644
--- a/src/Types.hx
+++ b/src/Types.hx
@@ -107,6 +107,12 @@ typedef VideoItem = {
isIframe:Bool
}
+typedef FlashbackItem = {
+ url:String,
+ duration:Float,
+ time:Float
+}
+
typedef WsEvent = {
type:WsEventType,
?connected:{
diff --git a/src/VideoList.hx b/src/VideoList.hx
index 2ed1d8f..094d2ab 100644
--- a/src/VideoList.hx
+++ b/src/VideoList.hx
@@ -17,7 +17,9 @@ class VideoList {
return items.length;
}
- public inline function getCurrentItem():VideoItem {
+ public var currentItem(get, never):VideoItem;
+
+ inline function get_currentItem():Null<VideoItem> {
return items[pos];
}
diff --git a/src/client/Main.hx b/src/client/Main.hx
index 69450d9..b1e0eb6 100644
--- a/src/client/Main.hx
+++ b/src/client/Main.hx
@@ -720,7 +720,8 @@ class Main {
});
}
for (emote in config.emotes) {
- final tag = emote.image.endsWith("mp4") ? 'video autoplay="" loop="" muted=""' : "img";
+ final isVideoExt = emote.image.endsWith("mp4") || emote.image.endsWith("webm");
+ final tag = isVideoExt ? 'video autoplay="" loop="" muted=""' : "img";
filters.push({
regex: new EReg("(^| )" + escapeRegExp(emote.name) + "(?!\\S)", "g"),
replace: '$1<$tag class="channel-emote" src="${emote.image}" title="${emote.name}"/>'
@@ -739,7 +740,8 @@ class Main {
}
smilesList.textContent = "";
for (emote in config.emotes) {
- final tag = emote.image.endsWith("mp4") ? "video" : "img";
+ final isVideoExt = emote.image.endsWith("mp4") || emote.image.endsWith("webm");
+ final tag = isVideoExt ? "video" : "img";
final el = document.createElement(tag);
el.className = "smile-preview";
el.dataset.src = emote.image;
diff --git a/src/client/Player.hx b/src/client/Player.hx
index 6113c07..75b44b5 100644
--- a/src/client/Player.hx
+++ b/src/client/Player.hx
@@ -92,7 +92,7 @@ class Player {
function setPlayer(newPlayer:IPlayer):Void {
if (player != newPlayer) {
if (player != null) {
- JsApi.fireVideoRemoveEvents(videoList.getCurrentItem());
+ JsApi.fireVideoRemoveEvents(videoList.currentItem);
player.removeVideo();
}
main.blinkTabWithTitle("*Video*");
@@ -139,7 +139,7 @@ class Player {
public function changeVideoSrc(src:String):Void {
if (!main.isVideoEnabled) return;
if (player == null) return;
- final item = videoList.getCurrentItem() ?? return;
+ final item = videoList.currentItem ?? return;
player.loadVideo({
url: src,
title: item.title,
@@ -152,7 +152,7 @@ class Player {
}
public function removeVideo():Void {
- JsApi.fireVideoRemoveEvents(videoList.getCurrentItem());
+ JsApi.fireVideoRemoveEvents(videoList.currentItem);
player.removeVideo();
ge("#currenttitle").textContent = Lang.get("nothingPlaying");
setPauseIndicator(true);
@@ -278,7 +278,7 @@ class Player {
var index = videoList.findIndex(item -> item.url == url);
if (index == -1) return;
- final isCurrent = videoList.getCurrentItem().url == url;
+ final isCurrent = videoList.currentItem.url == url;
videoList.removeItem(index);
updateCounters();
@@ -301,7 +301,7 @@ class Player {
if (pos == -1) return;
removeActiveLabel(videoList.pos);
videoList.setPos(pos);
- if (videoList.getCurrentItem().isTemp) removeElementItem(url);
+ if (videoList.currentItem.isTemp) removeElementItem(url);
videoList.skipItem();
updateCounters();
if (videoList.length == 0) return;
@@ -332,15 +332,14 @@ class Player {
}
public function setItems(list:Array<VideoItem>, ?pos:Int):Void {
- final currentUrl = videoList.pos >= videoList.length ? "" : videoList.getCurrentItem()
- .url;
+ final currentUrl = videoList.pos >= videoList.length ? "" : videoList.currentItem.url;
clearItems();
if (list.length == 0) return;
for (video in list) {
addVideoItem(video, true);
}
if (pos != null) videoList.setPos(pos);
- if (currentUrl != videoList.getCurrentItem().url) setVideo(videoList.pos);
+ if (currentUrl != videoList.currentItem.url) setVideo(videoList.pos);
else addActiveLabel(videoList.pos);
}
@@ -401,7 +400,7 @@ class Player {
public function getDuration():Float {
if (videoList.pos >= videoList.length) return 0;
- return videoList.getCurrentItem().duration;
+ return videoList.currentItem.duration;
}
public function isVideoLoaded():Bool {
@@ -451,7 +450,7 @@ class Player {
}
public function skipAd():Void {
- final item = videoList.getCurrentItem() ?? return;
+ final item = videoList.currentItem ?? return;
if (!youtube.isSupportedLink(item.url)) return;
final id = youtube.extractVideoId(item.url);
final url = 'https://sponsor.ajay.app/api/skipSegments?videoID=$id';
diff --git a/src/server/HttpServer.hx b/src/server/HttpServer.hx
index 4bf16c4..acb8955 100644
--- a/src/server/HttpServer.hx
+++ b/src/server/HttpServer.hx
@@ -21,13 +21,16 @@ class HttpServer {
"css" => "text/css",
"json" => "application/json",
"png" => "image/png",
- "jpg" => "image/jpg",
+ "jpg" => "image/jpeg",
+ "jpeg" => "image/jpeg",
"gif" => "image/gif",
+ "webp" => "image/webp",
"svg" => "image/svg+xml",
"ico" => "image/x-icon",
"wav" => "audio/wav",
"mp3" => "audio/mpeg",
"mp4" => "video/mp4",
+ "webm" => "video/webm",
"woff" => "application/font-woff",
"ttf" => "application/font-ttf",
"eot" => "application/vnd.ms-fontobject",
@@ -152,7 +155,7 @@ class HttpServer {
}
static function isMediaExtension(ext:String):Bool {
- return ext == "mp4" || ext == "mp3" || ext == "wav";
+ return ext == "mp4" || ext == "webm" || ext == "mp3" || ext == "wav";
}
static final matchLang = ~/^[A-z]+/;
diff --git a/src/server/Main.hx b/src/server/Main.hx
index ab48592..0da88e7 100644
--- a/src/server/Main.hx
+++ b/src/server/Main.hx
@@ -2,9 +2,11 @@ package server;
import Client.ClientData;
import Types.Config;
+import Types.FlashbackItem;
import Types.Message;
import Types.Permission;
import Types.UserList;
+import Types.VideoItem;
import Types.WsEvent;
import haxe.Json;
import haxe.Timer;
@@ -618,10 +620,13 @@ class Main {
if (!checkPermission(client, RemoveVideoPerm)) return;
if (videoList.length == 0) return;
final url = data.removeVideo.url;
- var index = videoList.findIndex(item -> item.url == url);
+ final index = videoList.findIndex(item -> item.url == url);
if (index == -1) return;
- final isCurrent = videoList.getCurrentItem().url == url;
+ final isCurrent = videoList.currentItem.url == url;
+ if (isCurrent && videoTimer.getTime() > FLASHBACK_DIST) {
+ saveFlashbackTime(videoList.currentItem);
+ }
videoList.removeItem(index);
if (isCurrent && videoList.length > 0) {
broadcast(data);
@@ -638,7 +643,7 @@ class Main {
if (videoList.length == 0) return;
if (!client.isLeader) return;
if (Math.abs(data.pause.time - videoTimer.getTime()) > FLASHBACK_DIST) {
- saveFlashbackTime();
+ saveFlashbackTime(videoList.currentItem);
}
videoTimer.setTime(data.pause.time);
videoTimer.pause();
@@ -651,7 +656,7 @@ class Main {
if (videoList.length == 0) return;
if (!client.isLeader) return;
if (Math.abs(data.play.time - videoTimer.getTime()) > FLASHBACK_DIST) {
- saveFlashbackTime();
+ saveFlashbackTime(videoList.currentItem);
}
videoTimer.setTime(data.play.time);
videoTimer.play();
@@ -662,11 +667,11 @@ class Main {
case GetTime:
if (videoList.length == 0) return;
- final maxTime = videoList.getCurrentItem().duration - 0.01;
+ final maxTime = videoList.currentItem.duration - 0.01;
if (videoTimer.getTime() > maxTime) {
videoTimer.pause();
videoTimer.setTime(maxTime);
- final skipUrl = videoList.getCurrentItem().url;
+ final skipUrl = videoList.currentItem.url;
Timer.delay(() -> {
skipVideo({
type: SkipVideo,
@@ -694,7 +699,7 @@ class Main {
if (videoList.length == 0) return;
if (!client.isLeader) return;
if (Math.abs(data.setTime.time - videoTimer.getTime()) > FLASHBACK_DIST) {
- saveFlashbackTime();
+ saveFlashbackTime(videoList.currentItem);
}
videoTimer.setTime(data.setTime.time);
broadcastExcept(client, {
@@ -716,7 +721,7 @@ class Main {
if (videoList.length == 0) return;
data.rewind.time += videoTimer.getTime();
if (data.rewind.time < 0) data.rewind.time = 0;
- saveFlashbackTime();
+ saveFlashbackTime(videoList.currentItem);
videoTimer.setTime(data.rewind.time);
broadcast({
type: data.type,
@@ -726,7 +731,7 @@ class Main {
case Flashback:
if (!checkPermission(client, RewindPerm)) return;
if (videoList.length == 0) return;
- loadFlashbackTime();
+ loadFlashbackTime(videoList.currentItem);
broadcast({
type: Rewind,
rewind: {
@@ -762,6 +767,9 @@ class Main {
case PlayItem:
if (!checkPermission(client, ChangeOrderPerm)) return;
+ if (videoTimer.getTime() > FLASHBACK_DIST) {
+ saveFlashbackTime(videoList.currentItem);
+ }
videoList.setPos(data.playItem.pos);
data.playItem.pos = videoList.pos;
restartWaitTimer();
@@ -790,6 +798,9 @@ class Main {
case ClearPlaylist:
if (isPlaylistLockedFor(client)) return;
if (!checkPermission(client, RemoveVideoPerm)) return;
+ if (videoTimer.getTime() > FLASHBACK_DIST) {
+ saveFlashbackTime(videoList.currentItem);
+ }
videoTimer.stop();
videoList.clear();
broadcast(data);
@@ -902,8 +913,13 @@ class Main {
function skipVideo(data:WsEvent):Void {
if (videoList.length == 0) return;
- final item = videoList.getCurrentItem();
+ final item = videoList.currentItem;
if (item.url != data.skipVideo.url) return;
+ final dur = videoList.currentItem.duration;
+ if (videoTimer.getTime() > FLASHBACK_DIST
+ && videoTimer.getTime() < dur - FLASHBACK_DIST) {
+ saveFlashbackTime(videoList.currentItem);
+ }
videoList.skipItem();
if (videoList.length > 0) restartWaitTimer();
broadcast(data);
@@ -959,7 +975,6 @@ class Main {
var loadedClientsCount = 0;
function restartWaitTimer():Void {
- if (videoTimer.getTime() > FLASHBACK_DIST) saveFlashbackTime();
videoTimer.stop();
if (waitVideoStart != null) waitVideoStart.stop();
waitVideoStart = Timer.delay(startVideoPlayback, VIDEO_START_MAX_DELAY);
@@ -979,18 +994,48 @@ class Main {
videoTimer.start();
}
- var flashbackTime = 0.0;
-
- function saveFlashbackTime() {
+ function saveFlashbackTime(item:VideoItem):Void {
+ final url = item.url;
+ final duration = item.duration;
final time = videoTimer.getTime();
+ final flashbackTime = findFlashbackTime(url, duration);
if (Math.abs(flashbackTime - time) < FLASHBACK_DIST) return;
- flashbackTime = time;
+ addRecentFlashback(url, duration, time);
}
- function loadFlashbackTime() {
+ function loadFlashbackTime(item:VideoItem):Void {
+ final url = item.url;
+ final duration = item.duration;
final time = videoTimer.getTime();
+ final flashbackTime = findFlashbackTime(url, duration);
videoTimer.setTime(flashbackTime);
- flashbackTime = time;
+ addRecentFlashback(url, duration, time);
+ }
+
+ function findFlashbackTime(url:String, duration:Float):Float {
+ return findFlashbackItem(url, duration)?.time ?? 0.0;
+ }
+
+ final flashbackTimes:Array<FlashbackItem> = [];
+
+ function findFlashbackItem(url:String, ?duration:Float):Null<FlashbackItem> {
+ var item = flashbackTimes.find(item -> item.url == url);
+ // if there is no url match, find recent flashback item with same duration
+ if (duration != null && item == null) {
+ item = flashbackTimes.find(item -> item.duration == duration);
+ }
+ return item;
+ }
+
+ function addRecentFlashback(url:String, duration:Float, time:Float):Void {
+ flashbackTimes.remove(findFlashbackItem(url));
+ flashbackTimes.unshift({
+ url: url,
+ duration: duration,
+ time: time
+ });
+ final length = flashbackTimes.count();
+ if (length > 10) flashbackTimes.pop();
}
function isPlaylistLockedFor(client:Client):Bool {
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage