Skip to content

Commit

Permalink
transcript progress styling
Browse files Browse the repository at this point in the history
  • Loading branch information
wesbos committed Sep 14, 2023
1 parent b431820 commit 5f1be39
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 22 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"@leveluptuts/svelte-side-menu": "^1.0.5",
"@prisma/client": "^5.1.1",
"@sentry/sveltekit": "^7.62.0",
"@sindresorhus/slugify": "^2.2.1",
"@types/emscripten": "^1.39.7",
"core-js": "^3.32.1",
"date-fns": "^2.30.0",
Expand Down
18 changes: 18 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/lib/transcript/Squiggle.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
--x: calc(25% + 3.5px);
--y: 0;
translate: var(--x) var(--y);
stroke: var(--purple);
stroke: var(--highlight);
width: 26px;
&.top {
top: 0;
Expand Down
52 changes: 52 additions & 0 deletions src/lib/transcript/TableOfContents.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<script lang="ts">
import { AINoteWithFriends } from '$server/ai/queries';
import slugify from '@sindresorhus/slugify';
export let aiShowNote: AINoteWithFriends;
</script>

<div class="toc">
<ul>
{#each aiShowNote?.summary || [] as summary}
<li>
<a href="#{slugify(summary.text)}">
<span class="timestamp">{summary.time}</span>
{summary.text}
</a>
</li>
{/each}
</ul>
</div>

<style>
ul {
margin: 0;
padding: 0;
border: 1px solid var(--purple);
border-radius: 10px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
}
li {
padding: 0;
line-height: initial;
list-style: none;
padding: 10px;
border-bottom: 1px solid var(--purple);
&:nth-child(odd) {
border-right: 1px solid var(--purple);
}
&:last-child {
border-bottom: none;
}
}
a {
font-size: var(--font-size-s);
text-decoration: none;
}
.timestamp {
display: block;
font-size: var(--font-size-xs);
color: var(--purple);
}
</style>
119 changes: 99 additions & 20 deletions src/lib/transcript/Transcript.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
import { Prisma } from '@prisma/client';
import { time } from 'console';
import 'core-js/full/map/group-by';
import slugify from '@sindresorhus/slugify';
export let transcript: TranscriptWithUtterances;
export let aiShowNote: AINoteWithFriends;
const slim_transcript = getSlimUtterances(transcript.utterances, 1).filter(
(utterance) => utterance.speakerId !== 99
);
// group Utterances by their summary
const def = { time: '00:00', text: '' };
const utterances_by_summary: Map<(typeof aiShowNote.summary)[0], SlimUtterance[]> = Map.groupBy(
type TopicSummary = (typeof aiShowNote.summary)[0];
const utterances_by_summary: Map<TopicSummary, SlimUtterance[]> = Map.groupBy(
slim_transcript,
(utterance: SlimUtterance) => {
const start = utterance.start;
Expand All @@ -26,16 +28,22 @@
}
);
console.log(utterances_by_summary);
import { player } from '$state/player';
import Squiggle from './Squiggle.svelte';
import TableOfContents from './TableOfContents.svelte';
$: currentUtterance = slim_transcript.find((utterance, index) => {
const nextUtteranceStart = slim_transcript[index + 1]?.start || utterance.end;
return $player.currentTime >= utterance.start && $player.currentTime <= nextUtteranceStart;
});
$: currentTopic = aiShowNote.summary.find((summary, index) => {
const nextSummary = aiShowNote.summary[index + 1];
const topicEnd = nextSummary ? tsToS(nextSummary.time) : Infinity;
const topicStart = tsToS(summary.time);
return $player.currentTime >= topicStart && $player.currentTime <= topicEnd;
});
const words = transcript.utterances
.map((utt) => utt.words)
.flat()
Expand All @@ -55,6 +63,28 @@
)
.map((word) => word.word)
.join(' ');
$: labelUtterance = function (utterance: SlimUtterance) {
if (utterance === currentUtterance) {
return 'current';
} else if (currentUtterance && currentUtterance?.end > utterance.end) {
return 'past';
} else {
return 'future';
}
};
$: placeTopic = function (summary: TopicSummary, utterances: SlimUtterance[]) {
console.log('Running Place Topic');
const summaryTimestamp = tsToS(summary.time);
const summaryEnd = utterances.at(-1)?.end || Infinity;
if (currentTopic?.id === summary.id) {
return 'current';
} else if ($player.currentTime > summaryEnd) {
return 'past';
} else {
return 'future';
}
};
</script>

<p><mark>{highlight_words}</mark></p>
Expand All @@ -64,22 +94,17 @@
<p>{currentUtterance?.transcript}</p>
<p>{currentUtterance?.utteranceIndex}</p>

<div>
<ul>
{#each aiShowNote?.summary || [] as summary}
<li>
{summary.text} - {tsToS(summary.time)}
</li>
{/each}
</ul>
</div>
<p>Current Topic:</p>
<p>{currentTopic?.text}</p>

<TableOfContents {aiShowNote} />

<div class="timeline">
{#each Array.from(utterances_by_summary) as [summary, utterances], i}
<section>
<header class="topic">
<header class="topic {placeTopic(summary, utterances)}">
<div class="gutter">
<div>
<div id={slugify(summary.text)}>
<strong>Topic {i}</strong>
<span>{summary.time}</span>
</div>
Expand All @@ -90,15 +115,28 @@
<Squiggle />
</div>
<div>
{placeTopic(summary, utterances)}
<br />
{currentTopic?.text}
<h4>{summary.text || 'Transcript'}</h4>
</div>
</header>
<div>
{#each utterances as utterance}
<div class="utterance">
{@const progress =
(($player.currentTime - utterance.start) / (utterance.end - utterance.start)) * 100}
<div
style="
--progress: {progress > 0 && progress < 100 ? `${progress}%` : '100%'};
"
class="utterance {labelUtterance(utterance, currentUtterance)}"
>
<div class="gutter">
<div>
<span>{format_time(utterance.start)}</span>
{labelUtterance(utterance)}
<button on:click={() => ($player.currentTime = utterance.start)}
>{format_time(utterance.start)}</button
>
<p class="speaker">
{utterance.speaker || `Guest ${utterance.speakerId}`}
</p>
Expand All @@ -118,9 +156,46 @@
</div>

<style>
.active {
background: red;
.timeline {
--highlight: var(--bg-2);
--future: var(--bg-2);
--current: var(--yellow);
--past: var(--yellow);
}
.past {
--highlight: var(--past);
}
.current {
--highlight: var(--yellow);
.marker {
/* --progress: 50%; */
background-image: linear-gradient(
180deg,
var(--highlight) 0%,
var(--highlight) var(--progress),
/* clear Spacer */ var(--bg) calc(var(--progress)),
var(--bg) calc(var(--progress) + 2px),
var(--future) calc(var(--progress) + 2px)
);
}
}
@keyframes pop {
0% {
transform: scale(1);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
header.current {
--progress: 100%;
}
h4 {
position: sticky;
top: 0;
Expand Down Expand Up @@ -165,7 +240,7 @@
grid-template-columns: 1fr;
background: var(--bg-1);
align-items: start;
background: linear-gradient(0deg, var(--purple) 0%, var(--purple) 50%);
background: linear-gradient(0deg, var(--highlight) 0%, var(--highlight) 50%);
background-size: 6px 100%;
background-repeat: repeat-y;
background-position: center;
Expand Down Expand Up @@ -198,10 +273,14 @@
display: block;
width: var(--size);
height: var(--size);
position: relative;
border-radius: 50%;
border: 1.5px solid var(--white);
background: var(--purple);
background: var(--highlight);
justify-self: center;
.current & {
animation: pop 1s 1;
}
}
.timeline {
Expand Down
3 changes: 2 additions & 1 deletion src/routes/shows/[show_number]/[slug]/[[tab]]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
async function handleClick(e: Event) {
const { target } = e;
if (target instanceof HTMLAnchorElement && target.matches(`a[href*='#t=']`)) {
console.log('click');
e.preventDefault();
const { href } = target;
player.update_time(href, show);
Expand Down Expand Up @@ -60,7 +61,7 @@

<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<section class="layout full" on:click|preventDefault={handleClick}>
<section class="layout full" on:click={handleClick}>
{#if $page.params.tab === 'transcript'}
<Transcript aiShowNote={show.aiShowNote} transcript={show.transcript} />
{:else}
Expand Down

0 comments on commit 5f1be39

Please sign in to comment.