Skip to content

Video

Contrato cross-surface para captura, playback e screen-capture de vídeo em apps Koder. Toggles de privacidade (`media.video.camera`, `media.video.screen`, `media.video.mic`) em Settings; defaults seguros (tudo OFF até prompt do SO); codecs canônicos (H.264/HEVC/AV1/VP9 in via kodec; H.264 + AAC out); widgets `KoderVideoPlayer` + `KoderVideoRecorder` + `KoderScreenCapture` em `engines/sdk/koder_kit`. Recording indicator obrigatório quando capture ativo. Upload size cap 500 MB. `<APP>-VIDEO-*` error map.

Source spec: specs/media/video.kmd

Full specification

Media — Video Spec — v0.1

Normative cross-surface spec para video I/O em apps Koder. Implementação obrigatória via widgets KoderVideo* em engines/sdk/koder_kit (Flutter) e koder_web_kit (JS) — nunca rolar video_player upstream ou <video> raw local. Codec layer via engines/kodec (canônica) ou Koda port (shadow-active).


Scope

Aplica-se a todo app Koder que grave, reproduza, ou faça screen-capture de vídeo: call recording, tutorial in-app, attachment de vídeo em chat, demo em landing, screen-share em ferramenta de dev, upload de vídeo de produto.

Surfaces cobertas: Flutter mobile (Android + iOS), Flutter desktop (Linux + macOS + Windows), Flutter web ou templ+HTMX, TV (playback; gravação fora de escopo em TV). CLI/TUI exigem path arg + delegam ao desktop player externo.


1 — MUST: expose "Vídeo" toggle group in Settings

Sub-seção "Vídeo" do agrupamento "Mídia" em Settings; deve conter, na ordem:

  1. Câmera (media.video.camera) — gate à camera
  2. Microfone para vídeo (media.video.mic) — gate ao mic durante gravação
  3. Compartilhar tela (media.video.screen) — gate ao screen-capture
  4. Resolução máxima (media.video.max_height) — dropdown 480 / 720 / 1080 / 2160
  5. Qualidade (media.video.bitrate_mbps) — slider 1-20 Mbps

Compartilha media.image.camera quando ambos coexistem (camera permission é granted ao app, não ao sub-uso); cada toggle controla uso, não permissão de SO.


2 — MUST: defaults seguros em fresh install

ChaveDefaultNotas
media.video.cameraOFFPrivacy-by-default
media.video.micOFFVídeo silencioso até user ativar
media.video.screenOFFScreen-capture nunca silent-on; sempre exige toggle + prompt do SO
media.video.max_height1080Cap em 4K só se Settings.advanced ativo (raras as redes)
media.video.bitrate_mbps55 Mbps casa com 1080p30 H.264 sem visible blocking

Quando qualquer toggle for OFF em runtime, o app deve parar qualquer capture ativo + liberar handles + dismiss screen-share dialog.


3 — MUST: privacidade + recording indicator

  • NUNCA auto-upload de gravação (user confirma antes do POST)
  • NUNCA screen-capture em background sem user-visible indicator
  • NUNCA keep camera open em background além de 5 s pós-leave
  • Recording indicator obrigatório: dot vermelho + timer + título da janela alterado para ● Recording — <app>; em mobile, system status bar fica vermelho (iOS) / mostra ícone (Android)
  • EXIF/metadata strip equivalente para vídeo (camera serial, GPS de container MP4); media.video.strip_metadata = true default

4 — MUST: widget surface no koder_kit

WidgetFunção
KoderVideoPlayerPlayback de KoderVideoRef ou URL; controls config (play/pause/seek/fullscreen/captions/speed)
KoderVideoRecorderGravação com preview + start/stop + flip-camera; gates media.video.camera
KoderScreenCaptureScreen share dialog + capture pipeline; gates media.video.screen; força recording indicator
KoderVideoPickerSheet "Gravar vídeo" / "Escolher da galeria"; retorna KoderVideoRef
KoderVideoThumbnailFrame thumbnail (default 1s mark) + lazy-load

