Accessible Video Quiz¶
A video-based memory quiz that is Born Accessible: a quiz cannot reach a senior unless it has both an audio description and captions, the audio description always plays before the video with no skip, captions are high-contrast and enlarged, and every answer is logged as a research record.
Where the code lives¶
src/features/video-quiz/types.ts—VideoQuizItem(authored content, includingaudioDescriptionandcaptions) andVideoQuizResponse, the research record whose field names mirror the approved schema.src/features/video-quiz/validation.ts—validateVideoQuiz/canPublish: the Born Accessible gate that blocks publication when the audio description or captions are missing.src/features/video-quiz/captions.ts— a resilient SRT parser andcueAtfor time-based lookup.src/features/video-quiz/export.ts—toCsvproducing the research-readyvideo_quiz_response.csvcolumns.src/features/video-quiz/logging.ts—buildVideoQuizResponseand the wrapped clock (keeps impure calls out of render for the React Compiler).src/features/video-quiz/video-quiz-screen.tsx— the player.app/(tabs)/video.tsx— the tab route.
Accessibility guarantees (WCAG 1.2.1, 1.2.2, 2.1.1)¶
- Mandatory audio description. The description phase always precedes the video and is announced to assistive technology; there is no skip.
- Mandatory captions. Captions render high-contrast (white on black) and
enlarged (120% by default via
defaultCaptionStyle). - Failsafe. A quiz that fails
validateVideoQuizrenders a high-contrast error and no playback control, so inaccessible content never plays. - Large controls. The play/pause control is at least 48x48pt with a clear role and label, and advertises voice equivalents in its hint.
- Nothing plays out of sight. Tapping Back or Home, or the app leaving the
foreground, stops the clip; a delayed autoplay whose grace period elapses
while the app is away never starts. Both screens share
src/hooks/use-pause-when-hidden.tsfor this, because the app has no transport control outside the player to silence it from.
Which video plays¶
Without an explicit item prop, the screen draws a shuffled order over
seedVideoQuizzes and walks it, so the same clip does not open every visit.
Because it shuffles the order rather than picking at random each time, every
video is seen once before any repeats, and a reshuffle at the end of a pass
never opens with the clip that just finished.
The draw happens once, in a lazy state initializer, so no randomness runs
during a re-render. random is injectable for tests. This is the same
pickPlayOrder helper the music quiz uses; see
src/lib/play-order.ts.
Research data (Lisa Part)¶
Each answer produces a VideoQuizResponse capturing video_quiz_id,
senior_id, timestamp, audio_description_used, captions_used,
response, accuracy, context, senior_response_time_ms, and
input_method. toCsv serializes a batch to the research-ready CSV.
Follow-ups (not in this branch)¶
- Real video playback and time-synchronized caption rendering (expo-video).
- Voice commands and voice answers (speech recognition), and caregiver audio recording for the description.
- Caregiver upload flow: SRT upload, verified auto-captioning, and the
publish-time enforcement of
validateVideoQuiz. - Persist responses and add the CSV export action to the Stats Display.