Fix : obs bug 1
Some checks failed
release / build (push) Successful in 38s
release / verify-windows (push) Failing after 1m3s

This commit is contained in:
jeanotx32
2026-08-11 19:04:32 +02:00
parent e284337fb2
commit b85a535dd8
2 changed files with 51 additions and 5 deletions

View File

@@ -33,6 +33,43 @@ type ObsSnapshot = Pick<
>;
const RECONNECT_DELAY_MS = 5000;
const CONNECT_TIMEOUT_MS = 10_000;
/** Borne une promesse qui pourrait ne jamais se résoudre. */
async function withTimeout<T>(promise: Promise<T>, ms: number, message: string): Promise<T> {
let timer: NodeJS.Timeout | undefined;
try {
return await Promise.race([
promise,
new Promise<never>((_, reject) => {
timer = setTimeout(() => reject(new Error(message)), ms);
}),
]);
} finally {
if (timer) clearTimeout(timer);
}
}
/**
* Traduit une erreur de connexion en message actionnable. Le brut
* (« ECONNREFUSED ») dit ce qui a échoué, jamais quoi faire ensuite.
*/
function describeConnectionError(err: unknown): string {
const message = err instanceof Error ? err.message : String(err);
const sysCode = (err as NodeJS.ErrnoException).code;
const obsCode = (err as { code?: unknown }).code;
if (sysCode === 'ECONNREFUSED' || message.includes('ECONNREFUSED')) {
return `${message} — rien n'écoute sur ce port. Lance OBS, puis Outils → Paramètres du serveur WebSocket → coche « Activer le serveur WebSocket ».`;
}
if (obsCode === 4009 || /authent/i.test(message)) {
return `${message} — mot de passe obs-websocket incorrect ou manquant. Dans OBS : Outils → Paramètres du serveur WebSocket → Afficher les informations de connexion.`;
}
if (sysCode === 'ENOTFOUND' || sysCode === 'EHOSTUNREACH' || sysCode === 'ETIMEDOUT') {
return `${message} — hôte injoignable. Vérifie l'adresse configurée pour cet agent.`;
}
return message;
}
/**
* Enveloppe obs-websocket : maintient la session, expose les actions du
@@ -101,16 +138,24 @@ export class ObsController extends EventEmitter {
this.connecting = (async () => {
try {
const info = await this.obs.connect(url, this.settings.password || undefined, {
rpcVersion: 1,
});
// Un port ouvert par autre chose qu'obs-websocket ne renvoie jamais de
// poignée de main : sans ce délai, la promesse resterait éternellement
// en attente et, comme elle est réutilisée ci-dessus, toute tentative
// ultérieure serait bloquée jusqu'au redémarrage de l'agent.
const info = await withTimeout(
this.obs.connect(url, this.settings.password || undefined, { rpcVersion: 1 }),
CONNECT_TIMEOUT_MS,
`aucune réponse après ${CONNECT_TIMEOUT_MS / 1000} s — le port répond mais ne parle pas obs-websocket ?`,
);
this.connected = true;
this.lastError = undefined;
this.cachedVersion = info.obsWebSocketVersion;
this.emit('log', 'info', `Connecté à OBS ${url} (obs-websocket ${info.obsWebSocketVersion})`);
} catch (err) {
this.connected = false;
this.lastError = err instanceof Error ? err.message : String(err);
this.lastError = describeConnectionError(err);
// Après un délai dépassé, le socket peut rester à demi ouvert.
await this.obs.disconnect().catch(() => undefined);
throw new Error(`Connexion à OBS impossible (${url}) : ${this.lastError}`);
} finally {
this.connecting = null;