fix : opening link 2
All checks were successful
release / build (push) Successful in 26s
release / verify-windows (push) Successful in 1m4s

This commit is contained in:
jeanotx32
2026-08-12 01:16:52 +02:00
parent a38baf9a88
commit 3bd4d5f2ba
4 changed files with 95 additions and 5 deletions

View File

@@ -246,9 +246,37 @@ Le mode de sortie du profil est forcé sur « Simple » : c'est la section que c
pilotent. Un paramètre refusé par la version d'OBS installée n'interrompt pas les autres —
il apparaît dans le compte rendu affiché sous le bouton « Appliquer maintenant ».
### Diagnostiquer une chute de performance
La fiche de l'agent sépare les deux goulots qu'OBS mesure distinctement. Les confondre mène
à régler le mauvais paramètre.
| Métrique | Ce qu'elle dit | Leviers |
| --- | --- | --- |
| **Perdu · rendu** | La scène n'a pas été composée à temps | Méthode de capture, définition de la scène, accélération 3D du bureau |
| **Perdu · encodage** | La scène était prête, l'encodeur n'a pas suivi | Preset plus léger, encodeur matériel |
| **Rendu** (ms) | Durée moyenne de composition d'une image | Doit rester bien sous `1000 / fps` (33 ms à 30 fps) |
Les compteurs cumulent depuis le lancement d'OBS, d'où l'affichage en pourcentage : sous
1 %, il n'y a rien à faire ; au-delà de quelques pour cent, le poste indiqué est saturé.
Changer de preset ou d'encodeur ne corrige **que** la colonne encodage. Si c'est le rendu
qui décroche, le problème est en amont d'OBS.
### Xorg, Wayland et le coût de la capture
Sur une VM sans accélération 3D, la méthode de capture pèse lourd :
- **Wayland** : OBS passe par PipeWire, le compositeur lui remet les images déjà composées.
- **Xorg** : la capture d'écran XSHM recopie tout le tampon à chaque image. La capture de
fenêtre XComposite est nettement plus économe — à préférer systématiquement.
Xorg n'est nécessaire que pour le rappel du plein écran par xdotool. Si le cadrage se fait
côté OBS, Wayland est le meilleur choix en performance.
Un preset trop lourd pour la VM fait chuter les images par seconde : la qualité perçue
baisse alors malgré un meilleur CRF. Après un changement, surveille « FPS » et « Frames
perdues » sur la fiche de l'agent.
baisse alors malgré un meilleur CRF. Après un changement, surveille « FPS » et les deux
colonnes de frames perdues sur la fiche de l'agent.
## Historique par VM

View File

@@ -62,7 +62,10 @@ type ObsSnapshot = Pick<
| 'cpuUsage'
| 'fps'
| 'droppedFrames'
| 'outputTotalFrames'
| 'renderSkippedFrames'
| 'renderTotalFrames'
| 'frameRenderTimeMs'
>;
const RECONNECT_DELAY_MS = 5000;
@@ -512,7 +515,10 @@ export class ObsController extends EventEmitter {
cpuUsage: stats.cpuUsage,
fps: stats.activeFps,
droppedFrames: stats.outputSkippedFrames,
outputTotalFrames: stats.outputTotalFrames,
renderSkippedFrames: stats.renderSkippedFrames,
renderTotalFrames: stats.renderTotalFrames,
frameRenderTimeMs: stats.averageFrameRenderTime,
};
} catch (err) {
this.lastError = err instanceof Error ? err.message : String(err);

View File

@@ -532,8 +532,23 @@ export interface AgentStatus {
/** Statistiques OBS. */
cpuUsage?: number;
fps?: number;
/**
* Deux goulots distincts, à ne pas confondre — c'est eux qui désignent la
* cause d'une chute de performance.
*
* `renderSkipped` : la composition de la scène n'a pas tenu la cadence. En
* cause : la méthode de capture, la définition, ou un bureau sans
* accélération 3D. Changer d'encodeur n'y ferait rien.
*
* `droppedFrames` (encodage) : la scène était prête mais l'encodeur n'a pas
* suivi. Là, le preset et l'encodeur sont les bons leviers.
*/
droppedFrames?: number;
outputTotalFrames?: number;
renderSkippedFrames?: number;
renderTotalFrames?: number;
/** Durée moyenne de composition d'une image, en millisecondes. */
frameRenderTimeMs?: number;
/** Statistiques machine (collectées par l'agent, pas par OBS). */
systemCpu?: number;

View File

@@ -102,7 +102,24 @@ export function AgentCard({
<Metric label="Disque libre" value={formatBytes(status.diskFreeBytes)} />
<Metric label="CPU OBS" value={formatPercent(status.cpuUsage)} />
<Metric label="FPS" value={status.fps ? status.fps.toFixed(0) : '—'} />
<Metric label="Frames perdues" value={String(status.droppedFrames ?? '—')} />
<Metric
label="Rendu"
value={
status.frameRenderTimeMs === undefined
? '—'
: `${status.frameRenderTimeMs.toFixed(1)} ms`
}
/>
<Metric
label="Perdu · rendu"
value={formatSkipped(status.renderSkippedFrames, status.renderTotalFrames)}
title="Composition de la scène trop lente : capture, définition, accélération 3D"
/>
<Metric
label="Perdu · encodage"
value={formatSkipped(status.droppedFrames, status.outputTotalFrames)}
title="Encodeur en retard : preset trop lourd ou CPU saturé"
/>
</div>
<div className="row">
@@ -260,15 +277,39 @@ function WatchStrip({
);
}
function Metric({ label, value, mono }: { label: string; value: string; mono?: boolean }) {
function Metric({
label,
value,
mono,
title,
}: {
label: string;
value: string;
mono?: boolean;
title?: string;
}) {
return (
<div className="metric">
<div className="metric" title={title}>
<span className="metric-label">{label}</span>
<span className={`metric-value${mono ? ' mono' : ''}`}>{value}</span>
</div>
);
}
/**
* Images perdues, en valeur absolue et en part du total.
*
* Les compteurs d'OBS cumulent depuis son lancement : « 4 200 » ne dit rien
* seul, « 4 200 (0,3 %) » dit que tout va bien, « 4 200 (38 %) » qu'il faut
* agir.
*/
function formatSkipped(skipped?: number, total?: number): string {
if (skipped === undefined) return '—';
if (!total) return String(skipped);
const share = (skipped / total) * 100;
return `${skipped} (${share < 0.1 && skipped > 0 ? '<0,1' : share.toFixed(1).replace('.', ',')} %)`;
}
function basename(filePath: string): string {
const parts = filePath.split(/[\\/]/);
return parts[parts.length - 1] ?? filePath;