11 KiB
Player próprio da Rádio 1313 na home (S25)
Status: rascunho Atualizado em: 2026-09-21 Issue: #1239 Priority: P2 Impeccable: C — componente novo (player) dentro da seção de som existente da home Design UI: docs/plans/radio-player-proprio-ui-design.html Appetite: ~1 dia eng; um outcome verificável — a rádio toca num player próprio, discreto, sem marca zeno, com CTA de compartilhar Responsável: —
Intenção
O embed oficial do zeno.fm que o S24 (#1235) montou na home ficou pequeno: o iframe de 150/168px corta título e capa e carrega a marca zeno. O humano quer um player próprio, mais discreto e com a cara da campanha, sobre o mesmo stream (https://stream.zeno.fm/hys86kx6k16tv), mais um CTA de compartilhar que manda o link público da rádio no Zeno.
Esta Issue é a sucessora explícita do S24: nova evidência de produto reverte os anti-goals dele ("não vira player custom", "não cria framework de consent/CSP"). Planos de Issues done/in-prod são imutáveis — docs/plans/radio-embed-direto.md não é editado nem reaberto; a reversão de propósito fica registrada aqui.
Ganho colateral a registrar com honestidade: o iframe do S24 traz GA G-2T527NZWVM + redes de anúncio em todo pageview da home (trade-off assumido lá). Com player próprio + preload="none", nenhum request de terceiro sai antes do gesto de play; a conexão com o stream só acontece ali. Isso reverte o trade-off para melhor, mas não promete analytics nem contador — não há dado nosso novo.
Persona e fluxo
- Persona / contexto: visitante e militante que chega pela home no celular (link no WhatsApp, busca, indicação), com pressa e em conexão qualquer.
- Job principal: ouvir a Rádio Jorge Solla 1313 num player que parece da campanha e poder mandar o link da rádio para alguém.
- Fluxo desejado: abre a home → rola até a seção de som → vê o player discreto "Rádio Jorge Solla 1313" com indicador "Ao vivo" → dá play e ouve (a conexão com o stream começa só agora); se um jingle estiver tocando, ele pausa → toca o "Compartilhar" e escolhe WhatsApp (mensagem pronta) ou copiar link → se o play falhar, vê um estado honesto com link para ouvir no Zeno.
- Anti-goals de produto: não redesenha a seção de som nem a grade/
/jingles; não vira proxy nem player de streaming próprio; não autoplay com som; não busca "tocando agora" nem analytics/contador; não cria consent/CSP novo; não mexe em schema.
Esboço de fluxo (C)
[visitante na home] → seção de som
→ player próprio: "Rádio Jorge Solla 1313" · [Ao vivo] · [▶] · [Compartilhar]
→ dá play → conecta no stream (sem request de terceiro antes) · toca
[jingle tocando] → pausa o jingle · [play no jingle] → pausa a rádio
→ "Compartilhar" → WhatsApp (mensagem pronta) | copiar link → feedback
[play falha/estola] → estado de erro + "ouvir no Zeno" + compartilhar (nunca spinner infinito)
[0 jingles] → rádio sozinha (compact) · [N jingles] → grade + "Ver todos" → /jingles
Design UI (C)
- Design UI (gate):
docs/plans/radio-player-proprio-ui-design.html— cenas: 390 mobile, 1280 desktop, variante compacta (0 jingles) e estados do player (parado, carregando, ao vivo, erro). Capa/arte é NEEDS ASSET: ativo oficial do kit 1313 (public/campaign-kit/README.md) ou disco neutro — nunca inventar capa nem usar banco de imagens.
Objetivo e aceite
- O iframe zeno some da home; o player próprio é a única superfície de rádio da seção, com título fixo "Rádio Jorge Solla 1313" e indicador "Ao vivo" — sem corte de título/capa.
- Só toca com gesto do visitante; com
preload="none"nenhum request ao stream ou a terceiros acontece antes do play. - Um áudio por vez na seção de som: play na rádio pausa o jingle em reprodução e vice-versa.
- Compartilhar envia a mensagem literal
Ouça a Rádio Jorge Solla 1313 — https://zeno.fm/radio/jorge-solla-1313/(WhatsApp + copiar link com feedback), reusando o padrão público. - Fail-soft: play que falha ou estola vira estado de erro com alternativa honesta (ouvir no Zeno / compartilhar) — nunca spinner infinito.
- Kill switch do S21 e variante compact preservados: 0 jingles → rádio sozinha; com jingles, grade e "Ver todos" seguem abaixo;
/jinglese o player dos jingles ficam intocados além da exclusividade. - Home segue estática (leitura única de
getPublishedJingleItems(), cache tagjingles); sem PII nova, sem Consent novo; MetaPixel da home intocado; sem overflow horizontal a 390px e operável por teclado com rótulos acessíveis.
Dados (intenção)
- Vou apresentar dados? Não — N/A: nenhum dado nosso é apresentado ou coletado; não há contador de ouvintes, analytics de reprodução nem metadados "tocando agora". A decisão do visitante é ouvir agora, não ler números.
- Decisões desbloqueadas: N/A — sem métrica que desbloqueie escolha de ator.
- Forma: N/A — sem dado agregado a definir.
Dados da decisão (literais)
- ID
S25; slugradio-player-proprio; tipofeature; PriorityP2; ImpeccableC; rota: a home/(sem rota nova). - Stream a tocar:
https://stream.zeno.fm/hys86kx6k16tv→ 302 para CDNstream-*.surfernetwork.comcom token assinado por request; resposta finalcontent-type: audio/mpeg,icy-name: Jorge Solla 1313, 128 kbps, 44.1 kHz; sem headers CORS/ACAO (playback em<audio>funciona; Web Audio/AnalyserNodeé impossível — fora de escopo). - Página pública da rádio (destino do compartilhar):
https://zeno.fm/radio/jorge-solla-1313/(HTTP 200, título "Listen to Jorge Solla 1313 | Zeno.FM"). - Nome exibido fixo: "Rádio Jorge Solla 1313" (confirmado pelo
icy-namedo stream). Sem metadado de "tocando agora". - Mensagem de compartilhamento literal:
Ouça a Rádio Jorge Solla 1313 — https://zeno.fm/radio/jorge-solla-1313/. - iframe que sai:
https://zeno.fm/player/jorge-solla-1313/(moldura 150/168px é o defeito); com ele sai o rastro de terceiros por pageview do S24 — GAG-2T527NZWVM+ redes de anúncio. - Design UI (gate):
docs/plans/radio-player-proprio-ui-design.html.
Direção no codebase (hipótese)
- Áreas prováveis:
src/components/jingles/—RadioEmbed.tsx(iframe) é o que sai de cena;JingleHomeSection.tsx:63troca a composição; o player novo nasce ao lado, reusando o padrão de<audio>já existente emJingleCards.tsx:92-140(play exclusivo comactiveId,preload="none", revert doplay()rejeitado). CSS: só.campaign-sound-titleemstyles.css:1158-1164é da seção; tokens--campaign-line/--campaign-band(:184-185) seguem. - Precedente a olhar:
ContentShareButton.tsx:44-108+ builderssrc/lib/contentShare.ts:11-48+wa.mesem destinatário (src/lib/phone.ts:62-67) + feedback de cópia (src/lib/copyFeedback.ts:68); S24docs/plans/radio-embed-direto.mde S22docs/plans/jingles-radio-homepage.md(histórico; não editar). - Risco de acoplamento: a exclusividade rádio↔jingle precisa de coordenação sem tocar em
/jingles; os testes pinam o iframe e terão de ser reescritos (tests/unit/radioEmbed.unit.spec.tsx,tests/unit/jingleHomeSection.unit.spec.tsx:42-53,tests/e2e/frontend.e2e.spec.ts:560-616,tests/e2e/frontendJingles.e2e.spec.ts:248-291) e a fixture do e2e só stuba o player zeno (tests/e2e/fixtures/e2eTest.ts:118-129);scripts/lib/e2e-affected-manifest.mjs:99-108mapeiasrc/components/jingles→frontendJingles; home estática/cachejingles; sem CSP/middleware no caminho.
Dependências
- Nenhuma dura. S24 = Issue #1235 (entregue 2026-09-20) — sucessora explícita; decisão revertida de propósito, plano imutável, não reabrir. Estação ativa no zeno.fm. Design hi-fi aprovado no gate.
Fora de escopo
- Visualizador/Web Audio (sem CORS no stream); "tocando agora" via API do Zeno; analytics de reprodução/contador de ouvintes.
- Proxy/stream próprio ou troca de provedor; download da rádio (é stream).
- Consent/CSP/banner de terceiros; migration/schema; qualquer Consent novo.
- Mudanças em
/jinglese na grade além da coordenação de exclusividade.
Rabbit holes de produto
- Virar proxy/CDN do áudio. Se alguém "só completar": infra de streaming, tokens, cache, uptime. Corte neste item:
<audio>apontando direto para o stream do Zeno. - "Tocando agora" e programação. Se alguém "só completar": API do Zeno, polling, metadado frágil. Corte: nome fixo + "Ao vivo".
- Analytics de ouvintes. Se alguém "só completar": contador, dashboard, vaidade. Corte: a rádio é um play, não um painel.
- Redesenhar a seção de som inteira. Se alguém "só completar": copy, headings, hero, grade. Corte: só o player e o CTA mudam.
- Capa inventada ou banco de imagens. Corte: ativo oficial do kit 1313 ou disco neutro.
Questões em aberto (produto)
- Acesso a "ouvir no Zeno" fora do erro? Opções: A) só no estado de erro, mantendo o player discreto | B) link persistente ao lado do player. Recomendação: A — o CTA de compartilhar já expõe a página da rádio; validar no design.
- Escopo da exclusividade rádio↔jingle? Opções: A) coordenação só na seção da home | B) coordenação global (inclui
/jingles). Recomendação: A —/jinglesfica intocado; o mecanismo é da implementação. - Forma do controle de compartilhar? Opções: A) popover com WhatsApp + copiar link (padrão dos cards) | B) botão único que abre o WhatsApp. Recomendação: A — reusa o padrão público com feedback; design decide a forma visual. (assumido — validar com produto)
- Capa/arte do player? Opções: A) ativo oficial do kit 1313 (
public/campaign-kit/README.md, ex.:estrela.png/marca-*) | B) disco neutro. Recomendação: A — asset oficial, sem inventar arte. Design resolve (NEEDS ASSET).
Referências
- GitHub Issue: a registrar (
S25); S24 = Issue #1235 (entregue; decisão revertida de propósito, não reabrir). - Design UI (gate):
docs/plans/radio-player-proprio-ui-design.html(+ assets emdocs/plans/radio-player-proprio-ui-design-assets/se houver). docs/plans/radio-embed-direto.md,docs/plans/jingles-radio-homepage.md— histórico do embed/facade (não editar).src/components/jingles/RadioEmbed.tsx,JingleHomeSection.tsx,JingleCards.tsx— o que sai/encaixa/reusa.src/components/ContentShareButton.tsx,src/lib/contentShare.ts,src/lib/phone.ts,src/lib/copyFeedback.ts— padrão público de compartilhar.public/campaign-kit/README.md— dona da marca/ativos.tests/unit/radioEmbed.unit.spec.tsx,tests/unit/jingleHomeSection.unit.spec.tsx,tests/e2e/frontend.e2e.spec.ts,tests/e2e/frontendJingles.e2e.spec.ts,tests/e2e/fixtures/e2eTest.ts,scripts/lib/e2e-affected-manifest.mjs— contratos que pinam o iframe.AGENTS.md— home estática/cache tagjinglese postura LGPD.