fix : opening link 2
This commit is contained in:
32
README.md
32
README.md
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user