mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
Implemented speaker color functions
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
|||||||
import { formatTime } from "../../lib/time";
|
import { formatTime } from "../../lib/time";
|
||||||
import ScrollToBottom from "./scrollToBottom";
|
import ScrollToBottom from "./scrollToBottom";
|
||||||
import { Topic } from "./webSocketTypes";
|
import { Topic } from "./webSocketTypes";
|
||||||
|
import { generateHighContrastColor } from "../lib/utils";
|
||||||
|
|
||||||
type TopicListProps = {
|
type TopicListProps = {
|
||||||
topics: Topic[];
|
topics: Topic[];
|
||||||
@@ -114,9 +115,18 @@ export function TopicList({
|
|||||||
<span className="font-mono text-slate-500">
|
<span className="font-mono text-slate-500">
|
||||||
[{formatTime(segment.start)}]
|
[{formatTime(segment.start)}]
|
||||||
</span>
|
</span>
|
||||||
<span className="font-bold text-slate-500">
|
<span
|
||||||
Speaker {segment.speaker}
|
className="font-bold text-slate-500"
|
||||||
</span>
|
style={{
|
||||||
|
color: generateHighContrastColor(
|
||||||
|
`Speaker ${segment.speaker}`,
|
||||||
|
[96, 165, 250],
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
(Speaker {segment.speaker}):
|
||||||
|
</span>{" "}
|
||||||
<span>{segment.text}</span>
|
<span>{segment.text}</span>
|
||||||
</p>
|
</p>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -56,38 +56,116 @@ export const useWebSockets = (transcriptId: string | null): UseWebSockets => {
|
|||||||
timestamp: 10,
|
timestamp: 10,
|
||||||
summary: "This is test topic 1",
|
summary: "This is test topic 1",
|
||||||
title: "Topic 1: Introduction to Quantum Mechanics",
|
title: "Topic 1: Introduction to Quantum Mechanics",
|
||||||
transcript:
|
text: "A brief overview of quantum mechanics and its principles.",
|
||||||
"A brief overview of quantum mechanics and its principles.",
|
segments: [
|
||||||
|
{
|
||||||
|
speaker: 1,
|
||||||
|
start: 0,
|
||||||
|
text: "This is the transcription of an example title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 2,
|
||||||
|
start: 10,
|
||||||
|
text: "This is the second speaker",
|
||||||
|
},
|
||||||
|
,
|
||||||
|
{
|
||||||
|
speaker: 3,
|
||||||
|
start: 90,
|
||||||
|
text: "This is the third speaker",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 4,
|
||||||
|
start: 90,
|
||||||
|
text: "This is the fourth speaker",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 5,
|
||||||
|
start: 123,
|
||||||
|
text: "This is the fifth speaker",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 6,
|
||||||
|
start: 300,
|
||||||
|
text: "This is the sixth speaker",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "2",
|
id: "2",
|
||||||
timestamp: 20,
|
timestamp: 20,
|
||||||
summary: "This is test topic 2",
|
summary: "This is test topic 2",
|
||||||
title: "Topic 2: Machine Learning Algorithms",
|
title: "Topic 2: Machine Learning Algorithms",
|
||||||
transcript:
|
text: "Understanding the different types of machine learning algorithms.",
|
||||||
"Understanding the different types of machine learning algorithms.",
|
segments: [
|
||||||
|
{
|
||||||
|
speaker: 1,
|
||||||
|
start: 0,
|
||||||
|
text: "This is the transcription of an example title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 2,
|
||||||
|
start: 10,
|
||||||
|
text: "This is the second speaker",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "3",
|
id: "3",
|
||||||
timestamp: 30,
|
timestamp: 30,
|
||||||
summary: "This is test topic 3",
|
summary: "This is test topic 3",
|
||||||
title: "Topic 3: Mental Health Awareness",
|
title: "Topic 3: Mental Health Awareness",
|
||||||
transcript: "Ways to improve mental health and reduce stigma.",
|
text: "Ways to improve mental health and reduce stigma.",
|
||||||
|
segments: [
|
||||||
|
{
|
||||||
|
speaker: 1,
|
||||||
|
start: 0,
|
||||||
|
text: "This is the transcription of an example title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 2,
|
||||||
|
start: 10,
|
||||||
|
text: "This is the second speaker",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "4",
|
id: "4",
|
||||||
timestamp: 40,
|
timestamp: 40,
|
||||||
summary: "This is test topic 4",
|
summary: "This is test topic 4",
|
||||||
title: "Topic 4: Basics of Productivity",
|
title: "Topic 4: Basics of Productivity",
|
||||||
transcript: "Tips and tricks to increase daily productivity.",
|
text: "Tips and tricks to increase daily productivity.",
|
||||||
|
segments: [
|
||||||
|
{
|
||||||
|
speaker: 1,
|
||||||
|
start: 0,
|
||||||
|
text: "This is the transcription of an example title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 2,
|
||||||
|
start: 10,
|
||||||
|
text: "This is the second speaker",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "5",
|
id: "5",
|
||||||
timestamp: 50,
|
timestamp: 50,
|
||||||
summary: "This is test topic 5",
|
summary: "This is test topic 5",
|
||||||
title: "Topic 5: Future of Aviation",
|
title: "Topic 5: Future of Aviation",
|
||||||
transcript:
|
text: "Exploring the advancements and possibilities in aviation.",
|
||||||
"Exploring the advancements and possibilities in aviation.",
|
segments: [
|
||||||
|
{
|
||||||
|
speaker: 1,
|
||||||
|
start: 0,
|
||||||
|
text: "This is the transcription of an example title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 2,
|
||||||
|
start: 10,
|
||||||
|
text: "This is the second speaker",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -104,8 +182,19 @@ export const useWebSockets = (transcriptId: string | null): UseWebSockets => {
|
|||||||
summary: "This is test topic 1",
|
summary: "This is test topic 1",
|
||||||
title:
|
title:
|
||||||
"Topic 1: Introduction to Quantum Mechanics, a brief overview of quantum mechanics and its principles.",
|
"Topic 1: Introduction to Quantum Mechanics, a brief overview of quantum mechanics and its principles.",
|
||||||
transcript:
|
text: "A brief overview of quantum mechanics and its principles.",
|
||||||
"A brief overview of quantum mechanics and its principles.",
|
segments: [
|
||||||
|
{
|
||||||
|
speaker: 1,
|
||||||
|
start: 0,
|
||||||
|
text: "This is the transcription of an example title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 2,
|
||||||
|
start: 10,
|
||||||
|
text: "This is the second speaker",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "2",
|
id: "2",
|
||||||
@@ -113,8 +202,19 @@ export const useWebSockets = (transcriptId: string | null): UseWebSockets => {
|
|||||||
summary: "This is test topic 2",
|
summary: "This is test topic 2",
|
||||||
title:
|
title:
|
||||||
"Topic 2: Machine Learning Algorithms, understanding the different types of machine learning algorithms.",
|
"Topic 2: Machine Learning Algorithms, understanding the different types of machine learning algorithms.",
|
||||||
transcript:
|
text: "Understanding the different types of machine learning algorithms.",
|
||||||
"Understanding the different types of machine learning algorithms.",
|
segments: [
|
||||||
|
{
|
||||||
|
speaker: 1,
|
||||||
|
start: 0,
|
||||||
|
text: "This is the transcription of an example title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 2,
|
||||||
|
start: 10,
|
||||||
|
text: "This is the second speaker",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "3",
|
id: "3",
|
||||||
@@ -122,7 +222,19 @@ export const useWebSockets = (transcriptId: string | null): UseWebSockets => {
|
|||||||
summary: "This is test topic 3",
|
summary: "This is test topic 3",
|
||||||
title:
|
title:
|
||||||
"Topic 3: Mental Health Awareness, ways to improve mental health and reduce stigma.",
|
"Topic 3: Mental Health Awareness, ways to improve mental health and reduce stigma.",
|
||||||
transcript: "Ways to improve mental health and reduce stigma.",
|
text: "Ways to improve mental health and reduce stigma.",
|
||||||
|
segments: [
|
||||||
|
{
|
||||||
|
speaker: 1,
|
||||||
|
start: 0,
|
||||||
|
text: "This is the transcription of an example title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 2,
|
||||||
|
start: 10,
|
||||||
|
text: "This is the second speaker",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "4",
|
id: "4",
|
||||||
@@ -130,7 +242,19 @@ export const useWebSockets = (transcriptId: string | null): UseWebSockets => {
|
|||||||
summary: "This is test topic 4",
|
summary: "This is test topic 4",
|
||||||
title:
|
title:
|
||||||
"Topic 4: Basics of Productivity, tips and tricks to increase daily productivity.",
|
"Topic 4: Basics of Productivity, tips and tricks to increase daily productivity.",
|
||||||
transcript: "Tips and tricks to increase daily productivity.",
|
text: "Tips and tricks to increase daily productivity.",
|
||||||
|
segments: [
|
||||||
|
{
|
||||||
|
speaker: 1,
|
||||||
|
start: 0,
|
||||||
|
text: "This is the transcription of an example title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 2,
|
||||||
|
start: 10,
|
||||||
|
text: "This is the second speaker",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "5",
|
id: "5",
|
||||||
@@ -138,8 +262,19 @@ export const useWebSockets = (transcriptId: string | null): UseWebSockets => {
|
|||||||
summary: "This is test topic 5",
|
summary: "This is test topic 5",
|
||||||
title:
|
title:
|
||||||
"Topic 5: Future of Aviation, exploring the advancements and possibilities in aviation.",
|
"Topic 5: Future of Aviation, exploring the advancements and possibilities in aviation.",
|
||||||
transcript:
|
text: "Exploring the advancements and possibilities in aviation.",
|
||||||
"Exploring the advancements and possibilities in aviation.",
|
segments: [
|
||||||
|
{
|
||||||
|
speaker: 1,
|
||||||
|
start: 0,
|
||||||
|
text: "This is the transcription of an example title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
speaker: 2,
|
||||||
|
start: 10,
|
||||||
|
text: "This is the second speaker",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,125 @@
|
|||||||
export function isDevelopment() {
|
export function isDevelopment() {
|
||||||
return process.env.NEXT_PUBLIC_ENV === "development";
|
return process.env.NEXT_PUBLIC_ENV === "development";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to calculate WCAG contrast ratio
|
||||||
|
export const getContrastRatio = (
|
||||||
|
foreground: [number, number, number],
|
||||||
|
background: [number, number, number],
|
||||||
|
) => {
|
||||||
|
const [r1, g1, b1] = foreground;
|
||||||
|
const [r2, g2, b2] = background;
|
||||||
|
|
||||||
|
const lum1 =
|
||||||
|
0.2126 * Math.pow(r1 / 255, 2.2) +
|
||||||
|
0.7152 * Math.pow(g1 / 255, 2.2) +
|
||||||
|
0.0722 * Math.pow(b1 / 255, 2.2);
|
||||||
|
const lum2 =
|
||||||
|
0.2126 * Math.pow(r2 / 255, 2.2) +
|
||||||
|
0.7152 * Math.pow(g2 / 255, 2.2) +
|
||||||
|
0.0722 * Math.pow(b2 / 255, 2.2);
|
||||||
|
|
||||||
|
return (Math.max(lum1, lum2) + 0.05) / (Math.min(lum1, lum2) + 0.05);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to hash string into 32-bit integer
|
||||||
|
// 🔴 DO NOT USE FOR CRYPTOGRAPHY PURPOSES 🔴
|
||||||
|
|
||||||
|
export function murmurhash3_32_gc(key: string, seed: number = 0) {
|
||||||
|
let remainder, bytes, h1, h1b, c1, c2, k1, i;
|
||||||
|
|
||||||
|
remainder = key.length & 3; // key.length % 4
|
||||||
|
bytes = key.length - remainder;
|
||||||
|
h1 = seed;
|
||||||
|
c1 = 0xcc9e2d51;
|
||||||
|
c2 = 0x1b873593;
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
while (i < bytes) {
|
||||||
|
k1 =
|
||||||
|
(key.charCodeAt(i) & 0xff) |
|
||||||
|
((key.charCodeAt(++i) & 0xff) << 8) |
|
||||||
|
((key.charCodeAt(++i) & 0xff) << 16) |
|
||||||
|
((key.charCodeAt(++i) & 0xff) << 24);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
|
||||||
|
k1 =
|
||||||
|
((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
|
||||||
|
k1 = (k1 << 15) | (k1 >>> 17);
|
||||||
|
k1 =
|
||||||
|
((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
|
||||||
|
|
||||||
|
h1 ^= k1;
|
||||||
|
h1 = (h1 << 13) | (h1 >>> 19);
|
||||||
|
h1b =
|
||||||
|
((h1 & 0xffff) * 5 + ((((h1 >>> 16) * 5) & 0xffff) << 16)) & 0xffffffff;
|
||||||
|
h1 = (h1b & 0xffff) + 0x6b64 + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
k1 = 0;
|
||||||
|
|
||||||
|
switch (remainder) {
|
||||||
|
case 3:
|
||||||
|
k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
|
||||||
|
case 2:
|
||||||
|
k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
|
||||||
|
case 1:
|
||||||
|
k1 ^= key.charCodeAt(i) & 0xff;
|
||||||
|
|
||||||
|
k1 =
|
||||||
|
((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) &
|
||||||
|
0xffffffff;
|
||||||
|
k1 = (k1 << 15) | (k1 >>> 17);
|
||||||
|
k1 =
|
||||||
|
((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) &
|
||||||
|
0xffffffff;
|
||||||
|
h1 ^= k1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 ^= key.length;
|
||||||
|
|
||||||
|
h1 ^= h1 >>> 16;
|
||||||
|
h1 =
|
||||||
|
((h1 & 0xffff) * 0x85ebca6b +
|
||||||
|
((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) &
|
||||||
|
0xffffffff;
|
||||||
|
h1 ^= h1 >>> 13;
|
||||||
|
h1 =
|
||||||
|
((h1 & 0xffff) * 0xc2b2ae35 +
|
||||||
|
((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) &
|
||||||
|
0xffffffff;
|
||||||
|
h1 ^= h1 >>> 16;
|
||||||
|
|
||||||
|
return h1 >>> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates a color that is guaranteed to have high contrast with the given background color (optional)
|
||||||
|
|
||||||
|
export const generateHighContrastColor = (
|
||||||
|
name: string,
|
||||||
|
backgroundColor: [number, number, number] | null = null,
|
||||||
|
) => {
|
||||||
|
const hash = murmurhash3_32_gc(name);
|
||||||
|
console.log(name, hash);
|
||||||
|
|
||||||
|
let red = (hash & 0xff0000) >> 16;
|
||||||
|
let green = (hash & 0x00ff00) >> 8;
|
||||||
|
let blue = hash & 0x0000ff;
|
||||||
|
|
||||||
|
const getCssColor = (red: number, green: number, blue: number) =>
|
||||||
|
`rgb(${red}, ${green}, ${blue})`;
|
||||||
|
|
||||||
|
if (!backgroundColor) return getCssColor(red, green, blue);
|
||||||
|
|
||||||
|
const contrast = getContrastRatio([red, green, blue], backgroundColor);
|
||||||
|
|
||||||
|
// Adjust the color to achieve better contrast if necessary (WCAG recommends at least 4.5:1 for text)
|
||||||
|
if (contrast < 4.5) {
|
||||||
|
red = Math.abs(255 - red);
|
||||||
|
green = Math.abs(255 - green);
|
||||||
|
blue = Math.abs(255 - blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return getCssColor(red, green, blue);
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user