This is awesome! Im having a hard time understanding how to get the JS code working on my computer. I have the js file uploaded in the same directory as the styles folder, but im unsure how to get it working.
I don’t think I got it 100% however. Like mentioned before by @leolabs, switching back and forth resets the lyrics page and makes it all go back to normal size etc.
When it is fully functional, everything is slightly over to the right side as well. Will post examples soon
This is a video I took to show you guys what’s happening. Exiting the lyrics page resets it and makes it not formatted correctly. But going back and saving the scripts file starts the script again and it fixes itself. However it is still slightly towards the bottom right corner without the proper spacing there.
There are still occasions where if I update lyrics in the middle of the song, it won’t resize but refreshing the page always fixes it for me. When I get near my machine, I will send everything I have in mine so you can compare.
I just made a few adjustments to the script so it can now handle navigating between pages:
let observer;
const init = () => {
const target = document.querySelector(".lyrics-page .lyrics div");
if (!target) {
console.log("This doesn't seem to be a lyrics page");
return;
}
const callback = async (mutationList) => {
const lyrics = document.querySelectorAll(".lyrics-line span");
const { textFit } = await import("./textFit.js");
lyrics.forEach((el) => {
el.style.display = "block";
el.style.width = el.parentElement.clientWidth + "px";
el.style.height = el.parentElement.clientHeight + "px";
});
// maxFontSize can be adjusted if the font becomes too large
textFit(lyrics, { multiLine: true, maxFontSize: 300 });
};
observer = new MutationObserver(callback);
observer.observe(target, { childList: true });
callback();
// Since AbleSet 2.4.0, you have access to real-time updates
ableset.getSocket("lyrics").on("tracksUpdated", () => {
setTimeout(callback, 1000);
});
};
// Keep track of the current URL so we can run
// the script again when navigating to a lyrics page
let lastLocation = "";
setInterval(() => {
if (location.href !== lastLocation && location.href.includes("/lyrics")) {
lastLocation = location.href;
observer?.disconnect();
init();
}
}, 1000);
Currently this isn’t possible because the script itself isn’t tagged as a module, so top-level import statements aren’t available, but I could change that in the next version
I wouldn’t worry about the import running multiple times though – those requests are most likely cached so it shouldn’t have any impact on performance.
The latest beta, AbleSet 2.5.0-beta.1, now supports top-level imports in the custom script. Starting with this version, you can use the following syntax to import modules:
import { textFit } from "./textFit.js";
let observer;
const init = () => {
const target = document.querySelector(".lyrics-page .lyrics div");
if (!target) {
console.log("This doesn't seem to be a lyrics page");
return;
}
const callback = async (mutationList) => {
const lyrics = document.querySelectorAll(".lyrics-line span");
lyrics.forEach((el) => {
el.style.display = "block";
el.style.width = el.parentElement.clientWidth + "px";
el.style.height = el.parentElement.clientHeight + "px";
});
// maxFontSize can be adjusted if the font becomes too large
textFit(lyrics, { multiLine: true, maxFontSize: 300 });
};
observer = new MutationObserver(callback);
observer.observe(target, { childList: true });
callback();
// Since AbleSet 2.4.0, you have access to real-time updates
ableset.getSocket("lyrics").on("tracksUpdated", () => {
setTimeout(callback, 1000);
});
};
// Keep track of the current URL so we can run
// the script again when navigating to a lyrics page
let lastLocation = "";
setInterval(() => {
if (location.href !== lastLocation && location.href.includes("/lyrics")) {
lastLocation = location.href;
observer?.disconnect();
init();
}
}, 1000);
This works incredibly. It is centered. For longer lines, it looks like there is zero padding between the text and the end of the screen. It might be nice to add a very small pad on the left and right sides of the screen.
Another thing… Is it possible for Ableset to remember which lyric page you selected when you tab back and forth? Right now, it just selected which ever one is first every time. This isn’t a huge deal, but it is annoying sometimes to have to reselect it if I tab out for a second to check something, etc.
I also like how Ableset scrolls along with it right now, but in ProPresenter it does not scroll and I want to make the transition as seamless as possible for the team. (hopefully they don’t even know until I tell them haha)
Is there a tag modifier to stop the auto-scroll? but instead jump between lyrics almost like frames?
It also could be a good option to allow you to target named lyrics tracks with tags within the CSS script or JS script so that the lyric page in Ableton session doesn’t need it, making it ever so much cleaner. So any track with “+LYRICS” called “Confidence-Monitor” automatically receives the [nozoom] [top] [nofade]
I am having an issue with the text scaling. It often times (especially when making changes to the lyrics or to any of the “Lyrics” tracks) changes back to the original size (much smaller than the scaled text), and needs to be refreshed each time this happens otherwise the text is too small to see on our Stage Display. This has always been the case since using Textfit.js and while it is annoying to not be able to make changes on the fly without the text refreshing and randomly changing to sizes much larger than the original or much smaller, it is manageable.
But what it has started doing (honestly, I don’t remember what version it started on), is reverting back to the original text size between each song and if myself or our sound engineer do not catch it, there is a good bit of time that goes by that the lyrics are very difficult to read.
I know this is a weird and unique setup but was just curious if there was a possible fix for this?
I just made a small modification to the code that checks the lines every second and if it notices that a line hasn’t been adjusted to the screen yet, it runs the script again. Here’s the new code:
import { textFit } from "./textFit.js";
let observer;
let interval;
const init = () => {
const target = document.querySelector(".lyrics-page .lyrics div");
if (!target) {
console.log("This doesn't seem to be a lyrics page");
return;
}
const callback = async (_a, _b, options) => {
const lyrics = document.querySelectorAll(".lyrics-line span");
lyrics.forEach((el) => {
el.style.display = "block";
el.style.width = el.parentElement.clientWidth + "px";
el.style.height = el.parentElement.clientHeight + "px";
});
// maxFontSize can be adjusted if the font becomes too large
textFit(lyrics, { multiLine: true, maxFontSize: 300, ...options });
};
observer = new MutationObserver(callback);
observer.observe(target, { childList: true });
callback();
// Since AbleSet 2.4.0, you have access to real-time updates
ableset.getSocket("lyrics").on("tracksUpdated", () => {
setTimeout(callback, 1000);
});
if (interval) {
clearInterval(interval);
}
// If a line is replaced, re-fit its text.
// This is a bit of a brute-force approach that just runs the fitting
// process every second and ignores lines that have already been adjusted.
setInterval(() => callback(null, null, { reProcess: false }), 1000);
};
// Keep track of the current URL so we can run
// the script again when navigating to a lyrics page
let lastLocation = "";
setInterval(() => {
if (location.href !== lastLocation && location.href.includes("/lyrics")) {
lastLocation = location.href;
observer?.disconnect();
init();
}
}, 1000);
I am attaching a screen recording of what is happening. It does fix the problem of the text getting smaller in between songs and increases the size of that text but a weird issue is occurring as it in “debouncing”.
Oh, that’s not looking good! Does this version work better?
import { textFit } from "./textFit.js";
let observer;
let interval;
const init = () => {
const target = document.querySelector(".lyrics-page .lyrics div");
if (!target) {
console.log("This doesn't seem to be a lyrics page");
return;
}
const callback = async (_a, _b, options) => {
const lyrics = document.querySelectorAll(
".lyrics-line span:not(.text-fit)"
);
lyrics.forEach((el) => {
el.style.display = "block";
el.style.width = el.parentElement.clientWidth + "px";
el.style.height = el.parentElement.clientHeight + "px";
el.classList.add("text-fit");
});
// maxFontSize can be adjusted if the font becomes too large
textFit(lyrics, { multiLine: true, maxFontSize: 300, ...options });
};
observer = new MutationObserver(callback);
observer.observe(target, { childList: true });
callback();
// Since AbleSet 2.4.0, you have access to real-time updates
ableset.getSocket("lyrics").on("tracksUpdated", () => {
setTimeout(callback, 1000);
});
if (interval) {
clearInterval(interval);
}
// If a line is replaced, re-fit its text.
// This is a bit of a brute-force approach that just runs the fitting
// process every second and ignores lines that have already been adjusted.
interval = setInterval(() => callback(null, null, { reProcess: false }), 1000);
};
// Keep track of the current URL so we can run
// the script again when navigating to a lyrics page
let lastLocation = "";
setInterval(() => {
if (location.href !== lastLocation && location.href.includes("/lyrics")) {
lastLocation = location.href;
observer?.disconnect();
init();
}
}, 1000);
An issue I have run into is that over time (usually about 2 or 3 minutes) the page begins to lag quite a bit when swapping lyrics and then goes unresponsive. I reverted back to the previous script and it worked fine so something is bogging down. As far as sizing between songs, it works brilliantly, the only issue is that it bogs down over time until the lyrics stop progressing. Also if I load the lyrics page and it sits without running the tracks, it will do the same thing so it seems to be happening the moment the page is loaded.