Skip to main content
Petanque Life

Match Recording & Live Production Studio [NEW] — **REBUILD: delvis levererad (D-STUDIO `0ec13810.m-1`)**

F09.04 47 features Planned

At a glance

The Match Recording & Live Production Studio turns any phone or tablet into a broadcast camera, then orchestrates 2 to 4 of them into a live-cut multi-camera production with score overlays, replays, and simultaneous streaming to YouTube, Twitch, Facebook, and Petanque Life. From a club final to a national championship, you get a TV-grade broadcast with no truck and no crew.

How it works

Open the Petanque Life app on one device and tap Record a match — that is a one-camera setup capturing the court with timecode, audio, and a synced match record. To produce a real broadcast, pair 2 to 4 phones or tablets with multi-device camera setup; each device gets a camera role (wide court view, close-up, cochonnet cam, player cam) and is locked to a shared timeline through Camera sync. Audio comes from any camera device or a separate microphone device for cleaner commentary.

A director uses Director mode on a separate iPad to choose the live feed: tap a thumbnail for manual camera switching, or let automatic camera switching follow the active end of the court via AI heuristics on score events. Picture-in-picture mode keeps a secondary angle on screen during big shots. A commentator on yet another device runs Commentator mode, with their voice mixed into the program feed.

Live overlays are auto-driven by the match scoring data already flowing through the app: live score overlay, mène counter and match progress bar, boule count indicator, tournament bracket/standings overlay, and player name/photo overlays when the camera focuses on a player. Sponsor logo overlay, lower thirds with ELO and recent form, custom text overlay, drawing tools on screen, and full telestrator (draw on paused/live video like sports TV) round out the graphics package. Pre-match player cards play as openers, post-mène summary graphics auto-generate after every end, and instant replay plus slow-motion replay or split-screen comparison let directors revisit critical boules.

Distribution is multi-platform. Direct stream to YouTube Live, Twitch, and Facebook Live runs over RTMP, optionally simultaneously, and an in-app live viewing player is always available to followers. An embeddable live player drops the same stream into federation and club websites, complete with live viewer count and chat integration, and stream schedule and notification alerts followers when the show goes live. Adaptive bitrate streaming and stream quality settings keep the picture watchable on rural 4G; for absolute worst-case, audio-only mode and score-only live feed step down gracefully.

Everything is recorded — local recording on each device plus cloud recording of every angle — so after the match you can re-cut with different camera angles, generate automatic highlight clips from score-change moments, manually clip with start/end markers, and produce an automatic match summary video. All assets land in the VOD archive, searchable by competition, player, and date, linked to the match record so the video plays from the match detail page. Offline recording with later upload guarantees nothing is lost when the venue WiFi drops.

Key capabilities

  • Single-phone recording up to 4-device live multi-camera production with synced timelines
  • Director mode with manual or AI-driven automatic camera switching plus picture-in-picture
  • Score, bracket, sponsor, lower-third, and custom-text overlays auto-driven by app match data
  • Telestrator, instant and slow-motion replay, split-screen, pre-match player cards, post-mène summaries
  • Simultaneous RTMP streaming to YouTube, Twitch, Facebook plus in-app and embeddable players
  • Cloud and local recording with auto-highlight, manual clipping, re-cut, and summary video
  • Adaptive bitrate, audio-only and score-only fallbacks, offline-record-and-upload for low-bandwidth venues

In practice

A regional federation hosts a Sunday final at a small club. The organising secretary brings four iPhones on tripods plus a borrowed iPad. She assigns one phone as wide court, one as cochonnet cam, two as player cams, and uses the iPad as Director.

A volunteer puts on a headset and takes the Commentator role from the bar. With one tap she goes live to YouTube and Facebook simultaneously; the live score overlay updates automatically every time the table-side scorer taps the score. She switches angles on big throws, drops a sponsor logo for the local hardware store between mènes, replays a winning carreau in slow motion, and at full time hits Generate summary — a two-minute highlight reel posts itself to the federation's news feed before the trophies are even handed out, and the full broadcast lives in the VOD archive linked to the match.

Features in this subsystem

