My lectures in “Data Science 2” fell behind early and never caught up. When I planned them, I assumed a speed I do not actually teach at.
The measurement
I record my own lectures, with OBS Studio capturing the screen and a RODE microphone for the audio. The recordings go into the university media library, where students watch them before the exam and nobody else does, me included. From each transcript, aligned with its deck, I got a number I had never had before: slides per minute of actual teaching.
Session (24/25) | Length | Slides | Slides/min | Character |
|---|---|---|---|---|
Probabilistic data structures | 76 min | 55 (whole deck) | 0.72 | narrated, nothing computed |
Jaccard distance | 48 min | ~19 | 0.40 | one long question from the room |
MapReduce | 48 min | ~18 | 0.38 | standard pace |
PageRank 1 | 98 min | 45 | 0.46 | 42 min computing at the board |
When I only narrate, I get through 0.72 slides a minute. When I compute something at the board, my rate drops to 0.46, and the 42 minutes at the board cost me twenty slides. My decks run 45 to 103 pages, so I had been overbooking by a factor of two, week after week, for years. I now plan with 35 to 45 slides per session, and I subtract 15 to 20 minutes for anything I derive live.
What got dropped
When I overbook a session, the shortfall is not spread evenly over the deck. I simply never reach the last slides, and from the transcripts I can see which ones got zero minutes:
Candidate | Size | Evidence from the recordings |
|---|---|---|
TrustRank, web spam, link farms | 24 slides | never delivered |
Streams, “advanced topics” | 22 slides | fragments only |
The item-item numeric example | 5 slides | flipped through in 80 seconds |
Evaluation and error measures | 4 slides | dropped, never made up |
The evaluation slides are the ones that hurt. They cover how you tell whether a recommender is any good, the exam relies on that material, and nothing in the plan showed that I had skipped it.
The pipeline
I ran the transcription locally on an RTX 4090, with faster-whisper 1.2 and the large-v3 model in float16:
from faster_whisper import WhisperModel
model = WhisperModel("large-v3", device="cuda", compute_type="float16")
segments, info = model.transcribe(
video, language="de", beam_size=5,
vad_filter=True, vad_parameters=dict(min_silence_duration_ms=800),
condition_on_previous_text=False,
)The language is fixed to German because my lectures are in German but full of English jargon, and otherwise autodetect flips mid-file. The VAD filter is on because Whisper otherwise invents sentences during the silences while I write at the board. And without condition_on_previous_text=False the transcription loops.
Alongside the transcript, the pipeline pulls a still from the video every two minutes, 47 per session, and renames each one to the time it was taken:
ffmpeg -nostdin -v error -y -i "$VIDEO" -vf "fps=1/120" -q:v 3 "$OUT/stills/tmp_%04d.jpg"
# frame i sits at (i-1)*2 minutes
for f in "$OUT"/stills/tmp_*.jpg; do
i=$((10#$(basename "$f" .jpg | cut -d_ -f2))); m=$(( (i-1)*2 ))
mv "$f" "$OUT/stills/$(printf '%02dh%02dm.jpg' $((m/60)) $((m%60)))"
doneWith that rename the two halves line up: 01h04m.jpg shows the slide that was on screen at 1:04, and the transcript says what I was saying at 1:04. Without it I would know the pace of my talking and nothing about the pace of the material. The -nostdin flag is there because the script runs ffmpeg inside a while read loop over a list of videos, and without it ffmpeg swallows the rest of the list.
The whole run covered twelve sessions and 17 hours of video, and it took 36 minutes of GPU time.
I did not write any of this code. I described what I wanted to Claude Opus 5, got back the code above plus the download and batch scripts around it, and it ran. I did not read the transcripts either. Opus read them and gave me an HTML page per session with a table of how the time was spent, eleven minutes of graph motivation here, ten minutes of live calculation there, next to the matching stills. I took the numbers above from those pages. The obvious next step from the same files is chapter marks for the recordings, which a student used to place by hand.
Five years ago this would have been a weekend project, and so it would never have happened. Now software that serves one person for one purpose, and takes an afternoon, is cheap enough to be worth writing.
What changes
I am now running the same pipeline over my other courses, starting with deep learning. Anyone who records their lectures is sitting on the same kind of data, and the cost of looking at it is now half an hour on a graphics card rather than seventeen hours of listening.
The first lecture went somewhat smooth: I did reword some things on the slides that departed too much from my original style (in particular the slides were too full), but then I was happy. To my surprise, the slides actually fit the alloted timeframe perfectly without any issues. I am quite curious how well this will hold up during the term! So if you’re lucky, I’ll post an update, also about student evaluations, at some point (in February?). However, since this is a blog, expect to never see the promised follow-up :-)
