Fixed logo spin + added automatic subtitle that maybe works
This commit is contained in:
4
package-lock.json
generated
4
package-lock.json
generated
@@ -5,7 +5,7 @@
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ncs-visualizer",
|
||||
"name": "audio-visualizer",
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.0",
|
||||
@@ -1299,4 +1299,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
glowIntensity: 0.6,
|
||||
logoSpin: false,
|
||||
logoSpinSpeed: 5,
|
||||
autoSubtitle: false,
|
||||
titlePosition: "top",
|
||||
};
|
||||
|
||||
@@ -71,7 +72,9 @@
|
||||
let glowIntensity = saved.glowIntensity;
|
||||
let logoSpin = saved.logoSpin;
|
||||
let logoSpinSpeed = saved.logoSpinSpeed;
|
||||
let autoSubtitle = saved.autoSubtitle;
|
||||
let titlePosition = saved.titlePosition;
|
||||
let capturedTrackLabel = "";
|
||||
let visualizerComponent;
|
||||
let toggleHidden = false;
|
||||
let hideTimer;
|
||||
@@ -99,6 +102,10 @@
|
||||
clearTimeout(hideTimer);
|
||||
}
|
||||
|
||||
$: if (autoSubtitle && capturedTrackLabel) {
|
||||
subtitle = capturedTrackLabel;
|
||||
}
|
||||
|
||||
$: {
|
||||
const settings = {
|
||||
selectedPreset,
|
||||
@@ -126,6 +133,7 @@
|
||||
glowIntensity,
|
||||
logoSpin,
|
||||
logoSpinSpeed,
|
||||
autoSubtitle,
|
||||
titlePosition,
|
||||
};
|
||||
try {
|
||||
@@ -183,6 +191,7 @@
|
||||
glowIntensity = defaults.glowIntensity;
|
||||
logoSpin = defaults.logoSpin;
|
||||
logoSpinSpeed = defaults.logoSpinSpeed;
|
||||
autoSubtitle = defaults.autoSubtitle;
|
||||
titlePosition = defaults.titlePosition;
|
||||
}
|
||||
|
||||
@@ -311,6 +320,7 @@
|
||||
{glowIntensity}
|
||||
{logoSpin}
|
||||
{logoSpinSpeed}
|
||||
bind:capturedTrackLabel
|
||||
bind:isListening
|
||||
bind:fileCurrentTime
|
||||
bind:fileDuration
|
||||
@@ -381,6 +391,7 @@
|
||||
bind:glowIntensity
|
||||
bind:logoSpin
|
||||
bind:logoSpinSpeed
|
||||
bind:autoSubtitle
|
||||
bind:titlePosition
|
||||
{isListening}
|
||||
{colorPresets}
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
let currentStream = null;
|
||||
let audioElement = null;
|
||||
let audioSourceNode = null;
|
||||
let capturedAudioTrack = null;
|
||||
let tabTitleInterval = null;
|
||||
export let capturedTrackLabel = "";
|
||||
let dataArray = new Uint8Array(128);
|
||||
let bufferLength = 128;
|
||||
|
||||
@@ -274,6 +277,16 @@
|
||||
// Stop the video track immediately — we only need audio
|
||||
stream.getVideoTracks().forEach((t) => t.stop());
|
||||
|
||||
// Store audio track for label polling (tab title)
|
||||
capturedAudioTrack = audioTracks[0];
|
||||
tabTitleInterval = setInterval(() => {
|
||||
if (capturedAudioTrack && capturedAudioTrack.readyState === "live") {
|
||||
capturedTrackLabel = capturedAudioTrack.label || "";
|
||||
} else {
|
||||
capturedTrackLabel = "";
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// Handle stream ending (user clicks "Stop sharing")
|
||||
stream.addEventListener("inactive", () => stopListening());
|
||||
audioTracks.forEach((track) =>
|
||||
@@ -721,6 +734,12 @@
|
||||
audioContext = null;
|
||||
}
|
||||
audioSourceNode = null;
|
||||
capturedAudioTrack = null;
|
||||
if (tabTitleInterval) {
|
||||
clearInterval(tabTitleInterval);
|
||||
tabTitleInterval = null;
|
||||
}
|
||||
capturedTrackLabel = "";
|
||||
isListening = false;
|
||||
dataArray = new Uint8Array(bufferLength);
|
||||
draw();
|
||||
@@ -793,6 +812,7 @@
|
||||
onDestroy(() => {
|
||||
if (animationId) cancelAnimationFrame(animationId);
|
||||
if (audioContext) audioContext.close();
|
||||
if (tabTitleInterval) clearInterval(tabTitleInterval);
|
||||
window.removeEventListener("resize", updateSize);
|
||||
});
|
||||
</script>
|
||||
@@ -807,9 +827,9 @@
|
||||
{#if logoUrl}
|
||||
<div
|
||||
class="logo-container"
|
||||
style="width: {baseRadius * 2}px; height: {baseRadius * 2}px; {logoSpin
|
||||
? `animation: logo-spin ${Math.max(0.5, 20 / logoSpinSpeed)}s linear infinite`
|
||||
: ''}"
|
||||
class:spinning={logoSpin}
|
||||
style="width: {baseRadius * 2}px; height: {baseRadius *
|
||||
2}px; --spin-duration: {Math.max(0.5, 20 / logoSpinSpeed)}s"
|
||||
>
|
||||
<img src={logoUrl} alt="Logo" />
|
||||
</div>
|
||||
@@ -861,7 +881,11 @@
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
@keyframes logo-spin {
|
||||
.logo-container.spinning {
|
||||
animation: logo-spin var(--spin-duration, 4s) linear infinite;
|
||||
}
|
||||
|
||||
@keyframes -global-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
export let logoSpin = false;
|
||||
export let logoSpinSpeed = 5;
|
||||
export let titlePosition = "top";
|
||||
export let autoSubtitle = false;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
@@ -610,7 +611,13 @@
|
||||
bind:value={subtitle}
|
||||
placeholder="Subtitle..."
|
||||
style="margin-top: 0.35rem"
|
||||
disabled={autoSubtitle}
|
||||
/>
|
||||
<div class="slider-row" style="margin-top: 0.35rem">
|
||||
<label>
|
||||
<input type="checkbox" bind:checked={autoSubtitle} /> Auto (Tab Title)
|
||||
</label>
|
||||
</div>
|
||||
<div class="inline-row" style="margin-top: 0.5rem">
|
||||
<input
|
||||
type="file"
|
||||
|
||||
Reference in New Issue
Block a user