[{"data":1,"prerenderedAt":505},["ShallowReactive",2],{"content-en-\u002Fplayers\u002Fpwa":3},{"id":4,"title":5,"author":6,"body":7,"date":6,"description":498,"extension":499,"meta":500,"navigation":172,"path":501,"seo":502,"stem":503,"tags":6,"__hash__":504},"content_en\u002Fplayers\u002Fpwa.md","PWA Player",null,{"type":8,"value":9,"toc":481},"minimark",[10,15,73,77,85,96,100,105,108,195,201,205,208,212,226,357,361,371,378,408,414,425,429,455,459,477],[11,12,14],"h2",{"id":13},"features","Features",[16,17,18,26,32,38,49,55,61,67],"ul",{},[19,20,21,25],"li",{},[22,23,24],"strong",{},"Offline-first"," — Service Worker caching with parallel chunk downloads and progressive streaming",[19,27,28,31],{},[22,29,30],{},"XLF layout rendering"," — video (MP4\u002FHLS), images, audio overlay, PDF, text\u002Fticker, web pages",[19,33,34,37],{},[22,35,36],{},"Campaign scheduling"," — priority-based campaigns, dayparting, interrupts, and overlays",[19,39,40,43,44,48],{},[22,41,42],{},"Playback control"," — skip to next\u002Fprevious layout via keyboard or click the timeline overlay (when enabled via ",[45,46,47],"code",{},"controls"," config)",[19,50,51,54],{},[22,52,53],{},"Multi-display sync"," — BroadcastChannel-based lead\u002Ffollower synchronized playback for video walls",[19,56,57,60],{},[22,58,59],{},"Real-time commands"," — collectNow, screenshot, changeLayout, overlayLayout via XMR WebSocket",[19,62,63,66],{},[22,64,65],{},"Proof of play"," — per-layout and per-widget duration tracking",[19,68,69,72],{},[22,70,71],{},"Screen Wake Lock"," — prevents display from sleeping during playback",[11,74,76],{"id":75},"same-origin-requirement","Same-Origin Requirement",[78,79,80,81,84],"p",{},"The PWA ",[22,82,83],{},"must"," be served from the same domain as the Xibo CMS. All API calls go to the CMS origin, and browsers block cross-origin requests.",[78,86,87,88,91,92,95],{},"For kiosk\u002Fdesktop use, the ",[22,89,90],{},"Electron"," or ",[22,93,94],{},"Chromium"," wrappers handle CORS at the proxy level — no same-origin restriction.",[11,97,99],{"id":98},"deployment","Deployment",[101,102,104],"h3",{"id":103},"on-the-cms-recommended","On the CMS (recommended)",[78,106,107],{},"Copy the build output to the CMS web directory:",[109,110,115],"pre",{"className":111,"code":112,"language":113,"meta":114,"style":114},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","# Build from source (PWA is part of the SDK monorepo)\ncd xiboplayer\npnpm install && pnpm --filter @xiboplayer\u002Fpwa run build\n\n# Deploy to CMS container\npodman cp packages\u002Fpwa\u002Fdist\u002F. xibo-cms-web:\u002Fvar\u002Fwww\u002Fcms\u002Fweb\u002Fchromeos\u002F\n","bash","",[45,116,117,126,137,167,174,180],{"__ignoreMap":114},[118,119,122],"span",{"class":120,"line":121},"line",1,[118,123,125],{"class":124},"sutJx","# Build from source (PWA is part of the SDK monorepo)\n",[118,127,129,133],{"class":120,"line":128},2,[118,130,132],{"class":131},"sptTA","cd",[118,134,136],{"class":135},"s_sjI"," xiboplayer\n",[118,138,140,144,147,151,154,158,161,164],{"class":120,"line":139},3,[118,141,143],{"class":142},"sbgvK","pnpm",[118,145,146],{"class":135}," install",[118,148,150],{"class":149},"sP7_E"," &&",[118,152,153],{"class":142}," pnpm",[118,155,157],{"class":156},"stzsN"," --filter",[118,159,160],{"class":135}," @xiboplayer\u002Fpwa",[118,162,163],{"class":135}," run",[118,165,166],{"class":135}," build\n",[118,168,170],{"class":120,"line":169},4,[118,171,173],{"emptyLinePlaceholder":172},true,"\n",[118,175,177],{"class":120,"line":176},5,[118,178,179],{"class":124},"# Deploy to CMS container\n",[118,181,183,186,189,192],{"class":120,"line":182},6,[118,184,185],{"class":142},"podman",[118,187,188],{"class":135}," cp",[118,190,191],{"class":135}," packages\u002Fpwa\u002Fdist\u002F.",[118,193,194],{"class":135}," xibo-cms-web:\u002Fvar\u002Fwww\u002Fcms\u002Fweb\u002Fchromeos\u002F\n",[78,196,197,198],{},"Access at: ",[45,199,200],{},"https:\u002F\u002Fyour-cms.example.com\u002Fplayer\u002Fpwa\u002F",[101,202,204],{"id":203},"with-electron-or-chromium-wrapper","With Electron or Chromium wrapper",[78,206,207],{},"The Electron and Chromium packages bundle the PWA automatically. No manual deployment needed — install the package and run.",[11,209,211],{"id":210},"keyboard-shortcuts","Keyboard Shortcuts",[78,213,214,215,218,219,221,222,225],{},"All keyboard shortcuts and mouse hover are ",[22,216,217],{},"disabled by default"," in the Electron and Chromium wrappers. Each control group must be explicitly enabled via the ",[45,220,47],{}," section in ",[45,223,224],{},"config.json",". When running the PWA standalone in a browser, shortcuts are available without configuration.",[227,228,229,245],"table",{},[230,231,232],"thead",{},[233,234,235,239,242],"tr",{},[236,237,238],"th",{},"Key",[236,240,241],{},"Control group",[236,243,244],{},"Action",[246,247,248,264,278,293,312,329,343],"tbody",{},[233,249,250,256,261],{},[251,252,253],"td",{},[45,254,255],{},"T",[251,257,258],{},[45,259,260],{},"controls.keyboard.debugOverlays",[251,262,263],{},"Toggle timeline overlay — shows schedule with conflict indicators",[233,265,266,271,275],{},[251,267,268],{},[45,269,270],{},"D",[251,272,273],{},[45,274,260],{},[251,276,277],{},"Toggle download overlay — shows media download progress",[233,279,280,285,290],{},[251,281,282],{},[45,283,284],{},"V",[251,286,287],{},[45,288,289],{},"controls.keyboard.videoControls",[251,291,292],{},"Toggle video controls on all videos",[233,294,295,304,309],{},[251,296,297,300,301],{},[45,298,299],{},"→"," \u002F ",[45,302,303],{},"PageDown",[251,305,306],{},[45,307,308],{},"controls.keyboard.playbackControl",[251,310,311],{},"Next layout",[233,313,314,322,326],{},[251,315,316,300,319],{},[45,317,318],{},"←",[45,320,321],{},"PageUp",[251,323,324],{},[45,325,308],{},[251,327,328],{},"Previous layout",[233,330,331,336,340],{},[251,332,333],{},[45,334,335],{},"Space",[251,337,338],{},[45,339,308],{},[251,341,342],{},"Pause \u002F resume",[233,344,345,350,354],{},[251,346,347],{},[45,348,349],{},"R",[251,351,352],{},[45,353,308],{},[251,355,356],{},"Revert to scheduled layout",[11,358,360],{"id":359},"debug-overlays","Debug Overlays",[78,362,363,364,366,367,370],{},"Debug overlays are controlled exclusively by ",[45,365,260],{}," in config.json. They are ",[22,368,369],{},"not"," triggered by the DEBUG log level — log levels only affect logging verbosity.",[101,372,374,375,377],{"id":373},"timeline-overlay-t","Timeline Overlay (",[45,376,255],{},")",[16,379,380,387,390,396,402,405],{},[19,381,382,383,386],{},"Current layout highlighted with a ",[45,384,385],{},"▶"," marker",[19,388,389],{},"Time range and duration for each entry",[19,391,392,395],{},[45,393,394],{},"[def]"," tag on default\u002Ffallback layouts",[19,397,398,401],{},[45,399,400],{},"OFFLINE"," badge when CMS connectivity is lost",[19,403,404],{},"Conflict indicators showing suppressed layouts",[19,406,407],{},"Click-to-skip — click any layout to jump to it",[101,409,411,412,377],{"id":410},"download-overlay-d","Download Overlay (",[45,413,270],{},[16,415,416,419,422],{},[19,417,418],{},"Active downloads with progress bars and speed",[19,420,421],{},"Queue depth",[19,423,424],{},"Idle status when all media is cached",[11,426,428],{"id":427},"service-worker-architecture","Service Worker Architecture",[16,430,431,437,443,449],{},[19,432,433,436],{},[22,434,435],{},"Progressive streaming"," — large media served via chunk streaming with Range requests",[19,438,439,442],{},[22,440,441],{},"XLF-driven downloads"," — parses layout XLF to download exactly the media needed",[19,444,445,448],{},[22,446,447],{},"Layout-ordered downloads"," — currently-playing layout downloads first",[19,450,451,454],{},[22,452,453],{},"Adaptive chunk sizing"," — adjusts based on device RAM (4GB\u002F8GB+ tiers)",[11,456,458],{"id":457},"links","Links",[16,460,461,470],{},[19,462,463],{},[464,465,469],"a",{"href":466,"rel":467},"https:\u002F\u002Fgithub.com\u002Fxibo-players\u002Fxiboplayer\u002Ftree\u002Fmain\u002Fpackages\u002Fpwa",[468],"nofollow","GitHub",[19,471,472],{},[464,473,476],{"href":474,"rel":475},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@xiboplayer\u002Fpwa",[468],"npm",[478,479,480],"style",{},"html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":114,"searchDepth":139,"depth":139,"links":482},[483,484,485,489,490,496,497],{"id":13,"depth":128,"text":14},{"id":75,"depth":128,"text":76},{"id":98,"depth":128,"text":99,"children":486},[487,488],{"id":103,"depth":139,"text":104},{"id":203,"depth":139,"text":204},{"id":210,"depth":128,"text":211},{"id":359,"depth":128,"text":360,"children":491},[492,494],{"id":373,"depth":139,"text":493},"Timeline Overlay (T)",{"id":410,"depth":139,"text":495},"Download Overlay (D)",{"id":427,"depth":128,"text":428},{"id":457,"depth":128,"text":458},"Browser-based Xibo signage player. Works in any modern browser — Chrome, Firefox, Edge. No installation needed, just open the URL.","md",{},"\u002Fplayers\u002Fpwa",{"title":5,"description":498},"players\u002Fpwa","Ge5vXshzZAO5jN5OA3u5PPxVx894t8NGdx2-gY2KRDI",1775148105253]