fix(shorts): orientation autoritaire, langues YouTube et autoplay fiable
CI / build-and-test (push) Successful in 14m18s

- format: des que largeur/hauteur sont connues, l'orientation fait autorite (horizontale/carree => jamais short, meme <75 s). Repli duree reserve aux providers muets
- dimensions mappees: Dailymotion (width,height), PeerTube (aspectRatio), Odysee (value.video.width/height) => validation verticale reelle
- YouTube: langue via snippet.defaultAudioLanguage (filtre FR/EN)
- autoplay: demarrage muet, suppression du deblocage automatique au scroll/selection (reload d'embed hors geste => ecran noir); son via le bouton dedie
- PeerTube embed: muted=1 pour l'autoplay
- server/search-filters.mjs: miroir de la regle d'orientation + tests mis a jour
This commit is contained in:
2026-09-29 14:51:56 -04:00
parent d4895bae92
commit 37681c4f53
7 changed files with 73 additions and 50 deletions
+4 -1
View File
@@ -197,6 +197,8 @@ export function isShortItem(item, providerId) {
}
// 2) + 3) Orientation (width/height quand le provider les expose).
// Dimensions connues ⇒ l'orientation fait AUTORITÉ : une horizontale/carrée
// n'est jamais un short, même courte.
const w = numOrZero(item.width);
const h = numOrZero(item.height);
if (w > 0 && h > 0) {
@@ -205,9 +207,10 @@ export function isShortItem(item, providerId) {
if (!hasKnownDuration) return false; // règle 3 : pas de durée ⇒ pas short
return d <= VERTICAL_SHORT_MAX_SECONDS; // règle 2
}
return false;
}
// 4) Repli durée seule (comportement historique inchangé).
// 4) Repli durée seule, uniquement quand l'orientation est inconnue.
// NOTE : l'ancien code excluait les titres contenant « short »
// (`&& !/short/i.test(title)`), ce qui est l'inverse de l'intuition : un
// vrai Short titré « … #shorts » était EXCLU du filtre shorts. Les tests
+12 -6
View File
@@ -209,15 +209,21 @@ expect(
!isShortItem({ title: 'clip carré', duration: 80, width: 1080, height: 1080, type: 'video' }),
'square 80s is not a short (orientation alone is not enough)',
);
// …mais à 30 s, la règle 4 (durée seule) le garde : non-régression historique.
// Dimensions connues non verticales ⇒ JAMAIS short, même à 30 s
// (l'orientation fait autorité ; plus de repli durée quand w/h sont connus).
expect(
matchesFilters({ id: 'a', title: 'clip carré', duration: 30, width: 1080, height: 1080, type: 'video' }, { type: 'shorts' }),
'square 30s still matches shorts via duration fallback',
!matchesFilters({ id: 'a', title: 'clip carré', duration: 30, width: 1080, height: 1080, type: 'video' }, { type: 'shorts' }),
'square 30s is not a short (orientation authoritative)',
);
// Règle 4 : horizontale 50 s ⇒ short (non-régression durée seule).
// Horizontale 50 s ⇒ PAS short (dimensions connues, non verticale).
expect(
isShortItem({ title: 'paysage', duration: 50, width: 1280, height: 720, type: 'video' }),
'horizontal 50s is a short (duration fallback)',
!isShortItem({ title: 'paysage', duration: 50, width: 1280, height: 720, type: 'video' }),
'horizontal 50s is not a short (orientation authoritative)',
);
// Repli durée seule réservé aux items SANS dimensions connues.
expect(
isShortItem({ title: 'courte sans dims', duration: 50, type: 'video' }),
'50s without dimensions is a short (duration fallback)',
);
// Règle 3 : verticale SANS durée connue ⇒ PAS short.
expect(