Fix : obs bug 1
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user