From dba50bb51d59527ff66e13b47e9c6a1cbca1261f Mon Sep 17 00:00:00 2001 From: Palawi Date: Wed, 28 Oct 2026 14:43:22 +0100 Subject: [PATCH 1/3] test(scripts): prepare the manual session and the readme quality shot --- scripts/cdp-run.ps1 | 1 + scripts/manual-session.ps1 | 47 ++++++++++++++++++++++++++++++++++ scripts/readme-screenshots.mjs | 4 +++ 3 files changed, 52 insertions(+) create mode 100644 scripts/manual-session.ps1 diff --git a/scripts/cdp-run.ps1 b/scripts/cdp-run.ps1 index cdfa9cf..437ee5d 100644 --- a/scripts/cdp-run.ps1 +++ b/scripts/cdp-run.ps1 @@ -3,6 +3,7 @@ $ErrorActionPreference = "Stop" $root = Split-Path -Parent $PSScriptRoot $out = Join-Path $root ("target\journals\" + [IO.Path]::GetFileNameWithoutExtension($Script)) Remove-Item $out -Recurse -Force -ErrorAction SilentlyContinue +New-Item -ItemType Directory -Force $out | Out-Null try { $env:WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS = "--remote-debugging-port=$Port" $launch = @{ Settings = $Settings; MainScreen = $true; Clips = $Clips; Copy = $Copy; Link = $Link; ClipsDir = $ClipsDir } diff --git a/scripts/manual-session.ps1 b/scripts/manual-session.ps1 new file mode 100644 index 0000000..8602769 --- /dev/null +++ b/scripts/manual-session.ps1 @@ -0,0 +1,47 @@ +param([string]$Root = "F:\PalaClips-tests\manual", [string]$LongClip = "F:\PalaClips-tests\scrub\Test\Test_2026-10-27_12-00-00_replay.mp4", [switch]$Stop) +$ErrorActionPreference = "Stop" +$repo = Split-Path -Parent $PSScriptRoot +$ffmpeg = Join-Path $repo "third_party\ffmpeg\bin\ffmpeg.exe" + +if ($Stop) { + Get-Process palaclips-app -ErrorAction SilentlyContinue | Where-Object { $_.Path -like "$repo\target\*" } | Stop-Process -Force -ErrorAction SilentlyContinue + Start-Sleep -Seconds 2 + Remove-Item Env:PALACLIPS_CONFIG_DIR, Env:PALACLIPS_TEST_WINDOW -ErrorAction SilentlyContinue + Remove-Item (Join-Path $repo "target\test-config") -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item $Root -Recurse -Force -ErrorAction SilentlyContinue + "app de test fermée, $Root et target\test-config supprimés" + return +} + +Remove-Item $Root -Recurse -Force -ErrorAction SilentlyContinue +$games = @("Fortnite", "Valorant", "Rocket League") +for ($index = 0; $index -lt 14; $index++) { + $game = $games[$index % 3] + $stamp = (Get-Date).AddMinutes(-10 * ($index + 1)) + $dir = Join-Path $Root $game + New-Item -ItemType Directory -Force $dir | Out-Null + $file = Join-Path $dir "$($game)_$($stamp.ToString('yyyy-MM-dd_HH-mm-ss'))_replay.mp4" + & $ffmpeg -hide_banner -loglevel error -y -f lavfi -i "testsrc2=size=640x360:rate=60:duration=12" ` + -f lavfi -i "sine=frequency=220:duration=12" -f lavfi -i "sine=frequency=330:duration=12" -f lavfi -i "sine=frequency=495:duration=12" ` + -map 0 -map 1 -map 2 -map 3 -c:v h264_nvenc -bf 0 -b:v 1M -g 60 -c:a aac -b:a 96k ` + -metadata:s:a:0 title="Mix complet" -metadata:s:a:0 handler_name="Mix complet" -metadata:s:a:1 title="Micro" ` + -metadata:s:a:1 handler_name="Micro" -metadata:s:a:2 title="Discord" -metadata:s:a:2 handler_name="Discord" $file + (Get-Item $file).LastWriteTime = $stamp +} +$many = Join-Path $Root "Pistes" +New-Item -ItemType Directory -Force $many | Out-Null +$titles = @("Mix complet", "Micro", "Jeu", "Discord", "Spotify", "Firefox", "OBS", "VLC") +$inputs = @("-f", "lavfi", "-i", "testsrc2=size=1280x720:rate=60:duration=40") +$maps = @("-map", "0") +for ($track = 0; $track -lt $titles.Count; $track++) { + $inputs += @("-f", "lavfi", "-i", "sine=frequency=$(200 + 60 * $track):beep_factor=$($track + 1):duration=40") + $maps += @("-map", "$($track + 1)", "-metadata:s:a:$track", "title=$($titles[$track])", "-metadata:s:a:$track", "handler_name=$($titles[$track])") +} +& $ffmpeg -hide_banner -loglevel error -y @inputs @maps -c:v h264_nvenc -bf 0 -b:v 3M -g 60 -c:a aac -b:a 96k (Join-Path $many "Pistes_$((Get-Date).AddMinutes(-1).ToString('yyyy-MM-dd_HH-mm-ss'))_replay.mp4") +$long = Join-Path $Root "Test" +New-Item -ItemType Directory -Force $long | Out-Null +New-Item -ItemType HardLink -Path (Join-Path $long (Split-Path $LongClip -Leaf)) -Target $LongClip | Out-Null + +$settings = '{ "onboarded": true, "engine": { "capture": { "kind": "primary_monitor" }, "replay": { "arm_on_startup": true, "duration_secs": 30, "after_secs": 10 } } }' +& (Join-Path $PSScriptRoot "app-isolated.ps1") -MainScreen -ClipsDir $Root -Settings $settings | Out-Null +"app de test ouverte, clips dans $Root" diff --git a/scripts/readme-screenshots.mjs b/scripts/readme-screenshots.mjs index f852b27..94cd132 100644 --- a/scripts/readme-screenshots.mjs +++ b/scripts/readme-screenshots.mjs @@ -59,6 +59,10 @@ if (mode === "onboarding") { await waitFor("document.querySelectorAll('.choice-card').length === 4", "question de la durée"); await sleep(2500); await shot("first-launch"); +} else if (mode === "quality") { + await click(LABELS.settings, "nav button"); + await sleep(2500); + await shot("replay-quality"); } else { await click(LABELS.gallery); await waitFor("document.querySelectorAll('[data-clip]').length > 0", "galerie"); From f0e6d7ab8c51fa49e8d6c7ff0b4e44d960f8b6e5 Mon Sep 17 00:00:00 2001 From: Palawi Date: Wed, 28 Oct 2026 14:43:22 +0100 Subject: [PATCH 2/3] docs(docs): report v1.4 and refresh the readme --- README.fr.md | 6 +- README.md | 7 ++- docs/HANDOFF.md | 37 +++++++++++- docs/PLAN.md | 21 +++++++ docs/reports/v1.4.md | 75 +++++++++++++++++++++++++ docs/screenshots/en/replay-quality.png | Bin 60506 -> 59291 bytes docs/screenshots/fr/replay-quality.png | Bin 63087 -> 61520 bytes 7 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 docs/reports/v1.4.md diff --git a/README.fr.md b/README.fr.md index cc98deb..2b19bbd 100644 --- a/README.fr.md +++ b/README.fr.md @@ -62,7 +62,9 @@ fonctionne avec les anti-triches comme Easy Anti-Cheat. - **Capture d'un écran ou d'une fenêtre** par Windows Graphics Capture ; une fenêtre est retrouvée par le nom de son programme après un redémarrage. - **Galerie de clips** avec un lecteur multipiste : écoute piste par piste (muet, solo, - volume), découpe, export, copie du fichier pour le coller dans Discord. + volume, retenus par clip ; Mix complet coupé à l'ouverture pour ne rien entendre en double), + déplacement fluide même sur un long clip HEVC, découpe, export, copie du fichier pour le + coller dans Discord. - **Compression à une taille cible** : 20 Mo pour Discord, 50 ou 500 Mo pour Nitro, ou une taille libre ; résolution et images par seconde choisies selon la taille, taille finale vérifiée. Depuis la galerie (un ou plusieurs clips), le lecteur ou par glisser-déposer depuis @@ -86,7 +88,7 @@ fonctionne avec les anti-triches comme Easy Anti-Cheat. | Replay & qualité | |---| -| ![Replay & qualité : taille d'un clip et Mo par minute, puis les réglages du replay, de l'enregistrement et communs](docs/screenshots/fr/replay-quality.png) | +| ![Replay & qualité en trois onglets (replay, enregistrement, commun), chacun avec son estimation de taille](docs/screenshots/fr/replay-quality.png) | ## Configuration requise diff --git a/README.md b/README.md index 2a0781e..9b59b7c 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,9 @@ Anti-Cheat. Without a hardware encoder, **encoding on the processor** in H.264 or AV1. - **Screen or window capture** through Windows Graphics Capture; a window is found again by its program name after a restart. -- **Clip gallery** with a multitrack player: listen track by track (mute, solo, volume), trim, - export, or copy the file to paste it into Discord. +- **Clip gallery** with a multitrack player: listen track by track (mute, solo, volume, + remembered per clip; Full mix muted on opening so nothing plays twice), smooth scrubbing even + on long HEVC clips, trim, export, or copy the file to paste it into Discord. - **Compress to a target size**: 20 MB for Discord, 50 or 500 MB for Nitro, or any size; resolution and frame rate follow the size, and the final size is checked. From the gallery (one or several clips), the player, or by dragging files from File Explorer. @@ -84,7 +85,7 @@ Anti-Cheat. | Replay & quality | |---| -| ![Replay & quality: clip size and MB per minute, then the replay, recording and shared settings](docs/screenshots/en/replay-quality.png) | +| ![Replay & quality in three tabs (replay, recording, shared), each with its size estimate](docs/screenshots/en/replay-quality.png) | ## Requirements diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 733d986..d3e0d3d 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -59,7 +59,15 @@ l'accord de Palawi. Brouillon relu connecté (version, signature = `.sig`, liens publics) ; vérifié sans connexion après publication : `latest.json` 1.3.1, installeur, `.sig`, page et CHANGELOG en 200. Branche : `dev`. -- **Dernière mise à jour :** 2026-10-26 +- **v1.4.0 en préparation (2026-10-27/28)** : six retours de Palawi, une PR chacun : défilement + d'État et 12 clips (#125), cellule Source = vraie source (#126, `SourceMode`, `source_changed`), + glisser fluide dans le lecteur (#124, `ScrubSession`), son « clip terminé » (#127, + `clip_saved.origin`), Replay & qualité en onglets (#128), Mix complet coupé à la lecture et + état par clip (#129, `player.mute_full_mix`, colonne `mix`). Décisions et mesures : + `docs/reports/v1.4.md`. Session manuelle de Palawi validée le 2026-10-28. Préparation de la + version : branche `chore/release-v1.4.0`. Reste : PR `dev` → `main`, tag et brouillon **avec + l'accord de Palawi**, puis publication avec son accord. +- **Dernière mise à jour :** 2026-10-28 ## Ce qui existe @@ -299,6 +307,23 @@ `size-estimate.ps1`, `many-tracks.ps1 [-Keep]`, `app-isolated.ps1 -RightScreen`. Preuves : `docs/reports/v1.3/`. +- **v1.4 (2026-10-27/28)** : + - Moteur : `events::SourceMode` (`capture_started.source_mode`, `source_changed` relevé chaque + seconde dans le fil d'encodage, `capture::display::refresh_hz`) ; `events::SaveOrigin` + (`clip_saved.origin` : `replay`, `post_roll`, `recording`) ; `chime::Sound::ClipFinished` ; + `Library::mix` / `set_mix` (colonne `mix`, ajoutée aux bases existantes). + - Shell : `player.mute_full_mix` dans `settings.json` (`get_player` / `set_player`), + `clip_mix` / `set_clip_mix` (`ClipMix { tracks, full_mix_chosen }`, volume borné) ; son joué + selon `origin` (rien pour un enregistrement, qui a son propre son de fin). + - Front : `lib/scrubSession.ts` (glisser : dessin immédiat, chargement après 120 ms ou au + relâchement, dernière position gagnante, audio tenu par `PlayerAudio.hold/release`) ; + `lib/qualityTabs.ts` (onglets, onglet retenu, `Destination.tab`) ; `lib/playerMix.ts` + (coupure du Mix complet seulement avec une piste Jeu ou appli, export sur l'état choisi). + - Scripts : `cdp-run.ps1` (app isolée + script CDP, sortie dans `target/journals/