Merge pull request #644 from j14i/j14i/video-refactoring

Re-encode video files for less gpu usage
This commit is contained in:
mr. m 2025-06-01 14:55:14 +02:00 committed by GitHub
commit 199d83f25c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 49 additions and 52 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Binary file not shown.

View file

@ -1,14 +1,9 @@
--- ---
import { motion } from 'motion/react' import { motion } from 'motion/react'
import { getTitleAnimation } from '~/animations' import { getTitleAnimation } from '~/animations'
import Description from '~/components/Description.astro'
import CompactModeVideo from '~/assets/CompactMode.webm'
import GlanceVideo from '~/assets/Glance.webm'
import SplitViewsVideo from '~/assets/SplitViews.webm'
import WorkspacesVideo from '~/assets/Workspaces.webm'
import { getLocale, getUI } from '~/utils/i18n' import { getLocale, getUI } from '~/utils/i18n'
import Description from './Description.astro'
import Video from './Video.astro' import Video from './Video.astro'
const locale = getLocale(Astro) const locale = getLocale(Astro)
@ -130,8 +125,7 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
playsinline playsinline
preload="none" preload="none"
class="feature-video" class="feature-video"
src={WorkspacesVideo} name="workspaces"
data-active="true"
/> />
<Video <Video
autoplay autoplay
@ -140,7 +134,7 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
playsinline playsinline
preload="none" preload="none"
class="feature-video" class="feature-video"
src={CompactModeVideo} name="compact-mode"
/> />
<Video <Video
autoplay autoplay
@ -149,7 +143,7 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
playsinline playsinline
preload="none" preload="none"
class="feature-video" class="feature-video"
src={GlanceVideo} name="glance"
/> />
<Video <Video
autoplay autoplay
@ -158,7 +152,7 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
playsinline playsinline
preload="none" preload="none"
class="feature-video" class="feature-video"
src={SplitViewsVideo} name="split-views"
/> />
</div> </div>
</div> </div>
@ -176,30 +170,45 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
descriptionEl.textContent = descriptions[0] descriptionEl.textContent = descriptions[0]
} }
function changeToFeature({ target }: { target: HTMLElement | undefined | null }) { function changeToFeature({ target }: MouseEvent | { target: HTMLElement }) {
target = target?.closest('.feature, .feature-tab') let targetEl: HTMLElement | null = target as HTMLElement
if (!target) return
const index = Array.from(features).indexOf(target) % 4 if (target instanceof HTMLElement) {
if (index === -1) return targetEl = target.closest('.feature, .feature-tab')
}
if (!targetEl) {
return
}
const index = Array.from(features).indexOf(targetEl) % 4
if (index === -1) {
return
}
// Update both mobile and desktop elements // Update both mobile and desktop elements
features.forEach((f, i) => { for (let i = 0; i < features.length; i += 1) {
const f = features[i]
if (i % 4 === index) { if (i % 4 === index) {
f.setAttribute('data-active', 'true') f.setAttribute('data-active', 'true')
} else { } else {
f.removeAttribute('data-active') f.removeAttribute('data-active')
} }
}) }
// Update mobile description // Update mobile description
const descriptionEl = document.querySelector('.feature-description') const descriptionEl = document.querySelector('.feature-description')
if (descriptionEl && descriptions) { if (descriptionEl && descriptions) {
descriptionEl.textContent = descriptions[index] descriptionEl.textContent = descriptions[index]
} }
const videos = document.querySelectorAll('.feature-video') as NodeListOf<HTMLVideoElement> const videos = document.querySelectorAll<HTMLVideoElement>('.feature-video')
videos.forEach((vid, i) => {
for (let i = 0; i < videos.length; i += 1) {
const vid = videos[i]
const yOffset = (i - index) * 20 const yOffset = (i - index) * 20
const zOffset = i === index ? 0 : -100 - Math.abs(i - index) * 50 const zOffset = i === index ? 0 : -100 - Math.abs(i - index) * 50
const scale = i === index ? 1 : 0.95 const scale = i === index ? 1 : 0.95
@ -220,16 +229,14 @@ const descriptions = Object.values(features.featureTabs).map(tab => tab.descript
vid.style.zIndex = String(1 - Math.abs(i - index)) vid.style.zIndex = String(1 - Math.abs(i - index))
vid.pause() vid.pause()
} }
}) }
} }
for (const feature of features) { for (const feature of features) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any feature.addEventListener('click', changeToFeature)
feature.addEventListener('click', changeToFeature as any)
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any changeToFeature({ target: features[0] })
changeToFeature({ target: features[0] as any })
</script> </script>
<style> <style>

View file

@ -1,7 +1,6 @@
--- ---
import { motion } from 'motion/react' import { motion } from 'motion/react'
import { getTitleAnimation } from '~/animations' import { getTitleAnimation } from '~/animations'
import HomePageVideo from '~/assets/HomePageVideo.webm'
import Button from '~/components/Button.astro' import Button from '~/components/Button.astro'
import Description from '~/components/Description.astro' import Description from '~/components/Description.astro'
import Title from '~/components/Title.astro' import Title from '~/components/Title.astro'
@ -86,7 +85,7 @@ const {
{...getHeroTitleAnimation()} {...getHeroTitleAnimation()}
> >
<Video <Video
src={HomePageVideo} name="hero-video"
autoplay autoplay
loop loop
muted muted

View file

@ -1,27 +1,19 @@
--- ---
const { src, class: className, ...rest } = Astro.props type Props = {
const type = src.split('.').pop() || 'webm' name: string
class?: string
} & astroHTML.JSX.VideoHTMLAttributes
const { name, class: className, ...rest }: Props = Astro.props
--- ---
{/* eslint-disable-next-line jsx-a11y/media-has-caption */} {/* eslint-disable-next-line jsx-a11y/media-has-caption */}
<video class:list={['w-fit', className]} data-src={src} preload="none" {...rest}> <video
<source src="" type={`video/${type}`} /> class:list={['w-fit', className]}
preload="none"
poster={`/media/${name}/poster.webp`}
{...rest}
>
<source src={`/media/${name}/video.webm`} type="video/webm" />
<source src={`/media/${name}/video.mp4`} type="video/mp4" />
</video> </video>
<script>
const videos = document.querySelectorAll('video[data-src]') as NodeListOf<HTMLVideoElement>
const loadVideo = (video: HTMLVideoElement) => {
const source = video.querySelector('source')
const dataSrc = video.getAttribute('data-src')
if (dataSrc && source) {
source.src = dataSrc
video.removeAttribute('data-src')
video.load()
}
}
for (const video of videos) {
loadVideo(video)
}
</script>

View file

@ -5,7 +5,6 @@ import SocialMediaStrip from '~/components/SocialMediaStrip.astro'
import ArrowRightIcon from '~/icons/ArrowRightIcon.astro' import ArrowRightIcon from '~/icons/ArrowRightIcon.astro'
import Layout from '~/layouts/Layout.astro' import Layout from '~/layouts/Layout.astro'
import whatsNewVideo from '~/assets/whats-new.mp4'
import Video from '~/components/Video.astro' import Video from '~/components/Video.astro'
import { releaseNotes } from '~/release-notes' import { releaseNotes } from '~/release-notes'
import whatsNewText from '~/release-notes/whats-new.json' import whatsNewText from '~/release-notes/whats-new.json'
@ -71,7 +70,7 @@ if (latestVersion.version.split('.').length > 2 && whatsNewText[1] !== latestVer
</div> </div>
<Video <Video
src={whatsNewVideo} name="whats-new"
autoplay autoplay
loop loop
muted muted