diff --git a/frontend/app.js b/frontend/app.js
index f53fa1d..3596f0d 100644
--- a/frontend/app.js
+++ b/frontend/app.js
@@ -37,6 +37,7 @@ let cropEnd = 0;
let cropMax = 0;
let activeThumb = null;
const activePlatforms = new Set(["envato", "artgrid", "google video"]);
+const hlsInstances = new WeakMap();
function setStatus(label, progress) {
statusLabel.textContent = label;
@@ -140,6 +141,31 @@ async function api(path, options = {}) {
return data;
}
+function attachVideoSource(video, src) {
+ detachVideoSource(video);
+ if (!src) {
+ return;
+ }
+ if (src.endsWith(".m3u8") && window.Hls && window.Hls.isSupported()) {
+ const hls = new window.Hls({ enableWorker: false });
+ hls.loadSource(src);
+ hls.attachMedia(video);
+ hlsInstances.set(video, hls);
+ return;
+ }
+ video.src = src;
+}
+
+function detachVideoSource(video) {
+ const existing = hlsInstances.get(video);
+ if (existing) {
+ existing.destroy();
+ hlsInstances.delete(video);
+ }
+ video.removeAttribute("src");
+ video.load();
+}
+
function renderResults(results) {
searchResults.innerHTML = "";
if (!results.length) {
@@ -158,7 +184,7 @@ function renderResults(results) {
node.querySelector("p").textContent = item.reason;
node.querySelector(".source-badge").textContent = item.source;
if (item.previewVideoUrl) {
- previewVideo.src = item.previewVideoUrl;
+ attachVideoSource(previewVideo, item.previewVideoUrl);
previewVideo.poster = item.thumbnailUrl || "";
const mediaArea = node.querySelector(".relative");
mediaArea.addEventListener("mouseenter", () => {
@@ -218,11 +244,10 @@ function openPreviewModal(preview) {
previewThumbnail.src = preview.thumbnail;
previewThumbnail.alt = preview.title;
previewVideo.pause();
- previewVideo.removeAttribute("src");
- previewVideo.load();
+ detachVideoSource(previewVideo);
previewMediaFrame.style.aspectRatio = "";
if (preview.previewStreamUrl) {
- previewVideo.src = preview.previewStreamUrl;
+ attachVideoSource(previewVideo, preview.previewStreamUrl);
previewVideo.classList.remove("hidden");
previewThumbnail.classList.add("hidden");
} else {
@@ -247,8 +272,7 @@ function openPreviewModal(preview) {
function closeModal() {
previewVideo.pause();
- previewVideo.removeAttribute("src");
- previewVideo.load();
+ detachVideoSource(previewVideo);
previewMediaFrame.style.aspectRatio = "";
previewModal.classList.add("hidden");
previewModal.classList.remove("flex");
@@ -393,9 +417,10 @@ for (const button of platformToggles) {
activePlatforms.add(platform);
}
syncPlatformButtons();
+ setStatus(`active platforms: ${Array.from(activePlatforms).join(", ")}`, 0);
});
}
connectWS();
syncPlatformButtons();
-setStatus("idle", 0);
+setStatus(`active platforms: ${Array.from(activePlatforms).join(", ")}`, 0);
diff --git a/frontend/index.html b/frontend/index.html
index b40715e..376b1f5 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -144,6 +144,6 @@
-
+