feat(AIMessage): add video content block for inline playback#295
Conversation
Adds a 'video' content block to AIMessage so chat bubbles can render an inline native <video> player, mirroring the existing audio content-block pattern (PR #285). - types.ts: add 'video' to the AIMessageContent.type union and a videoUrl field. - AIMessage.tsx: render a native <video controls preload=metadata> when a content block of type 'video' carries a videoUrl; guards against javascript: URLs and includes a captions <track> for a11y. - AIMessage.stories.tsx + sampleVideo.ts: add a WithVideoBlock story using a locally generated synthetic WebM (canvas + MediaRecorder), no network/CORS.
Deploying ui with
|
| Latest commit: |
2a33cf9
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://376de0d0.ui-6d0.pages.dev |
| Branch Preview URL: | https://feat-ai-message-video-block.ui-6d0.pages.dev |
There was a problem hiding this comment.
Pull request overview
Adds first-class video content blocks to the AI chat message rendering pipeline so consuming apps can display inline video/screen-recording playback inside AIMessage bubbles (mirroring the existing audio/image/file block patterns).
Changes:
- Extends
AIMessageContentto supporttype: 'video'with avideoUrlfield. - Renders inline native
<video controls preload="metadata">forvideocontent blocks with basic URL scheme guarding. - Adds a Storybook demo that generates a short local sample WebM via
canvas+MediaRecorder.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| src/components/AudioPlayer/sampleVideo.ts | New Storybook helper that generates a synthetic sample video blob URL via MediaRecorder. |
| src/components/AI/types.ts | Extends AIMessageContent union/type surface with video and videoUrl. |
| src/components/AI/AIMessage.tsx | Adds rendering support for video blocks using a native <video> element. |
| src/components/AI/AIMessage.stories.tsx | Adds a WithVideoBlock story that asynchronously generates and displays a sample recording. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…st sample video - AIMessage.tsx: pass content.text as the <video> aria-label. - types.ts: note text/mimeType also apply to video blocks. - sampleVideo.ts: detect a supported recorder mimeType (fallback to browser default) and build the Blob from recorder.mimeType. - AIMessage.stories.tsx: handle getSampleVideo() rejection with an error message.
I retriggered the PR checks by pushing a no-op commit ( |
garrity-miepub
left a comment
There was a problem hiding this comment.
Looks good! Nice addition to the chat!
Summary
Adds a
videocontent block toAIMessageso chat bubbles can render an inline native<video>player. This mirrors the already-mergedaudiocontent block (#285) and the existing image/file content-block pattern.Changes
types.ts— add'video'to theAIMessageContent.typeunion and an optionalvideoUrlfield.AIMessage.tsx— render a native<video controls preload="metadata">when a content block of typevideocarries avideoUrl. Guards againstjavascript:URLs (mirroring the audio/image/file blocks) and includes a captions<track>for a11y.AIMessage.stories.tsx+AudioPlayer/sampleVideo.ts— add aWithVideoBlockstory that generates a short synthetic WebM locally via canvas +MediaRecorder(no network / CORS), mirroringsampleAudio.ts.Motivation
Consuming apps (e.g. Ozwell) capture screen recordings during dictation and want users to play back the original recording inline next to its transcription. Since Ozwell renders the conversation through
AIChat/AIMessage(whichswitches oncontent.typeand returnsnullfor anything it doesn't recognize), the library needs to understand avideoblock — exactly as it now does foraudio(#285).Notes
AudioPlayer; video uses a native<video>element sinceAudioPlayeris audio-only.