KoderVideoRef: {uri, mime, durationMs, width, height, sizeBytes, hasAudio, codec, koderUserId?, workspaceId?}.


5 — MUST: format support

Decode (via engines/kodec): H.264, HEVC (HEIC pipeline), AV1, VP9 — container MP4, WebM, MOV.

Encode (default): H.264 + AAC + MP4 container. HEVC e AV1 são opt-in quando suportado pela surface (iOS encoder, browser MediaRecorder com codec hint).

Upload size cap: 500 MB pós-compress. Exceder → erro <APP>-VIDEO-SIZE-001 com sugestão de bitrate menor ou trim.

Compression knob: media.video.bitrate_mbps (§2) controla output; duração + resolução + bitrate determinam tamanho. App deve estimar size pré-encode e avisar se ultrapassar cap.


6 — MUST: error surface

CenárioIDTexto pt-BR
Permissão de câmera negada<APP>-VIDEO-CAM-001"Permita o acesso à câmera para gravar vídeo."
Permissão de mic negada<APP>-VIDEO-MIC-001"Permita o acesso ao microfone para vídeo com áudio."
Permissão de screen-capture negada<APP>-VIDEO-SCR-001"Permita o compartilhamento de tela para continuar."
Codec não suportado pelo decoder local<APP>-VIDEO-CDC-001"Este vídeo usa codec não suportado ($codec)."
Tamanho excede 500 MB<APP>-VIDEO-SIZE-001"Vídeo muito grande. Reduza qualidade ou corte trechos."
Upload falhou<APP>-VIDEO-NET-001"Falha ao enviar o vídeo. Tente novamente."
Encode falhou (kodec/hardware)<APP>-VIDEO-ENC-001"Falha ao processar o vídeo. Tente novamente ou reduza qualidade."

7 — Observability

  • Counters: media.video.recorded, media.video.uploaded, media.video.upload_error, media.video.screen_captured
  • Latency histograms: media.video.encode_ms, media.video.upload_ms, media.video.first_frame_ms (playback)
  • Não emitir métricas que vazem conteúdo (transcript, frames, file path) — apenas counters + latência + dimensões anonimizadas (resolução, codec, duration)

8 — Adoption checklist (per app)

  • Importa KoderMediaSettingsTile (sub-seção Vídeo visível)
  • Usa KoderVideoPlayer/KoderVideoRecorder/KoderScreenCapture (nunca video_player upstream raw)
  • Defaults da §2 respeitados em fresh install
  • Recording indicator obrigatório (§3)
  • Codec layer via engines/kodec (ou Koda port quando flipped)
  • Error map da §6 implementado
  • Upload path respeita multi-tenancy/contract.kmd

Non-normative — referências

  • Sibling specs: specs/media/image.kmd (camera shared), specs/media/audio.kmd (mic + recording indicator paralelo), specs/media/document.kmd
  • Codec engine: engines/kodec/ (canônica, Rust); Koda port em engines/lang/koda/lib/{mp4,mp3,wav}.kd (shadow-active per Flipping Point em CLAUDE.md)
  • Implementation surface: engines/sdk/koder_kit/lib/src/media/
  • Voice precedent (mic + privacy contract): specs/voice/wake-word.kmd

Other media capabilities

Image

Capture, picker, preview, crop, and upload. EXIF stripping ON by default; widgets KoderImagePicker / KoderImagePreview / KoderImageCropper.

Audio

Memos, podcasts, attachments, ringtones — generic audio, separate from voice/wake-word. Widgets KoderAudioPlayer / KoderAudioRecorder.

Document

Pick, preview, and OCR for PDF/DOCX/MD/TXT. Local-first OCR (tesseract); fallback to services/ai/ocr. Widgets KoderDocumentPicker / KoderOcrButton.