prismcast 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/README.md +26 -1
  2. package/dist/app.js +29 -2
  3. package/dist/app.js.map +1 -1
  4. package/dist/browser/cdp.js +1 -1
  5. package/dist/browser/cdp.js.map +1 -1
  6. package/dist/browser/channelSelection.d.ts +14 -4
  7. package/dist/browser/channelSelection.js +48 -704
  8. package/dist/browser/channelSelection.js.map +1 -1
  9. package/dist/browser/index.d.ts +18 -4
  10. package/dist/browser/index.js +205 -39
  11. package/dist/browser/index.js.map +1 -1
  12. package/dist/browser/tuning/fox.d.ts +19 -0
  13. package/dist/browser/tuning/fox.js +61 -0
  14. package/dist/browser/tuning/fox.js.map +1 -0
  15. package/dist/browser/tuning/hbo.d.ts +22 -0
  16. package/dist/browser/tuning/hbo.js +182 -0
  17. package/dist/browser/tuning/hbo.js.map +1 -0
  18. package/dist/browser/tuning/hulu.d.ts +30 -0
  19. package/dist/browser/tuning/hulu.js +514 -0
  20. package/dist/browser/tuning/hulu.js.map +1 -0
  21. package/dist/browser/tuning/sling.d.ts +22 -0
  22. package/dist/browser/tuning/sling.js +287 -0
  23. package/dist/browser/tuning/sling.js.map +1 -0
  24. package/dist/browser/tuning/thumbnailRow.d.ts +18 -0
  25. package/dist/browser/tuning/thumbnailRow.js +107 -0
  26. package/dist/browser/tuning/thumbnailRow.js.map +1 -0
  27. package/dist/browser/tuning/tileClick.d.ts +18 -0
  28. package/dist/browser/tuning/tileClick.js +102 -0
  29. package/dist/browser/tuning/tileClick.js.map +1 -0
  30. package/dist/browser/tuning/youtubeTv.d.ts +17 -0
  31. package/dist/browser/tuning/youtubeTv.js +99 -0
  32. package/dist/browser/tuning/youtubeTv.js.map +1 -0
  33. package/dist/browser/video.d.ts +2 -2
  34. package/dist/browser/video.js +18 -8
  35. package/dist/browser/video.js.map +1 -1
  36. package/dist/channels/index.js +131 -12
  37. package/dist/channels/index.js.map +1 -1
  38. package/dist/config/profiles.d.ts +5 -5
  39. package/dist/config/profiles.js +35 -11
  40. package/dist/config/profiles.js.map +1 -1
  41. package/dist/config/providers.d.ts +48 -4
  42. package/dist/config/providers.js +182 -22
  43. package/dist/config/providers.js.map +1 -1
  44. package/dist/config/sites.d.ts +10 -0
  45. package/dist/config/sites.js +96 -17
  46. package/dist/config/sites.js.map +1 -1
  47. package/dist/config/userChannels.js +21 -3
  48. package/dist/config/userChannels.js.map +1 -1
  49. package/dist/config/userConfig.d.ts +2 -1
  50. package/dist/config/userConfig.js +12 -4
  51. package/dist/config/userConfig.js.map +1 -1
  52. package/dist/index.js +10 -4
  53. package/dist/index.js.map +1 -1
  54. package/dist/routes/auth.js +6 -0
  55. package/dist/routes/auth.js.map +1 -1
  56. package/dist/routes/config.d.ts +5 -0
  57. package/dist/routes/config.js +273 -35
  58. package/dist/routes/config.js.map +1 -1
  59. package/dist/routes/debug.d.ts +6 -0
  60. package/dist/routes/debug.js +274 -0
  61. package/dist/routes/debug.js.map +1 -0
  62. package/dist/routes/index.d.ts +1 -0
  63. package/dist/routes/index.js +3 -0
  64. package/dist/routes/index.js.map +1 -1
  65. package/dist/routes/logs.js +17 -5
  66. package/dist/routes/logs.js.map +1 -1
  67. package/dist/routes/root.js +507 -128
  68. package/dist/routes/root.js.map +1 -1
  69. package/dist/routes/theme.js +7 -0
  70. package/dist/routes/theme.js.map +1 -1
  71. package/dist/service/commands.js +8 -8
  72. package/dist/service/commands.js.map +1 -1
  73. package/dist/service/generators.js +22 -16
  74. package/dist/service/generators.js.map +1 -1
  75. package/dist/streaming/fmp4Segmenter.d.ts +7 -0
  76. package/dist/streaming/fmp4Segmenter.js +124 -15
  77. package/dist/streaming/fmp4Segmenter.js.map +1 -1
  78. package/dist/streaming/hls.d.ts +74 -6
  79. package/dist/streaming/hls.js +212 -130
  80. package/dist/streaming/hls.js.map +1 -1
  81. package/dist/streaming/hlsSegments.js +11 -4
  82. package/dist/streaming/hlsSegments.js.map +1 -1
  83. package/dist/streaming/lifecycle.js +1 -1
  84. package/dist/streaming/lifecycle.js.map +1 -1
  85. package/dist/streaming/monitor.d.ts +1 -1
  86. package/dist/streaming/monitor.js +202 -53
  87. package/dist/streaming/monitor.js.map +1 -1
  88. package/dist/streaming/mp4Parser.d.ts +29 -1
  89. package/dist/streaming/mp4Parser.js +243 -18
  90. package/dist/streaming/mp4Parser.js.map +1 -1
  91. package/dist/streaming/mpegts.d.ts +5 -2
  92. package/dist/streaming/mpegts.js +122 -29
  93. package/dist/streaming/mpegts.js.map +1 -1
  94. package/dist/streaming/registry.d.ts +1 -1
  95. package/dist/streaming/registry.js.map +1 -1
  96. package/dist/streaming/setup.d.ts +13 -1
  97. package/dist/streaming/setup.js +136 -36
  98. package/dist/streaming/setup.js.map +1 -1
  99. package/dist/streaming/showInfo.js +9 -9
  100. package/dist/streaming/showInfo.js.map +1 -1
  101. package/dist/streaming/statusEmitter.js +5 -6
  102. package/dist/streaming/statusEmitter.js.map +1 -1
  103. package/dist/types/index.d.ts +16 -3
  104. package/dist/types/index.js +5 -1
  105. package/dist/types/index.js.map +1 -1
  106. package/dist/utils/debugFilter.d.ts +38 -0
  107. package/dist/utils/debugFilter.js +157 -0
  108. package/dist/utils/debugFilter.js.map +1 -0
  109. package/dist/utils/evaluate.js.map +1 -1
  110. package/dist/utils/ffmpeg.d.ts +5 -0
  111. package/dist/utils/ffmpeg.js +13 -2
  112. package/dist/utils/ffmpeg.js.map +1 -1
  113. package/dist/utils/fileLogger.d.ts +2 -1
  114. package/dist/utils/fileLogger.js +4 -2
  115. package/dist/utils/fileLogger.js.map +1 -1
  116. package/dist/utils/index.d.ts +1 -0
  117. package/dist/utils/index.js +1 -0
  118. package/dist/utils/index.js.map +1 -1
  119. package/dist/utils/logEmitter.d.ts +1 -0
  120. package/dist/utils/logEmitter.js.map +1 -1
  121. package/dist/utils/logger.d.ts +9 -8
  122. package/dist/utils/logger.js +52 -28
  123. package/dist/utils/logger.js.map +1 -1
  124. package/dist/utils/retry.d.ts +1 -1
  125. package/dist/utils/retry.js +3 -3
  126. package/dist/utils/retry.js.map +1 -1
  127. package/dist/utils/version.js +4 -9
  128. package/dist/utils/version.js.map +1 -1
  129. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"channelSelection.js","sourceRoot":"","sources":["../../src/browser/channelSelection.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG5C;;;;;;;;;;;GAWG;AAEH,gKAAgK;AAChK,mJAAmJ;AACnJ,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;AAEhD;;;GAGG;AACH,MAAM,UAAU,eAAe;IAE7B,aAAa,CAAC,KAAK,EAAE,CAAC;AACxB,CAAC;AAED;GACG;AAEH;;;;;;GAMG;AACH,KAAK,UAAU,cAAc,CAAC,IAAU,EAAE,MAAmB;IAE3D,mFAAmF;IACnF,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAEjB,yDAAyD;IACzD,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAE3C,OAAO,IAAI,CAAC;AACd,CAAC;AAED;GACG;AAEH;;;;;;;;;;;;;;GAcG;AACH,KAAK,UAAU,oBAAoB,CAAC,IAAU,EAAE,WAAmB;IAEjE,4JAA4J;IAC5J,YAAY;IACZ,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,CAAC,IAAY,EAAsB,EAAE;QAErF,MAAM,MAAM,GAAG,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAEhD,KAAI,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAEpC,+FAA+F;YAC/F,IAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAErC,MAAM,OAAO,GAAG,GAAG,CAAC,qBAAqB,EAAE,CAAC;gBAE5C,sEAAsE;gBACtE,IAAG,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;oBAE/C,8IAA8I;oBAC9I,IAAI,YAAY,GAAuB,GAAG,CAAC,aAAa,CAAC;oBAEzD,OAAM,YAAY,IAAI,CAAC,YAAY,KAAK,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;wBAEvD,MAAM,aAAa,GAAG,YAAY,CAAC,qBAAqB,EAAE,CAAC;wBAE3D,gJAAgJ;wBAChJ,gDAAgD;wBAChD,IAAG,aAAa,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;4BAE7C,oIAAoI;4BACpI,MAAM,UAAU,GAAG,YAAY,CAAC,gBAAgB,CAC9C,2HAA2H,CAC5H,CAAC;4BAEF,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;4BAEpD,KAAI,MAAM,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gCAE9C,MAAM,SAAS,GAAG,SAAS,CAAC,qBAAqB,EAAE,CAAC;gCACpD,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gCAE1D,4CAA4C;gCAC5C,iFAAiF;gCACjF,gCAAgC;gCAChC,8DAA8D;gCAC9D,MAAM,kBAAkB,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;gCAC1E,MAAM,aAAa,GAAG,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gCACtE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;gCAEvE,IAAG,kBAAkB,IAAI,aAAa,IAAI,SAAS,EAAE,CAAC;oCAEpD,wFAAwF;oCACvF,SAAyB,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;oCAEtG,MAAM,OAAO,GAAG,SAAS,CAAC,qBAAqB,EAAE,CAAC;oCAElD,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;gCACrF,CAAC;4BACH,CAAC;4BAED,yIAAyI;4BACzI,YAAY;4BACZ,MAAM,OAAO,GAAG,YAAY,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;4BAErD,KAAI,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gCAErC,MAAM,OAAO,GAAG,GAAG,CAAC,qBAAqB,EAAE,CAAC;gCAC5C,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gCACpD,MAAM,KAAK,GAAG,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;gCAE3C,MAAM,kBAAkB,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;gCACxE,MAAM,aAAa,GAAG,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;gCACpE,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC;gCAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;gCAErE,IAAG,kBAAkB,IAAI,aAAa,IAAI,WAAW,IAAI,SAAS,EAAE,CAAC;oCAEnE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;oCAE/E,MAAM,OAAO,GAAG,GAAG,CAAC,qBAAqB,EAAE,CAAC;oCAE5C,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;gCACrF,CAAC;4BACH,CAAC;wBACH,CAAC;wBAED,YAAY,GAAG,YAAY,CAAC,aAAa,CAAC;oBAC5C,CAAC;oBAED,wIAAwI;oBACxI,gBAAgB;oBAChB,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;oBAE/E,MAAM,UAAU,GAAG,GAAG,CAAC,qBAAqB,EAAE,CAAC;oBAE/C,OAAO,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,GAAG,EAAE,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;gBAChG,CAAC;YACH,CAAC;QACH,CAAC;QAED,6CAA6C;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,IAAG,WAAW,EAAE,CAAC;QAEf,MAAM,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAExC,4JAA4J;QAC5J,8JAA8J;QAC9J,QAAQ;QACR,IAAI,CAAC;YAEH,MAAM,IAAI,CAAC,eAAe,CACxB,GAAY,EAAE;gBAEZ,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;gBAE1C,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;YAClC,CAAC,EACD,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAChD,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YAEP,wDAAwD;QAC1D,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,6CAA6C,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACnF,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,KAAK,UAAU,iBAAiB,CAAC,IAAU,EAAE,WAAmB;IAE9D,kKAAkK;IAClK,4JAA4J;IAC5J,sDAAsD;IACtD,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,CAAC,IAAY,EAAsB,EAAE;QAEpF,MAAM,MAAM,GAAG,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAEhD,KAAI,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAEpC,IAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAErC,MAAM,OAAO,GAAG,GAAG,CAAC,qBAAqB,EAAE,CAAC;gBAE5C,4JAA4J;gBAC5J,sDAAsD;gBACtD,IAAG,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;oBAE/C,qJAAqJ;oBACrJ,0JAA0J;oBAC1J,IAAI,QAAQ,GAAuB,GAAG,CAAC,aAAa,CAAC;oBACrD,IAAI,eAAe,GAAuB,IAAI,CAAC;oBAE/C,OAAM,QAAQ,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;wBAE/C,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC;wBAE7B,iGAAiG;wBACjG,IAAG,CAAC,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,IAAI,QAAQ,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;4BAE3H,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;4BAEpF,MAAM,IAAI,GAAG,QAAQ,CAAC,qBAAqB,EAAE,CAAC;4BAE9C,IAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;gCAEzC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;4BACzE,CAAC;wBACH,CAAC;wBAED,sFAAsF;wBACtF,IAAG,CAAC,eAAe,EAAE,CAAC;4BAEpB,MAAM,IAAI,GAAG,QAAQ,CAAC,qBAAqB,EAAE,CAAC;4BAE9C,IAAG,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC;gCAEvG,eAAe,GAAG,QAAQ,CAAC;4BAC7B,CAAC;wBACH,CAAC;wBAED,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC;oBACpC,CAAC;oBAED,kFAAkF;oBAClF,IAAG,eAAe,EAAE,CAAC;wBAEnB,eAAe,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;wBAE3F,MAAM,IAAI,GAAG,eAAe,CAAC,qBAAqB,EAAE,CAAC;wBAErD,IAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;4BAEzC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;wBACzE,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,IAAG,CAAC,UAAU,EAAE,CAAC;QAEf,OAAO,EAAE,MAAM,EAAE,wCAAwC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC9E,CAAC;IAED,mDAAmD;IACnD,MAAM,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAEvC,iKAAiK;IACjK,uFAAuF;IACvF,MAAM,kBAAkB,GAAG,uDAAuD,CAAC;IAEnF,IAAI,CAAC;QAEH,MAAM,IAAI,CAAC,eAAe,CAAC,kBAAkB,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;IAC7F,CAAC;IAAC,MAAM,CAAC;QAEP,OAAO,EAAE,MAAM,EAAE,yDAAyD,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC/F,CAAC;IAED,gDAAgD;IAChD,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,CAAC,QAAgB,EAAsB,EAAE;QAExF,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAEhD,IAAG,CAAC,MAAM,EAAE,CAAC;YAEX,OAAO,IAAI,CAAC;QACd,CAAC;QAEA,MAAsB,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEnG,MAAM,IAAI,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;QAE5C,IAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;YAEzC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QACzE,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAEzB,IAAG,CAAC,UAAU,EAAE,CAAC;QAEf,OAAO,EAAE,MAAM,EAAE,0CAA0C,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAChF,CAAC;IAED,gDAAgD;IAChD,MAAM,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAEvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAWD;;;;;GAKG;AACH,KAAK,UAAU,oBAAoB,CAAC,IAAU;IAE5C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAsD,EAAE;QAE3F,MAAM,UAAU,GAAG,QAAQ,CAAC,gBAAgB,CAAC,8CAA8C,CAAC,CAAC;QAE7F,IAAG,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAE3B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,2BAA2B,CAAC;QAC3C,MAAM,OAAO,GAA+C,EAAE,CAAC;QAE/D,KAAI,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAEvC,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;YACpD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YAEnF,0FAA0F;YAC1F,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;YACnB,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,6CAA6C,CAAC,CAAC;YAE5E,IAAG,GAAG,EAAE,CAAC;gBAEP,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,gCAAgC,CAAC,CAAC;gBAEnE,IAAG,MAAM,EAAE,CAAC;oBAEV,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;oBAEvD,IAAG,KAAK,EAAE,CAAC;wBAET,6FAA6F;wBAC7F,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;oBACzC,CAAC;gBACH,CAAC;YACH,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,IAAG,CAAC,QAAQ,EAAE,CAAC;QAEb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,wDAAwD;IACxD,MAAM,QAAQ,GAAsB,EAAE,CAAC;IAEvC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAExC,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAEvB,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;QAEvE,yDAAyD;QACzD,IAAG,EAAE,CAAC,SAAS,IAAI,CAAC,EAAE,CAAC;YAErB,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,eAAe,CAAC,IAAU,EAAE,UAAkB;IAE3D,OAAO,iBAAiB,CAAC,IAAI,EAAE,CAAC,MAAc,EAAmC,EAAE;QAEjF,MAAM,MAAM,GAAG,2BAA2B,CAAC;QAC3C,MAAM,UAAU,GAAG,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,GAAG,MAAM,GAAG,KAAK,CAAC,CAAC;QAElF,KAAI,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAEvC,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;YACpD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YAEnF,IAAG,IAAI,KAAK,MAAM,EAAE,CAAC;gBAEnB,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,kCAAkC,CAAC,CAAC;gBAE3D,IAAG,CAAC,GAAG,EAAE,CAAC;oBAER,OAAO,IAAI,CAAC;gBACd,CAAC;gBAED,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,0BAA0B,CAAuB,CAAC;gBAElF,IAAG,CAAC,KAAK,EAAE,CAAC;oBAEV,OAAO,IAAI,CAAC;gBACd,CAAC;gBAED,KAAK,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAEjF,MAAM,IAAI,GAAG,KAAK,CAAC,qBAAqB,EAAE,CAAC;gBAE3C,IAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;oBAEzC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;gBACzE,CAAC;gBAED,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;AACnB,CAAC;AAED,4JAA4J;AAC5J,yJAAyJ;AACzJ,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAE9C,iKAAiK;AACjK,iKAAiK;AACjK,wIAAwI;AACxI,SAAS,oBAAoB,CAAC,IAAY;IAExC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;AACxD,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAS,mBAAmB,CAAC,QAA2B,EAAE,UAAkB;IAE1E,2JAA2J;IAC3J,MAAM,OAAO,GAAsB,EAAE,CAAC;IAEtC,KAAI,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAEzB,IAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAEpC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAED,yGAAyG;IACzG,IAAG,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAExB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gFAAgF;IAChF,IAAI,iBAAiB,GAAG,CAAC,CAAC,CAAC;IAE3B,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAEvC,IAAG,UAAU,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAEjD,iBAAiB,GAAG,CAAC,CAAC;YAEtB,MAAM;QACR,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,IAAI,aAAqB,CAAC;IAC1B,IAAI,aAAqB,CAAC;IAE1B,IAAG,iBAAiB,KAAK,CAAC,EAAE,CAAC;QAE3B,gFAAgF;QAChF,aAAa,GAAG,CAAC,CAAC,CAAC;QACnB,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACtC,CAAC;SAAM,IAAG,iBAAiB,KAAK,CAAC,CAAC,EAAE,CAAC;QAEnC,6EAA6E;QAC7E,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;QACrD,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC;IAClC,CAAC;SAAM,CAAC;QAEN,oCAAoC;QACpC,aAAa,GAAG,OAAO,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;QACxD,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC;IACtD,CAAC;IAED,oEAAoE;IACpE,KAAI,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAEzB,IAAG,CAAC,EAAE,CAAC,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,GAAG,aAAa,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAErG,OAAO,EAAE,CAAC,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,KAAK,UAAU,iBAAiB,CAAC,IAAU,EAAE,WAAmB,EAAE,gBAAwC;IAExG,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAAC;IAExD,kKAAkK;IAClK,kKAAkK;IAClK,4JAA4J;IAC5J,6CAA6C;IAC7C,IAAG,YAAY,EAAE,CAAC;QAEhB,IAAI,CAAC;YAEH,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACpG,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,EAAE,CAAE,EAAkB,CAAC,KAAK,EAAE,CAAC,CAAC;YAEpE,2EAA2E;YAC3E,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QAAC,OAAM,KAAK,EAAE,CAAC;YAEd,GAAG,CAAC,IAAI,CAAC,+CAA+C,EAAE,YAAY,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;IAED,8JAA8J;IAC9J,iHAAiH;IACjH,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,KAAI,IAAI,YAAY,GAAG,CAAC,EAAE,YAAY,GAAG,CAAC,EAAE,YAAY,EAAE,EAAE,CAAC;QAE3D,IAAI,CAAC;YAEH,MAAM,UAAU,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC;YAE/E,4CAA4C;YAC5C,MAAM,IAAI,CAAC,eAAe,CAAC,kCAAkC,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACvG,WAAW,GAAG,IAAI,CAAC;YAEnB,MAAM;QACR,CAAC;QAAC,MAAM,CAAC;YAEP,0GAA0G;YAC1G,IAAG,CAAC,YAAY,KAAK,CAAC,CAAC,IAAI,YAAY,EAAE,CAAC;gBAExC,GAAG,CAAC,KAAK,CAAC,uEAAuE,EAAE,YAAY,CAAC,CAAC;gBAEjG,IAAI,CAAC;oBAEH,4CAA4C;oBAC5C,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,EAAE,CAAE,EAAkB,CAAC,KAAK,EAAE,CAAC,CAAC;oBAEpE,4CAA4C;oBAC5C,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;gBACnB,CAAC;gBAAC,MAAM,CAAC;oBAEP,0DAA0D;gBAC5D,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAG,CAAC,WAAW,EAAE,CAAC;QAEhB,OAAO,EAAE,MAAM,EAAE,mCAAmC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACzE,CAAC;IAED,gIAAgI;IAChI,MAAM,UAAU,GAAG,GAAG,CAAC;IAEvB,sGAAsG;IACtG,MAAM,cAAc,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAEzD,8JAA8J;IAC9J,4JAA4J;IAC5J,uIAAuI;IACvI,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,SAAiB,EAAoD,EAAE;QAE3G,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,kCAAkC,CAAC,CAAC;QAEvE,IAAG,CAAC,GAAG,EAAE,CAAC;YAER,OAAO,IAAI,CAAC;QACd,CAAC;QAED,oDAAoD;QACpD,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC;QAEjC,IAAG,CAAC,MAAM,EAAE,CAAC;YAEX,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QAEzC,IAAG,YAAY,GAAG,SAAS,EAAE,CAAC;YAE5B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,+GAA+G;QAC/G,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC;QAEtC,IAAG,CAAC,QAAQ,EAAE,CAAC;YAEb,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,UAAU,GAAG,QAAQ,CAAC,qBAAqB,EAAE,CAAC,GAAG,GAAG,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC;QAE7F,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,SAAS,CAAC,EAAE,CAAC;IACzE,CAAC,EAAE,UAAU,CAAC,CAAC;IAEf,IAAG,CAAC,QAAQ,EAAE,CAAC;QAEb,OAAO,EAAE,MAAM,EAAE,+CAA+C,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACrF,CAAC;IAED,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC;IAE3C,iFAAiF;IACjF,MAAM,WAAW,GAAG,KAAK,EAAE,QAAgB,EAAiB,EAAE;QAE5D,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,QAAgB,EAAQ,EAAE;YAE7C,QAAQ,CAAC,eAAe,CAAC,SAAS,GAAG,QAAQ,CAAC;QAChD,CAAC,EAAE,UAAU,GAAG,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC;QAEzC,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC,CAAC;IAEF,yJAAyJ;IACzJ,IAAI,WAAW,GAAG,cAAc,CAAC;IAEjC,4JAA4J;IAC5J,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEpD,IAAG,SAAS,KAAK,SAAS,EAAE,CAAC;QAE3B,GAAG,CAAC,KAAK,CAAC,mCAAmC,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;QAEvE,MAAM,WAAW,CAAC,SAAS,CAAC,CAAC;QAE7B,iFAAiF;QACjF,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAElD,IAAG,QAAQ,EAAE,CAAC;YAEZ,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;YAEhE,IAAG,KAAK,EAAE,CAAC;gBAET,OAAO,MAAM,qBAAqB,CAAC,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;YACtF,CAAC;QACH,CAAC;QAED,wIAAwI;QACxI,GAAG,CAAC,KAAK,CAAC,yDAAyD,EAAE,WAAW,CAAC,CAAC;QAElF,aAAa,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACvC,CAAC;IAED,4JAA4J;IAC5J,yJAAyJ;IACzJ,8JAA8J;IAC9J,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,IAAI,GAAG,SAAS,GAAG,CAAC,CAAC;IACzB,MAAM,aAAa,GAAG,EAAE,CAAC;IACzB,IAAI,KAAK,GAAG,KAAK,CAAC;IAElB,KAAI,IAAI,SAAS,GAAG,CAAC,EAAE,SAAS,GAAG,aAAa,EAAE,SAAS,EAAE,EAAE,CAAC;QAE9D,IAAG,GAAG,GAAG,IAAI,EAAE,CAAC;YAEd,MAAM;QACR,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAEzC,4CAA4C;QAC5C,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;QAEvB,gFAAgF;QAChF,4CAA4C;QAC5C,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAElD,IAAG,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YAExC,SAAS;QACX,CAAC;QAED,kCAAkC;QAClC,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;QAErE,IAAG,UAAU,EAAE,CAAC;YAEd,KAAK,GAAG,IAAI,CAAC;YAEb,MAAM;QACR,CAAC;QAED,uJAAuJ;QACvJ,uJAAuJ;QACvJ,qDAAqD;QACrD,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QAE/E,IAAG,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAE7B,wGAAwG;YACxG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;YAEd,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACnC,MAAM,IAAI,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAExD,IAAG,cAAc,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAE3C,qGAAqG;YACrG,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC;YAEf,SAAS;QACX,CAAC;QAED,IAAG,cAAc,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAE1C,sGAAsG;YACtG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;YAEd,SAAS;QACX,CAAC;QAED,2JAA2J;QAC3J,qIAAqI;QACrI,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAE/D,IAAG,QAAQ,EAAE,CAAC;YAEZ,GAAG,CAAC,IAAI,CAAC,kDAAkD,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;YAEpF,WAAW,GAAG,QAAQ,CAAC;YACvB,KAAK,GAAG,IAAI,CAAC;YAEb,uHAAuH;YACvH,MAAM,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAEhD,IAAG,WAAW,KAAK,SAAS,EAAE,CAAC;gBAE7B,aAAa,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QAED,MAAM;IACR,CAAC;IAED,8JAA8J;IAC9J,4JAA4J;IAC5J,iEAAiE;IACjE,IAAG,CAAC,KAAK,EAAE,CAAC;QAEV,GAAG,CAAC,KAAK,CAAC,+DAA+D,EAAE,WAAW,CAAC,CAAC;QAExF,KAAI,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC;YAE5C,4CAA4C;YAC5C,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;YAEvB,4CAA4C;YAC5C,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,CAAC;YAElD,IAAG,CAAC,QAAQ,EAAE,CAAC;gBAEb,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;YAEhE,IAAG,KAAK,EAAE,CAAC;gBAET,KAAK,GAAG,IAAI,CAAC;gBAEb,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAG,CAAC,KAAK,EAAE,CAAC;QAEV,OAAO,EAAE,MAAM,EAAE,yBAAyB,GAAG,WAAW,GAAG,iBAAiB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACjG,CAAC;IAED,mHAAmH;IACnH,OAAO,MAAM,qBAAqB,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;AACnF,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,iBAAiB,CAAC,IAAU,EAAE,YAAgC,EAAE,OAAgB;IAE7F,IAAG,CAAC,YAAY,EAAE,CAAC;QAEjB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC;QAEH,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,EAAE,OAAO,EAAE,OAAO,IAAI,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAE/G,6JAA6J;QAC7J,4JAA4J;QAC5J,gJAAgJ;QAChJ,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,qBAAqB,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAErI,2JAA2J;QAC3J,mCAAmC;QACnC,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,CAAC,QAAgB,EAAmC,EAAE;YAErG,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAuB,CAAC;YAElE,IAAG,CAAC,EAAE,EAAE,CAAC;gBAEP,OAAO,IAAI,CAAC;YACd,CAAC;YAED,EAAE,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;YAE9E,MAAM,IAAI,GAAG,EAAE,CAAC,qBAAqB,EAAE,CAAC;YAExC,IAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;gBAEzC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;YACzE,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;QAEnB,IAAG,CAAC,UAAU,EAAE,CAAC;YAEf,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,YAAY,GAAG,+BAA+B,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACvG,CAAC;QAED,MAAM,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAEvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAM,KAAK,EAAE,CAAC;QAEd,OAAO,EAAE,MAAM,EAAE,gCAAgC,GAAG,YAAY,GAAG,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACvH,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,KAAK,UAAU,qBAAqB,CAAC,IAAU,EAAE,WAAmB,EAAE,YAAgC,EAAE,WAAmB;IAEzH,gJAAgJ;IAChJ,MAAM,kBAAkB,GAAG,CAAC,CAAC;IAE7B,8JAA8J;IAC9J,6DAA6D;IAC7D,MAAM,kBAAkB,GAAG,IAAI,CAAC;IAEhC,+FAA+F;IAC/F,MAAM,iBAAiB,GAAG,IAAI,CAAC;IAE/B,KAAI,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,kBAAkB,EAAE,OAAO,EAAE,EAAE,CAAC;QAE7D,4CAA4C;QAC5C,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAE7D,IAAG,CAAC,WAAW,EAAE,CAAC;YAEhB,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,WAAW,GAAG,4CAA4C,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACnH,CAAC;QAED,4CAA4C;QAC5C,MAAM,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAExC,yIAAyI;QACzI,MAAM,WAAW,GAAG,CAAC,OAAO,GAAG,kBAAkB,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC;QAExF,4CAA4C;QAC5C,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;QAExE,IAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YAElB,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,2FAA2F;QAC3F,IAAG,OAAO,GAAG,kBAAkB,GAAG,CAAC,EAAE,CAAC;YAEpC,GAAG,CAAC,KAAK,CAAC,mFAAmF,EAAE,WAAW,EAAE,OAAO,GAAG,CAAC,EAAE,kBAAkB,CAAC,CAAC;YAE7I,4CAA4C;YAC5C,MAAM,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,mCAAmC,GAAG,kBAAkB,GAAG,kCAAkC,GAAG,WAAW,GAAG,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACvJ,CAAC;AAED;GACG;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAU,EAAE,OAA4B;IAE1E,MAAM,EAAE,gBAAgB,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;IAEtD,wFAAwF;IACxF,IAAG,CAAC,gBAAgB,CAAC,QAAQ,KAAK,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;QAE9D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,6JAA6J;IAC7J,gKAAgK;IAChK,kKAAkK;IAClK,mIAAmI;IACnI,IAAG,gBAAgB,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;QAE7C,IAAI,CAAC;YAEH,MAAM,IAAI,CAAC,eAAe,CACxB,CAAC,IAAY,EAAW,EAAE;gBAExB,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC;YACjJ,CAAC,EACD,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,oBAAoB,EAAE,EACjD,eAAe,CAChB,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YAEP,sHAAsH;QACxH,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,IAAI,MAA6B,CAAC;IAElC,QAAO,gBAAgB,CAAC,QAAQ,EAAE,CAAC;QAEjC,KAAK,WAAW,CAAC,CAAC,CAAC;YAEjB,MAAM,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC;YAE1E,MAAM;QACR,CAAC;QAED,KAAK,cAAc,CAAC,CAAC,CAAC;YAEpB,MAAM,GAAG,MAAM,oBAAoB,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;YAE3D,MAAM;QACR,CAAC;QAED,KAAK,WAAW,CAAC,CAAC,CAAC;YAEjB,MAAM,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;YAExD,MAAM;QACR,CAAC;QAED,OAAO,CAAC,CAAC,CAAC;YAER,6FAA6F;YAC7F,GAAG,CAAC,IAAI,CAAC,yCAAyC,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAE/E,OAAO,EAAE,MAAM,EAAE,qCAAqC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,IAAG,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAEnB,GAAG,CAAC,IAAI,CAAC,4CAA4C,EAAE,eAAe,EAAE,MAAM,CAAC,MAAM,IAAI,iBAAiB,CAAC,CAAC;IAC9G,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"channelSelection.js","sourceRoot":"","sources":["../../src/browser/channelSelection.ts"],"names":[],"mappings":"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"}
@@ -51,9 +51,13 @@ export declare function getDataDir(): string;
51
51
  */
52
52
  export declare function ensureDataDirectory(): Promise<void>;
53
53
  /**
54
- * Terminates any Chrome processes that are still using our profile directory from previous runs. Chrome locks its profile directory while running, and if a
55
- * previous instance crashed without releasing the lock, we cannot launch a new browser with the same profile. This function uses pkill to find and terminate any
56
- * Chrome processes whose command line contains our profile directory path.
54
+ * Terminates any Chrome processes that are still using our profile directory from previous runs and waits for them to fully exit. Chrome locks its profile
55
+ * directory while running, and if a previous instance crashed without releasing the lock, we cannot launch a new browser with the same profile. This function
56
+ * uses pkill to find and terminate any Chrome processes whose command line contains our profile directory path, then polls pgrep to verify the processes have
57
+ * actually exited before returning.
58
+ *
59
+ * Waiting for exit is critical during service restarts. Without it, the new Chrome can launch while the old one is still releasing its profile lock and
60
+ * tabCapture extension state, causing stale capture errors that cascade into startup failures.
57
61
  *
58
62
  * This is called at startup before launching the browser to ensure a clean slate. It's safe to call even when no stale processes exist - pkill returns a non-zero
59
63
  * exit code when no processes match, which we ignore.
@@ -82,8 +86,8 @@ export declare function buildLaunchOptions(): LaunchOptions;
82
86
  *
83
87
  * - Returning the existing browser if it's still connected
84
88
  * - Launching a new browser if none exists or the previous one disconnected
89
+ * - Serializing concurrent callers so only one launch occurs at a time
85
90
  * - Waiting for the puppeteer-stream extension to initialize
86
- * - Minimizing the browser window to reduce GPU usage
87
91
  * - Setting up disconnect handlers for crash recovery
88
92
  * @returns The browser instance.
89
93
  * @throws If the browser cannot be launched.
@@ -177,6 +181,16 @@ export declare function startStalePageCleanup(): void;
177
181
  * the browser and streams.
178
182
  */
179
183
  export declare function stopStalePageCleanup(): void;
184
+ /**
185
+ * Starts the periodic browser restart eligibility check. This should be called once during server startup, after the browser is initialized. The interval runs
186
+ * indefinitely until stopBrowserRestartChecking() is called (typically during graceful shutdown).
187
+ */
188
+ export declare function startBrowserRestartChecking(): void;
189
+ /**
190
+ * Stops the browser restart checking interval and cancels any pending quiet timer. This should be called during graceful shutdown to prevent a restart from
191
+ * racing with server shutdown.
192
+ */
193
+ export declare function stopBrowserRestartChecking(): void;
180
194
  /**
181
195
  * Extracts the Puppeteer Stream extension files when running as a packaged executable. This copies the extension files from within the packaged binary to the
182
196
  * filesystem where Chrome can load them.
@@ -1,11 +1,11 @@
1
- import { LOG, evaluateWithAbort, formatError } from "../utils/index.js";
1
+ import { LOG, evaluateWithAbort, formatError, startTimer } from "../utils/index.js";
2
2
  import { getAllStreams, getStreamCount } from "../streaming/registry.js";
3
3
  import { getEffectivePreset, getPresetViewport } from "../config/presets.js";
4
4
  import { getExtensionPage, getStream, launch } from "puppeteer-stream";
5
5
  import { resizeAndMinimizeWindow, unminimizeWindow } from "./cdp.js";
6
6
  import { setBrowserChrome, setMaxSupportedViewport } from "./display.js";
7
7
  import { CONFIG } from "../config/index.js";
8
- import { clearGuideCache } from "./channelSelection.js";
8
+ import { clearChannelSelectionCaches } from "./channelSelection.js";
9
9
  import { emitSystemStatusChanged } from "../streaming/statusEmitter.js";
10
10
  import { execSync } from "node:child_process";
11
11
  import fs from "node:fs";
@@ -31,12 +31,33 @@ let currentBrowser = null;
31
31
  // The Chrome version string (e.g., "Chrome/144.0.7559.110") captured when the browser launches. Cleared when the browser disconnects. Used by the
32
32
  // health endpoint to report the active Chrome version.
33
33
  let currentChromeVersion = null;
34
+ // Timestamp (Date.now()) when the current browser instance was launched. Used by the opportunistic restart check to determine browser age. Cleared when the
35
+ // browser disconnects.
36
+ let browserLaunchTime = null;
37
+ // Launch mutex. When a browser launch is in progress, this holds the pending promise so that concurrent callers piggyback on the same launch instead of
38
+ // starting a second Chrome process. Cleared in a finally block once the launch settles.
39
+ let browserLaunchPromise = null;
34
40
  // The data directory stores Chrome's profile data and the streaming extension files. This is always ~/.prismcast, which provides a consistent location for
35
41
  // user-specific data regardless of how PrismCast is run.
36
42
  const dataDir = path.join(os.homedir(), ".prismcast");
37
43
  // The stale page cleanup interval handle, stored so we can clear it during graceful shutdown. The interval periodically checks for browser pages that are not
38
44
  // associated with active streams and closes them to prevent resource exhaustion.
39
45
  let stalePageCleanupInterval = null;
46
+ /* Opportunistic browser restart state. Chrome accumulates memory pressure, GPU process issues, and general flakiness over multi-hour sessions with continuous
47
+ * media playback. We proactively restart Chrome after it has been running for BROWSER_MAX_AGE, waiting for a quiet period with zero active streams before
48
+ * executing the restart. After the restart, a fresh browser is launched immediately so it is ready for the next stream request.
49
+ */
50
+ // Maximum browser uptime before considering a restart (6 hours).
51
+ const BROWSER_MAX_AGE = 6 * 60 * 60 * 1000;
52
+ // Duration of the quiet period (zero streams) required before executing the restart (5 minutes).
53
+ const BROWSER_RESTART_QUIET_PERIOD = 5 * 60 * 1000;
54
+ // How often to check whether the browser qualifies for a restart (30 seconds).
55
+ const BROWSER_RESTART_CHECK_INTERVAL = 30_000;
56
+ // Timer handle for the quiet period countdown. When set, the browser has exceeded BROWSER_MAX_AGE and we are waiting for BROWSER_RESTART_QUIET_PERIOD to
57
+ // elapse with zero active streams. Cancelled if a stream starts during the quiet period.
58
+ let restartQuietTimer = null;
59
+ // Interval handle for the periodic restart eligibility check.
60
+ let restartCheckInterval = null;
40
61
  // Flag indicating that the browser is being closed intentionally via closeBrowser(). When true, the disconnect handler skips error logging and stream termination
41
62
  // since these are handled by the shutdown code path. This prevents false "unexpected disconnect" errors during graceful shutdown.
42
63
  let gracefulShutdownInProgress = false;
@@ -96,7 +117,7 @@ const LOGIN_TIMEOUT_MS = 15 * 60 * 1000;
96
117
  export async function emitCurrentSystemStatus() {
97
118
  let pageCount = 0;
98
119
  try {
99
- if (currentBrowser && currentBrowser.isConnected()) {
120
+ if (currentBrowser?.connected) {
100
121
  const pages = await currentBrowser.pages();
101
122
  pageCount = pages.length;
102
123
  }
@@ -107,7 +128,7 @@ export async function emitCurrentSystemStatus() {
107
128
  const memUsage = process.memoryUsage();
108
129
  const status = {
109
130
  browser: {
110
- connected: !!currentBrowser && currentBrowser.isConnected(),
131
+ connected: !!currentBrowser && currentBrowser.connected,
111
132
  pageCount
112
133
  },
113
134
  memory: {
@@ -178,7 +199,7 @@ export function getDataDir() {
178
199
  export async function ensureDataDirectory() {
179
200
  try {
180
201
  await fsPromises.mkdir(dataDir, { recursive: true });
181
- LOG.info("Data directory ready: %s.", dataDir);
202
+ LOG.debug("browser", "Data directory ready: %s.", dataDir);
182
203
  }
183
204
  catch (error) {
184
205
  LOG.error("Failed to create data directory %s: %s.", dataDir, formatError(error));
@@ -200,9 +221,13 @@ export async function ensureDataDirectory() {
200
221
  * attempting to capture streams.
201
222
  */
202
223
  /**
203
- * Terminates any Chrome processes that are still using our profile directory from previous runs. Chrome locks its profile directory while running, and if a
204
- * previous instance crashed without releasing the lock, we cannot launch a new browser with the same profile. This function uses pkill to find and terminate any
205
- * Chrome processes whose command line contains our profile directory path.
224
+ * Terminates any Chrome processes that are still using our profile directory from previous runs and waits for them to fully exit. Chrome locks its profile
225
+ * directory while running, and if a previous instance crashed without releasing the lock, we cannot launch a new browser with the same profile. This function
226
+ * uses pkill to find and terminate any Chrome processes whose command line contains our profile directory path, then polls pgrep to verify the processes have
227
+ * actually exited before returning.
228
+ *
229
+ * Waiting for exit is critical during service restarts. Without it, the new Chrome can launch while the old one is still releasing its profile lock and
230
+ * tabCapture extension state, causing stale capture errors that cascade into startup failures.
206
231
  *
207
232
  * This is called at startup before launching the browser to ensure a clean slate. It's safe to call even when no stale processes exist - pkill returns a non-zero
208
233
  * exit code when no processes match, which we ignore.
@@ -214,12 +239,30 @@ export function killStaleChrome() {
214
239
  // Use pkill with -f to match against the full command line, not just the process name. This finds Chrome processes that were launched with our profile
215
240
  // directory. The command is wrapped in quotes to handle paths with spaces.
216
241
  execSync(["pkill -f \"", profileDir, "\""].join(""));
217
- LOG.info("Killed stale Chromium instances using %s.", profileDir);
242
+ LOG.debug("browser", "Killed stale Chrome instances using %s.", profileDir);
218
243
  }
219
244
  catch (_error) {
220
245
  // When pkill finds no matching processes, it returns a non-zero exit code. This is expected when there are no stale processes from a clean shutdown. We
221
- // silently ignore this expected case.
246
+ // silently ignore this expected case and skip the wait-for-exit polling below.
247
+ return;
222
248
  }
249
+ // Poll until the killed processes have fully exited. pgrep returns exit code 0 when matching processes exist and non-zero when none remain. We poll every
250
+ // 200ms for up to 5 seconds. This ensures Chrome has released its profile directory lock and tabCapture extension state before we launch a new instance.
251
+ const maxWaitMs = 5000;
252
+ const pollIntervalMs = 200;
253
+ const deadline = Date.now() + maxWaitMs;
254
+ while (Date.now() < deadline) {
255
+ try {
256
+ execSync(["pgrep -f \"", profileDir, "\""].join(""), { stdio: "ignore" });
257
+ // Processes still exist. Wait and check again.
258
+ execSync(["sleep ", String(pollIntervalMs / 1000)].join(""));
259
+ }
260
+ catch (_error) {
261
+ // pgrep returned non-zero — no matching processes remain. Chrome has fully exited.
262
+ return;
263
+ }
264
+ }
265
+ LOG.warn("Stale Chrome processes did not exit within %sms. Proceeding anyway.", maxWaitMs);
223
266
  }
224
267
  /**
225
268
  * Locates the Google Chrome executable on the system. The CHROME_BIN environment variable takes precedence, allowing operators to specify a non-standard
@@ -415,7 +458,7 @@ async function detectDisplayDimensions(browser) {
415
458
  // Cache the results for use by the preset system and window sizing.
416
459
  setBrowserChrome(dimensions.chromeWidth, dimensions.chromeHeight);
417
460
  setMaxSupportedViewport(maxWidth, maxHeight);
418
- LOG.debug("Display detection complete: screen %s\u00d7%s, chrome %s\u00d7%s, max viewport %s\u00d7%s.", dimensions.availWidth, dimensions.availHeight, dimensions.chromeWidth, dimensions.chromeHeight, maxWidth, maxHeight);
461
+ LOG.debug("browser", "Display detection complete: screen %s\u00d7%s, chrome %s\u00d7%s, max viewport %s\u00d7%s.", dimensions.availWidth, dimensions.availHeight, dimensions.chromeWidth, dimensions.chromeHeight, maxWidth, maxHeight);
419
462
  // Check if the configured preset needs to be degraded and warn the user.
420
463
  const presetResult = getEffectivePreset(CONFIG);
421
464
  if (presetResult.degraded && presetResult.maxViewport) {
@@ -450,11 +493,17 @@ async function detectDisplayDimensions(browser) {
450
493
  * This ensures streams fail gracefully rather than hanging indefinitely trying to use closed pages.
451
494
  */
452
495
  function handleBrowserDisconnect() {
453
- // Clear the browser reference and cached version so getCurrentBrowser() will launch a new instance on the next call.
496
+ // Clear the browser reference, launch timestamp, and cached version so getCurrentBrowser() will launch a new instance on the next call.
454
497
  currentBrowser = null;
498
+ browserLaunchTime = null;
455
499
  currentChromeVersion = null;
456
- // Clear the guide grid row number cache. The guide layout may change between browser sessions, so cached row positions could be stale.
457
- clearGuideCache();
500
+ // Cancel any pending restart quiet timer since the browser is already gone.
501
+ if (restartQuietTimer) {
502
+ clearTimeout(restartQuietTimer);
503
+ restartQuietTimer = null;
504
+ }
505
+ // Clear all channel selection caches. Cached state (guide row positions, discovered page URLs) may be stale in a new browser session.
506
+ clearChannelSelectionCaches();
458
507
  // Clear login state if login mode was active. We clear directly rather than calling endLoginMode() because the browser is already gone and we don't want to
459
508
  // attempt any browser operations.
460
509
  if (loginModeActive) {
@@ -490,19 +539,41 @@ function handleBrowserDisconnect() {
490
539
  *
491
540
  * - Returning the existing browser if it's still connected
492
541
  * - Launching a new browser if none exists or the previous one disconnected
542
+ * - Serializing concurrent callers so only one launch occurs at a time
493
543
  * - Waiting for the puppeteer-stream extension to initialize
494
- * - Minimizing the browser window to reduce GPU usage
495
544
  * - Setting up disconnect handlers for crash recovery
496
545
  * @returns The browser instance.
497
546
  * @throws If the browser cannot be launched.
498
547
  */
499
548
  export async function getCurrentBrowser() {
500
- // Fast path: if we have a browser and it's still connected, return it immediately. The isConnected() check verifies the DevTools Protocol connection is
549
+ // Fast path: if we have a browser and it's still connected, return it immediately. The connected property verifies the DevTools Protocol connection is
501
550
  // still alive.
502
- if (currentBrowser && currentBrowser.isConnected()) {
551
+ if (currentBrowser?.connected) {
503
552
  return currentBrowser;
504
553
  }
505
- // We need to launch a new browser. This happens on first stream request, after a browser crash, or during server warmup.
554
+ // If a launch is already in progress (e.g., from the restart path or a concurrent stream request), piggyback on that promise instead of starting a second
555
+ // Chrome process. Two concurrent launches with the same profile directory would contend on Chrome's profile lock.
556
+ if (browserLaunchPromise) {
557
+ return browserLaunchPromise;
558
+ }
559
+ // We need to launch a new browser. Store the promise so concurrent callers can piggyback on this launch.
560
+ browserLaunchPromise = launchBrowser();
561
+ try {
562
+ return await browserLaunchPromise;
563
+ }
564
+ finally {
565
+ browserLaunchPromise = null;
566
+ }
567
+ }
568
+ /**
569
+ * Launches a new browser instance and performs post-launch initialization (extension readiness, display detection, version capture). This is the inner launch
570
+ * function called by getCurrentBrowser() and serialized by the browserLaunchPromise mutex.
571
+ * @returns The browser instance.
572
+ * @throws If the browser cannot be launched.
573
+ */
574
+ async function launchBrowser() {
575
+ const browserElapsed = startTimer();
576
+ // This happens on first stream request, after a browser crash, during server warmup, or during an opportunistic restart.
506
577
  try {
507
578
  const options = buildLaunchOptions();
508
579
  // The launch function from puppeteer-stream wraps standard Puppeteer launch to inject the streaming extension. We pass our custom launch function that
@@ -510,6 +581,7 @@ export async function getCurrentBrowser() {
510
581
  currentBrowser = await launch({ launch: launchWithCustomArgs }, options);
511
582
  // Register a handler for browser disconnection. This ensures we clean up properly if the browser crashes or is closed unexpectedly.
512
583
  currentBrowser.on("disconnected", handleBrowserDisconnect);
584
+ LOG.debug("timing:browser", "Chrome process spawned. (+%sms)", browserElapsed());
513
585
  // Poll for the puppeteer-stream extension to finish initializing. The extension injects a START_RECORDING function into its options page context. We poll
514
586
  // for this function's existence rather than using a fixed delay, so the browser is ready as soon as the extension loads — typically 200-500ms rather than the
515
587
  // full configured timeout. Uses getExtensionPage() from puppeteer-stream to locate the extension's options page.
@@ -522,24 +594,26 @@ export async function getCurrentBrowser() {
522
594
  // assertExtensionLoaded() in puppeteer-stream will retry before each capture attempt, so this isn't fatal.
523
595
  LOG.warn("Extension did not initialize within %d ms. Streams may need additional time to start.", CONFIG.browser.initTimeout);
524
596
  }
597
+ LOG.debug("timing:browser", "Extension initialized. (+%sms)", browserElapsed());
525
598
  // Detect display dimensions to determine maximum supported viewport. This must happen before we start streaming so the preset system can degrade to a
526
599
  // smaller preset if needed.
527
600
  await detectDisplayDimensions(currentBrowser);
528
- // Minimize the browser window to reduce GPU usage and desktop clutter. The browser must be visible (not headless) for capture to work, but minimizing
529
- // it reduces resource consumption. CDP allows us to control window state without affecting capture.
530
- await minimizeBrowserWindow();
601
+ LOG.debug("timing:browser", "Display detection complete. (+%sms)", browserElapsed());
531
602
  // Log the Chrome version for diagnostic reference. This helps correlate browser behavior changes (tab unresponsiveness, memory pressure, capture issues)
532
603
  // with specific Chrome releases.
533
604
  const chromeVersion = await currentBrowser.version();
605
+ browserLaunchTime = Date.now();
534
606
  currentChromeVersion = chromeVersion;
535
607
  LOG.info("Chrome ready: %s.", chromeVersion);
608
+ LOG.debug("timing:browser", "Browser ready. Total: %sms.", browserElapsed());
536
609
  // Emit system status update for SSE subscribers.
537
610
  await emitCurrentSystemStatus();
538
611
  }
539
612
  catch (error) {
540
613
  LOG.error("Failed to launch browser: %s.", formatError(error));
541
- // Clear the browser reference and cached version on failure so the next call will attempt to launch again.
614
+ // Clear the browser reference, launch timestamp, and cached version on failure so the next call will attempt to launch again.
542
615
  currentBrowser = null;
616
+ browserLaunchTime = null;
543
617
  currentChromeVersion = null;
544
618
  throw error;
545
619
  }
@@ -557,7 +631,7 @@ export function getChromeVersion() {
557
631
  * @returns True if the browser is connected and ready for use, false otherwise.
558
632
  */
559
633
  export function isBrowserConnected() {
560
- return !!currentBrowser && currentBrowser.isConnected();
634
+ return !!currentBrowser && currentBrowser.connected;
561
635
  }
562
636
  /**
563
637
  * Resizes the browser window to the effective viewport and minimizes it. This function combines viewport sizing with minimization to ensure the window is
@@ -569,7 +643,7 @@ export function isBrowserConnected() {
569
643
  */
570
644
  export async function minimizeBrowserWindow() {
571
645
  // Guard against calling this when no browser is running.
572
- if (!currentBrowser || !currentBrowser.isConnected()) {
646
+ if (!currentBrowser?.connected) {
573
647
  return;
574
648
  }
575
649
  let tempPage = null;
@@ -607,7 +681,7 @@ export async function minimizeBrowserWindow() {
607
681
  }
608
682
  }
609
683
  // Resizing/minimizing is not critical - log a warning but don't fail the operation.
610
- LOG.warn("Could not resize and minimize browser window: %s.", formatError(error));
684
+ LOG.debug("browser", "Could not resize and minimize browser window: %s.", formatError(error));
611
685
  }
612
686
  }
613
687
  /**
@@ -616,7 +690,7 @@ export async function minimizeBrowserWindow() {
616
690
  */
617
691
  export async function getBrowserPages() {
618
692
  // Guard against calling this when no browser is running.
619
- if (!currentBrowser || !currentBrowser.isConnected()) {
693
+ if (!currentBrowser?.connected) {
620
694
  return [];
621
695
  }
622
696
  try {
@@ -641,19 +715,20 @@ export async function closeBrowser() {
641
715
  // calls to closeBrowser().
642
716
  setGracefulShutdown(true);
643
717
  const browserRef = currentBrowser;
644
- // Clear the reference and cached version early to prevent any new operations from using it.
718
+ // Clear the reference, launch timestamp, and cached version early to prevent any new operations from using it.
645
719
  currentBrowser = null;
720
+ browserLaunchTime = null;
646
721
  currentChromeVersion = null;
647
722
  if (!browserRef) {
648
723
  return;
649
724
  }
650
725
  // Stage 1: Try graceful close with a timeout. We use Promise.race to avoid hanging indefinitely if Chrome is unresponsive.
651
726
  let closedGracefully = false;
652
- if (browserRef.isConnected()) {
727
+ if (browserRef.connected) {
653
728
  try {
654
729
  await Promise.race([
655
730
  browserRef.close(),
656
- new Promise((_, reject) => setTimeout(() => reject(new Error("Browser close timed out")), 5000))
731
+ new Promise((_, reject) => setTimeout(() => { reject(new Error("Browser close timed out")); }, 5000))
657
732
  ]);
658
733
  closedGracefully = true;
659
734
  }
@@ -663,7 +738,7 @@ export async function closeBrowser() {
663
738
  LOG.warn("Browser did not close within 5 seconds. Forcing termination.");
664
739
  }
665
740
  else {
666
- LOG.debug("Browser close error: %s.", message);
741
+ LOG.debug("browser", "Browser close error: %s.", message);
667
742
  }
668
743
  }
669
744
  }
@@ -676,11 +751,11 @@ export async function closeBrowser() {
676
751
  const browserProcess = browserRef.process();
677
752
  if (browserProcess && !browserProcess.killed) {
678
753
  browserProcess.kill("SIGKILL");
679
- LOG.debug("Sent SIGKILL to browser process.");
754
+ LOG.debug("browser", "Sent SIGKILL to browser process.");
680
755
  }
681
756
  }
682
757
  catch (error) {
683
- LOG.debug("Browser process kill error: %s.", formatError(error));
758
+ LOG.debug("browser", "Browser process kill error: %s.", formatError(error));
684
759
  }
685
760
  }
686
761
  // Stage 3: As a final fallback, use pkill to ensure no Chrome processes using our profile remain.
@@ -710,7 +785,7 @@ export async function startLoginMode(url) {
710
785
  return { error: "Login is already in progress.", success: false };
711
786
  }
712
787
  // Ensure browser is available.
713
- if (!currentBrowser || !currentBrowser.isConnected()) {
788
+ if (!currentBrowser?.connected) {
714
789
  return { error: "Browser is not connected.", success: false };
715
790
  }
716
791
  try {
@@ -787,7 +862,7 @@ export async function endLoginMode() {
787
862
  loginUrl = null;
788
863
  loginStartTime = null;
789
864
  // Re-minimize the browser window.
790
- if (wasActive && currentBrowser && currentBrowser.isConnected()) {
865
+ if (wasActive && currentBrowser?.connected) {
791
866
  await minimizeBrowserWindow();
792
867
  }
793
868
  if (wasActive) {
@@ -840,7 +915,7 @@ export function getLoginStatus() {
840
915
  */
841
916
  export async function cleanupStalePages() {
842
917
  // Guard against calling this when no browser is running.
843
- if (!currentBrowser || !currentBrowser.isConnected()) {
918
+ if (!currentBrowser?.connected) {
844
919
  return;
845
920
  }
846
921
  try {
@@ -919,12 +994,12 @@ export async function cleanupStalePages() {
919
994
  }
920
995
  // Log only if we actually closed something, to avoid log spam from idle cleanup runs.
921
996
  if (closedCount > 0) {
922
- LOG.info("Cleaned up %s stale page(s).", closedCount);
997
+ LOG.debug("browser", "Cleaned up %s stale page(s).", closedCount);
923
998
  }
924
999
  }
925
1000
  catch (error) {
926
1001
  // Cleanup failure is not critical - log a warning and try again next interval.
927
- LOG.warn("Stale page cleanup failed: %s.", formatError(error));
1002
+ LOG.debug("browser", "Stale page cleanup failed: %s.", formatError(error));
928
1003
  }
929
1004
  }
930
1005
  /**
@@ -932,7 +1007,7 @@ export async function cleanupStalePages() {
932
1007
  * indefinitely until stopStalePageCleanup() is called (typically during graceful shutdown).
933
1008
  */
934
1009
  export function startStalePageCleanup() {
935
- stalePageCleanupInterval = setInterval(cleanupStalePages, CONFIG.recovery.stalePageCleanupInterval);
1010
+ stalePageCleanupInterval = setInterval(() => { void cleanupStalePages(); }, CONFIG.recovery.stalePageCleanupInterval);
936
1011
  }
937
1012
  /**
938
1013
  * Stops the stale page cleanup interval. This should be called during graceful shutdown to prevent the cleanup from running after we've started shutting down
@@ -944,6 +1019,97 @@ export function stopStalePageCleanup() {
944
1019
  stalePageCleanupInterval = null;
945
1020
  }
946
1021
  }
1022
+ /* Opportunistic browser restart functions. The check runs on a 30-second interval and, when the browser exceeds BROWSER_MAX_AGE with zero active streams, starts
1023
+ * a quiet period timer. The quiet timer is cancelled if a stream starts, ensuring active viewers are never disrupted. When the timer expires, the browser is
1024
+ * closed and immediately re-launched.
1025
+ */
1026
+ /**
1027
+ * Checks whether the browser qualifies for an opportunistic restart. Called periodically by the restart check interval. The check skips when any of these
1028
+ * conditions hold: graceful shutdown in progress, login mode active, browser not connected, browser age below threshold. If active streams exist, any pending
1029
+ * quiet timer is cancelled (streams started during the quiet period reset the countdown). Otherwise a quiet timer is started if one is not already running.
1030
+ */
1031
+ function checkBrowserRestart() {
1032
+ // Skip if the server is shutting down, login mode is active, or the browser is not connected.
1033
+ if (gracefulShutdownInProgress || loginModeActive || !currentBrowser || !currentBrowser.connected || !browserLaunchTime) {
1034
+ return;
1035
+ }
1036
+ // Skip if the browser has not exceeded the maximum age.
1037
+ const age = Date.now() - browserLaunchTime;
1038
+ if (age < BROWSER_MAX_AGE) {
1039
+ return;
1040
+ }
1041
+ // If there are active streams, cancel any pending quiet timer and return. Streams that start during the quiet period reset the countdown.
1042
+ if (getStreamCount() > 0) {
1043
+ if (restartQuietTimer) {
1044
+ LOG.debug("browser", "Browser restart quiet period cancelled — streams are active.");
1045
+ clearTimeout(restartQuietTimer);
1046
+ restartQuietTimer = null;
1047
+ }
1048
+ return;
1049
+ }
1050
+ // No active streams and the browser is old enough. Start the quiet timer if one is not already running.
1051
+ if (!restartQuietTimer) {
1052
+ LOG.debug("browser", "Browser uptime exceeds threshold. Quiet period started — restart will proceed if no streams start within %s minutes.", Math.round(BROWSER_RESTART_QUIET_PERIOD / 60000));
1053
+ restartQuietTimer = setTimeout(() => {
1054
+ void executeBrowserRestart();
1055
+ }, BROWSER_RESTART_QUIET_PERIOD);
1056
+ }
1057
+ }
1058
+ /**
1059
+ * Executes the opportunistic browser restart after the quiet period has elapsed. Performs a final guard check before proceeding, then closes the browser and
1060
+ * immediately re-launches a fresh instance.
1061
+ */
1062
+ async function executeBrowserRestart() {
1063
+ // Clear the timer handle.
1064
+ restartQuietTimer = null;
1065
+ // Final guard: re-check all preconditions. Conditions may have changed during the quiet period (e.g., a stream started just before the timer fired, login
1066
+ // mode was activated, or the browser disconnected on its own).
1067
+ if (gracefulShutdownInProgress || loginModeActive || (getStreamCount() > 0) || !currentBrowser || !currentBrowser.connected || !browserLaunchTime) {
1068
+ LOG.debug("browser", "Browser restart aborted — preconditions no longer met.");
1069
+ return;
1070
+ }
1071
+ const age = Date.now() - browserLaunchTime;
1072
+ const hours = Math.floor(age / 3600000);
1073
+ const minutes = Math.floor((age % 3600000) / 60000);
1074
+ LOG.info("Restarting browser for scheduled maintenance (uptime: %sh %sm).", hours, minutes);
1075
+ try {
1076
+ // closeBrowser() sets gracefulShutdownInProgress = true internally and performs multi-stage graceful close.
1077
+ await closeBrowser();
1078
+ // Reset the flag since the server is NOT shutting down — only the browser is restarting.
1079
+ setGracefulShutdown(false);
1080
+ // Launch a fresh browser instance so it is ready for the next stream request.
1081
+ await getCurrentBrowser();
1082
+ // Minimize the new window to reduce GPU usage and desktop clutter.
1083
+ await minimizeBrowserWindow();
1084
+ LOG.info("Browser restart complete. Fresh instance is ready.");
1085
+ }
1086
+ catch (error) {
1087
+ LOG.error("Browser restart failed: %s.", formatError(error));
1088
+ // Ensure the graceful shutdown flag is cleared even on failure so new stream requests can still launch a browser.
1089
+ setGracefulShutdown(false);
1090
+ }
1091
+ }
1092
+ /**
1093
+ * Starts the periodic browser restart eligibility check. This should be called once during server startup, after the browser is initialized. The interval runs
1094
+ * indefinitely until stopBrowserRestartChecking() is called (typically during graceful shutdown).
1095
+ */
1096
+ export function startBrowserRestartChecking() {
1097
+ restartCheckInterval = setInterval(checkBrowserRestart, BROWSER_RESTART_CHECK_INTERVAL);
1098
+ }
1099
+ /**
1100
+ * Stops the browser restart checking interval and cancels any pending quiet timer. This should be called during graceful shutdown to prevent a restart from
1101
+ * racing with server shutdown.
1102
+ */
1103
+ export function stopBrowserRestartChecking() {
1104
+ if (restartCheckInterval) {
1105
+ clearInterval(restartCheckInterval);
1106
+ restartCheckInterval = null;
1107
+ }
1108
+ if (restartQuietTimer) {
1109
+ clearTimeout(restartQuietTimer);
1110
+ restartQuietTimer = null;
1111
+ }
1112
+ }
947
1113
  /* When running as a packaged executable (created by the `pkg` tool), the application is bundled into a single binary. Node modules like puppeteer-stream are
948
1114
  * included in the bundle, but Chrome cannot load extensions from within the packaged binary - it needs actual files on the filesystem.
949
1115
  *
@@ -992,7 +1158,7 @@ export async function prepareExtension() {
992
1158
  throw error;
993
1159
  }
994
1160
  }
995
- LOG.info("Extension files prepared successfully.");
1161
+ LOG.debug("browser", "Extension files prepared successfully.");
996
1162
  }
997
1163
  catch (error) {
998
1164
  LOG.error("Extension preparation failed: %s.", formatError(error));