📤 Upload de Mídia (Áudio/Vídeo) → Jornada — Plano de 4h

Branch base: racoon-impl Objetivo: nova opção no menu WhatsApp para o cliente enviar uma mídia pronta (áudio ou vídeo), a IA gera apenas título e descrição, e o bot pergunta se deseja publicar numa jornada.


🎯 Escopo

O que é: o cliente já tem o conteúdo pronto (uma aula gravada, um áudio, um vídeo) e quer subir direto para a plataforma — sem geração de conteúdo por IA. A IA entra para criar título + descrição automaticamente a partir da transcrição.

Diferença para o Podcast: o podcast gera o áudio (AutoContent API). Aqui o cliente envia a mídia já finalizada. Fluxo mais curto e síncrono.

Menu Principal → ✏️ Criar Conteúdo → 📤 Enviar Mídia
   → cliente envia áudio OU vídeo
   → upload Racoon (storage + transcode)
   → transcrição (Whisper) → IA gera título + descrição
   → mostra preview (título/descrição) → confirma
   → "Publicar numa jornada?" → lista jornadas → anexa → URL

♻️ Reuso (quase tudo já existe)

Componente Arquivo Uso
Upload + transcode app/services/media/racoon_client.pyupload_bytes, wait_for_terminal, extract_playback_url, extract_transcript_text Sobe a mídia e obtém URL final
Transcrição app/services/media/openai_transcriber.pytranscribe_media_bytes Texto base para a IA
Download da mídia do WhatsApp app/services/media/processor.pyget_media_download_url, _download Baixa o arquivo enviado
Listar jornadas app/services/journey/manager.pylist_user_journeys Escopo do usuário
Anexar à jornada app/services/journey/manager.pyattach_podcast_to_journey (generalizar p/ vídeo) INSERT media+contents+formats+items
Seleção de jornada webhook.py → handlers journey_* / JourneyContext Reuso do fluxo de seleção
CTA URL / send app/services/whatsapp/sender.pysend_cta_url, send_message Mensagens
Contexto de sessão app/models/schemas.py + session/manager.py Novo MediaUploadContext

⏱️ Cronograma hora-a-hora

Hora 1 — Menu + contexto + fluxo de entrada

Hora 2 — Upload Racoon + IA título/descrição

Hora 3 — Confirmação + publicação em jornada

Hora 4 — Testes + smoke + PR


🗂️ Arquivos

Novos

Arquivo Função
app/services/media/metadata_ai.py generate_title_description(transcript, kind) — IA p/ título+descrição
tests/test_media_upload.py testes do fluxo

Modificados


✅ Critério de sucesso


⚠️ Riscos & mitigação

Risco Mitigação
Vídeo grande demora no transcode wait_for_terminal com timeout generoso (já usado no podcast); manda "⏳ processando"
Transcrição falha/vazia Fallback: título a partir do nome do arquivo + descrição genérica
Usuário sem jornada com permissão Encerra com "mídia salva" + CTA da URL (sem travar)
attach_podcast_to_journey muito acoplado a "audio" Refatorar com parâmetro item_type, default "audio" (retrocompatível com podcast)

⏭️ Próximo passo

Aprovar e iniciar pela Hora 1 (menu + contexto). A maior parte é colagem de peças já testadas (Racoon, transcrição, jornada) — risco baixo.