← Back to Projects

leptons1618@anishgiri.dev:~/case-studies/echoscript less writeup.md

AI / ML2024 May 20, 2024 3 min read

EchoScript

A YouTube URL in, a searchable transcript and a set of notes out — with the text and the video kept in sync.

published
May 20, 2024
read
3 min
stack
8 tools
outcomes
6
media
—

01The Problem

A two-hour talk contains maybe eight minutes you need, and video is the worst possible medium for finding them: you cannot search it, skim it, or quote it. Transcription alone does not fix that. A raw wall of transcript is only marginally easier to work with than the video, because once you find the sentence you wanted you have lost the one thing the video had — the ability to go and hear it said.

02The Solution

A Flask backend pulls audio with yt-dlp, normalises it through ffmpeg, and transcribes with Whisper or Faster-Whisper at a model size the user picks. Because Whisper returns timestamped segments rather than flat text, the React frontend can make every line a seek target: click a sentence, the player jumps to it. The same segments feed AI-generated notes, full-text search, and export to PDF, TXT or Notion.

The pipeline

1. Fetch yt-dlp takes the URL and pulls the audio stream only. Downloading video to throw the frames away is bandwidth spent on nothing, and audio-only is the difference between a few megabytes and a few hundred.

2. Normalise ffmpeg converts whatever came back into the sample rate and channel layout Whisper expects. This stage looks like a formality and is the one that fails most often in practice — which is why ffmpeg is a hard prerequisite in the setup instructions rather than a Python dependency that pip pretends to handle.

3. Transcribe Whisper, or Faster-Whisper, at a model size the user selects per job. This is the only real decision in the pipeline and it has no correct answer: tiny returns in a moment and mangles proper nouns, large is accurate and makes you wait. Exposing it as a setting rather than picking one is the honest response — the right trade depends on whether you are checking a fact or keeping a record.

4. Align Whisper does not return a blob of text. It returns segments, each with a start and end timestamp, and that detail is what the whole interface is built on. Nothing here has to do alignment; it has to avoid throwing away alignment that already exists.

5. Present React renders segments as clickable lines bound to the player’s seek. Search runs over the segment text, so a hit knows its own timestamp and can offer to take you there.

6. Summarise and export The transcript feeds note generation, and the result exports to PDF, TXT, or Notion.

Why the sync is the feature

It would have been easier to ship a transcript downloader. It would also have been close to useless, because the two things you do with a talk are find the bit and hear the bit, and a text file can only do the first.

The insight is small and cheap: Whisper’s timestamps are already there. Keeping segments as first-class objects all the way to the browser, instead of joining them into a string at the first opportunity, costs nothing at any stage and turns a document into an index into the video.

That shape then pays for itself twice. Search does not need its own timestamp index, because every searchable unit already carries one. Notes can cite a position rather than a paragraph.

GPU optional, and honest about it

CUDA is recommended and not required. On CPU, Faster-Whisper is the difference between “slow” and “not worth starting”, and the larger models stop being practical.

Rather than hide that, the UI streams progress while a job runs. A transcription is a long-running task and pretending otherwise produces the worst version of this app: a spinner that looks identical to a hang. Job history exists for the same reason — you start a two-hour video, you go away, and the result has to still be there when you come back.

Things it does not do

No speaker labels. Whisper transcribes what was said, not who said it, and attributing lines to speakers is a separate model and a separate alignment problem. A transcript that guesses at speakers is worse than one that admits it does not know, because the guess reads as fact.

No live captioning. The pipeline is batch from end to end — fetch, then convert, then transcribe — and a streaming version is a different architecture, not a flag on this one.

03Achievements

  1. Click any line of the transcript to jump the video to that moment — the segment timestamps Whisper already returns are what make this free.
  2. Model size is a user choice, not a build-time constant: tiny for a quick pass, large when accuracy matters, with Faster-Whisper for machines without a GPU.
  3. Full-text transcript search with keyboard navigation — Enter to search, F3 and Shift+F3 through hits, Escape to clear.
  4. AI notes and summaries generated from the transcript, exportable to PDF, TXT, or straight into Notion.
  5. Job history with status tracking, date and status filters, and sorting — because transcription is slow enough that you leave and come back.
  6. One-command dev startup for Linux, macOS and Windows, with dependency checks and configurable ports.

04Stack

PythonFlaskReactOpenAI WhisperFaster-Whisperyt-dlpffmpegNotion API