Adiciona player.html estático, corrige Pure mode e desativa translate no Chromium

---

- Criado `public/player.html` como arquivo estático verdadeiro (servido pelo Next.js sem processamento, equivalente ao nginx), com HLS.js, tentativa direta ao MediaMTX em `:8888`, fallback para proxy, e integração silenciosa com `WebOSServiceBridge` para supressão do screensaver WebOS;
- Pure mode "Run HTML" atualizado para apontar a `/player.html?id={id}` em vez de rota dinâmica; rewrite removido do `next.config.ts`;
- Toggles "Pure mode" e "Open in new tab" no menu do card corrigidos: toggle agora à esquerda e texto à direita, alinhados com os demais itens;
- Adicionado `TranslateEnabled: false` na managed policy do Chromium no `Dockerfile`, solução definitiva para suprimir o popup de tradução do Google;

---
This commit is contained in:
2026-04-27 16:41:39 -03:00
parent 0f17ea4e38
commit e0fd0af02e
4 changed files with 86 additions and 13 deletions
+81
View File
@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
*{margin:0;padding:0;box-sizing:border-box}
html,body{background:#000;overflow:hidden;width:100%;height:100%}
video{width:100vw;height:100vh;display:block;object-fit:contain}
#msg{
position:fixed;top:16px;left:50%;transform:translateX(-50%);
background:rgba(0,0,0,0.75);color:#fff;padding:8px 20px;
border-radius:8px;font-family:sans-serif;font-size:34px;
display:none;z-index:9
}
</style>
</head>
<body>
<video id="v" autoplay muted playsinline></video>
<div id="msg"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.4.12/hls.min.js"></script>
<script>
var params = new URLSearchParams(window.location.search);
var id = params.get('id') || '';
var proxyUrl = '/api/hls/live/' + id + '/index.m3u8';
var directUrl= 'http://' + window.location.hostname + ':8888/live/' + id + '/index.m3u8';
var activeSrc= proxyUrl;
var hls;
function showMsg(t){
var m=document.getElementById('msg');
m.textContent=t;m.style.display='block';
setTimeout(function(){m.style.display='none';},4000);
}
function load(src){
activeSrc=src;
if(hls)hls.destroy();
hls=new Hls({
liveSyncDurationCount:2,liveMaxLatencyDurationCount:4,
manifestLoadingTimeOut:10000,manifestLoadingMaxRetry:10,
fragLoadingTimeOut:10000,fragLoadingMaxRetry:10
});
hls.loadSource(src);
hls.attachMedia(document.getElementById('v'));
hls.on(Hls.Events.MANIFEST_PARSED,function(){document.getElementById('v').play();});
hls.on(Hls.Events.ERROR,function(e,d){
if(d.fatal){showMsg('Error: '+d.type+' — reconnecting...');setTimeout(function(){load(activeSrc);},3000);}
});
}
var last=0;
setInterval(function(){
var v=document.getElementById('v');
if(v.currentTime===last&&!v.paused){showMsg('Stream stalled — reloading...');load(activeSrc);}
last=v.currentTime;
},10000);
fetch(directUrl,{method:'HEAD',signal:AbortSignal.timeout(2000)})
.then(function(){load(directUrl);})
.catch(function(){load(proxyUrl);});
// WebOS screensaver suppression — fails silently if not available
if(typeof WebOSServiceBridge!=='undefined'){
var bridge=new WebOSServiceBridge();
bridge.onservicecallback=function(msg){
var m=JSON.parse(msg);
if(m.state==='Active'){
bridge.call(
'luna://com.webos.service.tvpower/power/responseScreenSaverRequest',
JSON.stringify({clientName:'decapstream',ack:false,timestamp:m.timestamp})
);
}
};
bridge.call(
'luna://com.webos.service.tvpower/power/registerScreenSaverRequest',
JSON.stringify({subscribe:true,clientName:'decapstream'})
);
}
</script>
</body>
</html>