47
ID Status Features
F09.04.01 In progress Record a match directly from the app (one phone = one camera) Delvis (m-1): enheten ansluter anonymt med engångskod/QR, får sitt eget device_token och en roll — men spelar inte in. Inspelningen: ⊘ — ägare m-3
F09.04.02 Shipped Multi-device camera setup (2-4 phones/tablets as camera sources for same match) m-1: 1—4 KAMERAenheter per produktion (studio.DeviceLimit, kod-deklarerat tak; commentator/director räknas inte), femte kameran ⇒ 409 studio_device_limit
F09.04.03 Shipped Camera role assignment (wide court view, close-up, cochonnet cam, player cam) m-1: wide|closeup|player|crowd + commentator|director ur studio.Roles(), serverade av GET /v1/studio/catalog
F09.04.04 In progress Automatic camera switching (AI-based or rule-based: switch to active end of court) Delvis (m-1) — REGELBASERAD, aldrig AI: score_to_closeup, score_to_wide, break_to_wide ur D-COMP:s live-händelser, med regelns NAMN bokfört på varje beslut. *»Active end«* ⇒ ⊘ — icke-mål: positionsdata om vilken ände som spelas finns inte i huset
F09.04.05 Shipped Manual camera switching (director/commentator selects which camera is live) m-1: PATCH …/program (If-Match), studio:direct eller en director-enhets eget token; switching_mode='manual' stänger auto-regeln
F09.04.06 In progress Picture-in-picture mode (main feed + small secondary camera) Delvis (m-1): PiP-tillståndet (av/på, enhet, hörn) är serverns och sänds till varje enhet. Bild-i-bild-kompositionen är video: ⊘ — ägare m-2
F09.04.07 Shipped Camera sync (all devices synchronized to same timeline) m-1: handskakning …:sync ⇒ MÄTT offset_ms, härlett sync_state ∈ {in_sync, drift, unknown} mot studio.SyncToleranceMs; produktionens started_clock_at är tidslinjens noll
F09.04.08 In progress Audio from any camera device (or separate microphone device) Delvis (m-1): ljudkällans VAL (none|this_device|commentator|device:<id>) är regi-tillstånd och validerat mot produktionens egna enheter. Ljud-mixen: ⊘ — ägare m-2
F09.04.09 Shipped Live score overlay (auto-synced from match scoring in app) m-1: valet i program_state.overlays, underlaget i overlay_data-ramen projicerat ur D-COMP vid läsning — ingen studio_*-tabell bär någonsin ett poäng
F09.04.10 In progress Player name/photo overlays when camera focuses on them Delvis (m-1): spelaretiketterna kommer ur D-COMP:s publika registreringar. Foto: ⊘ — ägare m-2 (en samtyckesgrindad bild i en sändning är ett eget beslut)
F09.04.11 In progress Mène counter and match progress bar Delvis (m-1): end_counter projiceras när D-COMP:s snapshot bär det, annars null + reason: end_counter_unavailable — aldrig ett påhittat »1«. Förloppsindikatorn är rendering: ⊘ — ägare m-2
F09.04.12 Planned Boule count indicator (how many boules each team has left) ⊘ — icke-mål i m-1: fältet finns och svarar ärligt {"state":"not_measured"}. Ingen producent av mätdata finns i huset, och ett »2–1« i en sändningsgrafik som ingen mätt är fabricerad data som tittarna ser
F09.04.13 In progress Tournament bracket/standings overlay Delvis (m-1): bracket är ett giltigt overlay-VAL. Renderingen: ⊘ — ägare m-2
F09.04.14 In progress Sponsor logo overlay (configurable per competition) Delvis (m-1): en REFERENS till D-COMM:s grafikpaket (embed_path ur förbundets default), eller null + reason: no_default_graphics. D-STUDIO bygger ingen egen grafikmotor
F09.04.15 In progress "Lower third" graphics (player stats, ELO, ranking) Delvis (m-1): samma referensmodell som ovan. ELO-/rankinginnehållet i paketet ägs av D-COMM/D-RANK
F09.04.16 Shipped Custom text overlay (commentator can add text messages) m-1: free_text i regi-tillståndet, max 140 tecken (studio.FreeTextMax), 422 too_long över taket. m-4: texten RENDERAS nu i bild när överlägget free_text är valt (husets ENDA renderare, internal/broadcast/render_live.go), och konsolens hjälptext säger det rakt ut i stället för »lagras«
F09.04.17 In progress Commentator mode (separate device for commentary audio) Delvis (m-1): rollen commentator, läget mode='commentator' och ljudkällan finns som tillstånd. m-4: kommentatorenheten fick sina VERKTYG — /studio/anslut renderar regimonitorn (WHEP) plus telestratorn, spelarkorten, summeringsvalet och fritexten, fail-closed ur join-kvittots director_actions[]; repris, frys och delad skärm är regins och nekas 403 med fältet i detaljen. Kvar som ⊘: kommentatorns LJUDKANAL (raden heter *audio*) — ägare m-5/ägarbeslut: ingen mixning av ett tal-spår in i programljudet finns i mediatjänsten
F09.04.18 Shipped Director mode (separate device to switch cameras and control overlays) m-1: mode='director'; en director-enhets token regisserar utan ett användarkonto (D-6)
F09.04.19 Shipped Drawing tools on screen (draw arrows, circles to demonstrate tactics) m-4: telestratorns strokes (arrow/circle/line/freehand) är DATA på programmet — PUT|DELETE …/program/telestrator, normaliserade koordinater i 0..1, tak 32 strokes × 256 punkter ur katalogen, kontrastprövade färger, renderade som <svg> UTAN JavaScript i husets enda renderare. Konsolen och kommentatorenheten ritar i SAMMA yta (studio-telestrator), med tangentbordsalternativ (WCAG 2.1.1)
F09.04.20 Shipped Telestrator (draw on paused/live video like sports TV) m-4: SAMMA yta som F09.04.19 i två lägen — rita på den levande bilden, eller frys den först (POST …/program:freeze) och rita på frysen. Bokförd avvikelse mot mockupen, som ritar två chips: skillnaden är BILDEN, inte verktyget, och två ytor hade varit två ritmotorer att hålla i synk
F09.04.21 Shipped Instant replay (mark moments, replay from any camera angle) m-4: POST …/program:replay {device_id, from_seconds_ago, duration_seconds, speed_percent} spelar ur valfri källas ringbuffert (90 s, ≤ 48 MiB per källa, MÄTT täckning i stream-health.replay_buffers[] — ytan erbjuder aldrig en repris ur en buffert ingen mätt). Insatsen är SERVERNS transienta tillstånd med sitt ends_at, högst EN åt gången, avslutad av mediatjänstens rapport eller av :end-insert; en score-ram avbryter den (D-11). m-1:s tidslinje bär insert_started/insert_ended
F09.04.22 Shipped Slow-motion replay m-4: speed_percent ur katalogen (100|50|25 ⇒ *Normal · ½ · ¼*) på :replay — alltså reprisens HASTIGHET och inte ett eget verktyg. Bokförd avvikelse mot mockupens *🐢 Slow motion*-chip: en LIVE-bild i slow motion utan drift är fysiskt omöjlig, så den enda ärliga slow motion är en repris ur ringbufferten
F09.04.23 Shipped Split-screen comparison (show two angles simultaneously) m-4: layout: "split" med split.{left,right}_device_id i PATCH …/program — split är en LAYOUT och inte ett överlägg, så kompositören sätter ihop bilden i mediatjänsten. PiP och split går inte ihop (422 studio_layout_conflict, pekaren på det fält anroparen ändrade) och auto-växlingen VILAR i split (layout_split), så en poäng aldrig tyst river isär den bild regissören ställt
F09.04.24 Shipped Pre-match player cards (show stats, ELO, recent form before match) m-4 (ägaren RÄTTAD från m-2): korten PROJICERAS vid läsning ur D-RANK:s egna sömmar — ingen studio_*-kolumn bär en rating (mätt över information_schema.columns). Sekretessen är spelarens: utan profile_public visas namn + klubb och stats_reason: profile_private, UTAN tal. Varje saknat värde renderas som — med sitt skäl (no_rating/no_history/format_unresolved/no_public_identity) — aldrig 0, aldrig 1200. Korten döljs automatiskt vid första poängen (play_hides_player_card, regelbaserat)
F09.04.25 Shipped Post-mène summary graphic (auto-generated after each end) m-4 (ägaren RÄTTAD från m-2): summeringen räknas ur D-COMP:s EGEN poängbok (score_entry, icke-ersatta rader) när score-ramen för en NY mène når bryggan — {end_number, points, scored_by, score_after, duration_seconds, visible_until}, EN end_summary_shown-händelse per ny mène och en om-rasterisering när fönstret gått ut. Ingen studio-tabell bär ett poäng, och varken servern eller ytan räknar en ställning: score_after är matchens egen. Den TOMMA rändens scored_by: "none" är ett eget besked, inte ett saknat värde
F09.04.26 Shipped Direct stream to YouTube Live (RTMP integration) m-3: youtube i den slutna plattformskatalogen (GET /v1/studio/catalog), registrerad EN gång som ett katalogmål med FÖRSEGLAD strömnyckel (stream_key_sealed, öppnas bara när måluppsättningen går till mediatjänsten) och kryssad per sändning. Adressen resolveras och PINNAS vid varje aktivering (SSRF-domen är husets enda); per-målshälsan är MÄTT ur mediatjänstens callback
F09.04.27 Shipped Direct stream to Twitch m-3: twitch i samma katalog och samma väg — plattformen är DATA, inte en kodgren, så en ny mottagare kräver varken migration eller frontend-release
F09.04.28 Shipped Direct stream to Facebook Live m-3: facebook med requires_rtmps i katalogen — ett rtmp:// mot Facebook avvisas 422 studio_target_rtmps_required redan vid registreringen, inte först när sändningen tystnar
F09.04.29 Shipped Multi-platform simultaneous streaming m-3: flera aktiverade länkar per sändning (tak studio.MaxStreamTargets, serverat i katalogen), reconcilierade som en MÄNGD mot mediatjänsten — ApplyTargets skickar den önskade uppsättningen, aldrig ett diff, så en missad händelse inte kan lämna en publicering igång som ingen bett om. Konsolens *»2 mål sänder · 1 återansluter«* RÄKNAS i servern, och ett fallet mål fäller aldrig de andra
F09.04.30 In progress In-app live viewing (watch directly in Petanque Life) Delvis (m-1): score-only — den publika läsningen ger sändningens tillstånd och D-COMP:s live-id, och appen/webben följer ställningen. Video i appen: ⊘ — ägare m-2
F09.04.31 Shipped Stream quality settings (adapt to available bandwidth) m-2: mediatjänsten kodar den adaptiva trappan och stream.renditions[] är SERVERNS stege. Ytorna renderar den som LÄSFÄLT (studio-kvalitet) respektive valbar rad (hls-spelare-kvalitet) — ingen yta bär en egen nivålista (grep-vaktat). Kvalitet per utgående mål är levererad av m-3: länkens quality överskriver katalogens default_quality, och effective_rendition är mediatjänstens MÄTTA svar om vad som faktiskt publiceras — auto = högsta PRODUCERADE steget, aldrig uppskalning
F09.04.32 Shipped Stream schedule and notification (followers get alerted) m-1: GET /v1/public/live/schedule?tenant= + följning genom viewer_follow (follow_type='broadcast') + notistypen broadcast_started, single-fire som DB-invariant med MÄTT utfall
F09.04.33 Shipped Embeddable live player for federation/club websites m-2: GET /embed/live/{slug}?tenant= (fristående HTML, frame-ancestors *, ingen extern resurs) och embed_snippet BYGGD AV SERVERN i …/playback — web /live visar den ordagrant i <code> med kopiera-knapp och bygger ALDRIG en egen iframe (grep-vaktat). Vy-spec: specs/web/views/embed-live.md
F09.04.34 Shipped Live viewer count and chat integration m-6 (0ec13810.m-6): tittarantalet är MÄTT ur anonym närvaro (POST /v1/public/live/{slug}/presence, viewer_count = unika aktiva tittarsessioner i katalogens fönster — aldrig follow_count) och livechatten är läsbar utan konto, skrivbar efter inloggning med eget visningsnamn, rapporterbar (tröskeln döljer), modererad (studio:moderate ∨ studio:manage: dölj/visa, avstängning per förbund, öppen/lugnt tempo/stängd) och gallrad av studio_chat_retention_tick. Kontraktet: specs/api/endpoints/studio-chat.md (t-1). Ytorna (t-2): web /live — pillen *🔴 Live · N tittare* med serverns tal, kortet *💬 Livechatt* (ström med Last-Event-ID, synlig pollning, rapport, de ärliga lägena) och sajtvärdens samma-ursprungs-söm; app /sandning/{slug} (talet + chatten) och /video/{slug} (view_count + VOD-hjärtslag); regi-konsolens block *Chatt & publik* (moderatorns kö, avstängningar, läget, kortet *Publik*); embeddens hjärtslag (pl-embed-live-2.js, CSP oförändrad). Bevis: tools/gate/dstudio-m6-e2e.mjs
F09.04.35 Shipped Local recording (save to device even without streaming) m-2: PATCH …/devices/{id} local_recording + enhetens egen inspelare (MediaRecorder ⇒ WebM på web, kamerans egen på native). Bytesen i den INJICERADE MediaBytesStore (app/lib/offline/media-bytes.ts) — aldrig i en egen store
F09.04.36 Shipped Cloud recording (save all camera feeds to cloud storage) m-2: recording_policy.cloud_all_tracks (☁️ i konsolen ⇒ PATCH …/productions/{id}), spåren finaliseras genom blob-porten vid :stop och listas i GET …/recordings med MÄTT längd, storlek och sha-256
F09.04.37 Shipped Automatic highlight generation (key moments based on score changes) m-5: POST …/highlights:generate föreslår EN markör per mène med poäng ur D-COMP:s poängbok (D-3 — oberoende av om regin valt auto-växling), fönstret ur katalogens lead/trail, idempotent per källrad; regissörens repriser blir auto_director-markörer. Konsolens *⚡ Auto-highlights* visar serverns MÄTTA kvitto (created + skäl) och granskningslistan. Kast-/carreau-baserade highlights: ingen producent (icke-mål)
F09.04.38 Shipped Manual highlight clipping (mark start/end of interesting moments) m-5: *✂️ Manuell klippning* — fönstret som m:ss eller förifyllt ur en markör, *Spara som markör* / *Rendera klipp* (mediatjänstens rendering, MÄTT längd). Att scrubba ett källspår i konsolen: ⊘ D-STUDIO-delta
F09.04.39 Shipped Post-match edit: re-cut with different camera angles m-5: :recut — samma fönster ur ett annat spår (kamerornas spår är utan grafik), valfri fart 100/50/25 %; en NY post, den gamla rörs aldrig
F09.04.40 Shipped Automatic match summary video (condensed highlights + score) m-5: *📼 Auto-sammanfattning* — de godkända markörerna i tidsordning (högst poäng först när budgeten inte räcker, urvalet bokfört) + ett slutställningskort ur D-COMP:s resultat. Den AI-genererade TEXT-sammanfattningen är ett icke-mål: ingen producent finns, och en genererad text som påstår sig beskriva en match är fabricerad data
F09.04.41 Shipped VOD archive (all recorded matches searchable by competition, player, date) m-5: det publika arkivet GET /v1/public/vod (sök i titel/beskrivning, faceter per tävling och publik spelare, datumintervall) och sektionen *Matcharkiv* på web /live med filtren som SERVERFRÅGOR. Visningsräknaren per video: levererad av m-6 — view_count på PublicVodItem, MÄTT ur VOD-närvaron (första hjärtslaget per nyckel och 24 h)
F09.04.42 Shipped Share match recording (link to specific match video) m-5: varje publicerad video har en fryst, delbar adress (share_url = /live/video/<slug>?tenant=), *🔗 Dela* i konsolen, arkivet, watch-sidan och appens /video/<slug>. Inbäddning av en VOD: ⊘ D-STUDIO-delta
F09.04.43 Shipped Video linked to match record (watch the video from the match detail page) m-5 (D-11 — en LÄSNING av arkivet, aldrig en kolumn i D-COMP): sektionen *Video* på web /resultat?competition=, app /tavling/[id] och videolänken på /min-match:s avslutade steg; varje arkivkort bär *Matchkort →*
F09.04.44 Shipped Audio-only mode (commentary without video for low bandwidth) m-2: audio_only är en RIKTIG rendition i master-spellistan (sist i renditions[]) och spelarens *🎧 Ljud* byter till den — aldrig en dämpad video som låtsas vara ett ljudläge
F09.04.45 Shipped Score-only live feed (text updates when video isn't possible) m-1: visionens §Scope 6 *score only* — den publika läsningen bär competition_ref (D-COMP:s live-id), och panelen återanvänder D-COMP:s egen live-vy. Ingen andra kanalklient
F09.04.46 Shipped Offline recording with later upload (record locally, upload when connected) m-2: collection studio-recording-upload i HUSETS offline-motor (styrningsklass media, identitet device:<deviceId>), replay PER POST genom enhetens eget token mot …/upload-sessions → …/parts/{n} → :complete; återupptagningens sanning är serverns parts_received[]. Registrerad i docs/migration/offline-persistence.md §3
F09.04.47 Shipped Adaptive bitrate streaming (auto-adjust quality) m-2: mediatjänsten kodar trappan, master-spellistan bär varianterna och spelarens *Auto* är hls.js/AVPlayer/ExoPlayers EGEN ABR över SAMMA renditioner — ingen yta väljer nivå åt tittaren