Compare commits
7 commits
0233a6a4a4
...
3a2b5a2f57
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a2b5a2f57 | ||
|
|
84744cd4a3 | ||
|
|
0b3d2e3dbc | ||
|
|
8d6f943375 | ||
|
|
af4d6200c6 | ||
|
|
5c77e4817d | ||
|
|
2373b81db7 |
11 changed files with 156 additions and 41 deletions
BIN
assets/video/BACKGROUND_VIDEO_MISSION_REVERSE_opt.mp4
Normal file
BIN
assets/video/BACKGROUND_VIDEO_MISSION_REVERSE_opt.mp4
Normal file
Binary file not shown.
BIN
assets/video/BACKGROUND_VIDEO_MISSION_opt.mp4
Normal file
BIN
assets/video/BACKGROUND_VIDEO_MISSION_opt.mp4
Normal file
Binary file not shown.
BIN
assets/video/Website_version_opt.mp4
Normal file
BIN
assets/video/Website_version_opt.mp4
Normal file
Binary file not shown.
BIN
assets/video/mobile_version_opt.mp4
Normal file
BIN
assets/video/mobile_version_opt.mp4
Normal file
Binary file not shown.
48
docs/ffmpeg.md
Normal file
48
docs/ffmpeg.md
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
# 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
|
||||||
|
|
@ -53,3 +53,37 @@ tabs:
|
||||||
- heading
|
- heading
|
||||||
headings:
|
headings:
|
||||||
- 3
|
- 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
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,8 @@ tabs:
|
||||||
type: fields
|
type: fields
|
||||||
fields:
|
fields:
|
||||||
backgroundVideo:
|
backgroundVideo:
|
||||||
label: Vidéo d'arrière-plan
|
label: Vidéo d'arrière-plan (desktop)
|
||||||
type: files
|
type: files
|
||||||
layout: cards
|
|
||||||
max: 1
|
max: 1
|
||||||
accept: video/*
|
accept: video/*
|
||||||
translate: false
|
translate: false
|
||||||
|
|
@ -52,3 +51,36 @@ tabs:
|
||||||
cover: true
|
cover: true
|
||||||
uploads:
|
uploads:
|
||||||
template: video
|
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
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$specificData = [
|
$specificData = [
|
||||||
'pageTitle' => $page->writer()->value(),
|
'pageTitle' => $page->writer()->value(),
|
||||||
'items' => $page->body()->toBlocks()->filter(fn($b) => $b->type() === 'text')->map(fn($block) => [
|
'backgroundVideo' => $page->backgroundVideo()->toFile()?->url(),
|
||||||
|
'backgroundVideoReverse' => $page->backgroundVideoReverse()->toFile()?->url(),
|
||||||
|
'items' => $page->body()->toBlocks()->filter(fn($b) => $b->type() === 'text')->map(fn($block) => [
|
||||||
'text' => $block->text()->value()
|
'text' => $block->text()->value()
|
||||||
])->values()
|
])->values()
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@ $specificData = [
|
||||||
'ctaPath' => $page->ctaLink()->toPage()?->id() ?? '#',
|
'ctaPath' => $page->ctaLink()->toPage()?->id() ?? '#',
|
||||||
'image' => $page->heroImage()->toFile()?->url()
|
'image' => $page->heroImage()->toFile()?->url()
|
||||||
],
|
],
|
||||||
'backgroundVideo' => $page->backgroundVideo()->toFile()?->url(),
|
'backgroundVideo' => $page->backgroundVideo()->toFile()?->url(),
|
||||||
|
'backgroundVideoPoster' => $page->backgroundVideoPoster()->toFile()?->url(),
|
||||||
|
'backgroundVideoMobile' => $page->backgroundVideoMobile()->toFile()?->url(),
|
||||||
|
'backgroundVideoMobilePoster' => $page->backgroundVideoMobilePoster()->toFile()?->url(),
|
||||||
'floatingBubbles' => $page->floatingBubbles()->toStructure()->map(function($bubble) {
|
'floatingBubbles' => $page->floatingBubbles()->toStructure()->map(function($bubble) {
|
||||||
return [
|
return [
|
||||||
'text' => $bubble->text()->value(),
|
'text' => $bubble->text()->value(),
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@
|
||||||
playsinline
|
playsinline
|
||||||
preload="auto"
|
preload="auto"
|
||||||
>
|
>
|
||||||
<source src="/assets/video/BACKGROUND_VIDEO_MISSION.mp4" type="video/mp4" />
|
<source src={data.backgroundVideo ?? '/assets/video/BACKGROUND_VIDEO_MISSION.mp4'} type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
<video
|
<video
|
||||||
bind:this={videoRev}
|
bind:this={videoRev}
|
||||||
|
|
@ -241,7 +241,7 @@
|
||||||
playsinline
|
playsinline
|
||||||
preload="auto"
|
preload="auto"
|
||||||
>
|
>
|
||||||
<source src="/assets/video/BACKGROUND_VIDEO_MISSION_REVERSE.mp4" type="video/mp4" />
|
<source src={data.backgroundVideoReverse ?? '/assets/video/BACKGROUND_VIDEO_MISSION_REVERSE.mp4'} type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,36 +7,34 @@
|
||||||
|
|
||||||
const currentLang = $derived(locale.current)
|
const currentLang = $derived(locale.current)
|
||||||
|
|
||||||
onMount(() => {
|
function playWhenReady(video) {
|
||||||
const playVideo = async (videoId) => {
|
if (!video) return
|
||||||
const video = document.getElementById(videoId)
|
|
||||||
if (video) {
|
const attempt = () => {
|
||||||
try {
|
video.muted = true
|
||||||
video.muted = true
|
video.playsInline = true
|
||||||
video.playsInline = true
|
video.play().catch(() => {
|
||||||
const playPromise = video.play()
|
// Autoplay bloqué : on attend une interaction
|
||||||
if (playPromise !== undefined) {
|
const onInteraction = () => {
|
||||||
await playPromise
|
video.play().catch(() => {})
|
||||||
}
|
document.removeEventListener('click', onInteraction)
|
||||||
} catch (error) {
|
document.removeEventListener('touchstart', onInteraction)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
document.addEventListener('click', onInteraction)
|
||||||
|
document.addEventListener('touchstart', onInteraction)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const timer = setTimeout(() => {
|
if (video.readyState >= 3) {
|
||||||
playVideo('home-video')
|
attempt()
|
||||||
playVideo('home-video-mobile')
|
} else {
|
||||||
}, 100)
|
video.addEventListener('canplay', attempt, { once: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return () => clearTimeout(timer)
|
onMount(() => {
|
||||||
|
playWhenReady(document.getElementById('home-video'))
|
||||||
|
playWhenReady(document.getElementById('home-video-mobile'))
|
||||||
})
|
})
|
||||||
|
|
||||||
function handleExplore() {
|
function handleExplore() {
|
||||||
|
|
@ -49,27 +47,25 @@
|
||||||
<figure class="home-figure">
|
<figure class="home-figure">
|
||||||
<video
|
<video
|
||||||
muted
|
muted
|
||||||
autoplay
|
|
||||||
playsinline
|
playsinline
|
||||||
loop
|
loop
|
||||||
controls={false}
|
preload="auto"
|
||||||
preload="metadata"
|
|
||||||
id="home-video"
|
id="home-video"
|
||||||
class="home-video home-video-desktop"
|
class="home-video home-video-desktop"
|
||||||
|
poster={data.backgroundVideoPoster ?? undefined}
|
||||||
>
|
>
|
||||||
<source src="/assets/video/Website_version.mp4" type="video/mp4" />
|
<source src={data.backgroundVideo ?? '/assets/video/Website_version.mp4'} type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
<video
|
<video
|
||||||
muted
|
muted
|
||||||
autoplay
|
|
||||||
playsinline
|
playsinline
|
||||||
loop
|
loop
|
||||||
controls={false}
|
preload="auto"
|
||||||
preload="metadata"
|
|
||||||
id="home-video-mobile"
|
id="home-video-mobile"
|
||||||
class="home-video home-video-mobile"
|
class="home-video home-video-mobile"
|
||||||
|
poster={data.backgroundVideoMobilePoster ?? undefined}
|
||||||
>
|
>
|
||||||
<source src="/assets/video/mobile_version_texte_fixe.mp4" type="video/mp4" />
|
<source src={data.backgroundVideoMobile ?? '/assets/video/mobile_version_texte_fixe.mp4'} type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue