Compare commits

..

No commits in common. "3a2b5a2f576ee9d8dfa1ad0de89616935bbb829d" and "0233a6a4a4de2069559808924c8d9b242825b370" have entirely different histories.

11 changed files with 44 additions and 159 deletions

Binary file not shown.

Binary file not shown.

View file

@ -1,48 +0,0 @@
# Commandes FFmpeg
## Qu'est-ce que FFmpeg ?
FFmpeg est un outil en ligne de commande open source pour traiter des fichiers audio et vidéo : conversion de formats, compression, extraction de frames, redimensionnement, etc. C'est la référence dans le domaine, utilisée par VLC, YouTube et la plupart des plateformes vidéo en coulisses.
### Installation
**macOS** (via Homebrew) :
```bash
brew install ffmpeg
```
**Linux (Debian/Ubuntu)** :
```bash
sudo apt install ffmpeg
```
**Windows** : télécharger le build depuis [ffmpeg.org/download.html](https://ffmpeg.org/download.html) et ajouter le dossier `bin/` au PATH.
Vérifier l'installation :
```bash
ffmpeg -version
```
---
## Compression vidéo (page d'accueil)
Compresse sans perte de résolution ni de framerate. CRF 23 = qualité par défaut libx264. `faststart` place l'atome `moov` en tête du fichier pour un démarrage immédiat en streaming.
```bash
# Desktop (1920x1080, 30fps) — 22MB → 5.8MB
ffmpeg -i Website_version.mp4 \
-c:v libx264 -preset slow -crf 23 -an -movflags +faststart \
Website_version_opt.mp4
# Mobile (1080x1920, 30fps) — 22MB → 4.8MB
ffmpeg -i mobile_version_texte_fixe.mp4 \
-c:v libx264 -preset slow -crf 23 -an -movflags +faststart \
mobile_version_opt.mp4
```
## Notes
- `-an` : supprime la piste audio (inutile pour des vidéos `muted` en fond)
- `-preset slow` : meilleure compression à qualité égale (encode plus lentement)
- `crf` : Constant Rate Factor — plus bas = meilleure qualité. 23 = défaut libx264, 18 = quasi-lossless

View file

@ -53,37 +53,3 @@ tabs:
- heading
headings:
- 3
media:
label: Médias
icon: image
columns:
- width: 1/2
sections:
mediaFields:
type: fields
fields:
backgroundVideo:
label: Vidéo d'arrière-plan (sens normal)
type: files
layout: cards
max: 1
accept: video/*
translate: false
image:
ratio: 16/9
cover: true
uploads:
template: video
backgroundVideoReverse:
label: Vidéo d'arrière-plan (sens inverse)
type: files
layout: cards
max: 1
accept: video/*
translate: false
image:
ratio: 16/9
cover: true
uploads:
template: video

View file

@ -41,8 +41,9 @@ tabs:
type: fields
fields:
backgroundVideo:
label: Vidéo d'arrière-plan (desktop)
label: Vidéo d'arrière-plan
type: files
layout: cards
max: 1
accept: video/*
translate: false
@ -51,36 +52,3 @@ tabs:
cover: true
uploads:
template: video
backgroundVideoPoster:
label: Poster vidéo desktop
type: files
layout: cards
max: 1
accept: image/*
translate: false
image:
ratio: 16/9
cover: true
help: Image affichée au besoin pendant le chargement de la vidéo
backgroundVideoMobile:
label: Vidéo d'arrière-plan (mobile)
type: files
max: 1
accept: video/*
translate: false
image:
ratio: 9/16
cover: true
uploads:
template: video
backgroundVideoMobilePoster:
label: Poster vidéo mobile
type: files
layout: cards
max: 1
accept: image/*
translate: false
image:
ratio: 9/16
cover: true
help: Image affichée au besoin pendant le chargement de la vidéo

View file

@ -1,10 +1,8 @@
<?php
$specificData = [
'pageTitle' => $page->writer()->value(),
'backgroundVideo' => $page->backgroundVideo()->toFile()?->url(),
'backgroundVideoReverse' => $page->backgroundVideoReverse()->toFile()?->url(),
'items' => $page->body()->toBlocks()->filter(fn($b) => $b->type() === 'text')->map(fn($block) => [
'pageTitle' => $page->writer()->value(),
'items' => $page->body()->toBlocks()->filter(fn($b) => $b->type() === 'text')->map(fn($block) => [
'text' => $block->text()->value()
])->values()
];

View file

@ -9,10 +9,7 @@ $specificData = [
'ctaPath' => $page->ctaLink()->toPage()?->id() ?? '#',
'image' => $page->heroImage()->toFile()?->url()
],
'backgroundVideo' => $page->backgroundVideo()->toFile()?->url(),
'backgroundVideoPoster' => $page->backgroundVideoPoster()->toFile()?->url(),
'backgroundVideoMobile' => $page->backgroundVideoMobile()->toFile()?->url(),
'backgroundVideoMobilePoster' => $page->backgroundVideoMobilePoster()->toFile()?->url(),
'backgroundVideo' => $page->backgroundVideo()->toFile()?->url(),
'floatingBubbles' => $page->floatingBubbles()->toStructure()->map(function($bubble) {
return [
'text' => $bubble->text()->value(),

View file

@ -232,7 +232,7 @@
playsinline
preload="auto"
>
<source src={data.backgroundVideo ?? '/assets/video/BACKGROUND_VIDEO_MISSION.mp4'} type="video/mp4" />
<source src="/assets/video/BACKGROUND_VIDEO_MISSION.mp4" type="video/mp4" />
</video>
<video
bind:this={videoRev}
@ -241,7 +241,7 @@
playsinline
preload="auto"
>
<source src={data.backgroundVideoReverse ?? '/assets/video/BACKGROUND_VIDEO_MISSION_REVERSE.mp4'} type="video/mp4" />
<source src="/assets/video/BACKGROUND_VIDEO_MISSION_REVERSE.mp4" type="video/mp4" />
</video>
</div>

View file

@ -7,34 +7,36 @@
const currentLang = $derived(locale.current)
function playWhenReady(video) {
if (!video) return
const attempt = () => {
video.muted = true
video.playsInline = true
video.play().catch(() => {
// Autoplay bloqué : on attend une interaction
const onInteraction = () => {
video.play().catch(() => {})
document.removeEventListener('click', onInteraction)
document.removeEventListener('touchstart', onInteraction)
}
document.addEventListener('click', onInteraction)
document.addEventListener('touchstart', onInteraction)
})
}
if (video.readyState >= 3) {
attempt()
} else {
video.addEventListener('canplay', attempt, { once: true })
}
}
onMount(() => {
playWhenReady(document.getElementById('home-video'))
playWhenReady(document.getElementById('home-video-mobile'))
const playVideo = async (videoId) => {
const video = document.getElementById(videoId)
if (video) {
try {
video.muted = true
video.playsInline = true
const playPromise = video.play()
if (playPromise !== undefined) {
await playPromise
}
} catch (error) {
console.log(`Autoplay failed for ${videoId}:`, error)
const playOnInteraction = () => {
video.play().catch(e => console.log('Fallback play failed:', e))
document.removeEventListener('click', playOnInteraction)
document.removeEventListener('touchstart', playOnInteraction)
}
document.addEventListener('click', playOnInteraction)
document.addEventListener('touchstart', playOnInteraction)
}
}
}
const timer = setTimeout(() => {
playVideo('home-video')
playVideo('home-video-mobile')
}, 100)
return () => clearTimeout(timer)
})
function handleExplore() {
@ -47,25 +49,27 @@
<figure class="home-figure">
<video
muted
autoplay
playsinline
loop
preload="auto"
controls={false}
preload="metadata"
id="home-video"
class="home-video home-video-desktop"
poster={data.backgroundVideoPoster ?? undefined}
>
<source src={data.backgroundVideo ?? '/assets/video/Website_version.mp4'} type="video/mp4" />
<source src="/assets/video/Website_version.mp4" type="video/mp4" />
</video>
<video
muted
autoplay
playsinline
loop
preload="auto"
controls={false}
preload="metadata"
id="home-video-mobile"
class="home-video home-video-mobile"
poster={data.backgroundVideoMobilePoster ?? undefined}
>
<source src={data.backgroundVideoMobile ?? '/assets/video/mobile_version_texte_fixe.mp4'} type="video/mp4" />
<source src="/assets/video/mobile_version_texte_fixe.mp4" type="video/mp4" />
</video>
</figure>
</div>