diff --git a/docs/changelog/2026-09-16-c181.md b/docs/changelog/2026-09-16-c181.md
new file mode 100644
index 00000000..e17f5cff
--- /dev/null
+++ b/docs/changelog/2026-09-16-c181.md
@@ -0,0 +1 @@
+**C181 — Acervo: o player volta a ter o YouTube in-page e espera a Câmara gerar o trecho (2026-09-16):** o aviso do dono era um defeito de duas cabeças na mesma fala. Primeira: depois do C178 a Câmara virou o caminho padrão, mas quem preferia o YouTube ficava sem volta na própria página (só o link externo "Abrir no YouTube", que sai da página). Segunda: o clique do player usava `SPEECH_VOD_PLAYER_POLICY` com `pollAttempts: 0`, então o primeiro `GERANDO` da Câmara já virava o estado "gerando" com "Tentar novamente" — a geração era curta e o retry "funcionava", provando que o app desistia cedo. A correção é pequena e simétrica. No `SpeechDetailPlayer`, o `
+ ) : resolution.kind === 'failed' ? (
+
+ {resolution.message ??
+ 'Não foi possível resolver o arquivo deste trecho na Câmara. Tente novamente.'}
+
+ O arquivo deste trecho não pôde ser verificado na Câmara agora.
+
+ ) : null
+ ) : null
+
// C178 — the exit block stays reachable in every state: the app never sees the
// reason the video cannot play, so the way out cannot depend on detecting it.
// The Câmara panel owns the primary CTA while it is idle ("Assistir o trecho");
@@ -416,17 +503,44 @@ export const SpeechDetailPlayer = ({
)}
-
+
)
@@ -517,6 +631,8 @@ export const SpeechDetailPlayer = ({
) : null}
+ {inlineNotice}
+
{publishedCut ? : null}
{selection ? (
diff --git a/src/utilities/speech/speechVodResolver.ts b/src/utilities/speech/speechVodResolver.ts
index d2dd2cd6..f9a3c00b 100644
--- a/src/utilities/speech/speechVodResolver.ts
+++ b/src/utilities/speech/speechVodResolver.ts
@@ -15,10 +15,11 @@ import {
* owns the wait budget through a `SpeechVodPolicy`, and the media verification
* (not the policy) decides what may reach the browser.
*
- * The player keeps the bounded click of C162 (`SPEECH_VOD_PLAYER_POLICY`); the
- * cut job (C169) needs the measured first-request window (~30s, then short
- * polls) plus the stored links as a last verified candidate, and passes
- * `SPEECH_VOD_CUT_POLICY` + `cachedUrls`.
+ * The player keeps a short click budget of its own (`SPEECH_VOD_PLAYER_POLICY`;
+ * C181 widened it to poll a transcode in progress) and stops before the cut
+ * job's window; the cut job (C169) needs the measured first-request window
+ * (~30s, then short polls) plus the stored links as a last verified candidate,
+ * and passes `SPEECH_VOD_CUT_POLICY` + `cachedUrls`.
*/
export type SpeechVodPolicy = {
@@ -34,13 +35,19 @@ export type SpeechVodPolicy = {
pollDelayMs: number
}
-/** C162's player click: short, no poll, immediate answer. */
+/**
+ * C181's player click: a short, own budget that waits out the Câmara's
+ * transcoding instead of treating the first `GERANDO` as a failure — 1 read +
+ * 2 polls of 3 s (~6 s extra), between the old immediate answer and the cut
+ * job's budget (a 45 s read timeout plus 2 polls of 5 s). The wait stays
+ * bounded; past it the honest "gerando" state and the retry remain.
+ */
export const SPEECH_VOD_PLAYER_POLICY: SpeechVodPolicy = {
statusTimeoutMs: 15_000,
statusRetries: 1,
retryDelayMs: 1_000,
- pollAttempts: 0,
- pollDelayMs: 1_000,
+ pollAttempts: 2,
+ pollDelayMs: 3_000,
}
/** C169's cut job: covers the measured ~30s first request and 1–2 short polls. */
diff --git a/tests/e2e/campaignSpeechAcervo.e2e.spec.ts b/tests/e2e/campaignSpeechAcervo.e2e.spec.ts
index 67fd095e..79cfcad7 100644
--- a/tests/e2e/campaignSpeechAcervo.e2e.spec.ts
+++ b/tests/e2e/campaignSpeechAcervo.e2e.spec.ts
@@ -11,11 +11,13 @@ import { assertCampaignRedirect, expect, rendered, test } from './fixtures/campa
* the filter URL contract and the detail's player/transcript/actions. The
* player picks the surface from the row coordinates — the Câmara excerpt as the
* default when the speech has one (stored-VOD capa resolved on click), a
- * clickable YouTube cover when it only has a session link (C178: YouTube is the
- * external exit, never an embedded entry) — and honest states when neither
- * exists — and the stored VOD link itself is never rendered (C162). Playback is
- * browser territory and is not asserted here; the HTML carries the contract
- * (`