-
Notifications
You must be signed in to change notification settings - Fork 30
Add looping videos to articles #14843
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Hello 👋! When you're ready to run Chromatic, please apply the You will need to reapply the label each time you want to run Chromatic. |
|
(AI suggestions sent me down the wrong path) |
|
This appears to be a CORS issue rather than a code issue. When developing locally we test on The white space appears when the poster image fails to upload for some reason? This is an intermittent issue (because: see screen shot above which loaded the poster image fine 2 mins after failing and 2 mins before failing again):
I noticed this comment in the last PR to touch the LoopVideoPlayer file: |
|
Can confirm that the video src/url strings are correct (pasting the url into the browser address bar loads the video) |
|
Viewing the article locally, using http://r.thegulocal.com:3030/Article/https://www.theguardian.com/media/2025/oct/08/conservative-late-night-talkshow URL. doesn't solve the issue: |
|
tl;dr: Looping videos now need to be served with a Chat messages: AnnaB, MarjanK Anna: We introduced (and rolled back) a crossOrigin="anonymous" header to looping videos so that we can retrieve the subtitle vtt file from uploads.guim. This change meant that both the video and the subtitle files are now requested as cross-origin CORS fetches, requiring fastly to include Access-Control-Allow-Origin headers. Unsuprisingly, uploads.guim already has https://www.theguardian.com as an allowed origin but some users were getting the following error Does anyone have any ideas as to why some users would be hitting this error? I'm wondering if some users could be getting a cached mp4 response that does not have the headers attached because we did not ask for them before this change was rolled out and if we therefore need to purge the cache for some videos. Does that sound plausible? Are we able to purge certain items in the uploads.guim cache? The fastly VCL is available here if anyone is interested in looking through it https://manage.fastly.com/configure/services/2TmfkSoyUoNo8aFNe6Htjs/versions/29/vcl/snippets/CORS%20headers Marjan [...etc] |
| "elementId", | ||
| "id" | ||
| ] | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to introduce LoopVideoInArticleElement? I think we should just be able to extend the existing MediaAtomBlockElement with the new attribute. Same story in renderElement.tsx, block-schema.json, content.ts.
Let me know if I've missed something!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I honestly don't know. I don't understand the purpose of these json files, though I expect they may be something to do with testing?
I defined it in renderElement.tsx because loop videos have a radically different structure to legacy self-hosted videos and components that display on a page all seem to get defined here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed (alongside the same change in a different json file)
| interface VideoAssets { | ||
| url: string; | ||
| export interface VideoAssets { | ||
| url?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is url optional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My fault - will attempt removal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
| subtitleSize?: string; | ||
| subtitleSource?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These attributes (subtitleSize and subtitleSource) don't exist on the element so will always be missing.
subtitleSize can probably be hardcoded in renderElement.tsx?
subtitleSource will require some thought. Might need to add it to the frontend PR..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See this comment about computing subtitleSource.
I believe subtitleSize and subtitleSource can safely be removed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
| const convertSubtitleSize = (val?: string): SubtitleSize => { | ||
| if (val == null) { | ||
| return 'small' as SubtitleSize; | ||
| } | ||
| if (['small', 'medium', 'large'].includes(val)) { | ||
| return val as SubtitleSize; | ||
| } | ||
| return 'small' as SubtitleSize; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully this isn't needed, we can just hardcode to an appropriate size (medium?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really hope so too. But newer loop videos with subtitles includes this data. I introduced this horrid little function to kill off a bunch of TypeScript errors. There must be a better solution!
| const [hasBeenPlayed, setHasBeenPlayed] = useState(false); | ||
| const [hasTrackedPlay, setHasTrackedPlay] = useState(false); | ||
|
|
||
| const [devicePixelRatio, setDevicePixelRatio] = useState(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Introducing state feels a bit unnecessary here, what was your thinking?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bug in the new LoopVideo player. The bug tries to access the browser window environment for the DPR value before the element has been mounted. So I decided to move the value to state and do the window check in a useUpdate hook. Thus once we get the correct DPR the component will rectify itself.
| <LoopVideoInArticle | ||
| assets={element.assets} | ||
| atomId={element.id} | ||
| uniqueId={`${Math.random()}`} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we could we use element.id or element.elementId here instead of using a random number?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. Will update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| height={400} | ||
| width={500} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do these numbers come from somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Magic numbers: currently represents the 5:4 aspect ratio used by loop videos. Could double to 1000/800 maybe for people using very wide displays? I think CSS overrides this in any case - need to check.
| caption={element.title} | ||
| isMainMedia={isMainMedia} | ||
| subtitleSize={element.subtitleSize} | ||
| subtitleSource={element.subtitleSource} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to grab the relevant asset with something like this:
const getSubtitleAsset = (assets: VideoAssets[]) => {
// Get the first subtitle asset from assets with a mimetype of 'text/vtt'
return assets.find((asset) => asset.mimeType === 'text/vtt');
}
Then:
| subtitleSource={element.subtitleSource} | |
| subtitleSource={getSubtitleAsset(assets)?.url} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!




What does this change?
TODO: write up!
Why?
Screenshots